Merge branch 'master' of github.com:llvmpy/llvmpy
This commit is contained in:
commit
b28a127d27
7 changed files with 142 additions and 144 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue