diff --git a/input.scm b/input.scm index a2f16ce..5b2f2fd 100644 --- a/input.scm +++ b/input.scm @@ -73,3 +73,25 @@ x (symbol? (quote null)) (symbol? 1) + +; ahahhahahah this is so ugly. +(define counter + ((lambda () + (begin + (define count 0) + (lambda () + (begin + (set! count (+ 1 count)) + count)))))) + +; hmm, some kind of looping construct would be nice. +(counter) +(counter) +(counter) +(counter) +(counter) +(counter) +(counter) +(counter) +(counter) +(counter) diff --git a/proc.go b/proc.go index 1d8a695..d6821d5 100644 --- a/proc.go +++ b/proc.go @@ -141,3 +141,81 @@ func issymbol(vals []interface{}) (interface{}, error) { _, ok := vals[0].(symbol) return ok, nil } + +type cmp_bin_i func(int64, int64) bool +type cmp_bin_f func(float64, float64) bool + +func cmp_left(vals []interface{}, fni cmp_bin_i, fnf cmp_bin_f) (bool, error) { + if len(vals) < 2 { + return false, errors.New("expected at least 2 arguments") + } + + var lasti int64 + var lastf float64 + var floating bool + + switch v := vals[0].(type) { + case float64: + floating = true + lastf = v + case int64: + lasti = v + default: + return false, fmt.Errorf("gt is not defined for %v", reflect.TypeOf(v)) + } + + for _, raw := range vals[1:] { + switch v := raw.(type) { + case float64: + if !floating { + floating = true + lastf = float64(lasti) + } + if !fnf(lastf, v) { + return false, nil + } + lastf = v + case int64: + if floating { + f := float64(v) + if !fnf(lastf, f) { + return false, nil + } + lastf = f + } else { + if !fni(lasti, v) { + return false, nil + } + lasti = v + } + default: + return false, errors.New("ooga booga") + } + } + + return true, nil +} + +func gt(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) +} + +func gte(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) +} + +func lt(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) +} + +func lte(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 31c56c1..6ee157d 100644 --- a/skeam.go +++ b/skeam.go @@ -31,6 +31,10 @@ var universe = &environment{map[symbol]interface{}{ "-": builtin(subtraction), "*": builtin(multiplication), "/": builtin(division), + ">": builtin(gt), + ">=": builtin(gte), + "<": builtin(lt), + "<=": builtin(lte), "length": builtin(length), "list": builtin(list), "list?": builtin(islist),