Finished editing PythonLangImpl6.rst.

This commit is contained in:
Maggie Mari 2012-08-21 17:59:44 -05:00
commit 16860436d4

View file

@ -105,7 +105,9 @@ keywords:
pass pass
class UnaryToken(object): class UnaryToken(object):
pass pass
... ...
def Tokenize(string): def Tokenize(string):
... ...
elif identifier == 'in': elif identifier == 'in':
@ -295,7 +297,8 @@ whenever we define a new binary operator:
def main(): def main():
... ...
g_binop_precedence['<'] = 10 g_binop_precedence['<'] = 10
g_binop_precedence['+'] = 20 g_binop_precedence['-'] = 20 g_binop_precedence['+'] = 20
g_binop_precedence['-'] = 20
g_binop_precedence['*'] = 40 g_binop_precedence['*'] = 40
... ...
@ -347,8 +350,8 @@ simple: we'll add a new function to do it:
def ParseUnary(self): def ParseUnary(self):
# If the current token is not an operator, it must be a primary expression. # If the current token is not an operator, it must be a primary expression.
if (not isinstance(self.current, CharacterToken) or if (not isinstance(self.current, CharacterToken) or
self.current in [CharacterToken('('), CharacterToken(',')]): self.current in [CharacterToken('('), CharacterToken(',')]):
return self.ParsePrimary() return self.ParsePrimary()
# If this is a unary operator, read it. # If this is a unary operator, read it.
operator = self.current.chara operator = self.current.chara
@ -826,11 +829,13 @@ Lexer
class UnaryToken(object): class UnaryToken(object):
pass pass
class IdentifierToken(object): def __init__(self, name): class IdentifierToken(object):
self.name = name def __init__(self, name):
self.name = name
class NumberToken(object): def __init__(self, value): class NumberToken(object):
self.value = value def __init__(self, value):
self.value = value
class CharacterToken(object): class CharacterToken(object):
def __init__(self, char): def __init__(self, char):
@ -894,12 +899,12 @@ Lexer
yield CharacterToken(string[0]) yield CharacterToken(string[0])
string = string[1:] string = string[1:]
yield EOFToken() yield EOFToken()
Abstract Syntax Tree (aka Parse Tree) Abstract Syntax Tree (aka Parse Tree)
------------------------------------- -------------------------------------
.. code-block:: python .. code-block:: python
# Base class for all expression nodes. # Base class for all expression nodes.
class ExpressionNode(object): class ExpressionNode(object):
@ -911,7 +916,8 @@ Abstract Syntax Tree (aka Parse Tree)
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
def CodeGen(self): return Constant.real(Type.double(), self.value) def CodeGen(self):
return Constant.real(Type.double(), self.value)
# Expression class for referencing a variable, like "a". # Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode): class VariableExpressionNode(ExpressionNode):
@ -978,7 +984,9 @@ Abstract Syntax Tree (aka Parse Tree)
self.then_branch = then_branch self.then_branch = then_branch
self.else_branch = else_branch self.else_branch = else_branch
def CodeGen(self): condition = self.condition.CodeGen() def CodeGen(self):
condition = self.condition.CodeGen()
# Convert condition to a bool by comparing equal to 0.0. # Convert condition to a bool by comparing equal to 0.0.
condition_bool = g_llvm_builder.fcmp( condition_bool = g_llvm_builder.fcmp(
@ -1114,370 +1122,436 @@ Abstract Syntax Tree (aka Parse Tree)
# Expression class for a unary operator. # Expression class for a unary operator.
class UnaryExpressionNode(ExpressionNode): class UnaryExpressionNode(ExpressionNode):
def __init__(self, operator, operand): self.operator = operator def __init__(self, operator, operand):
self.operand = operand self.operator = operator
self.operand = operand
def CodeGen(self): operand = self.operand.CodeGen() function =
g_llvm_module.get_function_named('unary' + self.operator) return def CodeGen(self):
g_llvm_builder.call(function, [operand], 'unop') operand = self.operand.CodeGen()
function = g_llvm_module.get_function_named('unary' + self.operator)
return g_llvm_builder.call(function, [operand], 'unop')
# This class represents the "prototype" for a function, which captures its name, # This class represents the "prototype" for a function, which captures its name,
# and its argument names (thus implicitly the number of arguments the function # and its argument names (thus implicitly the number of arguments the function
# takes), as well as if it is an operator. # takes), as well as if it is an operator.
class PrototypeNode(object): class PrototypeNode(object):
def __init__(self, name, args, is_operator=False, precedence=0): def __init__(self, name, args, is_operator=False, precedence=0):
self.name = name self.args = args self.is_operator = is_operator self.name = name
self.precedence = precedence self.args = args
self.is_operator = is_operator
def IsBinaryOp(self): return self.is_operator and len(self.args) == 2 self.precedence = precedence
def GetOperatorName(self): assert self.is_operator return self.name[-1] def IsBinaryOp(self):
return self.is_operator and len(self.args) == 2
def CodeGen(self): # Make the function type, eg. double(double,double).
funct_type = Type.function( Type.double(), [Type.double()] * def GetOperatorName(self):
len(self.args), False) assert self.is_operator
return self.name[-1]
::
def CodeGen(self):
function = Function.new(g_llvm_module, funct_type, self.name) # Make the function type, eg. double(double,double).
funct_type = Type.function(
# If the name conflicted, there was already something with the same name. Type.double(), [Type.double()] * len(self.args), False)
# If it has a body, don't allow redefinition or reextern.
if function.name != self.name: function = Function.new(g_llvm_module, funct_type, self.name)
function.delete()
function = g_llvm_module.get_function_named(self.name) # If the name conflicted, there was already something with the same name.
# If it has a body, don't allow redefinition or reextern.
# If the function already has a body, reject this. if function.name != self.name:
if not function.is_declaration: function.delete()
raise RuntimeError('Redefinition of function.') function = g_llvm_module.get_function_named(self.name)
# If the function took a different number of args, reject. # If the function already has a body, reject this.
if len(function.args) != len(self.args): if not function.is_declaration:
raise RuntimeError('Redeclaration of a function with different number ' raise RuntimeError('Redefinition of function.')
'of args.')
# If the function took a different number of args, reject.
# Set names for all arguments and add them to the variables symbol table. if len(function.args) != len(self.args):
for arg, arg_name in zip(function.args, self.args): raise RuntimeError('Redeclaration of a function with different number '
arg.name = arg_name 'of args.')
# Add arguments to variable symbol table.
g_named_values[arg_name] = arg # Set names for all arguments and add them to the variables symbol table.
for arg, arg_name in zip(function.args, self.args):
return function arg.name = arg_name
# Add arguments to variable symbol table.
g_named_values[arg_name] = arg
return function
# This class represents a function definition itself. # This class represents a function definition itself.
class FunctionNode(object): class FunctionNode(object):
def __init__(self, prototype, body): self.prototype = prototype def __init__(self, prototype, body):
self.body = body self.prototype = prototype
self.body = body
def CodeGen(self):
# Clear scope.
g_named_values.clear()
# Create a function object.
function = self.prototype.CodeGen()
# If this is a binary operator, install its precedence.
if self.prototype.IsBinaryOp():
operator = self.prototype.GetOperatorName()
g_binop_precedence[operator] = self.prototype.precedence
# Create a new basic block to start insertion into.
block = function.append_basic_block('entry')
global g_llvm_builder
g_llvm_builder = Builder.new(block)
# Finish off the function.
try:
return_value = self.body.CodeGen()
g_llvm_builder.ret(return_value)
# Validate the generated code, checking for consistency.
function.verify()
# Optimize the function.
g_llvm_pass_manager.run(function)
except:
function.delete()
if self.prototype.IsBinaryOp():
del g_binop_precedence[self.prototype.GetOperatorName()]
raise
return function
def CodeGen(self): # Clear scope. g_named_values.clear() Parser
------
::
.. code-block:: python
# Create a function object.
function = self.prototype.CodeGen()
# If this is a binary operator, install its precedence.
if self.prototype.IsBinaryOp():
operator = self.prototype.GetOperatorName()
g_binop_precedence[operator] = self.prototype.precedence
# Create a new basic block to start insertion into.
block = function.append_basic_block('entry')
global g_llvm_builder
g_llvm_builder = Builder.new(block)
# Finish off the function.
try:
return_value = self.body.CodeGen()
g_llvm_builder.ret(return_value)
# Validate the generated code, checking for consistency.
function.verify()
# Optimize the function.
g_llvm_pass_manager.run(function)
except:
function.delete()
if self.prototype.IsBinaryOp():
del g_binop_precedence[self.prototype.GetOperatorName()]
raise
return function
Parser
------
class Parser(object): class Parser(object):
def __init__(self, tokens): self.tokens = tokens self.Next() def __init__(self, tokens):
self.tokens = tokens
# Provide a simple token buffer. Parser.current is the current token the self.Next()
# parser is looking at. Parser.Next() reads another token from the lexer
and # updates Parser.current with its results. def Next(self): # Provide a simple token buffer. Parser.current is the current token the
self.current = self.tokens.next() # parser is looking at. Parser.Next() reads another token from the lexer and
# updates Parser.current with its results.
# Gets the precedence of the current token, or -1 if the token is not a def Next(self):
binary # operator. def GetCurrentTokenPrecedence(self): if self.current = self.tokens.next()
isinstance(self.current, CharacterToken): return
g_binop_precedence.get(self.current.char, -1) else: return -1 # Gets the precedence of the current token, or -1 if the token is not a binary
# operator.
# identifierexpr ::= identifier | identifier '(' expression* ')' def def GetCurrentTokenPrecedence(self):
ParseIdentifierExpr(self): identifier_name = self.current.name if isinstance(self.current, CharacterToken):
self.Next() # eat identifier. return g_binop_precedence.get(self.current.char, -1)
else:
:: return -1
if self.current != CharacterToken('('): # Simple variable reference. # identifierexpr ::= identifier | identifier '(' expression* ')'
return VariableExpressionNode(identifier_name) def ParseIdentifierExpr(self):
identifier_name = self.current.name
# Call. self.Next() # eat identifier.
self.Next() # eat '('.
args = [] if self.current != CharacterToken('('): # Simple variable reference.
if self.current != CharacterToken(')'): return VariableExpressionNode(identifier_name)
while True:
args.append(self.ParseExpression()) # Call.
if self.current == CharacterToken(')'): self.Next() # eat '('.
break args = []
elif self.current != CharacterToken(','): if self.current != CharacterToken(')'):
raise RuntimeError('Expected ")" or "," in argument list.') while True:
self.Next() args.append(self.ParseExpression())
if self.current == CharacterToken(')'):
self.Next() # eat ')'. break
return CallExpressionNode(identifier_name, args) elif self.current != CharacterToken(','):
raise RuntimeError('Expected ")" or "," in argument list.')
# numberexpr ::= number def ParseNumberExpr(self): result = self.Next()
NumberExpressionNode(self.current.value) self.Next() # consume the
number. return result self.Next() # eat ')'.
return CallExpressionNode(identifier_name, args)
# parenexpr ::= '(' expression ')' def ParseParenExpr(self): self.Next()
# eat '('. # numberexpr ::= number
def ParseNumberExpr(self):
:: result = NumberExpressionNode(self.current.value)
self.Next() # consume the number.
contents = self.ParseExpression() return result
if self.current != CharacterToken(')'): # parenexpr ::= '(' expression ')'
raise RuntimeError('Expected ")".') def ParseParenExpr(self):
self.Next() # eat ')'. self.Next() # eat '('.
return contents contents = self.ParseExpression()
# ifexpr ::= 'if' expression 'then' expression 'else' expression def if self.current != CharacterToken(')'):
ParseIfExpr(self): self.Next() # eat the if. raise RuntimeError('Expected ")".')
self.Next() # eat ')'.
::
return contents
# condition.
condition = self.ParseExpression() # ifexpr ::= 'if' expression 'then' expression 'else' expression
def ParseIfExpr(self):
if not isinstance(self.current, ThenToken): self.Next() # eat the if.
raise RuntimeError('Expected "then".')
self.Next() # eat the then. # condition.
condition = self.ParseExpression()
then_branch = self.ParseExpression()
if not isinstance(self.current, ThenToken):
if not isinstance(self.current, ElseToken): raise RuntimeError('Expected "then".')
raise RuntimeError('Expected "else".') self.Next() # eat the then.
self.Next() # eat the else.
then_branch = self.ParseExpression()
else_branch = self.ParseExpression()
if not isinstance(self.current, ElseToken):
return IfExpressionNode(condition, then_branch, else_branch) raise RuntimeError('Expected "else".')
self.Next() # eat the else.
# forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in'
expression def ParseForExpr(self): self.Next() # eat the for. else_branch = self.ParseExpression()
:: return IfExpressionNode(condition, then_branch, else_branch)
if not isinstance(self.current, IdentifierToken): # forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
raise RuntimeError('Expected identifier after for.') def ParseForExpr(self):
self.Next() # eat the for.
loop_variable = self.current.name
self.Next() # eat the identifier. if not isinstance(self.current, IdentifierToken):
raise RuntimeError('Expected identifier after for.')
if self.current != CharacterToken('='):
raise RuntimeError('Expected "=" after for variable.') loop_variable = self.current.name
self.Next() # eat the '='. self.Next() # eat the identifier.
start = self.ParseExpression() if self.current != CharacterToken('='):
raise RuntimeError('Expected "=" after for variable.')
if self.current != CharacterToken(','): self.Next() # eat the '='.
raise RuntimeError('Expected "," after for start value.')
self.Next() # eat the ','. start = self.ParseExpression()
end = self.ParseExpression() if self.current != CharacterToken(','):
raise RuntimeError('Expected "," after for start value.')
# The step value is optional. self.Next() # eat the ','.
if self.current == CharacterToken(','):
self.Next() # eat the ','. end = self.ParseExpression()
step = self.ParseExpression()
else: # The step value is optional.
step = None if self.current == CharacterToken(','):
self.Next() # eat the ','.
if not isinstance(self.current, InToken): step = self.ParseExpression()
raise RuntimeError('Expected "in" after for variable specification.') else:
self.Next() # eat 'in'. step = None
body = self.ParseExpression() if not isinstance(self.current, InToken):
raise RuntimeError('Expected "in" after for variable specification.')
return ForExpressionNode(loop_variable, start, end, step, body) self.Next() # eat 'in'.
# primary ::= identifierexpr | numberexpr | parenexpr | ifexpr | body = self.ParseExpression()
forexpr def ParsePrimary(self): if isinstance(self.current,
IdentifierToken): return self.ParseIdentifierExpr() elif return ForExpressionNode(loop_variable, start, end, step, body)
isinstance(self.current, NumberToken): return self.ParseNumberExpr()
elif isinstance(self.current, IfToken): return self.ParseIfExpr() elif # primary ::= identifierexpr | numberexpr | parenexpr | ifexpr | forexpr
isinstance(self.current, ForToken): return self.ParseForExpr() elif def ParsePrimary(self):
self.current == CharacterToken('('): return self.ParseParenExpr() else: if isinstance(self.current, IdentifierToken):
raise RuntimeError('Unknown token when expecting an expression.') return self.ParseIdentifierExpr()
elif isinstance(self.current, NumberToken):
# unary ::= primary | unary_operator unary def ParseUnary(self): # If return self.ParseNumberExpr()
the current token is not an operator, it must be a primary expression. elif isinstance(self.current, IfToken):
if (not isinstance(self.current, CharacterToken) or self.current in return self.ParseIfExpr()
[CharacterToken('('), CharacterToken(',')]): return self.ParsePrimary() elif isinstance(self.current, ForToken):
return self.ParseForExpr()
:: elif self.current == CharacterToken('('):
return self.ParseParenExpr()
# If this is a unary operator, read it. else:
operator = self.current.char raise RuntimeError('Unknown token when expecting an expression.')
self.Next() # eat the operator.
return UnaryExpressionNode(operator, self.ParseUnary()) # unary ::= primary | unary_operator unary
def ParseUnary(self):
# binoprhs ::= (binary_operator unary)* def ParseBinOpRHS(self, left, # If the current token is not an operator, it must be a primary expression.
left_precedence): # If this is a binary operator, find its precedence. if (not isinstance(self.current, CharacterToken) or
while True: precedence = self.GetCurrentTokenPrecedence() self.current in [CharacterToken('('), CharacterToken(',')]):
return self.ParsePrimary()
::
# If this is a unary operator, read it.
# If this is a binary operator that binds at least as tightly as the operator = self.current.char
# current one, consume it; otherwise we are done. self.Next() # eat the operator.
if precedence < left_precedence: return UnaryExpressionNode(operator, self.ParseUnary())
return left
# binoprhs ::= (binary_operator unary)*
binary_operator = self.current.char def ParseBinOpRHS(self, left, left_precedence):
self.Next() # eat the operator. # If this is a binary operator, find its precedence.
while True:
# Parse the unary expression after the binary operator. precedence = self.GetCurrentTokenPrecedence()
right = self.ParseUnary()
# If this is a binary operator that binds at least as tightly as the
# If binary_operator binds less tightly with right than the operator after # current one, consume it; otherwise we are done.
# right, let the pending operator take right as its left. if precedence < left_precedence:
next_precedence = self.GetCurrentTokenPrecedence() return left
if precedence < next_precedence:
right = self.ParseBinOpRHS(right, precedence + 1) binary_operator = self.current.char
self.Next() # eat the operator.
# Merge left/right.
left = BinaryOperatorExpressionNode(binary_operator, left, right) # Parse the unary expression after the binary operator.
right = self.ParseUnary()
# expression ::= unary binoprhs def ParseExpression(self): left =
self.ParseUnary() return self.ParseBinOpRHS(left, 0) # If binary_operator binds less tightly with right than the operator after
# right, let the pending operator take right as its left.
# prototype # ::= id '(' id* ')' # ::= binary LETTER number? (id, id) # next_precedence = self.GetCurrentTokenPrecedence()
::= unary LETTER (id) def ParsePrototype(self): precedence = None if if precedence < next_precedence:
isinstance(self.current, IdentifierToken): kind = 'normal' right = self.ParseBinOpRHS(right, precedence + 1)
function_name = self.current.name self.Next() # eat function name. elif
isinstance(self.current, UnaryToken): kind = 'unary' self.Next() # eat # Merge left/right.
'unary'. if not isinstance(self.current, CharacterToken): raise left = BinaryOperatorExpressionNode(binary_operator, left, right)
RuntimeError('Expected an operator after "unary".') function_name =
'unary' + self.current.char self.Next() # eat the operator. elif # expression ::= unary binoprhs
isinstance(self.current, BinaryToken): kind = 'binary' self.Next() # eat def ParseExpression(self):
'binary'. if not isinstance(self.current, CharacterToken): raise left = self.ParseUnary()
RuntimeError('Expected an operator after "binary".') function_name = return self.ParseBinOpRHS(left, 0)
'binary' + self.current.char self.Next() # eat the operator. if
isinstance(self.current, NumberToken): if not 1 <= self.current.value <= # prototype # ::= id '(' id* ')'
100: raise RuntimeError('Invalid precedence: must be in range [1, # ::= binary LETTER number? (id, id)
100].') precedence = self.current.value self.Next() # eat the # ::= unary LETTER (id)
precedence. else: raise RuntimeError('Expected function name, "unary" or def ParsePrototype(self):
"binary" in ' 'prototype.') precedence = None
if isinstance(self.current, IdentifierToken):
:: kind = 'normal'
function_name = self.current.name
if self.current != CharacterToken('('): self.Next() # eat function name.
raise RuntimeError('Expected "(" in prototype.') elif isinstance(self.current, UnaryToken):
self.Next() # eat '('. kind = 'unary'
self.Next() # eat 'unary'.
arg_names = [] if not isinstance(self.current, CharacterToken):
while isinstance(self.current, IdentifierToken): raise RuntimeError('Expected an operator after "unary".')
arg_names.append(self.current.name) function_name = 'unary' + self.current.char
self.Next() self.Next() # eat the operator.
elif isinstance(self.current, BinaryToken):
if self.current != CharacterToken(')'): kind = 'binary'
raise RuntimeError('Expected ")" in prototype.') self.Next() # eat 'binary'.
if not isinstance(self.current, CharacterToken):
# Success. raise RuntimeError('Expected an operator after "binary".')
self.Next() # eat ')'. function_name = 'binary' + self.current.char
self.Next() # eat the operator.
if kind == 'unary' and len(arg_names) != 1: if isinstance(self.current, NumberToken):
raise RuntimeError('Invalid number of arguments for a unary operator.') if not 1 <= self.current.value <= 100:
elif kind == 'binary' and len(arg_names) != 2: raise RuntimeError('Invalid precedence: must be in range [1, 100].')
raise RuntimeError('Invalid number of arguments for a binary operator.') precedence = self.current.value
self.Next() # eat the precedence.
return PrototypeNode(function_name, arg_names, kind != 'normal', precedence) else:
raise RuntimeError('Expected function name, "unary" or "binary" in '
# definition ::= 'def' prototype expression def ParseDefinition(self): 'prototype.')
self.Next() # eat def. proto = self.ParsePrototype() body =
self.ParseExpression() return FunctionNode(proto, body) if self.current != CharacterToken('('):
raise RuntimeError('Expected "(" in prototype.')
# toplevelexpr ::= expression def ParseTopLevelExpr(self): proto = self.Next() # eat '('.
PrototypeNode('', []) return FunctionNode(proto, self.ParseExpression())
arg_names = []
# external ::= 'extern' prototype def ParseExtern(self): self.Next() # while isinstance(self.current, IdentifierToken):
eat extern. return self.ParsePrototype() arg_names.append(self.current.name)
self.Next()
# Top-Level parsing def HandleDefinition(self):
self.Handle(self.ParseDefinition, 'Read a function definition:') if self.current != CharacterToken(')'):
raise RuntimeError('Expected ")" in prototype.')
def HandleExtern(self): self.Handle(self.ParseExtern, 'Read an extern:')
# Success.
def HandleTopLevelExpression(self): try: function = self.Next() # eat ')'.
self.ParseTopLevelExpr().CodeGen() result =
g_llvm_executor.run_function(function, []) print 'Evaluated to:', if kind == 'unary' and len(arg_names) != 1:
result.as_real(Type.double()) except Exception, e: print 'Error:', e raise RuntimeError('Invalid number of arguments for a unary operator.')
try: self.Next() # Skip for error recovery. except: pass elif kind == 'binary' and len(arg_names) != 2:
raise RuntimeError('Invalid number of arguments for a binary operator.')
def Handle(self, function, message): try: print message,
function().CodeGen() except Exception, e: print 'Error:', e try: return PrototypeNode(function_name, arg_names, kind != 'normal', precedence)
self.Next() # Skip for error recovery. except: pass
# definition ::= 'def' prototype expression
Main driver code. def ParseDefinition(self):
----------------- self.Next() # eat def.
proto = self.ParsePrototype()
def main(): # Set up the optimizer pipeline. Start with registering info body = self.ParseExpression()
about how the # target lays out data structures. return FunctionNode(proto, body)
g_llvm_pass_manager.add(g_llvm_executor.target_data) # Do simple
"peephole" optimizations and bit-twiddling optzns. # toplevelexpr ::= expression
g_llvm_pass_manager.add(PASS_INSTRUCTION_COMBINING) # Reassociate def ParseTopLevelExpr(self):
expressions. g_llvm_pass_manager.add(PASS_REASSOCIATE) # Eliminate proto = PrototypeNode('', [])
Common SubExpressions. g_llvm_pass_manager.add(PASS_GVN) # Simplify return FunctionNode(proto, self.ParseExpression())
the control flow graph (deleting unreachable blocks, etc).
g_llvm_pass_manager.add(PASS_CFG_SIMPLIFICATION) # external ::= 'extern' prototype
def ParseExtern(self):
g_llvm_pass_manager.initialize() self.Next() # eat extern.
return self.ParsePrototype()
# Install standard binary operators. # 1 is lowest possible precedence.
40 is the highest. g_binop_precedence['<'] = 10 # Top-Level parsing
g_binop_precedence['+'] = 20 g_binop_precedence['-'] = 20 def HandleDefinition(self):
g_binop_precedence['*'] = 40 self.Handle(self.ParseDefinition, 'Read a function definition:')
# Run the main "interpreter loop". while True: print 'ready>', try: raw def HandleExtern(self):
= raw_input() except KeyboardInterrupt: break self.Handle(self.ParseExtern, 'Read an extern:')
:: def HandleTopLevelExpression(self):
try:
parser = Parser(Tokenize(raw)) function = self.ParseTopLevelExpr().CodeGen()
while True: result = g_llvm_executor.run_function(function, [])
# top ::= definition | external | expression | EOF print 'Evaluated to:', result.as_real(Type.double())
if isinstance(parser.current, EOFToken): except Exception, e:
break print 'Error:', e
if isinstance(parser.current, DefToken): try:
parser.HandleDefinition() self.Next() # Skip for error recovery.
elif isinstance(parser.current, ExternToken): except:
parser.HandleExtern() pass
else:
parser.HandleTopLevelExpression() def Handle(self, function, message):
try:
# Print out all of the generated code. print '', g_llvm_module print message, function().CodeGen()
except Exception, e:
if **name** == '__main__': main() print 'Error:', e
try:
self.Next() # Skip for error recovery.
except:
pass
Main driver code.
-----------------
.. code-block:: python
def main():
# Set up the optimizer pipeline. Start with registering info about how the
# target lays out data structures.
g_llvm_pass_manager.add(g_llvm_executor.target_data)
# Do simple "peephole" optimizations and bit-twiddling optzns.
g_llvm_pass_manager.add(PASS_INSTRUCTION_COMBINING)
# Reassociate expressions.
g_llvm_pass_manager.add(PASS_REASSOCIATE)
# Eliminate Common SubExpressions.
g_llvm_pass_manager.add(PASS_GVN)
# Simplify the control flow graph (deleting unreachable blocks, etc).
g_llvm_pass_manager.add(PASS_CFG_SIMPLIFICATION)
g_llvm_pass_manager.initialize()
# Install standard binary operators.
# 1 is lowest possible precedence. 40 is the highest.
g_binop_precedence['<'] = 10
g_binop_precedence['+'] = 20
g_binop_precedence['-'] = 20
g_binop_precedence['*'] = 40
# Run the main "interpreter loop".
while True:
print 'ready>',
try:
raw = raw_input()
except KeyboardInterrupt:
break
parser = Parser(Tokenize(raw))
while True:
# top ::= definition | external | expression | EOF
if isinstance(parser.current, EOFToken):
break
if isinstance(parser.current, DefToken):
parser.HandleDefinition()
elif isinstance(parser.current, ExternToken):
parser.HandleExtern()
else:
parser.HandleTopLevelExpression()
# Print out all of the generated code.
print '', g_llvm_module
if __name__ == '__main__':
main()