Esempio n. 1
0
func (self *Let) Eval(s *scope.Scope) value.Value {
	// The <init>s are evaluated in the current environment
	// (in some unspecified order), the <variable>s are bound
	// to fresh locations holding the results, the <body> is
	// evaluated in the extended environment, and the value(s)
	// of the last expression of <body> is(are) returned.

	env := scope.NewScope(s)
	extended := scope.NewScope(s)
	for i := 0; i < len(self.Patterns); i++ {
		binder.Define(extended, self.Patterns[i].Identifier, self.Exprs[i].Eval(env))
	}
	return self.Body.Eval(extended)
}
Esempio n. 2
0
func (self *LetRec) Eval(s *scope.Scope) value.Value {
	// The <variable>s are bound to fresh locations holding undefined values,
	// the <init>s are evaluated in the resulting environment
	// (in some unspecified order), each <variable> is assigned to the result of
	// the corresponding <init>, the <body> is evaluated in the resulting
	// environment, and the value(s) of the last expression in <body> is(are)
	// returned. Each binding of a <variable> has the entire letrec expression
	// as its region, making it possible to define mutually recursive procedures.

	env := scope.NewScope(s)
	extended := make([]*scope.Scope, len(self.Patterns))
	for i := 0; i < len(self.Patterns); i++ {
		extended[i] = scope.NewScope(env)
		binder.Define(extended[i], self.Patterns[i].Identifier, self.Exprs[i].Eval(env))
	}
	for i := 0; i < len(extended); i++ {
		env.PutAll(extended[i])
	}
	return self.Body.Eval(env)
}
Esempio n. 3
0
func (self *Go) Eval(env *scope.Scope) value.Value {
	// We need to recover the panic message of goroutine
	go func() {
		defer func() {
			if err := recover(); err != nil {
				fmt.Println(err)
			}
		}()
		self.Expr.Eval(scope.NewScope(env))
	}()
	return nil
}
Esempio n. 4
0
func (self *LetStar) Eval(env *scope.Scope) value.Value {
	// Let* is similar to let, but the bindings are performed sequentially
	// from left to right, and the region of a binding indicated by
	// (<variable> <init>) is that part of the let* expression to the right
	// of the binding. Thus the second binding is done in an environment in
	// which the first binding is visible, and so on.

	for i := 0; i < len(self.Patterns); i++ {
		env = scope.NewScope(env)
		binder.Define(env, self.Patterns[i].Identifier, self.Exprs[i].Eval(env))
	}
	return self.Body.Eval(env)
}
Esempio n. 5
0
func (self *Call) Eval(s *scope.Scope) value.Value {
	callee := self.Callee.Eval(s)
	// we will handle (+ . (1)) latter
	args := EvalList(self.Args, s)

	switch callee.(type) {
	case *value.Closure:
		curry := callee.(*value.Closure)
		env := scope.NewScope(curry.Env.(*scope.Scope))
		lambda, ok := curry.Body.(*Lambda)
		if !ok {
			panic(fmt.Sprint("unexpected type: ", curry.Body))
		}
		// bind call arguments to parameters
		// these nodes should be in Lisp pair structure
		BindArguments(env, lambda.Params, converter.SliceToPairValues(args))
		return lambda.Body.Eval(env)
	case value.PrimFunc:
		return callee.(value.PrimFunc).Apply(args)
	default:
		panic(fmt.Sprintf("%s: not allowed in a call context, args: %s", callee, self.Args[0]))
	}
}