From 98617309c4658c7bdcaad732e2cda8bf244c5a95 Mon Sep 17 00:00:00 2001 From: zongor Date: Sat, 18 Mar 2023 22:26:32 -0400 Subject: [PATCH] add initial servehttp --- .vscode/launch.json | 30 ++++----- examples/http_hello_world.vqe | 8 +++ main.go | 5 +- varaq/interpreter.go | 119 +++++++++++++++++----------------- varaq/scanner.go | 15 ++--- varaq/token.go | 4 +- 6 files changed, 92 insertions(+), 89 deletions(-) mode change 100755 => 100644 .vscode/launch.json create mode 100644 examples/http_hello_world.vqe mode change 100755 => 100644 main.go mode change 100755 => 100644 varaq/interpreter.go mode change 100755 => 100644 varaq/scanner.go mode change 100755 => 100644 varaq/token.go diff --git a/.vscode/launch.json b/.vscode/launch.json old mode 100755 new mode 100644 index e2276f3..cf1b9c2 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,16 +1,16 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Package", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "main.go", - "args": ["examples/test.vqe"] - }, - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "main.go", + "args": ["examples/http_hello_world.vqe"] + } + ] +} diff --git a/examples/http_hello_world.vqe b/examples/http_hello_world.vqe new file mode 100644 index 0000000..e5b26fe --- /dev/null +++ b/examples/http_hello_world.vqe @@ -0,0 +1,8 @@ +{ +"" disp newline +"" disp newline +"" disp newline +"

nuqneH 'u'?

" disp newline +"" disp newline +"" disp +} ":3333" servehttp diff --git a/main.go b/main.go old mode 100755 new mode 100644 index d822dfd..f6df85a --- a/main.go +++ b/main.go @@ -20,8 +20,8 @@ func main() { func repl() { scanner := bufio.NewScanner(os.Stdin) - fmt.Print("> ") for scanner.Scan() { + fmt.Print("> ") line := scanner.Text() if len(line) == 0 { return @@ -30,7 +30,6 @@ func repl() { if err != nil { fmt.Printf("%v\n", err) } - fmt.Print("> ") } } @@ -55,7 +54,7 @@ func interpret(src string) error { } code := varaq.Parse(tokens) - err = varaq.Interpret(code, os.Args[1:]) + err = varaq.Interpret(code, os.Args[1:], os.Stdout) if err != nil { fmt.Printf("%v\n", err) return err diff --git a/varaq/interpreter.go b/varaq/interpreter.go old mode 100755 new mode 100644 index b136546..b82e347 --- a/varaq/interpreter.go +++ b/varaq/interpreter.go @@ -3,9 +3,11 @@ package varaq import ( "bufio" "fmt" + "io" "math" "math/rand" "net" + "net/http" "os" "strconv" "strings" @@ -46,14 +48,14 @@ func pop() (Expr, error) { return res, nil } -func identifierToObj(c Expr, idx int, argv []string) error { +func identifierToObj(c Expr, idx int, argv []string, w io.Writer) error { k, k_ok := c.Value.(string) if k_ok { o := get(k) if o.Tok == UNDEFINED { return fmt.Errorf("identifier %s undefined @%v", k, idx) } else if o.Tok == FUNCTION { - e := Interpret(o, argv) + e := Interpret(o, argv, w) if e != nil { if e == fmt.Errorf("escape") { return nil @@ -70,8 +72,8 @@ func identifierToObj(c Expr, idx int, argv []string) error { return nil } -func (c Expr) idToExpr(idx int, argv []string) (Expr, error) { - e := identifierToObj(c, idx, argv) +func (c Expr) idToExpr(idx int, argv []string, w io.Writer) (Expr, error) { + e := identifierToObj(c, idx, argv, w) if e != nil { return Expr{UNDEFINED, nil, nil, 0}, e } @@ -84,8 +86,8 @@ func (c Expr) idToExpr(idx int, argv []string) (Expr, error) { return vv, nil } -func (c Expr) idToS(idx int, argv []string) (string, error) { - v, e := c.idToExpr(idx, argv) +func (c Expr) idToS(idx int, argv []string, w io.Writer) (string, error) { + v, e := c.idToExpr(idx, argv, w) if e != nil { return "", e } @@ -93,13 +95,13 @@ func (c Expr) idToS(idx int, argv []string) (string, error) { return fmt.Sprintf("%b", v.Value), nil } -func popArgs(idx int, argv []string) (Expr, Expr, error) { +func popArgs(idx int, argv []string, w io.Writer) (Expr, Expr, error) { b, e := pop() if e != nil { return Expr{UNDEFINED, nil, nil, 0}, Expr{UNDEFINED, nil, nil, 0}, e } if b.Tok == IDENTIFIER { - b, e = b.idToExpr(idx, argv) + b, e = b.idToExpr(idx, argv, w) if e != nil { return Expr{UNDEFINED, nil, nil, 0}, Expr{UNDEFINED, nil, nil, 0}, e } @@ -109,7 +111,7 @@ func popArgs(idx int, argv []string) (Expr, Expr, error) { return Expr{UNDEFINED, nil, nil, 0}, Expr{UNDEFINED, nil, nil, 0}, e } if a.Tok == IDENTIFIER { - a, e = a.idToExpr(idx, argv) + a, e = a.idToExpr(idx, argv, w) if e != nil { return Expr{UNDEFINED, nil, nil, 0}, Expr{UNDEFINED, nil, nil, 0}, e } @@ -118,7 +120,7 @@ func popArgs(idx int, argv []string) (Expr, Expr, error) { return a, b, nil } -func Interpret(code Expr, argv []string) error { +func Interpret(code Expr, argv []string, w io.Writer) error { for idx, c := range code.Exprs { switch c.Tok { case NUMBER: @@ -170,33 +172,6 @@ func Interpret(code Expr, argv []string) error { push(stack[n-2]) stack = append(stack[:n-2], stack[n-3:]...) - case PICK: - n := len(stack) - 1 - a, e := pop() - if e != nil { - return e - } - if a.Tok == IDENTIFIER { - a = get(a.Value.(string)) - } - - if a.Tok == NUMBER { - idx := int(a.Value.(float64)) - - if idx <= 0 { - return fmt.Errorf("`pick`: index must be a positive nonzero value") - } - if n-idx < 0 { - return fmt.Errorf("`pick`: stack underflow") - } - if idx > n { - return fmt.Errorf("`pick`: stack overflow") - } - push(stack[n-idx]) - } else { - return fmt.Errorf("cannot `pick` index is not a number @%v", idx) - } - case DEPTH: push(Expr{NUMBER, nil, float64(len(stack)), 0}) case CLEAR: @@ -206,7 +181,7 @@ func Interpret(code Expr, argv []string) error { if idx-1 >= 0 && code.Exprs[idx-1].Tok == TILDE { push(c) } else { - e := identifierToObj(c, idx, argv) + e := identifierToObj(c, idx, argv, w) if e != nil { return e } @@ -229,9 +204,9 @@ func Interpret(code Expr, argv []string) error { } case DUMP: for n := len(stack) - 1; n >= 0; n-- { - fmt.Println(stack[n]) + fmt.Fprintf(w, "%v\n", stack[n]) } - fmt.Println("=== end of dump ===") + fmt.Fprintf(w, "=== end of dump ===\n") case NAME: fun, e := pop() if e != nil { @@ -273,7 +248,7 @@ func Interpret(code Expr, argv []string) error { } if fun.Tok == FUNCTION && logical.Tok == BOOLEAN { if logical.Value.(bool) { - Interpret(fun, argv) + Interpret(fun, argv, w) } } else { return fmt.Errorf("cannot `ifyes` not a function or bool @%v", idx) @@ -289,7 +264,7 @@ func Interpret(code Expr, argv []string) error { } if fun.Tok == FUNCTION && logical.Tok == BOOLEAN { if !logical.Value.(bool) { - Interpret(fun, argv) + Interpret(fun, argv, w) } } else { return fmt.Errorf("cannot `ifno` not a function or bool @%v", idx) @@ -311,7 +286,7 @@ func Interpret(code Expr, argv []string) error { return e } if fun.Tok == FUNCTION { - Interpret(fun, argv) + Interpret(fun, argv, w) } else { return fmt.Errorf("cannot `eval` not a function @%v", idx) } @@ -328,7 +303,7 @@ func Interpret(code Expr, argv []string) error { } if fun.Tok == FUNCTION && count.Tok == NUMBER { for n := int64(0); n < int64(count.Value.(float64)); n++ { - err := Interpret(fun, argv) + err := Interpret(fun, argv, w) if err != nil { return err } @@ -436,7 +411,7 @@ func Interpret(code Expr, argv []string) error { var v2_s string if v1.Tok == IDENTIFIER { - v1_s, e = v1.idToS(idx, argv) + v1_s, e = v1.idToS(idx, argv, w) if e != nil { return e } @@ -462,7 +437,7 @@ func Interpret(code Expr, argv []string) error { } if v2.Tok == IDENTIFIER { - v2_s, e = v2.idToS(idx, argv) + v2_s, e = v2.idToS(idx, argv, w) if e != nil { return e } @@ -530,7 +505,7 @@ func Interpret(code Expr, argv []string) error { } } case ADD: - a, b, e := popArgs(idx, argv) + a, b, e := popArgs(idx, argv, w) if e != nil { return e } @@ -541,7 +516,7 @@ func Interpret(code Expr, argv []string) error { return fmt.Errorf("cannot `add` values are not numbers @%v", idx) } case SUB: - a, b, e := popArgs(idx, argv) + a, b, e := popArgs(idx, argv, w) if e != nil { return e } @@ -552,7 +527,7 @@ func Interpret(code Expr, argv []string) error { return fmt.Errorf("cannot `sub` values are not numbers @%v", idx) } case MUL: - a, b, e := popArgs(idx, argv) + a, b, e := popArgs(idx, argv, w) if e != nil { return e } @@ -563,7 +538,7 @@ func Interpret(code Expr, argv []string) error { return fmt.Errorf("cannot `mul` values are not numbers @%v", idx) } case DIV: - a, b, e := popArgs(idx, argv) + a, b, e := popArgs(idx, argv, w) if e != nil { return e } @@ -574,7 +549,7 @@ func Interpret(code Expr, argv []string) error { return fmt.Errorf("cannot `div` values are not numbers @%v", idx) } case IDIV: - a, b, e := popArgs(idx, argv) + a, b, e := popArgs(idx, argv, w) if e != nil { return e } @@ -585,7 +560,7 @@ func Interpret(code Expr, argv []string) error { return fmt.Errorf("cannot `idiv` values are not numbers @%v", idx) } case MOD: - a, b, e := popArgs(idx, argv) + a, b, e := popArgs(idx, argv, w) if e != nil { return e } @@ -596,7 +571,7 @@ func Interpret(code Expr, argv []string) error { return fmt.Errorf("cannot `mod` values are not numbers @%v", idx) } case POW: - a, b, e := popArgs(idx, argv) + a, b, e := popArgs(idx, argv, w) if e != nil { return e } @@ -1215,15 +1190,15 @@ func Interpret(code Expr, argv []string) error { return e } if a.Tok == IDENTIFIER { - fmt.Printf("%v\n", get(a.Value.(string))) + fmt.Fprintf(w, "%v", get(a.Value.(string))) } else if a.Tok == NUMBER { if a.Value.(float64) == float64(int64(a.Value.(float64))) { - fmt.Printf("%d\n", int64(a.Value.(float64))) + fmt.Fprintf(w, "%d", int64(a.Value.(float64))) } else { - fmt.Printf("%f\n", a.Value.(float64)) + fmt.Fprintf(w, "%f", a.Value.(float64)) } } else { - fmt.Printf("%v\n", a.Value) + fmt.Fprintf(w, "%v", a.Value) } case LISTEN: var str string @@ -1245,9 +1220,9 @@ func Interpret(code Expr, argv []string) error { } fmt.Fprintf(os.Stderr, "%v", a.Value) case NEWLINE: - fmt.Println() + fmt.Fprintf(w, "\n") case TAB: - fmt.Println("\t") + fmt.Fprintf(w, "\t") case WHEREAMI: conn, e := net.Dial("udp", "8.8.8.8:80") if e != nil { @@ -1257,9 +1232,31 @@ func Interpret(code Expr, argv []string) error { localAddr := conn.LocalAddr().(*net.UDPAddr) - fmt.Println(localAddr.IP.String()) + fmt.Fprintf(w, "%s\n", localAddr.IP.String()) + case SERVEHTTP: + str, e := pop() + if e != nil { + return e + } + if str.Tok != STRING { + return fmt.Errorf("cannot `servehttp` exptected a string for the port @%v", idx) + } + + http.ListenAndServe(str.Value.(string), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/html; charset=utf-8") + fun, e := pop() + if e != nil { + return + } + if fun.Tok == FUNCTION { + Interpret(fun, nil, w) + } else { + return + } + })) + case VERSION: - fmt.Println("var'aq -- 0.9.1 Martoq") + fmt.Fprintf(w, "var'aq -- 0.9.1 Martoq") case ARGV: arg := Expr{LIST, make([]Expr, 0), nil, 0} for _, v := range argv { diff --git a/varaq/scanner.go b/varaq/scanner.go old mode 100755 new mode 100644 index da9fba6..8cfe958 --- a/varaq/scanner.go +++ b/varaq/scanner.go @@ -175,14 +175,13 @@ var keywords = map[string]TokenType{ "pongmI'": VERSION, "nuqDaq_jIH": WHEREAMI, // All the ones after this are a part of the var'aq superset - "rot": ROT, - "jIr": ROT, - "over": OVER, - "QI": OVER, - "depth": DEPTH, - "juv": DEPTH, - "pick": PICK, - "woH": PICK, + "rot": ROT, + "jIr": ROT, + "over": OVER, + "QI": OVER, + "depth": DEPTH, + "juv": DEPTH, + "servehttp": SERVEHTTP, } func isDigit(s string) bool { diff --git a/varaq/token.go b/varaq/token.go old mode 100755 new mode 100644 index 49a8331..84dacc4 --- a/varaq/token.go +++ b/varaq/token.go @@ -105,7 +105,7 @@ const ( OVER ROT DEPTH - PICK + SERVEHTTP ) var tokens = [...]string{ @@ -210,7 +210,7 @@ var tokens = [...]string{ OVER: "OVER", ROT: "ROT", DEPTH: "DEPTH", - PICK: "PICK", + SERVEHTTP: "SERVEHTTP", } func (me TokenType) String() string {