예제 #1
0
파일: eval.go 프로젝트: rread/rsi
func readList2(lex Tokenizer) (Data, error) {
	c, err := read(lex)
	if err != nil {
		return nil, fmt.Errorf("Failed to complete list: %v\n", err)
	}
	if c == nil {
		return Empty, nil
	}

	// handle (a b . c) but (a b . c d) is an error.
	if c == _dot {
		last, err := read(lex)
		if err != nil {
			return nil, err
		}
		end, _ := read(lex)
		if end != nil {
			return nil, fmt.Errorf("More than one object follows .")
		}

		log.Printf("last %v", last)
		return last, nil
	}

	rest, err := readList2(lex)
	if err != nil {
		return nil, err
	}
	return cons(c, rest), nil
}
예제 #2
0
파일: pair.go 프로젝트: rread/rsi
func pairp(d Data) Boolean {
	_, ok := d.(*Pair)
	if !ok {
		log.Printf("pairp %T %v %v", d, d, ok)
	}
	return Boolean(ok)
}
예제 #3
0
파일: eval.go 프로젝트: rread/rsi
func let(expr Data, env *Env) (Data, error) {
	arguments := internalMap(car, car(expr))
	if err := getError(arguments); err != nil {
		return nil, err
	}

	values := internalMap(cadr, car(expr))
	if err := getError(values); err != nil {
		return nil, err
	}

	body := cdr(expr)
	if err := getError(body); err != nil {
		return nil, err
	}

	result := cons(cons(_lambda, cons(arguments, body)), values)
	log.Printf("lambda %v", result)

	return eval(result, env)
}
예제 #4
0
파일: eval.go 프로젝트: rread/rsi
func isTrue(i Data) Boolean {
	log.Printf("isTrue %T %v", i, i)
	if b, ok := i.(Boolean); ok {
		return b
	}
	if _, ok := i.(Symbol); ok {
		return true
	}
	if n, ok := i.(Number); ok {
		return !(n == 0)
	}
	if _, ok := i.(*Pair); ok {
		return true
	}
	if _, ok := i.(Null); ok {
		return true
	}
	if _, ok := i.(String); ok {
		return true
	}
	return false
}
예제 #5
0
파일: eval.go 프로젝트: rread/rsi
func evalSequential(e Data, env *Env) (Data, error) {
	var v Data
	e, err := getPair(e)
	if err != nil {
		return nil, err
	}
	for !nullp(e) {
		log.Printf("begin: %v", e)
		v, err = eval(car(e), env)
		if err != nil {
			return nil, err
		}
		if nullp(cdr(e)) {
			break
		}
		e, err = listNext(e)
		if err != nil {
			return nil, err
		}

	}
	return v, nil

}
예제 #6
0
파일: eval.go 프로젝트: rread/rsi
func eval(expr Data, env *Env) (Data, error) {
	log.Printf("eval: %T: %v\n", expr, expr)
	switch e := expr.(type) {
	case Boolean:
		return e, nil
	case Symbol:
		return env.FindVar(e)
	case Number:
		return e, nil
	case String:
		return e, nil
	case Null:
		return e, nil
	case *Pair:
		c, _ := getSymbol(car(e))
		/* non-Symbols fall through to default */
		switch c {
		case _quote:
			return cadr(e), nil
		case _define:
			return evalDefine(e, env)
		case _set:
			return evalSet(e, env)
		case _if:
			return evalIf(e, env)
		case _let:
			return evalLet(e, env)
		case _begin:
			return evalSequential(cdr(e), env)
		case _quit:
			os.Exit(0)
		case _lambda:
			params, err := getList(cadr(e))
			if err != nil {
				return nil, fmt.Errorf("bad params: %v", err)
			}
			body, err := getList(cddr(e))
			if err != nil {
				return nil, fmt.Errorf("bad body: %v", err)
			}
			return evalLambda(params, body, env)
		case _vars:
			for k, v := range env.vars {
				log.Printf("%v: %v\n", k, v)
			}
			return nil, nil
		default:
			log.Printf("procedure call %v", e)
			proc, err := eval(car(e), env)
			if err != nil {
				return nil, err
			}
			args, err := evalArgs(cdr(e), env)
			if err != nil {
				return nil, err
			}
			switch f := proc.(type) {
			case InternalFunc:
				return f(args)
			case *Lambda:
				var err error
				env, err = ExtendEnv(f.params, args, f.envt)
				if err != nil {
					return nil, err
				}
				return evalSequential(f.body, env)
			default:
				return nil, fmt.Errorf("apply to a non function: %#v %v", proc, args)
			}

		}
	case nil:
		log.Fatal("parsed a nil?")
		return nil, nil
	}
	return nil, fmt.Errorf("Unparsable expression: %v", expr)
}