func AddArgs(env *Environment, argNames, args types.Type) (err error) { var nameP, valueP, name, value types.Type for nameP, valueP = argNames, args; nameP != nil && valueP != nil; { name, err = types.Car(nameP) if err != nil { return } value, err = types.Car(valueP) if err != nil { return } Define(env, name.(*types.Symbol), value) nameP, err = types.Cdr(nameP) valueP, err = types.Cdr(valueP) } if nameP != nil || valueP != nil { return fmt.Errorf("Wrong number of arguments. Expected %s, got %s", argNames, args) } return }
func eq(env interface{}, args t.Type) (t.Type, error) { first, _ := t.Car(args) for args, _ := t.Cdr(args); args != nil; args, _ = t.Cdr(args) { arg, _ := t.Car(args) if !t.Eq(first, arg) { return &t.Bool{false}, nil } } return &t.Bool{true}, nil }
func equal_Number(env interface{}, args t.Type) (t.Type, error) { arg, _ := t.Car(args) first, ok := arg.(*t.Number) if !ok { return nil, fmt.Errorf("=: Not a number: %s", arg) } for args, _ := t.Cdr(args); args != nil; args, _ = t.Cdr(args) { arg, _ := t.Car(args) if !t.Eqv(first, arg) { return &t.Bool{false}, nil } } return &t.Bool{true}, nil }
func if_s(env *environment.Environment, a types.Type) (types.Type, error) { test, err := types.Car(a) if err != nil { return nil, err } b, err := Eval(env, test) if err != nil { return nil, err } var toEval types.Type if b.(*types.Bool).Value { toEval, err = types.Cadr(a) if err != nil { return nil, err } } else { temp, err := types.Cdr(a) if err != nil { return nil, err } toEval, err = types.Cadr(temp) if err != nil { return nil, err } } return Eval(env, toEval) }
func listToArray(env *environment.Environment, list *types.Pair) (argList []types.Type, err error) { for a := list; a != nil; { car, err := types.Car(a) if err != nil { return nil, err } r, err := Eval(env, car) if err != nil { return nil, err } argList = append(argList, r) tempA, err := types.Cdr(a) if err != nil { return nil, err } var ok bool a, ok = tempA.(*types.Pair) if !ok && a != nil { return nil, fmt.Errorf("Eval: arguments not list: %s", tempA) } } return }
func evalArgs(env *environment.Environment, args types.Type) (types.Type, error) { if args == nil { return nil, nil } arg, err := types.Car(args) if err != nil { return nil, err } car, err := Eval(env, arg) if err != nil { return nil, err } next, err := types.Cdr(args) if err != nil { return nil, err } cdr, err := evalArgs(env, next) if err != nil { return nil, err } return types.Cons(car, cdr), nil }
func sub(env interface{}, args t.Type) (t.Type, error) { arg, _ := t.Car(args) n, ok := arg.(*t.Number) if !ok { return nil, fmt.Errorf("SUB: Not a number: %s", arg) } total := n.Value for args, _ := t.Cdr(args); args != nil; args, _ = t.Cdr(args) { arg, _ := t.Car(args) n, ok := arg.(*t.Number) if !ok { return nil, fmt.Errorf("SUB: Not a number: %s", arg) } total = total - n.Value } return &t.Number{total}, nil }
func lambda(env *environment.Environment, a types.Type) (types.Type, error) { args, err := types.Car(a) if err != nil { return nil, fmt.Errorf("%s\nLAMBDA: unable to get argument list: %s", err, a) } text, err := types.Cdr(a) if err != nil { return nil, fmt.Errorf("%s\nLAMBDA: unable to get function body: %s", err, a) } return &types.SFunction{text, args, env}, nil }
func applySpecialForm(env *environment.Environment, name string, args types.Type) (types.Type, error) { switch name { case "quote": return types.Car(args) case "define": return nil, define(env, args) case "lambda": return lambda(env, args) case "if": return if_s(env, args) } return nil, nil }
func add(env interface{}, args t.Type) (t.Type, error) { var total int64 = 0 for ; args != nil; args, _ = t.Cdr(args) { arg, _ := t.Car(args) n, ok := arg.(*t.Number) if !ok { return nil, fmt.Errorf("ADD: Not a number: %s", arg) } total = total + n.Value } return &t.Number{total}, nil }
func define(env *environment.Environment, args types.Type) error { name, err := types.Car(args) if err != nil { return err } value, err := types.Cadr(args) if err != nil { return err } evaldValue, err := Eval(env, value) if err != nil { return err } environment.Define(env, name.(*types.Symbol), evaldValue) return nil }
func Eval(env *environment.Environment, f types.Type) (types.Type, error) { if types.IsPair(f) { car, err := types.Car(f) if err != nil { return nil, err } cdr, err := types.Cdr(f) if err != nil { return nil, err } return Apply(env, car, cdr) } if types.IsSymbol(f) { return environment.Get(env, f.(*types.Symbol)) } return f, nil }
func begin(env interface{}, args t.Type) (t.Type, error) { var ( result, expr t.Type err error ) for ; args != nil; args, _ = t.Cdr(args) { expr, err = t.Car(args) if err != nil { return nil, err } //fmt.Printf("%s\n", expr) result, err = Eval(env.(*e.Environment), expr) if err != nil { return nil, err } } return result, nil }