예제 #1
0
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
}
예제 #2
0
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
}
예제 #3
0
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
}
예제 #4
0
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)
}
예제 #5
0
func Get(env *Environment, sym *types.Symbol) (types.Type, error) {
	for e := env; e != nil; e = e.parent {
		for v := e.env; v != nil; {
			testSym, err := types.Caar(v)
			if err != nil {
				return nil, &envError{fmt.Sprintf("Checking for %s", sym.Value), err}
			}

			if types.Eqv(sym, testSym) {
				if r, err := types.Cdar(v); err != nil {
					return nil, &envError{fmt.Sprintf("Checking for %s", sym.Value), err}
				} else {
					return r, nil
				}
			}

			nextV, _ := types.Cdr(v)

			var ok bool
			v, ok = nextV.(*types.Pair)
			if !ok {
				return nil, &envError{m: "Corrupt environment!!!"}
			}
		}
	}

	return nil, &envError{m: fmt.Sprintf("Unknown variable: %s", sym.Value)}
}
예제 #6
0
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
}
예제 #7
0
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
}
예제 #8
0
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
}
예제 #9
0
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
}
예제 #10
0
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
}
예제 #11
0
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
}
예제 #12
0
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
}