mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-31 09:25:42 +00:00
many edits, patch by Kelly Wilson!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44157 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -41,15 +41,16 @@ Variables / SSA Construction</li>
|
||||
|
||||
<p>Welcome to Chapter 6 of the "<a href="index.html">Implementing a language
|
||||
with LLVM</a>" tutorial. At this point in our tutorial, we now have a fully
|
||||
functional language that is fairly minimal, but also useful. One big problem
|
||||
with it though is that it doesn't have many useful operators (like division,
|
||||
logical negation, or even any comparisons other than less-than.</p>
|
||||
functional language that is fairly minimal, but also useful. There
|
||||
is still one big problem with it, however. Our language doesn't have many
|
||||
useful operators (like division, logical negation, or even any comparisons
|
||||
besides less-than).</p>
|
||||
|
||||
<p>This chapter of the tutorial takes a wild digression into adding user-defined
|
||||
operators to the simple and beautiful Kaleidoscope language, giving us a
|
||||
simple and ugly language in some ways, but also a powerful one at the same time.
|
||||
operators to the simple and beautiful Kaleidoscope language. This digression now gives
|
||||
us a simple and ugly language in some ways, but also a powerful one at the same time.
|
||||
One of the great things about creating your own language is that you get to
|
||||
decide what is good or bad. In this tutorial we'll assume that it is okay and
|
||||
decide what is good or bad. In this tutorial we'll assume that it is okay to
|
||||
use this as a way to show some interesting parsing techniques.</p>
|
||||
|
||||
<p>At the end of this tutorial, we'll run through an example Kaleidoscope
|
||||
@@ -73,8 +74,8 @@ capability to Kaleidoscope, which will let the user round out the set of
|
||||
operators that are supported.</p>
|
||||
|
||||
<p>The point of going into user-defined operators in a tutorial like this is to
|
||||
show the power and flexibility of using a hand-written parser. The parser we
|
||||
are using so far is using recursive descent for most parts of the grammar, and
|
||||
show the power and flexibility of using a hand-written parser. Thus far, the parser
|
||||
we have been implementing uses recursive descent for most parts of the grammar and
|
||||
operator precedence parsing for the expressions. See <a
|
||||
href="LangImpl2.html">Chapter 2</a> for details. Without using operator
|
||||
precedence parsing, it would be very difficult to allow the programmer to
|
||||
@@ -152,12 +153,12 @@ static int gettok() {
|
||||
|
||||
<p>This just adds lexer support for the unary and binary keywords, like we
|
||||
did in <a href="LangImpl5.html#iflexer">previous chapters</a>. One nice thing
|
||||
about our current AST is that we represent binary operators fully generally
|
||||
with their ASCII code as the opcode. For our extended operators, we'll use the
|
||||
about our current AST, is that we represent binary operators with full generalisation
|
||||
by using their ASCII code as the opcode. For our extended operators, we'll use this
|
||||
same representation, so we don't need any new AST or parser support.</p>
|
||||
|
||||
<p>On the other hand, we have to be able to represent the definitions of these
|
||||
new operators, in the "def binary| 5" part of the function definition. In the
|
||||
new operators, in the "def binary| 5" part of the function definition. In our
|
||||
grammar so far, the "name" for the function definition is parsed as the
|
||||
"prototype" production and into the <tt>PrototypeAST</tt> AST node. To
|
||||
represent our new user-defined operators as prototypes, we have to extend
|
||||
@@ -257,14 +258,14 @@ static PrototypeAST *ParsePrototype() {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>This is all fairly straight-forward parsing code, and we have already seen
|
||||
a lot of similar code in the past. One interesting piece of this is the part
|
||||
that sets up <tt>FnName</tt> for binary operators. This builds names like
|
||||
"binary@" for a newly defined "@" operator. This takes advantage of the fact
|
||||
that symbol names in the LLVM symbol table are allowed to have any character in
|
||||
them, even including embedded nul characters.</p>
|
||||
<p>This is all fairly straightforward parsing code, and we have already seen
|
||||
a lot of similar code in the past. One interesting part about the code above is
|
||||
the couple lines that set up <tt>FnName</tt> for binary operators. This builds names
|
||||
like "binary@" for a newly defined "@" operator. This then takes advantage of the
|
||||
fact that symbol names in the LLVM symbol table are allowed to have any character in
|
||||
them, including embedded nul characters.</p>
|
||||
|
||||
<p>The next interesting piece is codegen support for these binary operators.
|
||||
<p>The next interesting thing to add, is codegen support for these binary operators.
|
||||
Given our current structure, this is a simple addition of a default case for our
|
||||
existing binary operator node:</p>
|
||||
|
||||
@@ -301,10 +302,10 @@ Value *BinaryExprAST::Codegen() {
|
||||
<p>As you can see above, the new code is actually really simple. It just does
|
||||
a lookup for the appropriate operator in the symbol table and generates a
|
||||
function call to it. Since user-defined operators are just built as normal
|
||||
functions (because the "prototype" boils down into a function with the right
|
||||
functions (because the "prototype" boils down to a function with the right
|
||||
name) everything falls into place.</p>
|
||||
|
||||
<p>The final missing piece is a bit of top level magic, here:</p>
|
||||
<p>The final piece of code we are missing, is a bit of top level magic:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@@ -330,10 +331,9 @@ Function *FunctionAST::Codegen() {
|
||||
|
||||
<p>Basically, before codegening a function, if it is a user-defined operator, we
|
||||
register it in the precedence table. This allows the binary operator parsing
|
||||
logic we already have to handle it. Since it is a fully-general operator
|
||||
precedence parser, this is all we need to do to "extend the grammar".</p>
|
||||
logic we already have in place to handle it. Since we are working on a fully-general operator precedence parser, this is all we need to do to "extend the grammar".</p>
|
||||
|
||||
<p>With that, we have useful user-defined binary operators. This builds a lot
|
||||
<p>Now we have useful user-defined binary operators. This builds a lot
|
||||
on 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 - lets
|
||||
see what it takes.</p>
|
||||
@@ -347,7 +347,7 @@ see what it takes.</p>
|
||||
<div class="doc_text">
|
||||
|
||||
<p>Since we don't currently support unary operators in the Kaleidoscope
|
||||
language, we'll need to add everything for them. Above, we added simple
|
||||
language, we'll need to add everything to support them. Above, we added simple
|
||||
support for the 'unary' keyword to the lexer. In addition to that, we need an
|
||||
AST node:</p>
|
||||
|
||||
@@ -390,14 +390,14 @@ static ExprAST *ParseUnary() {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>The grammar we add is pretty straight-forward here. If we see a unary
|
||||
<p>The grammar we add is pretty straightforward here. If we see a unary
|
||||
operator when parsing a primary operator, we eat the operator as a prefix and
|
||||
parse the remaining piece as another unary operator. This allows us to handle
|
||||
multiple unary operators (e.g. "!!x"). Note that unary operators can't have
|
||||
ambiguous parses like binary operators can, so there is no need for precedence
|
||||
information.</p>
|
||||
|
||||
<p>The problem with the above is that we need to call ParseUnary from somewhere.
|
||||
<p>The problem with this function, is that we need to call ParseUnary from somewhere.
|
||||
To do this, we change previous callers of ParsePrimary to call ParseUnary
|
||||
instead:</p>
|
||||
|
||||
@@ -424,7 +424,7 @@ static ExprAST *ParseExpression() {
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>With these two simple changes, we now parse unary operators and build the
|
||||
<p>With these two simple changes, we are now able to parse unary operators and build the
|
||||
AST for them. Next up, we need to add parser support for prototypes, to parse
|
||||
the unary operator prototype. We extend the binary operator code above
|
||||
with:</p>
|
||||
@@ -587,7 +587,7 @@ Evaluated to 0.000000
|
||||
|
||||
<p>Based on these simple primitive operations, we can start to define more
|
||||
interesting things. For example, here's a little function that solves for the
|
||||
number of iterations it takes for a function in the complex plane to
|
||||
number of iterations it takes a function in the complex plane to
|
||||
converge:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
@@ -779,8 +779,8 @@ and powerful language. It may not be self-similar :), but it can be used to
|
||||
plot things that are!</p>
|
||||
|
||||
<p>With this, we conclude the "adding user-defined operators" chapter of the
|
||||
tutorial. We successfully extended our language with the ability to extend the
|
||||
language in the library, and showed how this can be used to build a simple but
|
||||
tutorial. We have successfully augmented our language, adding the ability to extend the
|
||||
language in the library, and we have shown how this can be used to build a simple but
|
||||
interesting end-user application in Kaleidoscope. At this point, Kaleidoscope
|
||||
can build a variety of applications that are functional and can call functions
|
||||
with side-effects, but it can't actually define and mutate a variable itself.
|
||||
@@ -790,7 +790,7 @@ with side-effects, but it can't actually define and mutate a variable itself.
|
||||
languages, and it is not at all obvious how to <a href="LangImpl7.html">add
|
||||
support for mutable variables</a> without having to add an "SSA construction"
|
||||
phase to your front-end. In the next chapter, we will describe how you can
|
||||
add this without building SSA in your front-end.</p>
|
||||
add variable mutation without building SSA in your front-end.</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
Reference in New Issue
Block a user