eval: add write, eval arguments before applying function
This commit is contained in:
10
ast/ast.go
10
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
|
||||
|
32
eval/eval.go
32
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) {
|
||||
|
4
main.go
4
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())
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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, " ")
|
||||
|
Reference in New Issue
Block a user