Merge branch 'master' of github.com:llvmpy/llvmpy

This commit is contained in:
Siu Kwan Lam 2012-08-14 16:59:17 -07:00
commit b28a127d27
7 changed files with 142 additions and 144 deletions

View file

@ -26,7 +26,7 @@ We've tried to put this tutorial together in a way that makes chapters
easy to skip over if you are already familiar with or are uninterested
in the various pieces. The structure of the tutorial is:
- :ref:`Chapter 1 <chapter1anchor>`: **Introduction to the Kaleidoscope
- **`Chapter 1 <#language>`_: Introduction to the Kaleidoscope
language, and the definition of its Lexer** -- This shows where we
are going and the basic functionality that we want it to do. In order
to make this tutorial maximally understandable and hackable, we
@ -34,44 +34,44 @@ in the various pieces. The structure of the tutorial is:
parser generators. LLVM obviously works just fine with such tools,
feel free to use one if you prefer.
- `Chapter 2 <PythonLangImpl2.html>`_: **Implementing a Parser and
- **`Chapter 2 <PythonLangImpl2.html>`_: Implementing a Parser and
AST** -- With the lexer in place, we can talk about parsing
techniques and basic AST construction. This tutorial describes
recursive descent parsing and operator precedence parsing. Nothing in
Chapters 1 or 2 is LLVM-specific, the code doesn't even import the
LLVM modules at this point. :)
- `Chapter 3 <PythonLangImpl3.html>`_: **Code generation to LLVM IR**
- **`Chapter 3 <PythonLangImpl3.html>`_: Code generation to LLVM IR**
-- With the AST ready, we can show off how easy generation of LLVM IR
really is.
- `Chapter 4 <PythonLangImpl4.html>`_: **Adding JIT and Optimizer
- **`Chapter 4 <PythonLangImpl4.html>`_: Adding JIT and Optimizer
support** -- Because a lot of people are interested in using LLVM as
a JIT, we'll dive right into it and show you the 3 lines it takes to
add JIT support. LLVM is also useful in many other ways, but this is
one simple and "sexy" way to shows off its power. :)
- `Chapter 5 <PythonLangImpl5.html>`_: **Extending the Language:
- **`Chapter 5 <PythonLangImpl5.html>`_: Extending the Language:
Control Flow** -- With the language up and running, we show how to
extend it with control flow operations (if/then/else and a 'for'
loop). This gives us a chance to talk about simple SSA construction
and control flow.
- `Chapter 6 <PythonLangImpl6.html>`_: **Extending the Language:
- **`Chapter 6 <PythonLangImpl6.html>`_: Extending the Language:
User-defined Operators** -- This is a silly but fun chapter that
talks about extending the language to let the user program define
their own arbitrary unary and binary operators (with assignable
precedence!). This lets us build a significant piece of the
"language" as library routines.
- `Chapter 7 <PythonLangImpl7.html>`_: **Extending the Language:
- **`Chapter 7 <PythonLangImpl7.html>`_: Extending the Language:
Mutable Variables** -- This chapter talks about adding user-defined
local variables along with an assignment operator. The interesting
part about this is how easy and trivial it is to construct SSA form
in LLVM: no, LLVM does *not* require your front-end to construct SSA
form!
- `Chapter 8 <PythonLangImpl8.html>`_: **Conclusion and other useful
- **`Chapter 8 <PythonLangImpl8.html>`_: Conclusion and other useful
LLVM tidbits** -- This chapter wraps up the series by talking about
potential ways to extend the language, but also includes a bunch of
pointers to info about "special topics" like adding garbage
@ -94,10 +94,8 @@ play with languages!
--------------
.. _chapter1anchor:
The Basic Language
====================
The Basic Language
================================
This tutorial will be illustrated with a toy language that we'll call
"`Kaleidoscope <http://en.wikipedia.org/wiki/Kaleidoscope>`_\ " (derived
@ -154,7 +152,7 @@ Lets dive into the implementation of this language!
--------------
The Lexer
The Lexer
====================
When it comes to implementing a language, the first thing needed is the

View file

@ -753,19 +753,19 @@ external libraries at all for this.
pass
class IdentifierToken(object):
def **init**\ (self, name):
def __init__(self, name):
self.name = name
class NumberToken(object):
def **init**\ (self, value):
def __init__(self, value):
self.value = value
class CharacterToken(object):
def **init**\ (self, char):
def __init__(self, char):
self.char = char
def **eq**\ (self, other):
def __eq__(self, other):
return isinstance(other, CharacterToken) and self.char == other.char
def **ne**\ (self, other):
def __ne__(self, other):
return not self == other
# Regular expressions that tokens and comments of our language.
@ -815,24 +815,24 @@ external libraries at all for this.
# Expression class for numeric literals like "1.0".
class NumberExpressionNode(ExpressionNode):
def **init**\ (self, value):
def __init__(self, value):
self.value = value
# Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode):
def **init**\ (self, name):
def __init__(self, name):
self.name = name
# Expression class for a binary operator.
class BinaryOperatorExpressionNode(ExpressionNode):
def **init**\ (self, operator, left, right):
def __init__(self, operator, left, right):
self.operator = operator
self.left = left
self.right = right
# Expression class for function calls.
class CallExpressionNode(ExpressionNode):
def **init**\ (self, callee, args):
def __init__(self, callee, args):
self.callee = callee
self.args = args
@ -840,12 +840,12 @@ external libraries at all for this.
# and its argument names (thus implicitly the number of arguments the function
# takes).
class PrototypeNode(object):
def **init**\ (self, name, args):
def __init__(self, name, args):
self.name = name
self.args = args
# This class represents a function definition itself.
class FunctionNode(object): def **init**\ (self, prototype, body):
class FunctionNode(object): def __init__(self, prototype, body):
self.prototype = prototype self.body = body
Parser

View file

@ -5,7 +5,7 @@ Chapter 3: Code generation to LLVM IR
Written by `Chris Lattner <mailto:sabre@nondot.org>`_ and `Max
Shawabkeh <http://max99x.com>`_
Introduction # {#intro}
Introduction
=======================
Welcome to Chapter 3 of the `Implementing a language with
@ -25,7 +25,7 @@ page <http://www.mdevan.org/llvmpy/examples.html>`_
--------------
Code Generation Setup # {#basics}
Code Generation Setup
=================================
In order to generate LLVM IR, we want some simple setup to get started.
@ -37,14 +37,14 @@ First we define code generation methods in each AST node class:
# Expression class for numeric literals like
"1.0". class NumberExpressionNode(ExpressionNode):
def **init**\ (self, value): self.value = value
def __init__(self, value): self.value = value
def CodeGen(self): ...
# Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode):
def **init**\ (self, name): self.name = name
def __init__(self, name): self.name = name
def CodeGen(self): ...
@ -107,7 +107,7 @@ that this has already been done, and we'll just use it to emit code.
--------------
Expression Code Generation # {#exprs}
Expression Code Generation
=====================================
Generating LLVM code for expression nodes is very straightforward: less
@ -254,7 +254,7 @@ basic framework.
--------------
Function Code Generation # {#funcs}
Function Code Generation
===================================
Code generation for prototypes and functions must handle a number of
@ -479,7 +479,7 @@ this bug; see what you can come up with! Here is a testcase:
--------------
Driver Changes and Closing Thoughts # {#driver}
Driver Changes and Closing Thoughts
===============================================
For now, code generation to LLVM doesn't really get us much, except that
@ -584,7 +584,7 @@ running code!
--------------
Full Code Listing # {#code}
Full Code Listing
===========================
Here is the complete code listing for our running example, enhanced with
@ -623,15 +623,15 @@ need to `download <../download.html>`_ and
class ExternToken(object): pass
class IdentifierToken(object): def **init**\ (self, name): self.name =
class IdentifierToken(object): def __init__(self, name): self.name =
name
class NumberToken(object): def **init**\ (self, value): self.value =
class NumberToken(object): def __init__(self, value): self.value =
value
class CharacterToken(object): def **init**\ (self, char): self.char =
char def **eq**\ (self, other): return isinstance(other, CharacterToken)
and self.char == other.char def **ne**\ (self, other): return not self
class CharacterToken(object): def __init__(self, char): self.char =
char def __eq__(self, other): return isinstance(other, CharacterToken)
and self.char == other.char def __ne__(self, other): return not self
== other
# Regular expressions that tokens and comments of our language.
@ -682,14 +682,14 @@ need to `download <../download.html>`_ and
# Expression class for numeric literals like "1.0".
class NumberExpressionNode(ExpressionNode):
def **init**\ (self, value): self.value = value
def __init__(self, value): self.value = value
def CodeGen(self): return Constant.real(Type.double(), self.value)
# Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode):
def **init**\ (self, name): self.name = name
def __init__(self, name): self.name = name
def CodeGen(self): if self.name in g_named_values: return
g_named_values[self.name] else: raise RuntimeError('Unknown variable
@ -698,7 +698,7 @@ need to `download <../download.html>`_ and
# Expression class for a binary operator.
class BinaryOperatorExpressionNode(ExpressionNode):
def **init**\ (self, operator, left, right): self.operator = operator
def __init__(self, operator, left, right): self.operator = operator
self.left = left self.right = right
def CodeGen(self): left = self.left.CodeGen() right =
@ -722,7 +722,7 @@ need to `download <../download.html>`_ and
# Expression class for function calls.
class CallExpressionNode(ExpressionNode):
def **init**\ (self, callee, args): self.callee = callee self.args =
def __init__(self, callee, args): self.callee = callee self.args =
args
def CodeGen(self): # Look up the name in the global module table. callee
@ -743,7 +743,7 @@ need to `download <../download.html>`_ and
# takes).
class PrototypeNode(object):
def **init**\ (self, name, args): self.name = name self.args = args
def __init__(self, name, args): self.name = name self.args = args
def CodeGen(self): # Make the function type, eg. double(double,double).
funct_type = Type.function( Type.double(), [Type.double()] \*
@ -779,7 +779,7 @@ need to `download <../download.html>`_ and
# This class represents a function definition itself.
class FunctionNode(object):
def **init**\ (self, prototype, body): self.prototype = prototype
def __init__(self, prototype, body): self.prototype = prototype
self.body = body
def CodeGen(self): # Clear scope. g_named_values.clear()
@ -812,7 +812,7 @@ need to `download <../download.html>`_ and
class Parser(object):
def **init**\ (self, tokens, binop_precedence): self.tokens = tokens
def __init__(self, tokens, binop_precedence): self.tokens = tokens
self.binop_precedence = binop_precedence self.Next()
# Provide a simple token buffer. Parser.current is the current token the
@ -976,4 +976,4 @@ need to `download <../download.html>`_ and
# Print out all of the generated code. print '', g_llvm_module
if **name** == '**main**\ ': main()
if **name** == '__main__': main()

View file

@ -5,7 +5,7 @@ Chapter 4: Adding JIT and Optimizer Support
Written by `Chris Lattner <mailto:sabre@nondot.org>`_ and `Max
Shawabkeh <http://max99x.com>`_
Introduction # {#intro}
Introduction
=======================
Welcome to Chapter 4 of the `Implementing a language with
@ -18,7 +18,7 @@ code for the Kaleidoscope language.
--------------
Trivial Constant Folding # {#trivialconstfold}
Trivial Constant Folding
==============================================
Our demonstration for Chapter 3 is elegant and easy to extend.
@ -92,7 +92,7 @@ use, in the form of "passes".
--------------
LLVM Optimization Passes # {#optimizerpasses}
LLVM Optimization Passes
=============================================
LLVM provides many optimization passes, which do many different sorts of
@ -216,7 +216,7 @@ about executing it!
--------------
Adding a JIT Compiler # {#jit}
Adding a JIT Compiler
==============================
Code that is available in LLVM IR can have a wide variety of tools
@ -388,7 +388,7 @@ issues along the way.
--------------
Full Code Listing # {#code}
Full Code Listing
===========================
Here is the complete code listing for our running example, enhanced with
@ -434,15 +434,15 @@ the LLVM JIT and optimizer:
class ExternToken(object): pass
class IdentifierToken(object): def **init**\ (self, name): self.name =
class IdentifierToken(object): def __init__(self, name): self.name =
name
class NumberToken(object): def **init**\ (self, value): self.value =
class NumberToken(object): def __init__(self, value): self.value =
value
class CharacterToken(object): def **init**\ (self, char): self.char =
char def **eq**\ (self, other): return isinstance(other, CharacterToken)
and self.char == other.char def **ne**\ (self, other): return not self
class CharacterToken(object): def __init__(self, char): self.char =
char def __eq__(self, other): return isinstance(other, CharacterToken)
and self.char == other.char def __ne__(self, other): return not self
== other
# Regular expressions that tokens and comments of our language.
@ -493,14 +493,14 @@ the LLVM JIT and optimizer:
# Expression class for numeric literals like "1.0".
class NumberExpressionNode(ExpressionNode):
def **init**\ (self, value): self.value = value
def __init__(self, value): self.value = value
def CodeGen(self): return Constant.real(Type.double(), self.value)
# Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode):
def **init**\ (self, name): self.name = name
def __init__(self, name): self.name = name
def CodeGen(self): if self.name in g_named_values: return
g_named_values[self.name] else: raise RuntimeError('Unknown variable
@ -509,7 +509,7 @@ the LLVM JIT and optimizer:
# Expression class for a binary operator.
class BinaryOperatorExpressionNode(ExpressionNode):
def **init**\ (self, operator, left, right): self.operator = operator
def __init__(self, operator, left, right): self.operator = operator
self.left = left self.right = right
def CodeGen(self): left = self.left.CodeGen() right =
@ -533,7 +533,7 @@ the LLVM JIT and optimizer:
# Expression class for function calls.
class CallExpressionNode(ExpressionNode):
def **init**\ (self, callee, args): self.callee = callee self.args =
def __init__(self, callee, args): self.callee = callee self.args =
args
def CodeGen(self): # Look up the name in the global module table. callee
@ -554,7 +554,7 @@ the LLVM JIT and optimizer:
# takes).
class PrototypeNode(object):
def **init**\ (self, name, args): self.name = name self.args = args
def __init__(self, name, args): self.name = name self.args = args
def CodeGen(self): # Make the function type, eg. double(double,double).
funct_type = Type.function( Type.double(), [Type.double()] \*
@ -590,7 +590,7 @@ the LLVM JIT and optimizer:
# This class represents a function definition itself.
class FunctionNode(object):
def **init**\ (self, prototype, body): self.prototype = prototype
def __init__(self, prototype, body): self.prototype = prototype
self.body = body
def CodeGen(self): # Clear scope. g_named_values.clear()
@ -626,7 +626,7 @@ the LLVM JIT and optimizer:
class Parser(object):
def **init**\ (self, tokens, binop_precedence): self.tokens = tokens
def __init__(self, tokens, binop_precedence): self.tokens = tokens
self.binop_precedence = binop_precedence self.Next()
# Provide a simple token buffer. Parser.current is the current token the
@ -805,4 +805,4 @@ the LLVM JIT and optimizer:
# Print out all of the generated code. print '', g_llvm_module
if **name** == '**main**\ ': main()
if **name** == '__main__': main()

View file

@ -5,7 +5,7 @@ Chapter 5: Extending the Language: Control Flow
Written by `Chris Lattner <mailto:sabre@nondot.org>`_ and `Max
Shawabkeh <http://max99x.com>`_
Introduction # {#intro}
Introduction
=======================
Welcome to Chapter 5 of the `Implementing a language with
@ -21,7 +21,7 @@ extend Kaleidoscope to have an if/then/else expression plus a simple
--------------
If/Then/Else # {#ifthen}
If/Then/Else
========================
Extending Kaleidoscope to support if/then/else is quite straightforward.
@ -60,7 +60,7 @@ down.
Now that we know what we "want", let's break this down into its
constituent pieces.
Lexer Extensions for If/Then/Else ## {#iflexer}
Lexer Extensions for If/Then/Else
-----------------------------------------------
The lexer extensions are straightforward. First we add new token classes
@ -88,7 +88,7 @@ pretty simple stuff:
AST Extensions for If/Then/Else ## {#ifast}
AST Extensions for If/Then/Else
-------------------------------------------
To represent the new expression we add a new AST node for it:
@ -99,7 +99,7 @@ To represent the new expression we add a new AST node for it:
# Expression class for if/then/else. class
IfExpressionNode(ExpressionNode):
def **init**\ (self, condition, then_branch, else_branch):
def __init__(self, condition, then_branch, else_branch):
self.condition = condition self.then_branch = then_branch
self.else_branch = else_branch
@ -109,7 +109,7 @@ To represent the new expression we add a new AST node for it:
The AST node just has pointers to the various subexpressions.
Parser Extensions for If/Then/Else ## {#ifparser}
Parser Extensions for If/Then/Else
-------------------------------------------------
Now that we have the relevant tokens coming from the lexer and we have
@ -160,7 +160,7 @@ Next we hook it up as a primary expression:
LLVM IR for If/Then/Else ## {#ifir}
LLVM IR for If/Then/Else
-----------------------------------
Now that we have it parsing and building the AST, the final piece is
@ -260,7 +260,7 @@ really easy to generate the Phi node, so we choose to do it directly.
Okay, enough of the motivation and overview, lets generate code!
Code Generation for If/Then/Else ## {#ifcodegen}
Code Generation for If/Then/Else
------------------------------------------------
In order to generate code for this, we implement the ``Codegen`` method
@ -423,7 +423,7 @@ languages...
--------------
'for' Loop Expression # {#for}
'for' Loop Expression
==============================
Now that we know how to add basic control flow constructs to the
@ -456,7 +456,7 @@ the future when we have mutable variables, it will get more useful.
As before, lets talk about the changes that we need to Kaleidoscope to
support this.
Lexer Extensions for the 'for' Loop ## {#forlexer}
Lexer Extensions for the 'for' Loop
--------------------------------------------------
The lexer extensions are the same sort of thing as for if/then/else:
@ -490,7 +490,7 @@ The lexer extensions are the same sort of thing as for if/then/else:
AST Extensions for the 'for' Loop ## {#forast}
AST Extensions for the 'for' Loop
----------------------------------------------
The AST node is just as simple. It basically boils down to capturing the
@ -502,7 +502,7 @@ variable name and the constituent expressions in the node.
# Expression class for for/in. class
ForExpressionNode(ExpressionNode):
def **init**\ (self, loop_variable, start, end, step, body):
def __init__(self, loop_variable, start, end, step, body):
self.loop_variable = loop_variable self.start = start self.end = end
self.step = step self.body = body
@ -510,7 +510,7 @@ variable name and the constituent expressions in the node.
Parser Extensions for the 'for' Loop ## {#forparser}
Parser Extensions for the 'for' Loop
----------------------------------------------------
The parser code is also fairly standard. The only interesting thing here
@ -564,7 +564,7 @@ value to null in the AST node:
LLVM IR for the 'for' Loop ## {#forir}
LLVM IR for the 'for' Loop
--------------------------------------
Now we get to the good part: the LLVM IR we want to generate for this
@ -591,7 +591,7 @@ This loop contains all the same constructs we saw before: a phi node,
several expressions, and some basic blocks. Lets see how this fits
together.
Code Generation for the 'for' Loop ## {#forcodegen}
Code Generation for the 'for' Loop
---------------------------------------------------
The first part of Codegen is very simple: we just output the start
@ -788,7 +788,7 @@ operators <PythonLangImpl6.html>`_ to our poor innocent language.
--------------
Full Code Listing # {#code}
Full Code Listing
===========================
Here is the complete code listing for our running example, enhanced with
@ -835,15 +835,15 @@ the if/then/else and for expressions:
ThenToken(object): pass class ElseToken(object): pass class
ForToken(object): pass class InToken(object): pass
class IdentifierToken(object): def **init**\ (self, name): self.name =
class IdentifierToken(object): def __init__(self, name): self.name =
name
class NumberToken(object): def **init**\ (self, value): self.value =
class NumberToken(object): def __init__(self, value): self.value =
value
class CharacterToken(object): def **init**\ (self, char): self.char =
char def **eq**\ (self, other): return isinstance(other, CharacterToken)
and self.char == other.char def **ne**\ (self, other): return not self
class CharacterToken(object): def __init__(self, char): self.char =
char def __eq__(self, other): return isinstance(other, CharacterToken)
and self.char == other.char def __ne__(self, other): return not self
== other
# Regular expressions that tokens and comments of our language.
@ -904,14 +904,14 @@ the if/then/else and for expressions:
# Expression class for numeric literals like "1.0".
class NumberExpressionNode(ExpressionNode):
def **init**\ (self, value): self.value = value
def __init__(self, value): self.value = value
def CodeGen(self): return Constant.real(Type.double(), self.value)
# Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode):
def **init**\ (self, name): self.name = name
def __init__(self, name): self.name = name
def CodeGen(self): if self.name in g_named_values: return
g_named_values[self.name] else: raise RuntimeError('Unknown variable
@ -920,7 +920,7 @@ the if/then/else and for expressions:
# Expression class for a binary operator.
class BinaryOperatorExpressionNode(ExpressionNode):
def **init**\ (self, operator, left, right): self.operator = operator
def __init__(self, operator, left, right): self.operator = operator
self.left = left self.right = right
def CodeGen(self): left = self.left.CodeGen() right =
@ -944,7 +944,7 @@ the if/then/else and for expressions:
# Expression class for function calls.
class CallExpressionNode(ExpressionNode):
def **init**\ (self, callee, args): self.callee = callee self.args =
def __init__(self, callee, args): self.callee = callee self.args =
args
def CodeGen(self): # Look up the name in the global module table. callee
@ -963,7 +963,7 @@ the if/then/else and for expressions:
# Expression class for if/then/else.
class IfExpressionNode(ExpressionNode):
def **init**\ (self, condition, then_branch, else_branch):
def __init__(self, condition, then_branch, else_branch):
self.condition = condition self.then_branch = then_branch
self.else_branch = else_branch
@ -1014,7 +1014,7 @@ the if/then/else and for expressions:
# Expression class for for/in.
class ForExpressionNode(ExpressionNode):
def **init**\ (self, loop_variable, start, end, step, body):
def __init__(self, loop_variable, start, end, step, body):
self.loop_variable = loop_variable self.start = start self.end = end
self.step = step self.body = body
@ -1095,7 +1095,7 @@ the if/then/else and for expressions:
# takes).
class PrototypeNode(object):
def **init**\ (self, name, args): self.name = name self.args = args
def __init__(self, name, args): self.name = name self.args = args
def CodeGen(self): # Make the function type, eg. double(double,double).
funct_type = Type.function( Type.double(), [Type.double()] \*
@ -1131,7 +1131,7 @@ the if/then/else and for expressions:
# This class represents a function definition itself.
class FunctionNode(object):
def **init**\ (self, prototype, body): self.prototype = prototype
def __init__(self, prototype, body): self.prototype = prototype
self.body = body
def CodeGen(self): # Clear scope. g_named_values.clear()
@ -1167,7 +1167,7 @@ the if/then/else and for expressions:
class Parser(object):
def **init**\ (self, tokens, binop_precedence): self.tokens = tokens
def __init__(self, tokens, binop_precedence): self.tokens = tokens
self.binop_precedence = binop_precedence self.Next()
# Provide a simple token buffer. Parser.current is the current token the
@ -1408,4 +1408,4 @@ the if/then/else and for expressions:
# Print out all of the generated code. print '', g_llvm_module
if **name** == '**main**\ ': main()
if **name** == '__main__': main()

View file

@ -5,7 +5,7 @@ Chapter 6: Extending the Language: User-defined Operators
Written by `Chris Lattner <mailto:sabre@nondot.org>`_ and `Max
Shawabkeh <http://max99x.com>`_
Introduction # {#intro}
Introduction
=======================
Welcome to Chapter 6 of the `Implementing a language with
@ -27,7 +27,7 @@ At the end of this tutorial, we'll run through an example Kaleidoscope
application that `renders the Mandelbrot set <#example>`_. This gives an
example of what you can build with Kaleidoscope and its feature set.
User-defined Operators: the Idea # {#idea}
User-defined Operators: the Idea
==========================================
The "operator overloading" that we will add to Kaleidoscope is more
@ -77,7 +77,7 @@ operators.
--------------
User-defined Binary Operators # {#binary}
User-defined Binary Operators
=========================================
Adding support for user-defined binary operators is pretty simple with
@ -113,7 +113,7 @@ keywords:
implicitly the number of arguments the function # takes), as well as if
it is an operator. 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.precedence = precedence
@ -266,7 +266,7 @@ the previous framework we built for other operators. Adding unary
operators is a bit more challenging, because we don't have any framework
for it yet - let's see what it takes.
User-defined Unary Operators # {#unary}
User-defined Unary Operators
=======================================
Since we don't currently support unary operators in the Kaleidoscope
@ -280,7 +280,7 @@ that, we need an AST node:
# Expression class for a unary operator. class
UnaryExpressionNode(ExpressionNode):
def **init**\ (self, operator, operand): self.operator = operator
def __init__(self, operator, operand): self.operator = operator
self.operand = operand
def CodeGen(self): ...
@ -386,7 +386,7 @@ predefined operators.
--------------
Kicking the Tires # {#example}
Kicking the Tires
==============================
It is somewhat hard to believe, but with a few simple extensions we've
@ -674,7 +674,7 @@ front-end.
--------------
Full Code Listing # {#code}
Full Code Listing
===========================
Here is the complete code listing for our running example, enhanced with
@ -725,15 +725,15 @@ the if/then/else and for expressions:
ForToken(object): pass class InToken(object): pass class
BinaryToken(object): pass class UnaryToken(object): pass
class IdentifierToken(object): def **init**\ (self, name): self.name =
class IdentifierToken(object): def __init__(self, name): self.name =
name
class NumberToken(object): def **init**\ (self, value): self.value =
class NumberToken(object): def __init__(self, value): self.value =
value
class CharacterToken(object): def **init**\ (self, char): self.char =
char def **eq**\ (self, other): return isinstance(other, CharacterToken)
and self.char == other.char def **ne**\ (self, other): return not self
class CharacterToken(object): def __init__(self, char): self.char =
char def __eq__(self, other): return isinstance(other, CharacterToken)
and self.char == other.char def __ne__(self, other): return not self
== other
# Regular expressions that tokens and comments of our language.
@ -798,14 +798,14 @@ the if/then/else and for expressions:
# Expression class for numeric literals like "1.0".
class NumberExpressionNode(ExpressionNode):
def **init**\ (self, value): self.value = value
def __init__(self, value): self.value = value
def CodeGen(self): return Constant.real(Type.double(), self.value)
# Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode):
def **init**\ (self, name): self.name = name
def __init__(self, name): self.name = name
def CodeGen(self): if self.name in g_named_values: return
g_named_values[self.name] else: raise RuntimeError('Unknown variable
@ -814,7 +814,7 @@ the if/then/else and for expressions:
# Expression class for a binary operator.
class BinaryOperatorExpressionNode(ExpressionNode):
def **init**\ (self, operator, left, right): self.operator = operator
def __init__(self, operator, left, right): self.operator = operator
self.left = left self.right = right
def CodeGen(self): left = self.left.CodeGen() right =
@ -839,7 +839,7 @@ the if/then/else and for expressions:
# Expression class for function calls.
class CallExpressionNode(ExpressionNode):
def **init**\ (self, callee, args): self.callee = callee self.args =
def __init__(self, callee, args): self.callee = callee self.args =
args
def CodeGen(self): # Look up the name in the global module table. callee
@ -858,7 +858,7 @@ the if/then/else and for expressions:
# Expression class for if/then/else.
class IfExpressionNode(ExpressionNode):
def **init**\ (self, condition, then_branch, else_branch):
def __init__(self, condition, then_branch, else_branch):
self.condition = condition self.then_branch = then_branch
self.else_branch = else_branch
@ -909,7 +909,7 @@ the if/then/else and for expressions:
# Expression class for for/in.
class ForExpressionNode(ExpressionNode):
def **init**\ (self, loop_variable, start, end, step, body):
def __init__(self, loop_variable, start, end, step, body):
self.loop_variable = loop_variable self.start = start self.end = end
self.step = step self.body = body
@ -988,7 +988,7 @@ the if/then/else and for expressions:
# Expression class for a unary operator.
class UnaryExpressionNode(ExpressionNode):
def **init**\ (self, operator, operand): self.operator = operator
def __init__(self, operator, operand): self.operator = operator
self.operand = operand
def CodeGen(self): operand = self.operand.CodeGen() function =
@ -1000,7 +1000,7 @@ the if/then/else and for expressions:
# takes), as well as if it is an operator.
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.precedence = precedence
@ -1042,7 +1042,7 @@ the if/then/else and for expressions:
# This class represents a function definition itself.
class FunctionNode(object):
def **init**\ (self, prototype, body): self.prototype = prototype
def __init__(self, prototype, body): self.prototype = prototype
self.body = body
def CodeGen(self): # Clear scope. g_named_values.clear()
@ -1085,7 +1085,7 @@ the if/then/else and for expressions:
class Parser(object):
def **init**\ (self, tokens): self.tokens = tokens self.Next()
def __init__(self, tokens): self.tokens = tokens self.Next()
# Provide a simple token buffer. Parser.current is the current token the
# parser is looking at. Parser.Next() reads another token from the lexer
@ -1354,4 +1354,4 @@ the if/then/else and for expressions:
# Print out all of the generated code. print '', g_llvm_module
if **name** == '**main**\ ': main()
if **name** == '__main__': main()

View file

@ -5,7 +5,7 @@ Chapter 7: Extending the Language: Mutable Variables / SSA construction
Written by `Chris Lattner <mailto:sabre@nondot.org>`_ and `Max
Shawabkeh <http://max99x.com>`_
Introduction # {#intro}
Introduction
=======================
Welcome to Chapter 7 of the `Implementing a language with
@ -31,7 +31,7 @@ for your front-end to build SSA form: LLVM provides highly tuned and
well tested support for this, though the way it works is a bit
unexpected for some.
Why is this a hard problem? # {#why}
Why is this a hard problem?
====================================
To understand why mutable variables cause complexities in SSA
@ -80,7 +80,7 @@ it. However, SSA construction requires non-trivial algorithms and data
structures, so it is inconvenient and wasteful for every front-end to
have to reproduce this logic.
Memory in LLVM # {#memory}
Memory in LLVM
==========================
The 'trick' here is that while LLVM does require all register values to
@ -258,7 +258,7 @@ mutable variables now!
--------------
Mutable Variables in Kaleidoscope # {#kalvars}
Mutable Variables in Kaleidoscope
==============================================
Now that we know the sort of problem we want to tackle, lets see what
@ -299,7 +299,7 @@ operator, then extend Kaleidoscope to support new variable definitions.
--------------
Adjusting Existing Variables for Mutation # {#adjustments}
Adjusting Existing Variables for Mutation
==========================================================
The symbol table in Kaleidoscope is managed at code generation time by
@ -503,7 +503,7 @@ we'll add the assignment operator.
--------------
New Assignment Operator # {#assignment}
New Assignment Operator
=======================================
With our current framework, adding a new assignment operator is really
@ -587,7 +587,7 @@ own local variables. Let's add this next!
--------------
User-defined Local Variables # {#localvars}
User-defined Local Variables
===========================================
Adding var/in is just like any other other extensions we made to
@ -615,7 +615,7 @@ var/in, it looks like this:
# Expression class for var/in. class
VarExpressionNode(ExpressionNode):
def **init**\ (self, variables, body): self.variables = variables
def __init__(self, variables, body): self.variables = variables
self.body = body
def CodeGen(self): ...
@ -802,7 +802,7 @@ dominance frontier" computation anywhere in sight.
--------------
Full Code Listing # {#code}
Full Code Listing
===========================
Here is the complete code listing for our running example, enhanced with
@ -861,15 +861,15 @@ mutable variables and var/in support:
BinaryToken(object): pass class UnaryToken(object): pass class
VarToken(object): pass
class IdentifierToken(object): def **init**\ (self, name): self.name =
class IdentifierToken(object): def __init__(self, name): self.name =
name
class NumberToken(object): def **init**\ (self, value): self.value =
class NumberToken(object): def __init__(self, value): self.value =
value
class CharacterToken(object): def **init**\ (self, char): self.char =
char def **eq**\ (self, other): return isinstance(other, CharacterToken)
and self.char == other.char def **ne**\ (self, other): return not self
class CharacterToken(object): def __init__(self, char): self.char =
char def __eq__(self, other): return isinstance(other, CharacterToken)
and self.char == other.char def __ne__(self, other): return not self
== other
# Regular expressions that tokens and comments of our language.
@ -936,14 +936,14 @@ mutable variables and var/in support:
# Expression class for numeric literals like "1.0".
class NumberExpressionNode(ExpressionNode):
def **init**\ (self, value): self.value = value
def __init__(self, value): self.value = value
def CodeGen(self): return Constant.real(Type.double(), self.value)
# Expression class for referencing a variable, like "a".
class VariableExpressionNode(ExpressionNode):
def **init**\ (self, name): self.name = name
def __init__(self, name): self.name = name
def CodeGen(self): if self.name in g_named_values: return
g_llvm_builder.load(g_named_values[self.name], self.name) else:
@ -952,7 +952,7 @@ mutable variables and var/in support:
# Expression class for a binary operator.
class BinaryOperatorExpressionNode(ExpressionNode):
def **init**\ (self, operator, left, right): self.operator = operator
def __init__(self, operator, left, right): self.operator = operator
self.left = left self.right = right
def CodeGen(self): # A special case for '=' because we don't want to
@ -994,7 +994,7 @@ mutable variables and var/in support:
# Expression class for function calls.
class CallExpressionNode(ExpressionNode):
def **init**\ (self, callee, args): self.callee = callee self.args =
def __init__(self, callee, args): self.callee = callee self.args =
args
def CodeGen(self): # Look up the name in the global module table. callee
@ -1013,7 +1013,7 @@ mutable variables and var/in support:
# Expression class for if/then/else.
class IfExpressionNode(ExpressionNode):
def **init**\ (self, condition, then_branch, else_branch):
def __init__(self, condition, then_branch, else_branch):
self.condition = condition self.then_branch = then_branch
self.else_branch = else_branch
@ -1064,7 +1064,7 @@ mutable variables and var/in support:
# Expression class for for/in.
class ForExpressionNode(ExpressionNode):
def **init**\ (self, loop_variable, start, end, step, body):
def __init__(self, loop_variable, start, end, step, body):
self.loop_variable = loop_variable self.start = start self.end = end
self.step = step self.body = body
@ -1146,7 +1146,7 @@ mutable variables and var/in support:
# Expression class for a unary operator.
class UnaryExpressionNode(ExpressionNode):
def **init**\ (self, operator, operand): self.operator = operator
def __init__(self, operator, operand): self.operator = operator
self.operand = operand
def CodeGen(self): operand = self.operand.CodeGen() function =
@ -1156,7 +1156,7 @@ mutable variables and var/in support:
# Expression class for var/in.
class VarExpressionNode(ExpressionNode):
def **init**\ (self, variables, body): self.variables = variables
def __init__(self, variables, body): self.variables = variables
self.body = body
def CodeGen(self): old_bindings = {} function =
@ -1204,7 +1204,7 @@ mutable variables and var/in support:
# takes), as well as if it is an operator.
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.precedence = precedence
@ -1251,7 +1251,7 @@ mutable variables and var/in support:
# This class represents a function definition itself.
class FunctionNode(object):
def **init**\ (self, prototype, body): self.prototype = prototype
def __init__(self, prototype, body): self.prototype = prototype
self.body = body
def CodeGen(self): # Clear scope. g_named_values.clear()
@ -1297,7 +1297,7 @@ mutable variables and var/in support:
class Parser(object):
def **init**\ (self, tokens): self.tokens = tokens self.Next()
def __init__(self, tokens): self.tokens = tokens self.Next()
# Provide a simple token buffer. Parser.current is the current token the
# parser is looking at. Parser.Next() reads another token from the lexer
@ -1608,4 +1608,4 @@ mutable variables and var/in support:
# Print out all of the generated code. print '', g_llvm_module
if **name** == '**main**\ ': main()
if **name** == '__main__': main()