def extend(env, variables, values): if is_pair(variables): if is_pair(values): return cons(cons(variables.car, values.car), extend(env, variables.cdr, values.cdr)) else: raise ValueError("Too few values") elif is_null(variables): if is_null(values): return env else: raise ValueError("Too many values") elif is_symbol(variables): return cons(cons(variables, values), env) else: raise RuntimeError("Branch should be unreachable")
def __init__(self, *exprs): super().__init__() if len(exprs) == 0: self.exprs = Nil elif len(exprs) == 1 and is_pair(exprs[0]): self.exprs = exprs[0] else: self.exprs = Nil for x in exprs[::-1]: self.exprs = cons(x, self.exprs)
def main(): definitial('x') defprimitive('+', lambda args: args.car + args.cadr, 2) defprimitive('-', lambda args: args.car - args.cadr, 2) defprimitive('<', lambda args: args.car < args.cadr, 2) defprimitive('cons', lambda args: cons(args.car, args.cadr), 2) definitial('list', lambda args: args) definitial('fib', lambda args: args) while True: exprs = read() # our version of read returns a list of expressions for expr in exprs: value = evaluate(expr, GLOBAL_ENV) print(value)
def resume(self, vs): return self.k.resume(cons(self.v, vs))
def test_eval_apply_lambda(): func = LambdaExpr(cons(Symbol("a"), cons(Symbol("b"), Nil)), cons(ApplyExpr(VariableExpr(Symbol("+")), cons(VariableExpr(Symbol("a")), cons(VariableExpr(Symbol("b")), Nil))), Nil)) expr = ApplyExpr(func, cons(QuoteExpr(5), cons(QuoteExpr(2), Nil))) expr.evaluate(GLOBAL_ENV, AssertEqCont(7))
def test_eval_apply_primitive(): expr = ApplyExpr(VariableExpr(Symbol("+")), cons(QuoteExpr(1), cons(QuoteExpr(2), Nil))) expr.evaluate(GLOBAL_ENV, AssertEqCont(3))
def test_eval_lambda(): expr = LambdaExpr(cons(Symbol("a"), cons(Symbol("b"), Nil)), cons(QuoteExpr(42), Nil)) expr.evaluate(NullEnv(), AssertInstanceCont(Function))
def test_eval_begin(): expr = BeginExpr(QuoteExpr(1), QuoteExpr(2), QuoteExpr(3)) expr.evaluate(NullEnv(), AssertEqCont(3)) expr = BeginExpr(cons(QuoteExpr(1), cons(QuoteExpr(2), cons(QuoteExpr(3), Nil)))) expr.evaluate(NullEnv(), AssertEqCont(3))
def primitive(name, value, vs, arity, k): if arity == length(vs): return k.resume(value(vs)) else: raise TypeError("incorrect arity {} {}".format(name, vs)) GLOBAL_ENV = NullEnv() definitial('f') definitial('foo') definitial('bar') definitial('x') definitial('y') definitial('z') defprimitive('null?', lambda args: is_null(args.car), 1) defprimitive('cons', lambda args: cons(args.car, args.cadr), 2) defprimitive('car', lambda args: args.caar, 1) defprimitive('cdr', lambda args: args.cdar, 1) defprimitive('+', lambda args: args.car + args.cadr, 2) defprimitive('-', lambda args: args.car - args.cadr, 2) defprimitive('*', lambda args: args.car * args.cadr, 2) defprimitive('/', lambda args: args.car / args.cadr, 2) definitial('println', Primitive('println', lambda args, r, k: k.resume( print() if is_null(args) else print(str(args)[1:-1])))) definitial( 'call/cc', Primitive( 'call/cc', lambda vs, r, k: vs.car.invoke(cons(k, Nil), r, k) if length( vs) == 1 else wrong(
def primitive(name, value, vs, arity, k): if arity == length(vs): return k.resume(value(vs)) else: raise TypeError("incorrect arity {} {}".format(name, vs)) GLOBAL_ENV = NullEnv() definitial('f') definitial('foo') definitial('bar') definitial('x') definitial('y') definitial('z') defprimitive('null?', lambda args: is_null(args.car), 1) defprimitive('cons', lambda args: cons(args.car, args.cadr), 2) defprimitive('car', lambda args: args.caar, 1) defprimitive('cdr', lambda args: args.cdar, 1) defprimitive('+', lambda args: args.car + args.cadr, 2) defprimitive('-', lambda args: args.car - args.cadr, 2) defprimitive('*', lambda args: args.car * args.cadr, 2) defprimitive('/', lambda args: args.car / args.cadr, 2) definitial( 'println', Primitive( 'println', lambda args, r, k: k.resume(print() if is_null(args) else print( str(args)[1:-1])))) definitial( 'call/cc',
def definitial(name, value=None): global GLOBAL_ENV GLOBAL_ENV = cons(cons(name, value), GLOBAL_ENV) return name
def evlis(exps, env): if is_pair(exps): argument = evaluate(exps.car, env) return cons(argument, evlis(exps.cdr, env)) else: return Nil
def primitive(name, value, vs, arity, k): if arity == length(vs): return k.resume(value(vs)) else: raise TypeError("incorrect arity {} {}".format(name, vs)) GLOBAL_ENV = NullEnv() definitial('f') definitial('foo') definitial('bar') definitial('x') definitial('y') definitial('z') defprimitive('null?', lambda args: is_null(args.car), 1) defprimitive('cons', lambda args: cons(args.car, args.cadr), 2) defprimitive('car', lambda args: args.caar, 1) defprimitive('cdr', lambda args: args.cdar, 1) defprimitive('+', lambda args: args.car + args.cadr, 2) defprimitive('-', lambda args: args.car - args.cadr, 2) defprimitive('*', lambda args: args.car * args.cadr, 2) defprimitive('/', lambda args: args.car / args.cadr, 2) definitial( 'println', Primitive( 'println', lambda args, r, k: k.resume(print() if is_null(args) else print( str(args)[1:-1])))) # ======================================================================== # begin exercise-specific code