From 688c8800654ba3c1622d1e9ed2a8c9895af4ecad Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Mon, 17 Jun 2013 11:11:17 -0400 Subject: [PATCH] added `and`, `or`, and `=` the equality implementation is probably wrong. --- cmp.go | 10 ++++++++++ skeam.go | 3 +++ special.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/cmp.go b/cmp.go index 76e4147..7488358 100644 --- a/cmp.go +++ b/cmp.go @@ -99,3 +99,13 @@ var lte = builtin{ return cmp_left(vals, fni, fnf) }, } + +var equals = builtin{ + name: "=", + variadic: true, + fn: func(vals []interface{}) (interface{}, error) { + fni := func(x, y int64) bool { return x == y } + fnf := func(x, y float64) bool { return x == y } + return cmp_left(vals, fni, fnf) + }, +} diff --git a/skeam.go b/skeam.go index 0842d19..1b8622a 100644 --- a/skeam.go +++ b/skeam.go @@ -63,6 +63,9 @@ var universe = &environment{map[symbol]interface{}{ symbol(gte.name): gte, symbol(lt.name): lt, symbol(lte.name): lte, + symbol(equals.name): equals, + symbol(and.name): and, + symbol(or.name): or, symbol(cons.name): cons, symbol(car.name): car, symbol(cdr.name): cdr, diff --git a/special.go b/special.go index 28a6f17..e0576be 100644 --- a/special.go +++ b/special.go @@ -141,9 +141,18 @@ func booleanize(v interface{}) bool { // // would evaluate to "bar" var _if = special{ - name: "if", - arity: 3, + name: "if", + arity: 2, + variadic: true, fn: func(env *environment, args []interface{}) (interface{}, error) { + if len(args) > 3 { + return nil, arityError{ + expected: 3, + received: len(args), + name: "ifpooop", + variadic: false, + } + } v, err := eval(args[0], env) if err != nil { return nil, err @@ -152,7 +161,10 @@ var _if = special{ if booleanize(v) { return eval(args[1], env) } - return eval(args[2], env) + if len(args) == 3 { + return eval(args[2], env) + } + return nil, nil }, } @@ -281,3 +293,39 @@ var names = special{ return env.keys(), nil }, } + +var and = special{ + name: "and", + arity: 1, + variadic: true, + fn: func(env *environment, args []interface{}) (interface{}, error) { + for _, v := range args { + t, err := eval(v, env) + if err != nil { + return false, err + } + if !booleanize(t) { + return false, nil + } + } + return true, nil + }, +} + +var or = special{ + name: "or", + arity: 1, + variadic: true, + fn: func(env *environment, args []interface{}) (interface{}, error) { + for _, v := range args { + t, err := eval(v, env) + if err != nil { + return false, err + } + if booleanize(t) { + return true, nil + } + } + return false, nil + }, +}