From f114369c650b3a90113fdf312954d9ee69326ab3 Mon Sep 17 00:00:00 2001 From: hellerve Date: Mon, 14 May 2018 22:03:46 +0200 Subject: [PATCH] eval: add len --- README.md | 3 +-- ast/ast.go | 14 +++++++------- eval/eval.go | 30 +++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4124fa9..516680b 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,8 @@ - Destructuring assignment - `maptable` - `coerce` -- `len` - `mac` -- `\`` +- ````` - `w/link` - `aform` - ... diff --git a/ast/ast.go b/ast/ast.go index d4a826c..fa84409 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -94,14 +94,14 @@ func (ast *AST) Pretty() string { rest = " . " + *val.Rest } // TODO: opt - opt := "" + opt := "" iter := val.Opt.IterFunc() for kv, ok := iter(); ok; kv, ok = iter() { - opt += "(o " + kv.Key.(string) + " " + kv.Value.(*AST).Pretty() + ")" - } - if val.HasOpt() && (val.HasRest() || len(agg) != 0) { - opt = " " + opt - } + opt += "(o " + kv.Key.(string) + " " + kv.Value.(*AST).Pretty() + ")" + } + if val.HasOpt() && (val.HasRest() || len(agg) != 0) { + opt = " " + opt + } body := val.Body.Pretty() return "(fn (" + strings.Join(agg, " ") + rest + opt + ") " + body + ")" } else if ast.Tag == Char { @@ -167,5 +167,5 @@ func (f *Func) HasRest() bool { } func (f *Func) HasOpt() bool { - return f.Opt.Len() != 0 + return f.Opt.Len() != 0 } diff --git a/eval/eval.go b/eval/eval.go index a84e35a..d9ef2e0 100644 --- a/eval/eval.go +++ b/eval/eval.go @@ -26,6 +26,7 @@ func RootEnv() ast.Env { "pr": evalPr, "table": evalTable, "type": evalType, + "len": evalLen, } for k, v := range prims { @@ -302,7 +303,7 @@ func evalFn(input []*ast.AST, e ast.Env) (*ast.AST, error) { body := input[1] - fe := ast.NewEnv(&e) + fe := ast.NewEnv(&e) res := ast.AST{ast.Fn, ast.Func{argsStr, rest, opt, body, fe}} return &res, nil @@ -453,6 +454,33 @@ func evalType(l []*ast.AST) (*ast.AST, error) { return l[0].Type(), nil } +func evalLen(l []*ast.AST) (*ast.AST, error) { + err := checkArity(l, 1, "len") + + if err != nil { + return nil, err + } + + cnt := 0 + elem := l[0] + + switch elem.Tag { + case ast.Quoted: + // TODO: error handling + cnt = len(elem.Val.(*ast.AST).Val.([]*ast.AST)) + case ast.String: + cnt = len(elem.Val.(string)) + case ast.Table: + cnt = len(elem.Val.(map[*ast.AST]*ast.AST)) + default: + return nil, fmt.Errorf("Cannot get length of %s", elem.Pretty()) + } + + res := ast.AST{ast.Num, float64(cnt)} + + return &res, nil +} + func evalSymbolList(l []*ast.AST, e ast.Env) (*ast.AST, error) { sym := l[0].Val.(string)