Finished editing PythonLangImpl5.rst

This commit is contained in:
Maggie Mari 2012-08-19 13:17:33 -05:00
commit cb7b778bfd

View file

@ -114,13 +114,13 @@ To represent the new expression we add a new AST node for it:
# Expression class for if/then/else. # Expression class for if/then/else.
class IfExpressionNode(ExpressionNode): class IfExpressionNode(ExpressionNode):
def __init__(self, condition, then_branch, else_branch): def __init__(self, condition, then_branch, else_branch):
self.condition = condition self.condition = condition
self.then_branch = then_branch self.then_branch = then_branch
self.else_branch = else_branch self.else_branch = else_branch
def CodeGen(self): def CodeGen(self):
... ...
@ -1257,7 +1257,8 @@ Parser
def __init__(self, tokens, binop_precedence): def __init__(self, tokens, binop_precedence):
self.tokens = tokens self.tokens = tokens
self.binop_precedence = binop_precedence self.Next() self.binop_precedence = binop_precedence
self.Next()
# Provide a simple token buffer. Parser.current is the current token the # Provide a simple token buffer. Parser.current is the current token the
# parser is looking at. Parser.Next() reads another token from the lexer and # parser is looking at. Parser.Next() reads another token from the lexer and
@ -1279,7 +1280,7 @@ Parser
self.Next() # eat identifier. self.Next() # eat identifier.
if self.current != CharacterToken('('): # Simple variable reference. if self.current != CharacterToken('('): # Simple variable reference.
return VariableExpressionNode(identifier_name) return VariableExpressionNode(identifier_name)
# Call. # Call.
self.Next() # eat '('. self.Next() # eat '('.
@ -1375,131 +1376,173 @@ Parser
return ForExpressionNode(loop_variable, start, end, step, body) return ForExpressionNode(loop_variable, start, end, step, body)
# primary ::= identifierexpr | numberexpr | parenexpr | ifexpr | # primary ::= identifierexpr | numberexpr | parenexpr | ifexpr | forexpr
forexpr def ParsePrimary(self): if isinstance(self.current, def ParsePrimary(self):
IdentifierToken): return self.ParseIdentifierExpr() elif if isinstance(self.current, IdentifierToken):
isinstance(self.current, NumberToken): return self.ParseNumberExpr() return self.ParseIdentifierExpr()
elif isinstance(self.current, IfToken): return self.ParseIfExpr() elif elif isinstance(self.current, NumberToken):
isinstance(self.current, ForToken): return self.ParseForExpr() elif return self.ParseNumberExpr()
self.current == CharacterToken('('): return self.ParseParenExpr() else: elif isinstance(self.current, IfToken):
raise RuntimeError('Unknown token when expecting an expression.') return self.ParseIfExpr()
elif isinstance(self.current, ForToken):
return self.ParseForExpr()
elif self.current == CharacterToken('('):
return self.ParseParenExpr()
else:
raise RuntimeError('Unknown token when expecting an expression.')
# binoprhs ::= (operator primary)* def ParseBinOpRHS(self, left, # binoprhs ::= (operator primary)*
left_precedence): # If this is a binary operator, find its precedence. def ParseBinOpRHS(self, left, left_precedence):
while True: precedence = self.GetCurrentTokenPrecedence() # If this is a binary operator, find its precedence.
while True:
precedence = self.GetCurrentTokenPrecedence()
:: # If this is a binary operator that binds at least as tightly as the
# current one, consume it; otherwise we are done.
if precedence < left_precedence:
return left
# If this is a binary operator that binds at least as tightly as the binary_operator = self.current.char
# current one, consume it; otherwise we are done. self.Next() # eat the operator.
if precedence < left_precedence:
return left
binary_operator = self.current.char # Parse the primary expression after the binary operator.
self.Next() # eat the operator. right = self.ParsePrimary()
# Parse the primary expression after the binary operator. # If binary_operator binds less tightly with right than the operator after
right = self.ParsePrimary() # right, let the pending operator take right as its left.
next_precedence = self.GetCurrentTokenPrecedence()
if precedence < next_precedence:
right = self.ParseBinOpRHS(right, precedence + 1)
# If binary_operator binds less tightly with right than the operator after # Merge left/right.
# right, let the pending operator take right as its left. left = BinaryOperatorExpressionNode(binary_operator, left, right)
next_precedence = self.GetCurrentTokenPrecedence()
if precedence < next_precedence:
right = self.ParseBinOpRHS(right, precedence + 1)
# Merge left/right. # expression ::= primary binoprhs
left = BinaryOperatorExpressionNode(binary_operator, left, right) def ParseExpression(self):
left = self.ParsePrimary()
return self.ParseBinOpRHS(left, 0)
# expression ::= primary binoprhs def ParseExpression(self): left = # prototype ::= id '(' id* ')'
self.ParsePrimary() return self.ParseBinOpRHS(left, 0) def ParsePrototype(self):
if not isinstance(self.current, IdentifierToken):
raise RuntimeError('Expected function name in prototype.')
# prototype ::= id '(' id* ')' def ParsePrototype(self): if not function_name = self.current.name
isinstance(self.current, IdentifierToken): raise RuntimeError('Expected self.Next() # eat function name.
function name in prototype.')
:: if self.current != CharacterToken('('):
raise RuntimeError('Expected "(" in prototype.')
self.Next() # eat '('.
function_name = self.current.name arg_names = []
self.Next() # eat function name. while isinstance(self.current, IdentifierToken):
arg_names.append(self.current.name)
self.Next()
if self.current != CharacterToken('('): if self.current != CharacterToken(')'):
raise RuntimeError('Expected "(" in prototype.') raise RuntimeError('Expected ")" in prototype.')
self.Next() # eat '('.
arg_names = [] # Success.
while isinstance(self.current, IdentifierToken): self.Next() # eat ')'.
arg_names.append(self.current.name)
self.Next()
if self.current != CharacterToken(')'): return PrototypeNode(function_name, arg_names)
raise RuntimeError('Expected ")" in prototype.')
# Success. # definition ::= 'def' prototype expression
self.Next() # eat ')'. def ParseDefinition(self):
self.Next() # eat def.
proto = self.ParsePrototype()
body = self.ParseExpression()
return FunctionNode(proto, body)
return PrototypeNode(function_name, arg_names) # toplevelexpr ::= expression
def ParseTopLevelExpr(self):
proto = PrototypeNode('', [])
return FunctionNode(proto, self.ParseExpression())
# definition ::= 'def' prototype expression def ParseDefinition(self): # external ::= 'extern' prototype
self.Next() # eat def. proto = self.ParsePrototype() body = def ParseExtern(self):
self.ParseExpression() return FunctionNode(proto, body) self.Next() # eat extern.
return self.ParsePrototype()
# toplevelexpr ::= expression def ParseTopLevelExpr(self): proto = # Top-Level parsing
PrototypeNode('', []) return FunctionNode(proto, self.ParseExpression()) def HandleDefinition(self):
self.Handle(self.ParseDefinition, 'Read a function definition:')
# external ::= 'extern' prototype def ParseExtern(self): self.Next() # def HandleExtern(self):
eat extern. return self.ParsePrototype() self.Handle(self.ParseExtern, 'Read an extern:')
# Top-Level parsing def HandleDefinition(self): def HandleTopLevelExpression(self):
self.Handle(self.ParseDefinition, 'Read a function definition:') try:
function = self.ParseTopLevelExpr().CodeGen()
result = g_llvm_executor.run_function(function, [])
print 'Evaluated to:', result.as_real(Type.double())
except Exception, e:
print 'Error:', e
try:
self.Next() # Skip for error recovery.
except:
pass
def HandleExtern(self): self.Handle(self.ParseExtern, 'Read an extern:') def Handle(self, function, message):
try:
print message, function().CodeGen()
except Exception, e:
print 'Error:', e
try:
self.Next() # Skip for error recovery.
except:
pass
def HandleTopLevelExpression(self): try: function = Main driver code.
self.ParseTopLevelExpr().CodeGen() result = -----------------
g_llvm_executor.run_function(function, []) print 'Evaluated to:',
result.as_real(Type.double()) except Exception, e: print 'Error:', e
try: self.Next() # Skip for error recovery. except: pass
def Handle(self, function, message): try: print message, .. code-block:: python
function().CodeGen() except Exception, e: print 'Error:', e try:
self.Next() # Skip for error recovery. except: pass
Main driver code. 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)
def main(): # Set up the optimizer pipeline. Start with registering info g_llvm_pass_manager.initialize()
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.
operator_precedence = {
'<': 10,
'+': 20,
'-': 20,
'*': 40
}
# Install standard binary operators. # 1 is lowest possible precedence. # Run the main "interpreter loop".
40 is the highest. operator_precedence = { '<': 10, '+': 20, '-': 20, while True:
'*': 40 } print 'ready>',
try:
raw = raw_input()
except KeyboardInterrupt:
break
# Run the main "interpreter loop". while True: print 'ready>', try: raw parser = Parser(Tokenize(raw), operator_precedence)
= raw_input() except KeyboardInterrupt: break 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
parser = Parser(Tokenize(raw), operator_precedence) if __name__ == '__main__':
while True: main()
# 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()