added tests
This commit is contained in:
parent
73188b5200
commit
6da93ed87f
1 changed files with 74 additions and 14 deletions
88
chapter7.py
88
chapter7.py
|
|
@ -715,8 +715,8 @@ class LLVMCodeGenerator(object):
|
||||||
# curvar = load var
|
# curvar = load var
|
||||||
# nextvariable = curvar + step
|
# nextvariable = curvar + step
|
||||||
# store nextvar -> var
|
# store nextvar -> var
|
||||||
# br endcond, loop, endloop
|
# br endcond, loop, afterloop
|
||||||
# outloop:
|
# afterloop:
|
||||||
|
|
||||||
# Create an alloca for the induction var. Save and restore location of
|
# Create an alloca for the induction var. Save and restore location of
|
||||||
# our builder because _create_entry_block_alloca may modify it (llvmlite
|
# our builder because _create_entry_block_alloca may modify it (llvmlite
|
||||||
|
|
@ -776,6 +776,42 @@ class LLVMCodeGenerator(object):
|
||||||
# The 'for' expression always returns 0
|
# The 'for' expression always returns 0
|
||||||
return self.builder.constant(ir.DoubleType(), 0.0)
|
return self.builder.constant(ir.DoubleType(), 0.0)
|
||||||
|
|
||||||
|
def _codegen_VarExprAST(self, node):
|
||||||
|
old_bindings = []
|
||||||
|
|
||||||
|
for name, init in node.vars:
|
||||||
|
# Emit the initializer before adding the variable to scope. This
|
||||||
|
# prefents the initializer from referencing the variable itself.
|
||||||
|
if init is not None:
|
||||||
|
init_val = self._codegen(init)
|
||||||
|
else:
|
||||||
|
init_val = self.builder.constant(ir.DoubleType(), 0.0)
|
||||||
|
|
||||||
|
# Create an alloca for the induction var and store the init value to
|
||||||
|
# it. Save and restore location of our builder because
|
||||||
|
# _create_entry_block_alloca may modify it (llvmlite issue #44).
|
||||||
|
saved_block = self.builder.block
|
||||||
|
var_addr = self._create_entry_block_alloca(name)
|
||||||
|
self.builder.position_at_end(saved_block)
|
||||||
|
self.builder.store(init_val, var_addr)
|
||||||
|
|
||||||
|
# We're going to shadow this name in the symbol table now; remember
|
||||||
|
# what to restore.
|
||||||
|
old_bindings.append(self.func_symtab.get(name))
|
||||||
|
self.func_symtab[name] = var_addr
|
||||||
|
|
||||||
|
# Now all the vars are in scope. Codegen the body.
|
||||||
|
body_val = self._codegen(node.body)
|
||||||
|
|
||||||
|
# Restore the old bindings.
|
||||||
|
for i, (name, _) in enumerate(node.vars):
|
||||||
|
if old_bindings[i] is not None:
|
||||||
|
self.func_symtab[name] = old_bindings[i]
|
||||||
|
else:
|
||||||
|
del self.func_symtab[name]
|
||||||
|
|
||||||
|
return body_val
|
||||||
|
|
||||||
def _codegen_CallExprAST(self, node):
|
def _codegen_CallExprAST(self, node):
|
||||||
callee_func = self.module.globals.get(node.callee, None)
|
callee_func = self.module.globals.get(node.callee, None)
|
||||||
if callee_func is None or not isinstance(callee_func, ir.Function):
|
if callee_func is None or not isinstance(callee_func, ir.Function):
|
||||||
|
|
@ -978,21 +1014,45 @@ class TestParser(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestEvaluator(unittest.TestCase):
|
class TestEvaluator(unittest.TestCase):
|
||||||
def test_custom_binop(self):
|
def test_var_expr(self):
|
||||||
e = KaleidoscopeEvaluator()
|
e = KaleidoscopeEvaluator()
|
||||||
e.evaluate('def binary %(a b) a - b')
|
e.evaluate('''
|
||||||
self.assertEqual(e.evaluate('10 % 5'), 5)
|
def foo(x y z)
|
||||||
self.assertEqual(e.evaluate('100 % 5.5'), 94.5)
|
var s1 = x + y, s2 = z + y in
|
||||||
|
s1 * s2
|
||||||
|
''')
|
||||||
|
self.assertEqual(e.evaluate('foo(1, 2, 3)'), 15)
|
||||||
|
|
||||||
|
e = KaleidoscopeEvaluator()
|
||||||
|
e.evaluate('def binary : 1 (x y) y')
|
||||||
|
e.evaluate('''
|
||||||
|
def foo(step)
|
||||||
|
var accum in
|
||||||
|
(for i = 0, i < 10, step in
|
||||||
|
accum = accum + i) : accum
|
||||||
|
''')
|
||||||
|
# Note that Kaleidoscope's 'for' loop executes the last iteration even
|
||||||
|
# when the condition is no longer fulfilled after the step is done.
|
||||||
|
# 0 + 2 + 4 + 6 + 8 + 10
|
||||||
|
self.assertEqual(e.evaluate('foo(2)'), 30)
|
||||||
|
|
||||||
|
def test_nested_var_exprs(self):
|
||||||
|
e = KaleidoscopeEvaluator()
|
||||||
|
e.evaluate('''
|
||||||
|
def foo(x y z)
|
||||||
|
var s1 = x + y, s2 = z + y in
|
||||||
|
var s3 = s1 * s2 in
|
||||||
|
s3 * 100
|
||||||
|
''')
|
||||||
|
self.assertEqual(e.evaluate('foo(1, 2, 3)'), 1500)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
#p = Parser()
|
|
||||||
#print(p.parse_toplevel('def binary% 77(a b) a + b').dump())
|
|
||||||
#print(p.parse_toplevel('def fra(x t) x % t').dump())
|
|
||||||
kalei = KaleidoscopeEvaluator()
|
kalei = KaleidoscopeEvaluator()
|
||||||
#kalei.evaluate('def foo(t) for i = 65, i < t, 1 in putchard(i)')
|
|
||||||
kalei.evaluate('def binary: 1 (x y) y')
|
kalei.evaluate('def binary: 1 (x y) y')
|
||||||
kalei.evaluate('def test(x) putchard(x) : x = 65 : putchard(x) : x = 66 : putchard(x)')
|
kalei.evaluate('''
|
||||||
kalei.evaluate('test(77)')
|
def foo(x y z)
|
||||||
#kalei.evaluate('foo(80)', llvmdump=True)
|
var s1 = x + y, s2 = z + y in
|
||||||
#print(kalei.evaluate('5 % 10', optimize=False, llvmdump=True))
|
s1 * s2
|
||||||
|
''')
|
||||||
|
print(kalei.evaluate('foo(1, 2, 3)'))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue