eval: add len

This commit is contained in:
2018-05-14 22:03:46 +02:00
parent 4be6927dc2
commit f114369c65
3 changed files with 37 additions and 10 deletions

View File

@@ -9,9 +9,8 @@
- Destructuring assignment - Destructuring assignment
- `maptable` - `maptable`
- `coerce` - `coerce`
- `len`
- `mac` - `mac`
- `\`` - `````
- `w/link` - `w/link`
- `aform` - `aform`
- ... - ...

View File

@@ -94,14 +94,14 @@ func (ast *AST) Pretty() string {
rest = " . " + *val.Rest rest = " . " + *val.Rest
} }
// TODO: opt // TODO: opt
opt := "" opt := ""
iter := val.Opt.IterFunc() iter := val.Opt.IterFunc()
for kv, ok := iter(); ok; kv, ok = iter() { for kv, ok := iter(); ok; kv, ok = iter() {
opt += "(o " + kv.Key.(string) + " " + kv.Value.(*AST).Pretty() + ")" opt += "(o " + kv.Key.(string) + " " + kv.Value.(*AST).Pretty() + ")"
} }
if val.HasOpt() && (val.HasRest() || len(agg) != 0) { if val.HasOpt() && (val.HasRest() || len(agg) != 0) {
opt = " " + opt opt = " " + opt
} }
body := val.Body.Pretty() body := val.Body.Pretty()
return "(fn (" + strings.Join(agg, " ") + rest + opt + ") " + body + ")" return "(fn (" + strings.Join(agg, " ") + rest + opt + ") " + body + ")"
} else if ast.Tag == Char { } else if ast.Tag == Char {
@@ -167,5 +167,5 @@ func (f *Func) HasRest() bool {
} }
func (f *Func) HasOpt() bool { func (f *Func) HasOpt() bool {
return f.Opt.Len() != 0 return f.Opt.Len() != 0
} }

View File

@@ -26,6 +26,7 @@ func RootEnv() ast.Env {
"pr": evalPr, "pr": evalPr,
"table": evalTable, "table": evalTable,
"type": evalType, "type": evalType,
"len": evalLen,
} }
for k, v := range prims { for k, v := range prims {
@@ -302,7 +303,7 @@ func evalFn(input []*ast.AST, e ast.Env) (*ast.AST, error) {
body := input[1] body := input[1]
fe := ast.NewEnv(&e) fe := ast.NewEnv(&e)
res := ast.AST{ast.Fn, ast.Func{argsStr, rest, opt, body, fe}} res := ast.AST{ast.Fn, ast.Func{argsStr, rest, opt, body, fe}}
return &res, nil return &res, nil
@@ -453,6 +454,33 @@ func evalType(l []*ast.AST) (*ast.AST, error) {
return l[0].Type(), nil 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) { func evalSymbolList(l []*ast.AST, e ast.Env) (*ast.AST, error) {
sym := l[0].Val.(string) sym := l[0].Val.(string)