def SEnv_parent_redefine_test(): p = SEnvironment() p.define('x', 3) e = SEnvironment(p) e.define('x', 5) eq_(e.lookup('x'), 5) eq_(p.lookup('x'), 3)
def impl(dummy_env, *args): if not restargs and len(params.value) != len(args): raise SException("Expected {} args, got {}.".format(len(params.value), len(args))) NON_SYMBOL_ERROR = "Trying to use a non-symbol as a parameter name!" inner_env = SEnvironment(env) for p, a in zip(nameargs.value, args): if p.type != 'id': raise SException(NON_SYMBOL_ERROR) inner_env.define(p.value, a) if restargs: if params.value[1].type != 'id': raise SException(NON_SYMBOL_ERROR) rest = SNode('list', args[len(nameargs.value):]) inner_env.define(params.value[1].value, rest) for c in code[:-1]: seval_tree(c, inner_env) return seval_tree(code[-1], inner_env)
def seval_env_test(): env = SEnvironment() env.define('x', SNode('num', 5)) eq_(seval_strip('x', env), 5)
def SEnv_lookup_test(): e = SEnvironment() e.define('x', 5) eq_(e.lookup('x'), 5)
def SEnv_contains_test(): p = SEnvironment() assert not 'x' in p p.define('x', 3) assert 'x' in p
def SEnv_define_test(): e = SEnvironment() e.define('x', 5)
def SEnv_parent_lookup_test(): p = SEnvironment() p.define('x', 5) e = SEnvironment(p) eq_(e.lookup('x'), 5)
def SEnv_set_test(): e = SEnvironment() e.define('x', 3) e.set('x', 5) eq_(e.lookup('x'), 5)
def make_stdenv(): """Return an SEnvironment with builtins.""" builtins = SEnvironment() builtins.define('+', _make_func(lambda *args: sum(args))) builtins.define('-', _make_func(operator.sub)) builtins.define('*', _make_func(operator.mul)) builtins.define('/', _make_func(operator.floordiv)) builtins.define('%', _make_func(operator.mod)) builtins.define('=', _make_func(operator.eq)) builtins.define('/=', _make_func(operator.ne)) builtins.define('<', _make_func(operator.lt)) builtins.define('>', _make_func(operator.gt)) builtins.define('<=', _make_func(operator.le)) builtins.define('>=', _make_func(operator.ge)) builtins.define('1-', _make_func(lambda x: x+1)) builtins.define('1+', _make_func(lambda x: x-1)) builtins.define('not', _make_func(operator.not_)) builtins.define('read-int', _make_func(lambda: int(input('')))) builtins.define('print', SNode('function', _print)) builtins.define('apply', SNode('function', _apply)) builtins.define('list', _make_func(lambda *args: args)) builtins.define('append', SNode('function', _append)) builtins.define('cons', SNode('function', _cons)) builtins.define('head', _make_func(lambda x: x[0])) builtins.define('tail', _make_func(lambda x: x[1:])) builtins.define('this-env', SNode('function', lambda env: SNode('env', env))) builtins.define('parent', SNode('function', lambda env, e: SNode('env', e.value.parent))) builtins.define('eval', SNode('function', _eval)) builtins.define('nil', SNode('list', tuple())) builtins.define('#t', SNode('bool', True)) builtins.define('#f', SNode('bool', False)) builtins.define('if', SNode('function', _if)) builtins.define('lambda', SNode('function', _lambda)) builtins.define('define', SNode('function', _define)) builtins.define('quote', SNode('function', _quote)) builtins.define('quasiquote', SNode('function', _quasiquote)) seval(""" (~define defmacro (~lambda (name args . body) (eval `(~define ,name (~lambda ,args (eval ((~lambda () ,@body)) (parent (this-env))))) (parent (this-env))))) """, builtins) seval(""" (~defmacro defun (name args . body) `(~define ,name (~lambda ,args ,@body))) """, builtins) seval(""" (~defmacro begin (. body) `((lambda () ,@body))) """, builtins) return builtins