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 {