func readList2(lex Tokenizer) (Data, error) { c, err := read(lex) if err != nil { return nil, fmt.Errorf("Failed to complete list: %v\n", err) } if c == nil { return Empty, nil } // handle (a b . c) but (a b . c d) is an error. if c == _dot { last, err := read(lex) if err != nil { return nil, err } end, _ := read(lex) if end != nil { return nil, fmt.Errorf("More than one object follows .") } log.Printf("last %v", last) return last, nil } rest, err := readList2(lex) if err != nil { return nil, err } return cons(c, rest), nil }
func pairp(d Data) Boolean { _, ok := d.(*Pair) if !ok { log.Printf("pairp %T %v %v", d, d, ok) } return Boolean(ok) }
func let(expr Data, env *Env) (Data, error) { arguments := internalMap(car, car(expr)) if err := getError(arguments); err != nil { return nil, err } values := internalMap(cadr, car(expr)) if err := getError(values); err != nil { return nil, err } body := cdr(expr) if err := getError(body); err != nil { return nil, err } result := cons(cons(_lambda, cons(arguments, body)), values) log.Printf("lambda %v", result) return eval(result, env) }
func isTrue(i Data) Boolean { log.Printf("isTrue %T %v", i, i) if b, ok := i.(Boolean); ok { return b } if _, ok := i.(Symbol); ok { return true } if n, ok := i.(Number); ok { return !(n == 0) } if _, ok := i.(*Pair); ok { return true } if _, ok := i.(Null); ok { return true } if _, ok := i.(String); ok { return true } return false }
func evalSequential(e Data, env *Env) (Data, error) { var v Data e, err := getPair(e) if err != nil { return nil, err } for !nullp(e) { log.Printf("begin: %v", e) v, err = eval(car(e), env) if err != nil { return nil, err } if nullp(cdr(e)) { break } e, err = listNext(e) if err != nil { return nil, err } } return v, nil }
func eval(expr Data, env *Env) (Data, error) { log.Printf("eval: %T: %v\n", expr, expr) switch e := expr.(type) { case Boolean: return e, nil case Symbol: return env.FindVar(e) case Number: return e, nil case String: return e, nil case Null: return e, nil case *Pair: c, _ := getSymbol(car(e)) /* non-Symbols fall through to default */ switch c { case _quote: return cadr(e), nil case _define: return evalDefine(e, env) case _set: return evalSet(e, env) case _if: return evalIf(e, env) case _let: return evalLet(e, env) case _begin: return evalSequential(cdr(e), env) case _quit: os.Exit(0) case _lambda: params, err := getList(cadr(e)) if err != nil { return nil, fmt.Errorf("bad params: %v", err) } body, err := getList(cddr(e)) if err != nil { return nil, fmt.Errorf("bad body: %v", err) } return evalLambda(params, body, env) case _vars: for k, v := range env.vars { log.Printf("%v: %v\n", k, v) } return nil, nil default: log.Printf("procedure call %v", e) proc, err := eval(car(e), env) if err != nil { return nil, err } args, err := evalArgs(cdr(e), env) if err != nil { return nil, err } switch f := proc.(type) { case InternalFunc: return f(args) case *Lambda: var err error env, err = ExtendEnv(f.params, args, f.envt) if err != nil { return nil, err } return evalSequential(f.body, env) default: return nil, fmt.Errorf("apply to a non function: %#v %v", proc, args) } } case nil: log.Fatal("parsed a nil?") return nil, nil } return nil, fmt.Errorf("Unparsable expression: %v", expr) }