diff --git a/README.rst b/README.rst
index 307df8d..9ff7a11 100644
--- a/README.rst
+++ b/README.rst
@@ -20,6 +20,10 @@ that exposes LLVM to Python. For tips on setting up ``llvmlite`` with LLVM, `see
this blog post
`_.
+This repository is fairly complete - the whole Kaleidoscope language is
+implemented. The only thing missing is Chapter 8 - Debug Information, because
+``llvlite`` does not yet support convenient emission of debug info.
+
How to use this code
--------------------
diff --git a/chapter3and4.py b/chapter3and4.py
index c5f61dc..f426400 100644
--- a/chapter3and4.py
+++ b/chapter3and4.py
@@ -559,5 +559,5 @@ if __name__ == '__main__':
kalei = KaleidoscopeEvaluator()
print(kalei.evaluate('def adder(a b) a + b'))
print(kalei.evaluate('def foo(x) (1+2+x)*(x+(1+2))'))
- print(kalei.evaluate('foo(3)', optimize=True, llvmdump=True))
+ print(kalei.evaluate('foo(3)'))
print(kalei.evaluate('foo(adder(3, 3)*4)', optimize=True, llvmdump=True))
diff --git a/chapter5.py b/chapter5.py
index 58f7bf8..360d747 100644
--- a/chapter5.py
+++ b/chapter5.py
@@ -7,6 +7,7 @@ from enum import Enum
import llvmlite.ir as ir
import llvmlite.binding as llvm
+
# Each token is a tuple of kind and value. kind is one of the enumeration values
# in TokenKind. value is the textual value of the token in the input.
class TokenKind(Enum):
@@ -213,7 +214,7 @@ class FunctionAST(ASTNode):
def is_anonymous(self):
return self.proto.name.startswith('_anon')
-
+
def dump(self, indent=0):
s = '{0}{1}[{2}]\n'.format(
' ' * indent, self.__class__.__name__, self.proto.dump())
@@ -226,7 +227,7 @@ class ParseError(Exception): pass
class Parser(object):
"""Parser for the Kaleidoscope language.
-
+
After the parser is created, invoke parse_toplevel multiple times to parse
Kaleidoscope source into an AST.
"""
@@ -344,7 +345,7 @@ class Parser(object):
self._match(TokenKind.ELSE)
else_expr = self._parse_expression()
return IfExprAST(cond_expr, then_expr, else_expr)
-
+
# forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expr
def _parse_for_expr(self):
self._get_next_token() # consume the 'for'
@@ -364,7 +365,7 @@ class Parser(object):
self._match(TokenKind.IN)
body = self._parse_expression()
return ForExprAST(id_name, start_expr, end_expr, step_expr, body)
-
+
# binoprhs ::= ( primary)*
def _parse_binop_rhs(self, expr_prec, lhs):
"""Parse the right-hand-side of a binary expression.
@@ -514,7 +515,7 @@ class LLVMCodeGenerator(object):
self.builder.position_at_start(then_bb)
then_val = self._codegen(node.then_expr)
self.builder.branch(merge_bb)
-
+
# Emission of then_val could have modified the current basic block. To
# properly set up the PHI, remember which block the 'then' part ends in.
then_bb = self.builder.block
@@ -532,7 +533,7 @@ class LLVMCodeGenerator(object):
phi.add_incoming(then_val, then_bb)
phi.add_incoming(else_val, else_bb)
return phi
-
+
def _codegen_ForExprAST(self, node):
# Output this as:
# ...
@@ -615,7 +616,7 @@ class LLVMCodeGenerator(object):
raise CodegenError('Call argument length mismatch', node.callee)
call_args = [self._codegen(arg) for arg in node.args]
return self.builder.call(callee_func, call_args, 'calltmp')
-
+
def _codegen_PrototypeAST(self, node):
funcname = node.name
# Create a function type
@@ -675,7 +676,7 @@ class KaleidoscopeEvaluator(object):
self._add_builtins(self.codegen.module)
self.target = llvm.Target.from_default_triple()
-
+
def evaluate(self, codestr, optimize=True, llvmdump=False):
"""Evaluate code in codestr.
@@ -685,7 +686,7 @@ class KaleidoscopeEvaluator(object):
# Parse the given code and generate code from it
ast = Parser().parse_toplevel(codestr)
self.codegen.generate_code(ast)
-
+
if llvmdump:
print('======== Unoptimized LLVM IR')
print(str(self.codegen.module))
@@ -764,13 +765,13 @@ class TestEvaluator(unittest.TestCase):
e = KaleidoscopeEvaluator()
e.evaluate('''
def foo(a b c)
- if a < b
+ if a < b
then if a < c then a * 2 else c * 2
else b * 2''')
self.assertEqual(e.evaluate('foo(1, 20, 300)'), 2)
self.assertEqual(e.evaluate('foo(10, 2, 300)'), 4)
self.assertEqual(e.evaluate('foo(100, 2000, 30)'), 60)
-
+
def test_for(self):
# For doesn't return anything, so just make sure evaluating it doesn't
# crash.
@@ -785,6 +786,11 @@ class TestEvaluator(unittest.TestCase):
if __name__ == '__main__':
+ # Evaluate some code.
kalei = KaleidoscopeEvaluator()
kalei.evaluate('def foo(a b) for x = 65, x < a, b in putchard(x)')
- print(kalei.evaluate('foo(79, 1)', optimize=True, llvmdump=True))
+
+ # We call these for their side effect of printing to stdout, so don't care
+ # about the return value.
+ kalei.evaluate('foo(79, 1)')
+ kalei.evaluate('putchard(10)')