Skip to content

Commit

Permalink
test implemantion of the http module FAILED
Browse files Browse the repository at this point in the history
  • Loading branch information
tacheraSasi committed Dec 6, 2024
1 parent efe9b13 commit 53b6d02
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 35 deletions.
70 changes: 35 additions & 35 deletions evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ if (10 > 1) {
},
{
`{"jina": "Avi"}[func(x) {x}];`,
"Line 1: Samahani, UNDO (FUNCTION) haitumiki if ufunguo",
"Line 1: Samahani, FUNC (FUNCTION) haitumiki if ufunguo",
},
}

Expand Down Expand Up @@ -603,31 +603,31 @@ func TestInExpression(t *testing.T) {
expected bool
}{
{
"'a' ktk 'habari'",
"'a' in 'habari'",
true,
},
{
"'c' ktk 'habari'",
"'c' in 'habari'",
false,
},
{
"1 ktk [1, 2, 3]",
"1 in [1, 2, 3]",
true,
},
{
"4 ktk [1, 2, 3]",
"4 in [1, 2, 3]",
false,
},
{
"'a' ktk {'a': 'apple', 'b': 'banana'}",
"'a' in {'a': 'apple', 'b': 'banana'}",
true,
},
{
"'apple' ktk {'a': 'apple', 'b': 'banana'}",
"'apple' in {'a': 'apple', 'b': 'banana'}",
false,
},
{
"'c' ktk {'a': 'apple', 'b': 'banana'}",
"'c' in {'a': 'apple', 'b': 'banana'}",
false,
},
}
Expand Down Expand Up @@ -748,7 +748,7 @@ func TestPostfixExpression(t *testing.T) {
func TestWhileLoop(t *testing.T) {
input := `
i = 10
wakati (i > 0){
while (i > 0){
i--
}
i
Expand All @@ -768,7 +768,7 @@ func TestWhileLoop(t *testing.T) {
func TestForLoop(t *testing.T) {
input := `
output = ""
kwa i ktk "mojo" {
for i in "mojo" {
output += i
}
output
Expand All @@ -787,9 +787,9 @@ func TestForLoop(t *testing.T) {
func TestBreakLoop(t *testing.T) {
input := `
i = 0
wakati (i < 10) {
while (i < 10) {
if (i == 5) {
vunja
break
}
i++
}
Expand All @@ -807,10 +807,10 @@ func TestBreakLoop(t *testing.T) {

input = `
output = ""
kwa i ktk "mojo" {
for i in "mojo" {
output += i
if (i == 'o') {
vunja
break
}
}
output
Expand All @@ -830,10 +830,10 @@ func TestBreakLoop(t *testing.T) {
func TestContinueLoop(t *testing.T) {
input := `
i = 0
wakati (i < 10) {
while (i < 10) {
i++
if (i == 5) {
endelea
continue
}
i++
}
Expand All @@ -851,9 +851,9 @@ func TestContinueLoop(t *testing.T) {

input = `
output = ""
kwa i ktk "mojo" {
for i in "mojo" {
if (i == 'o') {
endelea
continue
}
output += i
}
Expand All @@ -880,14 +880,14 @@ func TestSwitchStatement(t *testing.T) {
`
i = 5
switch (i) {
ikiwa 2 {
case 2 {
output = 2
}
ikiwa 5 {
case 5 {
output = 5
}
kawaida {
output = "haijulikani"
default {
output = "failed"
}
}
output
Expand All @@ -898,29 +898,29 @@ func TestSwitchStatement(t *testing.T) {
`
i = 5
switch (i) {
ikiwa 2 {
case 2 {
output = 2
}
kawaida {
output = "haijulikani"
default {
output = "failed"
}
}
output
`,
"haijulikani",
"failed",
},
{
`
i = 5
switch (i) {
ikiwa 5 {
case 5 {
output = 5
}
ikiwa 2 {
case 2 {
output = 2
}
kawaida {
output = "haijulikani"
default {
output = "failed"
}
}
output
Expand All @@ -942,7 +942,7 @@ func TestSwitchStatement(t *testing.T) {
}

if s.Value != tt.expected {
t.Errorf("Wrong Value, want='haijulikani', got=%s", s.Value)
t.Errorf("Wrong Value, want='failed', got=%s", s.Value)
}

}
Expand Down Expand Up @@ -1029,19 +1029,19 @@ func TestStringMethods(t *testing.T) {
expected interface{}
}{
{
"'mambo'.idadi()",
"'mambo'.len()",
5,
},
{
"'mambo'.herufikubwa()",
"'mambo'.upper()",
"MAMBO",
},
{
"'MaMbO'.herufindogo()",
"'MaMbO'.lower()",
"mambo",
},
{
"'habari'.gawa('a')",
"'habari'.split('a')",
"[h, b, ri]",
},
}
Expand Down
145 changes: 145 additions & 0 deletions module/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package module

import (
"encoding/json"
"net/http"
"strings"

"github.com/ekilie/vint-lang/object"
)

var HttpFunctions = map[string]object.ModuleFunction{}

func init() {
HttpFunctions["createServer"] = createServer
HttpFunctions["listen"] = listen
}

type HttpServer struct {
routes map[string]map[string]*object.Function // Method -> Path -> Handler
}

// Global map of created servers
var servers = map[string]*HttpServer{}

func createServer(args []object.Object, env *object.Environment) object.Object {
serverID := "default"
if len(args) > 0 {
id, ok := args[0].(*object.String)
if !ok {
return &object.Error{Message: "Server ID must be a string"}
}
serverID = id.Value
}

if _, exists := servers[serverID]; exists {
return &object.Error{Message: "Server already exists with ID: " + serverID}
}

servers[serverID] = &HttpServer{routes: make(map[string]map[string]*object.Function)}
return &object.String{Value: serverID}
}

func listen(args []object.Object, env *object.Environment) object.Object {
if len(args) < 2 {
return &object.Error{Message: "Usage: listen(serverID, port)"}
}

serverID, ok := args[0].(*object.String)
if !ok {
return &object.Error{Message: "Server ID must be a string"}
}

port, ok := args[1].(*object.String)
if !ok {
return &object.Error{Message: "Port must be a string"}
}

server, exists := servers[serverID.Value]
if !exists {
return &object.Error{Message: "No server found with ID: " + serverID.Value}
}

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
method := strings.ToUpper(r.Method)
path := r.URL.Path

if server.routes[method] == nil || server.routes[method][path] == nil {
http.NotFound(w, r)
return
}

handler := server.routes[method][path]

// Prepare arguments for the handler function
params := map[string]object.Object{
"method": &object.String{Value: method},
"path": &object.String{Value: path},
}

// Parse JSON body if provided
if r.Body != nil && r.Method == "POST" {
defer r.Body.Close()
var body map[string]interface{}
if err := json.NewDecoder(r.Body).Decode(&body); err == nil {
params["body"] = convertGoMapToDict(body)
}
}

handlerEnv := object.NewEnclosedEnvironment(handler.Env)
for key, value := range params {
handlerEnv.Set(key, value)
}

// Call the handler function
result := Eval(handler.Body, handlerEnv)
if errObj, ok := result.(*object.Error); ok {
http.Error(w, errObj.Message, http.StatusInternalServerError)
} else {
w.WriteHeader(http.StatusOK)
w.Write([]byte(result.Inspect()))
}
})

go func() {
if err := http.ListenAndServe(":"+port.Value, nil); err != nil {
panic(err)
}
}()

return &object.String{Value: "Server listening on port " + port.Value}
}

func (s *HttpServer) AddRoute(method, path string, handler *object.Function) object.Object {
if s.routes[method] == nil {
s.routes[method] = make(map[string]*object.Function)
}
s.routes[method][path] = handler
return &object.Boolean{Value: true}
}

// Converts Go map to object.Dict
func convertGoMapToDict(data map[string]interface{}) *object.Dict {
dict := &object.Dict{Pairs: make(map[object.HashKey]object.DictPair)}
for key, value := range data {
strKey := &object.String{Value: key}
var valObj object.Object

switch v := value.(type) {
case string:
valObj = &object.String{Value: v}
case float64:
valObj = &object.Float{Value: v}
case bool:
valObj = &object.Boolean{Value: v}
case map[string]interface{}:
valObj = convertGoMapToDict(v)
default:
valObj = &object.Null{}
}

hashKey := strKey.HashKey()
dict.Pairs[hashKey] = object.DictPair{Key: strKey, Value: valObj}
}
return dict
}

0 comments on commit 53b6d02

Please sign in to comment.