func listLen(d Data) int { if nullp(d) { return 0 } var i int for { i++ d = cdr(d) if nullp(d) { break } if !pairp(d) { log.Fatal("expecting a list") } } return i }
func main() { debug := flag.Bool("debug", false, "Enable debugging") flag.Parse() flag.Args() if *debug { log.SetLevel(log.Debug) } env := DefaultEnv() if flag.NArg() > 0 { for _, f := range flag.Args() { buf, err := ioutil.ReadFile(f) if err != nil { log.Fatal(err) } repl(string(buf), env) } } replCLI(env) }
func read(l Tokenizer) (Data, error) { t := l.NextItem() if t == nil { return nil, ErrorEOF } //log.Debugf("scan: %v\n", t) switch t.Token { case lexer.LEFT_PAREN: return readList(l) case lexer.RIGHT_PAREN: return nil, nil case lexer.SYMBOL: return internSymbol(t.Lit), nil case lexer.QUOTE: return readQuote(l) case lexer.NUMBER: v, err := strconv.ParseFloat(t.Lit, 64) if err != nil { log.Fatal("Number fail:", err) } return Number(v), nil case lexer.EOF: return nil, ErrorEOF case lexer.STRING: return StringWithValue(t.Lit), nil case lexer.TRUE: return T, nil case lexer.FALSE: return False, nil case lexer.DOT: return _dot, nil case lexer.ILLEGAL: return nil, errors.New(t.Lit) case lexer.COMMENT: return read(l) } return nil, errors.New("Malformed input") }
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) }