示例#1
0
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
}
示例#2
0
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
}