def qq_loop(acc: MalList, elt: MalExpression) -> MalList: if isinstance(elt, MalList): lst = elt.native() if len(lst) == 2: fst = lst[0] if isinstance(fst, MalSymbol) and fst.native() == u"splice-unquote": return MalList([MalSymbol(u"concat"), lst[1], acc]) return MalList([MalSymbol(u"cons"), quasiquote(elt), acc])
def test_env_constructor_binds_multiple(self): env = Env( outer=None, binds=[MalSymbol("a"), MalSymbol("b")], exprs=[MalInt(44), MalInt(32)], ) self.assertEqual(44, env.get("a").native()) self.assertEqual(32, env.get("b").native())
def test_def(self): env = Env(None) self.assertEqual( 1, step3_env.EVAL( MalList([MalSymbol("def!"), MalSymbol("a"), MalInt(1)]), env).native(), ) self.assertEqual(1, env.get("a").native())
def test_let_basic(self): env = Env(None) self.assertEqual( 2, step3_env.EVAL( MalList([ MalSymbol("let*"), MalList([MalSymbol("c"), MalInt(2)]), MalSymbol("c"), ]), env, ).native(), )
def quasiquote(ast: MalExpression) -> MalExpression: if isinstance(ast, MalList): lst = ast.native() if len(lst) == 2: fst = lst[0] if isinstance(fst, MalSymbol) and fst.native() == u'unquote': return lst[1] return qq_foldr(lst) elif isinstance(ast, MalVector): return MalList([MalSymbol("vec"), qq_foldr(ast.native())]) elif isinstance(ast, MalSymbol) or isinstance(ast, MalHash_map): return MalList([MalSymbol("quote"), ast]) else: return ast
def quasiquote(ast: MalExpression) -> MalExpression: if not is_pair(ast): return MalList([MalSymbol("quote"), ast]) elif core.equal(ast.native()[0], MalSymbol("unquote")).native(): return ast.native()[1] elif (is_pair(ast.native()[0]) and core.equal(ast.native()[0].native()[0], MalSymbol("splice-unquote")).native()): return MalList([ MalSymbol("concat"), ast.native()[0].native()[1], quasiquote(MalList(ast.native()[1:])), ]) else: return MalList([ MalSymbol("cons"), quasiquote(ast.native()[0]), quasiquote(MalList(ast.native()[1:])), ])
def test_if_basic_false_no_fourth_arg(self): env = Env(None) self.assertEqual( "nil", str( step4_if_fn_do.EVAL( MalList([MalSymbol("if"), MalBoolean(False), MalInt(4321)]), env ) ), )
def test_let_advanced(self): env = Env(None) env.set( "+", mal_types.MalFunctionCompiled( lambda a: MalInt(a[0].native() + a[1].native())), ) self.assertEqual( 4, step3_env.EVAL( MalList([ MalSymbol("let*"), MalList([MalSymbol("c"), MalInt(2)]), MalList([MalSymbol("+"), MalSymbol("c"), MalInt(2)]), ]), env, ).native(), )
def test_if_basic_false(self): env = Env(None) self.assertEqual( 1234, step4_if_fn_do.EVAL( MalList( [MalSymbol("if"), MalBoolean(False), MalInt(4321), MalInt(1234)] ), env, ).native(), )
def test_eval_1_plus_1(self): env = Env(None) env.set( "+", mal_types.MalFunctionCompiled( lambda a: MalInt(a[0].native() + a[1].native())), ) self.assertEqual( 2, step3_env.EVAL(MalList([MalSymbol("+"), MalInt(1), MalInt(1)]), env).native(), )
def symbol(arg: MalExpression) -> MalExpression: assert isinstance(arg, MalString) return MalSymbol(arg.unreadable_str())
def visit_mDerefExpression(self, node, children) -> MalList: return MalList([MalSymbol("deref"), children[0]])
def visit_mUnquotedExpression(self, node, children) -> MalList: return MalList([MalSymbol("unquote"), children[0]])
def visit_mWithMetaExpression(self, node, children) -> MalList: return MalList([MalSymbol("with-meta"), children[1], children[0]])
def visit_mSymbol(self, node, children) -> MalSymbol: return MalSymbol(node.value)
def test_env_constructor_binds(self): env = Env(outer=None, binds=[MalSymbol("a")], exprs=[MalInt(3)]) self.assertEqual(3, env.get("a").native())