eval: add len
This commit is contained in:
@@ -9,9 +9,8 @@
|
|||||||
- Destructuring assignment
|
- Destructuring assignment
|
||||||
- `maptable`
|
- `maptable`
|
||||||
- `coerce`
|
- `coerce`
|
||||||
- `len`
|
|
||||||
- `mac`
|
- `mac`
|
||||||
- `\``
|
- `````
|
||||||
- `w/link`
|
- `w/link`
|
||||||
- `aform`
|
- `aform`
|
||||||
- ...
|
- ...
|
||||||
|
14
ast/ast.go
14
ast/ast.go
@@ -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
|
||||||
}
|
}
|
||||||
|
30
eval/eval.go
30
eval/eval.go
@@ -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)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user