diff --git a/ast/ast.go b/ast/ast.go index fa84409..9011fd1 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -120,6 +120,16 @@ func (ast *AST) Pretty() string { return fmt.Sprintf("%v", ast.Val) } +func (ast *AST) String() string { + switch ast.Tag { + case List, Quoted, Fn, Table, Prim: + return ast.Pretty() + case Char: + return string(ast.Val.(rune)) + } + return fmt.Sprintf("%v", ast.Val) +} + type Env struct { parent *Env Values map[string]*AST diff --git a/eval/eval.go b/eval/eval.go index c14e7e2..2ba5f4b 100644 --- a/eval/eval.go +++ b/eval/eval.go @@ -24,6 +24,7 @@ func RootEnv() ast.Env { "cdr": evalCdr, "null?": evalNull, "pr": evalPr, + "write": evalWrite, "table": evalTable, "type": evalType, "len": evalLen, @@ -318,11 +319,23 @@ func funcApply(f ast.Func, args []*ast.AST, e ast.Env) (*ast.AST, error) { } for i, a := range f.Params { - f.Env.Values[a] = args[i] + evald, err := Eval(args[i], e) + if err != nil { + return nil, err + } + f.Env.Values[a] = evald } if f.HasRest() { - lst := ast.AST{ast.List, args[plen:]} + var l []*ast.AST + for _, arg := range args[plen:] { + evald, err := Eval(arg, e) + if err != nil { + return nil, err + } + l = append(l, evald) + } + lst := ast.AST{ast.List, l} quoted := ast.AST{ast.Quoted, &lst} f.Env.Values[*f.Rest] = "ed } else { @@ -330,7 +343,11 @@ func funcApply(f ast.Func, args []*ast.AST, e ast.Env) (*ast.AST, error) { i := plen for kv, ok := iter(); ok; kv, ok = iter() { if i < alen { - f.Env.Values[kv.Key.(string)] = args[i] + evald, err := Eval(args[i], e) + if err != nil { + return nil, err + } + f.Env.Values[kv.Key.(string)] = evald } else { f.Env.Values[kv.Key.(string)] = kv.Value.(*ast.AST) } @@ -350,6 +367,15 @@ func evalPr(l []*ast.AST) (*ast.AST, error) { return &nilVal, nil } +func evalWrite(l []*ast.AST) (*ast.AST, error) { + var toPrint []string + for _, elem := range l { + toPrint = append(toPrint, elem.String()) + } + fmt.Print(strings.Join(toPrint, " ")) + return &nilVal, nil +} + func evalIf(l []*ast.AST, e ast.Env) (*ast.AST, error) { i := 0 for i < len(l) { diff --git a/main.go b/main.go index 5d0475c..0cdeb33 100644 --- a/main.go +++ b/main.go @@ -94,14 +94,12 @@ func runFile(path string) { return } - evald, err := eval.Eval(expanded, e) + _, err = eval.Eval(expanded, e) if err != nil { fmt.Println(err) return } - - fmt.Println(evald.Pretty()) } } diff --git a/parser/parser.go b/parser/parser.go index 4211e1d..75e3f33 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -76,17 +76,20 @@ func parseValue(input []string) (*ast.AST, error, []string) { } if input[0][0] == '"' { - agg := []string{input[0]} + start := input[0] + agg := []string{start} input = input[1:] - for { - if len(input) == 0 { - return nil, errors.New("Unmatched \""), input - } - token := input[0] - input = input[1:] - agg = append(agg, token) - if token[len(token)-1] == '"' { - break + if start[len(start)-1] != '"' { + for { + if len(input) == 0 { + return nil, errors.New("Unmatched \""), input + } + token := input[0] + input = input[1:] + agg = append(agg, token) + if token[len(token)-1] == '"' { + break + } } } joined := strings.Join(agg, " ")