func scm_define(args *goscm.Pair, env *goscm.Environ) (goscm.SCMT, error) { symb := args.Car switch reflect.TypeOf(symb) { case reflect.TypeOf(&goscm.Symbol{}): tobind, err := args.Cdr.(*goscm.Pair).Car.Eval(env) if err != nil { return goscm.SCM_Nil, err } env.Add(symb.(*goscm.Symbol), tobind) return symb, nil case reflect.TypeOf(&goscm.Pair{}): name := symb.(*goscm.Pair).Car.(*goscm.Symbol) proc_args := symb.(*goscm.Pair).Cdr proc_body := args.Cdr proc_tail := goscm.Cons(proc_args, proc_body) proc, err := scm_lambda(proc_tail, env) if err != nil { return goscm.SCM_Nil, err } env.Add(name, proc) return name, nil default: return goscm.SCM_Nil, errors.New("Attempting to define type: " + reflect.TypeOf(symb).String()) } }
func scm_cons(args *goscm.Pair, env *goscm.Environ) (goscm.SCMT, error) { first := args.Car second_cell, ok := args.Cdr.(*goscm.Pair) if !ok { return goscm.SCM_Nil, errors.New("Weird (unexpected) dotted list") } if second_cell == goscm.SCM_Nil { return goscm.SCM_Nil, errors.New("Too few arguments") } second := second_cell.Car if second_cell.Cdr != goscm.SCM_Nil { return goscm.SCM_Nil, errors.New("Too many arguments") } return goscm.Cons(first, second), nil }
func read_list(b *bufio.Reader) (goscm.SCMT, error) { c, err := b.ReadByte() if c == ')' { return goscm.SCM_Nil, nil } if c == '.' { cdr, err := Read(b) if err != nil { return goscm.SCM_Nil, err } err = chomp_meaningless(b) if err != nil { return goscm.SCM_Nil, err } c, err = b.ReadByte() if c != ')' { return goscm.SCM_Nil, errors.New("Dot in list appears in wrong place") } if err != nil { return goscm.SCM_Nil, err } return cdr, nil } b.UnreadByte() elem, err := Read(b) if err != nil { return goscm.SCM_Nil, err } tail, err := read_list(b) if err != nil { return goscm.SCM_Nil, err } return goscm.Cons(elem, tail), nil }
func scm_reverse(args *goscm.Pair, env *goscm.Environ) (goscm.SCMT, error) { if args == goscm.SCM_Nil { return goscm.SCM_Nil, errors.New("Expected exactly one argument") } if args.Cdr != goscm.SCM_Nil { return goscm.SCM_Nil, errors.New("Expected exactly one argument") } if reflect.TypeOf(args.Car) != reflect.TypeOf(&goscm.Pair{}) { return goscm.SCM_Nil, errors.New("Expected list type") } list, err := args.Car.(*goscm.Pair).ToSlice() if err != nil { return goscm.SCM_Nil, err } ret := goscm.SCM_Nil for i := 0; i < len(list); i++ { ret = goscm.Cons(list[i], ret) } return ret, nil }
func scm_map(args *goscm.Pair, env *goscm.Environ) (goscm.SCMT, error) { argss, err := args.ToSlice() if err != nil { return goscm.SCM_Nil, err } if len(argss) < 2 { return goscm.SCM_Nil, errors.New("Too few arguments") } if len(argss) > 2 { return goscm.SCM_Nil, errors.New("Too many arguments") } proc, ok := argss[0].(goscm.Func) if !ok { return goscm.SCM_Nil, errors.New("Non-function in first position") } if reflect.TypeOf(argss[1]) != reflect.TypeOf(&goscm.Pair{}) { return goscm.SCM_Nil, errors.New("Expected pair") } tail, err := argss[1].(*goscm.Pair).ToSlice() if err != nil { return goscm.SCM_Nil, err } ret := goscm.SCM_Nil for i := len(tail) - 1; i >= 0; i-- { result, err := proc.Apply(goscm.NewList(tail[i]), env) if err != nil { return goscm.SCM_Nil, err } ret = goscm.Cons(result, ret) } return ret, nil }