func cdr(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 1 { return nil, scheme.ProcError("cdr requires exactly 1 argument") } if !scheme.IsCons(args[0]) { return nil, scheme.ProcError("cdr requires a cons argument") } return args[0].(*scheme.Cons).Cdr, nil }
func div(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 2 { return nil, scheme.ProcError("/ requires exactly 2 arguments") } if !scheme.IsNumber(args[0]) || !scheme.IsNumber(args[1]) { return nil, scheme.ProcError("/ requires all number arguments") } left := args[0].(*scheme.Number).Val right := args[1].(*scheme.Number).Val return scheme.NumberFromInt(left / right), nil }
func setcdr(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 2 { return nil, scheme.ProcError("set-cdr! requires exactly 2 arguments") } pair := args[0] value := args[1] if !scheme.IsCons(pair) { return nil, scheme.ProcError("set-cdr! requires a cons argument") } pair.(*scheme.Cons).Cdr = value return scheme.Nil, nil }
func plus(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) < 2 { return nil, scheme.ProcError("+ requires at least 2 arguments") } var sum int64 = 0 for _, a := range args { if scheme.IsNumber(a) { sum += a.(*scheme.Number).Val } else { return nil, scheme.ProcError("+ requires all number arguments") } } return scheme.NumberFromInt(sum), nil }
func mul(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) < 2 { return nil, scheme.ProcError("* requires at least 2 arguments") } var product int64 = 1 for _, a := range args { if scheme.IsNumber(a) { product *= a.(*scheme.Number).Val } else { return nil, scheme.ProcError("* requires all number arguments") } } return scheme.NumberFromInt(product), nil }
func define(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 2 { return nil, scheme.ProcError("define requires exactly 2 arguments") } idSym, ok := args[0].(*scheme.Symbol) if !ok { return nil, scheme.ProcError("invalid argument to define") } val, err := eval.Eval(s, args[1]) if err != nil { return nil, err } s.DefineHigh(idSym, val) return scheme.Nil, nil }
func display(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 1 { return nil, scheme.ProcError("display requires exactly one argument") } fmt.Printf("%s", args[0]) return scheme.Nil, nil }
func lambda(s *scheme.Scope, ss []scheme.Sexpr) (scheme.Sexpr, error) { if len(ss) < 2 { return nil, scheme.ProcError("lambda at least 2 arguments") } exprs := ss[1:] evalScopeParent := scheme.NewScope(s) lArgs := ss[0] f := func(callScope *scheme.Scope, ss []scheme.Sexpr) (scheme.Sexpr, error) { args := lArgs evalScope := scheme.NewScope(evalScopeParent) aC, ok := args.(*scheme.Cons) for args != scheme.Nil { if len(ss) == 0 { return nil, scheme.ProcError("invalid number of arguments") } if !ok { val := scheme.Unflatten(ss) s, k := args.(*scheme.Symbol) if !k { return nil, scheme.ProcError("Invalid parameter specification") } evalScope.Define(s, val) goto done } arg := aC.Car val := ss[0] s, k := arg.(*scheme.Symbol) if !k { return nil, scheme.ProcError("invalid parameter specification") } evalScope.Define(s, val) ss = ss[1:] args = aC.Cdr aC, ok = args.(*scheme.Cons) } if len(ss) > 0 { return nil, scheme.ProcError("Invalid number of arguments") } done: for _, e := range exprs[0 : len(exprs)-1] { eval.Eval(evalScope, e) } return eval.Eval(evalScope, exprs[len(exprs)-1]) } return scheme.CreateFunction(f, "lamba"), nil }
func nullCheck(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 1 { return nil, scheme.ProcError("null? requires exactly 1 argument") } _, ok := args[0].(*scheme.NilPrim) if ok { return scheme.True, nil } else { return scheme.False, nil } return nil, nil }
func booleanCheck(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 1 { return nil, scheme.ProcError("boolean? requires exactly 1 argument") } _, ok := args[0].(*scheme.Boolean) if ok { return scheme.True, nil } else { return scheme.False, nil } return nil, nil }
func procCheck(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 1 { return nil, scheme.ProcError("proc? requires exactly 1 argument") } _, okF := args[0].(*scheme.Function) _, okP := args[0].(*scheme.Primitive) if okF || okP { return scheme.True, nil } else { return scheme.False, nil } return nil, nil }
func let(s *scheme.Scope, ss []scheme.Sexpr) (scheme.Sexpr, error) { if len(ss) < 1 { return nil, scheme.ProcError("let requires at least one argument") } evalScope := scheme.NewScope(s) bindings, err := scheme.Flatten(ss[0]) if err != nil { return nil, err } for _, b := range bindings { bs, err := scheme.Flatten(b) if err != nil { return nil, err } if len(bs) != 2 { return nil, scheme.ProcError("invalid binding on let") } sym, ok := bs[0].(*scheme.Symbol) if !ok { return nil, scheme.ProcError("invalid binding on let") } val, err := eval.Eval(s, bs[1]) if err != nil { return nil, err } evalScope.Define(sym, val) } prog := ss[1:] var last scheme.Sexpr = scheme.Nil for _, l := range prog { last, err = eval.Eval(evalScope, l) if err != nil { return nil, err } } return last, nil }
func read(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 0 { return nil, scheme.ProcError("read must have no arguments") } br := bufio.NewReader(os.Stdin) str, err := br.ReadString('\n') r := strings.NewReader(str) _, c := lexer.Lex(r) expr, err := parser.Parse(c) if err != nil { return nil, err } return expr, nil }
func primFor(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 2 { return nil, scheme.ProcError("for requires exactly two arguments") } cond := args[0] expr := args[1] var val scheme.Sexpr = scheme.Nil cv, err := eval.Eval(s, cond) if err != nil { return nil, err } for cv != scheme.Nil && cv != scheme.False { val, err = eval.Eval(s, expr) if err != nil { return nil, err } cv, err = eval.Eval(s, cond) if err != nil { return nil, err } } return val, nil }
func cons(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 2 { return nil, scheme.ProcError("cons requires exactly 2 arguments") } return &scheme.Cons{args[0], args[1]}, nil }
func primEval(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 1 { return nil, scheme.ProcError("eval requires exactly one argument") } return eval.Eval(s, args[0]) }
func quote(s *scheme.Scope, args []scheme.Sexpr) (scheme.Sexpr, error) { if len(args) != 1 { return nil, scheme.ProcError("quote requires exactly one argument") } return args[0], nil }