blob: c30eaedad12ce66576b13c1d118262341fea47db [file] [log] [blame]
Sean Silvad7fb3962012-12-05 00:26:32 +00001============================================================
2Kaleidoscope: Extending the Language: User-defined Operators
3============================================================
4
5.. contents::
6 :local:
7
Sean Silvad7fb3962012-12-05 00:26:32 +00008Chapter 6 Introduction
9======================
10
11Welcome to Chapter 6 of the "`Implementing a language with
12LLVM <index.html>`_" tutorial. At this point in our tutorial, we now
13have a fully functional language that is fairly minimal, but also
14useful. There is still one big problem with it, however. Our language
15doesn't have many useful operators (like division, logical negation, or
16even any comparisons besides less-than).
17
18This chapter of the tutorial takes a wild digression into adding
19user-defined operators to the simple and beautiful Kaleidoscope
20language. This digression now gives us a simple and ugly language in
21some ways, but also a powerful one at the same time. One of the great
22things about creating your own language is that you get to decide what
23is good or bad. In this tutorial we'll assume that it is okay to use
24this as a way to show some interesting parsing techniques.
25
26At the end of this tutorial, we'll run through an example Kaleidoscope
Alex Denisov596e9792015-12-15 20:50:29 +000027application that `renders the Mandelbrot set <#kicking-the-tires>`_. This gives an
Sean Silvad7fb3962012-12-05 00:26:32 +000028example of what you can build with Kaleidoscope and its feature set.
29
30User-defined Operators: the Idea
31================================
32
33The "operator overloading" that we will add to Kaleidoscope is more
34general than languages like C++. In C++, you are only allowed to
35redefine existing operators: you can't programatically change the
36grammar, introduce new operators, change precedence levels, etc. In this
37chapter, we will add this capability to Kaleidoscope, which will let the
38user round out the set of operators that are supported.
39
40The point of going into user-defined operators in a tutorial like this
41is to show the power and flexibility of using a hand-written parser.
42Thus far, the parser we have been implementing uses recursive descent
43for most parts of the grammar and operator precedence parsing for the
44expressions. See `Chapter 2 <LangImpl2.html>`_ for details. Without
45using operator precedence parsing, it would be very difficult to allow
46the programmer to introduce new operators into the grammar: the grammar
47is dynamically extensible as the JIT runs.
48
49The two specific features we'll add are programmable unary operators
50(right now, Kaleidoscope has no unary operators at all) as well as
51binary operators. An example of this is:
52
53::
54
55 # Logical unary not.
56 def unary!(v)
57 if v then
58 0
59 else
60 1;
61
62 # Define > with the same precedence as <.
63 def binary> 10 (LHS RHS)
64 RHS < LHS;
65
66 # Binary "logical or", (note that it does not "short circuit")
67 def binary| 5 (LHS RHS)
68 if LHS then
69 1
70 else if RHS then
71 1
72 else
73 0;
74
75 # Define = with slightly lower precedence than relationals.
76 def binary= 9 (LHS RHS)
77 !(LHS < RHS | LHS > RHS);
78
79Many languages aspire to being able to implement their standard runtime
80library in the language itself. In Kaleidoscope, we can implement
81significant parts of the language in the library!
82
83We will break down implementation of these features into two parts:
84implementing support for user-defined binary operators and adding unary
85operators.
86
87User-defined Binary Operators
88=============================
89
90Adding support for user-defined binary operators is pretty simple with
91our current framework. We'll first add support for the unary/binary
92keywords:
93
94.. code-block:: c++
95
96 enum Token {
97 ...
98 // operators
Lang Hames59b0da82015-08-19 18:15:58 +000099 tok_binary = -11,
100 tok_unary = -12
Sean Silvad7fb3962012-12-05 00:26:32 +0000101 };
102 ...
103 static int gettok() {
104 ...
Lang Hames59b0da82015-08-19 18:15:58 +0000105 if (IdentifierStr == "for")
106 return tok_for;
107 if (IdentifierStr == "in")
108 return tok_in;
109 if (IdentifierStr == "binary")
110 return tok_binary;
111 if (IdentifierStr == "unary")
112 return tok_unary;
Sean Silvad7fb3962012-12-05 00:26:32 +0000113 return tok_identifier;
114
115This just adds lexer support for the unary and binary keywords, like we
Alex Denisov596e9792015-12-15 20:50:29 +0000116did in `previous chapters <LangImpl5.html#lexer-extensions-for-if-then-else>`_. One nice thing
Sean Silvad7fb3962012-12-05 00:26:32 +0000117about our current AST, is that we represent binary operators with full
118generalisation by using their ASCII code as the opcode. For our extended
119operators, we'll use this same representation, so we don't need any new
120AST or parser support.
121
122On the other hand, we have to be able to represent the definitions of
123these new operators, in the "def binary\| 5" part of the function
124definition. In our grammar so far, the "name" for the function
125definition is parsed as the "prototype" production and into the
126``PrototypeAST`` AST node. To represent our new user-defined operators
127as prototypes, we have to extend the ``PrototypeAST`` AST node like
128this:
129
130.. code-block:: c++
131
132 /// PrototypeAST - This class represents the "prototype" for a function,
133 /// which captures its argument names as well as if it is an operator.
134 class PrototypeAST {
135 std::string Name;
136 std::vector<std::string> Args;
Lang Hames09bf4c12015-08-18 18:11:06 +0000137 bool IsOperator;
Sean Silvad7fb3962012-12-05 00:26:32 +0000138 unsigned Precedence; // Precedence if a binary op.
Lang Hames59b0da82015-08-19 18:15:58 +0000139
Sean Silvad7fb3962012-12-05 00:26:32 +0000140 public:
Lang Hames09bf4c12015-08-18 18:11:06 +0000141 PrototypeAST(const std::string &name, std::vector<std::string> Args,
142 bool IsOperator = false, unsigned Prec = 0)
143 : Name(name), Args(std::move(Args)), IsOperator(IsOperator),
144 Precedence(Prec) {}
Sean Silvad7fb3962012-12-05 00:26:32 +0000145
Lang Hames09bf4c12015-08-18 18:11:06 +0000146 bool isUnaryOp() const { return IsOperator && Args.size() == 1; }
147 bool isBinaryOp() const { return IsOperator && Args.size() == 2; }
Sean Silvad7fb3962012-12-05 00:26:32 +0000148
149 char getOperatorName() const {
150 assert(isUnaryOp() || isBinaryOp());
151 return Name[Name.size()-1];
152 }
153
154 unsigned getBinaryPrecedence() const { return Precedence; }
155
Lang Hames2d789c32015-08-26 03:07:41 +0000156 Function *codegen();
Sean Silvad7fb3962012-12-05 00:26:32 +0000157 };
158
159Basically, in addition to knowing a name for the prototype, we now keep
160track of whether it was an operator, and if it was, what precedence
161level the operator is at. The precedence is only used for binary
162operators (as you'll see below, it just doesn't apply for unary
163operators). Now that we have a way to represent the prototype for a
164user-defined operator, we need to parse it:
165
166.. code-block:: c++
167
168 /// prototype
169 /// ::= id '(' id* ')'
170 /// ::= binary LETTER number? (id, id)
Lang Hames09bf4c12015-08-18 18:11:06 +0000171 static std::unique_ptr<PrototypeAST> ParsePrototype() {
Sean Silvad7fb3962012-12-05 00:26:32 +0000172 std::string FnName;
173
174 unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
175 unsigned BinaryPrecedence = 30;
176
177 switch (CurTok) {
178 default:
Lang Hamesf9878c52016-03-25 17:33:32 +0000179 return LogErrorP("Expected function name in prototype");
Sean Silvad7fb3962012-12-05 00:26:32 +0000180 case tok_identifier:
181 FnName = IdentifierStr;
182 Kind = 0;
183 getNextToken();
184 break;
185 case tok_binary:
186 getNextToken();
187 if (!isascii(CurTok))
Lang Hamesf9878c52016-03-25 17:33:32 +0000188 return LogErrorP("Expected binary operator");
Sean Silvad7fb3962012-12-05 00:26:32 +0000189 FnName = "binary";
190 FnName += (char)CurTok;
191 Kind = 2;
192 getNextToken();
193
194 // Read the precedence if present.
195 if (CurTok == tok_number) {
196 if (NumVal < 1 || NumVal > 100)
Lang Hamesf9878c52016-03-25 17:33:32 +0000197 return LogErrorP("Invalid precedecnce: must be 1..100");
Sean Silvad7fb3962012-12-05 00:26:32 +0000198 BinaryPrecedence = (unsigned)NumVal;
199 getNextToken();
200 }
201 break;
202 }
203
204 if (CurTok != '(')
Lang Hamesf9878c52016-03-25 17:33:32 +0000205 return LogErrorP("Expected '(' in prototype");
Sean Silvad7fb3962012-12-05 00:26:32 +0000206
207 std::vector<std::string> ArgNames;
208 while (getNextToken() == tok_identifier)
209 ArgNames.push_back(IdentifierStr);
210 if (CurTok != ')')
Lang Hamesf9878c52016-03-25 17:33:32 +0000211 return LogErrorP("Expected ')' in prototype");
Sean Silvad7fb3962012-12-05 00:26:32 +0000212
213 // success.
214 getNextToken(); // eat ')'.
215
216 // Verify right number of names for operator.
217 if (Kind && ArgNames.size() != Kind)
Lang Hamesf9878c52016-03-25 17:33:32 +0000218 return LogErrorP("Invalid number of operands for operator");
Sean Silvad7fb3962012-12-05 00:26:32 +0000219
Lang Hames59b0da82015-08-19 18:15:58 +0000220 return llvm::make_unique<PrototypeAST>(FnName, std::move(ArgNames), Kind != 0,
221 BinaryPrecedence);
Sean Silvad7fb3962012-12-05 00:26:32 +0000222 }
223
224This is all fairly straightforward parsing code, and we have already
225seen a lot of similar code in the past. One interesting part about the
226code above is the couple lines that set up ``FnName`` for binary
227operators. This builds names like "binary@" for a newly defined "@"
228operator. This then takes advantage of the fact that symbol names in the
229LLVM symbol table are allowed to have any character in them, including
230embedded nul characters.
231
232The next interesting thing to add, is codegen support for these binary
233operators. Given our current structure, this is a simple addition of a
234default case for our existing binary operator node:
235
236.. code-block:: c++
237
Lang Hames2d789c32015-08-26 03:07:41 +0000238 Value *BinaryExprAST::codegen() {
239 Value *L = LHS->codegen();
240 Value *R = RHS->codegen();
Lang Hames59b0da82015-08-19 18:15:58 +0000241 if (!L || !R)
242 return nullptr;
Sean Silvad7fb3962012-12-05 00:26:32 +0000243
244 switch (Op) {
Lang Hames59b0da82015-08-19 18:15:58 +0000245 case '+':
246 return Builder.CreateFAdd(L, R, "addtmp");
247 case '-':
248 return Builder.CreateFSub(L, R, "subtmp");
249 case '*':
250 return Builder.CreateFMul(L, R, "multmp");
Sean Silvad7fb3962012-12-05 00:26:32 +0000251 case '<':
252 L = Builder.CreateFCmpULT(L, R, "cmptmp");
253 // Convert bool 0/1 to double 0.0 or 1.0
Mehdi Amini03b42e42016-04-14 21:59:01 +0000254 return Builder.CreateUIToFP(L, Type::getDoubleTy(LLVMContext),
Sean Silvad7fb3962012-12-05 00:26:32 +0000255 "booltmp");
Lang Hames59b0da82015-08-19 18:15:58 +0000256 default:
257 break;
Sean Silvad7fb3962012-12-05 00:26:32 +0000258 }
259
260 // If it wasn't a builtin binary operator, it must be a user defined one. Emit
261 // a call to it.
Lang Hames59b0da82015-08-19 18:15:58 +0000262 Function *F = TheModule->getFunction(std::string("binary") + Op);
Sean Silvad7fb3962012-12-05 00:26:32 +0000263 assert(F && "binary operator not found!");
264
265 Value *Ops[2] = { L, R };
266 return Builder.CreateCall(F, Ops, "binop");
267 }
268
269As you can see above, the new code is actually really simple. It just
270does a lookup for the appropriate operator in the symbol table and
271generates a function call to it. Since user-defined operators are just
272built as normal functions (because the "prototype" boils down to a
273function with the right name) everything falls into place.
274
275The final piece of code we are missing, is a bit of top-level magic:
276
277.. code-block:: c++
278
Lang Hames2d789c32015-08-26 03:07:41 +0000279 Function *FunctionAST::codegen() {
Sean Silvad7fb3962012-12-05 00:26:32 +0000280 NamedValues.clear();
281
Lang Hames2d789c32015-08-26 03:07:41 +0000282 Function *TheFunction = Proto->codegen();
Lang Hames59b0da82015-08-19 18:15:58 +0000283 if (!TheFunction)
284 return nullptr;
Sean Silvad7fb3962012-12-05 00:26:32 +0000285
286 // If this is an operator, install it.
287 if (Proto->isBinaryOp())
288 BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
289
290 // Create a new basic block to start insertion into.
Mehdi Amini03b42e42016-04-14 21:59:01 +0000291 BasicBlock *BB = BasicBlock::Create(LLVMContext, "entry", TheFunction);
Sean Silvad7fb3962012-12-05 00:26:32 +0000292 Builder.SetInsertPoint(BB);
293
Lang Hames2d789c32015-08-26 03:07:41 +0000294 if (Value *RetVal = Body->codegen()) {
Sean Silvad7fb3962012-12-05 00:26:32 +0000295 ...
296
297Basically, before codegening a function, if it is a user-defined
298operator, we register it in the precedence table. This allows the binary
299operator parsing logic we already have in place to handle it. Since we
300are working on a fully-general operator precedence parser, this is all
301we need to do to "extend the grammar".
302
303Now we have useful user-defined binary operators. This builds a lot on
304the previous framework we built for other operators. Adding unary
305operators is a bit more challenging, because we don't have any framework
306for it yet - lets see what it takes.
307
308User-defined Unary Operators
309============================
310
311Since we don't currently support unary operators in the Kaleidoscope
312language, we'll need to add everything to support them. Above, we added
313simple support for the 'unary' keyword to the lexer. In addition to
314that, we need an AST node:
315
316.. code-block:: c++
317
318 /// UnaryExprAST - Expression class for a unary operator.
319 class UnaryExprAST : public ExprAST {
320 char Opcode;
Lang Hames09bf4c12015-08-18 18:11:06 +0000321 std::unique_ptr<ExprAST> Operand;
Lang Hames59b0da82015-08-19 18:15:58 +0000322
Sean Silvad7fb3962012-12-05 00:26:32 +0000323 public:
Lang Hames09bf4c12015-08-18 18:11:06 +0000324 UnaryExprAST(char Opcode, std::unique_ptr<ExprAST> Operand)
325 : Opcode(Opcode), Operand(std::move(Operand)) {}
Lang Hames2d789c32015-08-26 03:07:41 +0000326 virtual Value *codegen();
Sean Silvad7fb3962012-12-05 00:26:32 +0000327 };
328
329This AST node is very simple and obvious by now. It directly mirrors the
330binary operator AST node, except that it only has one child. With this,
331we need to add the parsing logic. Parsing a unary operator is pretty
332simple: we'll add a new function to do it:
333
334.. code-block:: c++
335
336 /// unary
337 /// ::= primary
338 /// ::= '!' unary
Lang Hames09bf4c12015-08-18 18:11:06 +0000339 static std::unique_ptr<ExprAST> ParseUnary() {
Sean Silvad7fb3962012-12-05 00:26:32 +0000340 // If the current token is not an operator, it must be a primary expr.
341 if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
342 return ParsePrimary();
343
344 // If this is a unary operator, read it.
345 int Opc = CurTok;
346 getNextToken();
Lang Hames09bf4c12015-08-18 18:11:06 +0000347 if (auto Operand = ParseUnary())
348 return llvm::unique_ptr<UnaryExprAST>(Opc, std::move(Operand));
349 return nullptr;
Sean Silvad7fb3962012-12-05 00:26:32 +0000350 }
351
352The grammar we add is pretty straightforward here. If we see a unary
353operator when parsing a primary operator, we eat the operator as a
354prefix and parse the remaining piece as another unary operator. This
355allows us to handle multiple unary operators (e.g. "!!x"). Note that
356unary operators can't have ambiguous parses like binary operators can,
357so there is no need for precedence information.
358
359The problem with this function, is that we need to call ParseUnary from
360somewhere. To do this, we change previous callers of ParsePrimary to
361call ParseUnary instead:
362
363.. code-block:: c++
364
365 /// binoprhs
366 /// ::= ('+' unary)*
Lang Hames09bf4c12015-08-18 18:11:06 +0000367 static std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec,
368 std::unique_ptr<ExprAST> LHS) {
Sean Silvad7fb3962012-12-05 00:26:32 +0000369 ...
370 // Parse the unary expression after the binary operator.
Lang Hames09bf4c12015-08-18 18:11:06 +0000371 auto RHS = ParseUnary();
Lang Hames59b0da82015-08-19 18:15:58 +0000372 if (!RHS)
373 return nullptr;
Sean Silvad7fb3962012-12-05 00:26:32 +0000374 ...
375 }
376 /// expression
377 /// ::= unary binoprhs
378 ///
Lang Hames09bf4c12015-08-18 18:11:06 +0000379 static std::unique_ptr<ExprAST> ParseExpression() {
380 auto LHS = ParseUnary();
Lang Hames59b0da82015-08-19 18:15:58 +0000381 if (!LHS)
382 return nullptr;
Sean Silvad7fb3962012-12-05 00:26:32 +0000383
Lang Hames09bf4c12015-08-18 18:11:06 +0000384 return ParseBinOpRHS(0, std::move(LHS));
Sean Silvad7fb3962012-12-05 00:26:32 +0000385 }
386
387With these two simple changes, we are now able to parse unary operators
388and build the AST for them. Next up, we need to add parser support for
389prototypes, to parse the unary operator prototype. We extend the binary
390operator code above with:
391
392.. code-block:: c++
393
394 /// prototype
395 /// ::= id '(' id* ')'
396 /// ::= binary LETTER number? (id, id)
397 /// ::= unary LETTER (id)
Lang Hames09bf4c12015-08-18 18:11:06 +0000398 static std::unique_ptr<PrototypeAST> ParsePrototype() {
Sean Silvad7fb3962012-12-05 00:26:32 +0000399 std::string FnName;
400
401 unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
402 unsigned BinaryPrecedence = 30;
403
404 switch (CurTok) {
405 default:
Lang Hamesf9878c52016-03-25 17:33:32 +0000406 return LogErrorP("Expected function name in prototype");
Sean Silvad7fb3962012-12-05 00:26:32 +0000407 case tok_identifier:
408 FnName = IdentifierStr;
409 Kind = 0;
410 getNextToken();
411 break;
412 case tok_unary:
413 getNextToken();
414 if (!isascii(CurTok))
Lang Hamesf9878c52016-03-25 17:33:32 +0000415 return LogErrorP("Expected unary operator");
Sean Silvad7fb3962012-12-05 00:26:32 +0000416 FnName = "unary";
417 FnName += (char)CurTok;
418 Kind = 1;
419 getNextToken();
420 break;
421 case tok_binary:
422 ...
423
424As with binary operators, we name unary operators with a name that
425includes the operator character. This assists us at code generation
426time. Speaking of, the final piece we need to add is codegen support for
427unary operators. It looks like this:
428
429.. code-block:: c++
430
Lang Hames2d789c32015-08-26 03:07:41 +0000431 Value *UnaryExprAST::codegen() {
432 Value *OperandV = Operand->codegen();
Lang Hames59b0da82015-08-19 18:15:58 +0000433 if (!OperandV)
434 return nullptr;
Sean Silvad7fb3962012-12-05 00:26:32 +0000435
436 Function *F = TheModule->getFunction(std::string("unary")+Opcode);
Lang Hames59b0da82015-08-19 18:15:58 +0000437 if (!F)
Lang Hamesf9878c52016-03-25 17:33:32 +0000438 return LogErrorV("Unknown unary operator");
Sean Silvad7fb3962012-12-05 00:26:32 +0000439
440 return Builder.CreateCall(F, OperandV, "unop");
441 }
442
443This code is similar to, but simpler than, the code for binary
444operators. It is simpler primarily because it doesn't need to handle any
445predefined operators.
446
447Kicking the Tires
448=================
449
450It is somewhat hard to believe, but with a few simple extensions we've
451covered in the last chapters, we have grown a real-ish language. With
452this, we can do a lot of interesting things, including I/O, math, and a
453bunch of other things. For example, we can now add a nice sequencing
454operator (printd is defined to print out the specified value and a
455newline):
456
457::
458
459 ready> extern printd(x);
460 Read extern:
461 declare double @printd(double)
462
463 ready> def binary : 1 (x y) 0; # Low-precedence operator that ignores operands.
464 ..
465 ready> printd(123) : printd(456) : printd(789);
466 123.000000
467 456.000000
468 789.000000
469 Evaluated to 0.000000
470
471We can also define a bunch of other "primitive" operations, such as:
472
473::
474
475 # Logical unary not.
476 def unary!(v)
477 if v then
478 0
479 else
480 1;
481
482 # Unary negate.
483 def unary-(v)
484 0-v;
485
486 # Define > with the same precedence as <.
487 def binary> 10 (LHS RHS)
488 RHS < LHS;
489
490 # Binary logical or, which does not short circuit.
491 def binary| 5 (LHS RHS)
492 if LHS then
493 1
494 else if RHS then
495 1
496 else
497 0;
498
499 # Binary logical and, which does not short circuit.
500 def binary& 6 (LHS RHS)
501 if !LHS then
502 0
503 else
504 !!RHS;
505
506 # Define = with slightly lower precedence than relationals.
507 def binary = 9 (LHS RHS)
508 !(LHS < RHS | LHS > RHS);
509
510 # Define ':' for sequencing: as a low-precedence operator that ignores operands
511 # and just returns the RHS.
512 def binary : 1 (x y) y;
513
514Given the previous if/then/else support, we can also define interesting
515functions for I/O. For example, the following prints out a character
516whose "density" reflects the value passed in: the lower the value, the
517denser the character:
518
519::
520
521 ready>
522
523 extern putchard(char)
524 def printdensity(d)
525 if d > 8 then
526 putchard(32) # ' '
527 else if d > 4 then
528 putchard(46) # '.'
529 else if d > 2 then
530 putchard(43) # '+'
531 else
532 putchard(42); # '*'
533 ...
534 ready> printdensity(1): printdensity(2): printdensity(3):
535 printdensity(4): printdensity(5): printdensity(9):
536 putchard(10);
537 **++.
538 Evaluated to 0.000000
539
540Based on these simple primitive operations, we can start to define more
541interesting things. For example, here's a little function that solves
542for the number of iterations it takes a function in the complex plane to
543converge:
544
545::
546
547 # Determine whether the specific location diverges.
548 # Solve for z = z^2 + c in the complex plane.
Hans Wennborg1d8b31b2016-06-14 16:05:12 +0000549 def mandelconverger(real imag iters creal cimag)
Sean Silvad7fb3962012-12-05 00:26:32 +0000550 if iters > 255 | (real*real + imag*imag > 4) then
551 iters
552 else
Hans Wennborg1d8b31b2016-06-14 16:05:12 +0000553 mandelconverger(real*real - imag*imag + creal,
Sean Silvad7fb3962012-12-05 00:26:32 +0000554 2*real*imag + cimag,
555 iters+1, creal, cimag);
556
557 # Return the number of iterations required for the iteration to escape
Hans Wennborg1d8b31b2016-06-14 16:05:12 +0000558 def mandelconverge(real imag)
559 mandelconverger(real, imag, 0, real, imag);
Sean Silvad7fb3962012-12-05 00:26:32 +0000560
561This "``z = z2 + c``" function is a beautiful little creature that is
562the basis for computation of the `Mandelbrot
563Set <http://en.wikipedia.org/wiki/Mandelbrot_set>`_. Our
564``mandelconverge`` function returns the number of iterations that it
565takes for a complex orbit to escape, saturating to 255. This is not a
566very useful function by itself, but if you plot its value over a
567two-dimensional plane, you can see the Mandelbrot set. Given that we are
568limited to using putchard here, our amazing graphical output is limited,
569but we can whip together something using the density plotter above:
570
571::
572
Hans Wennborg1d8b31b2016-06-14 16:05:12 +0000573 # Compute and plot the mandelbrot set with the specified 2 dimensional range
Sean Silvad7fb3962012-12-05 00:26:32 +0000574 # info.
575 def mandelhelp(xmin xmax xstep ymin ymax ystep)
576 for y = ymin, y < ymax, ystep in (
577 (for x = xmin, x < xmax, xstep in
Hans Wennborg1d8b31b2016-06-14 16:05:12 +0000578 printdensity(mandelconverge(x,y)))
Sean Silvad7fb3962012-12-05 00:26:32 +0000579 : putchard(10)
580 )
581
582 # mandel - This is a convenient helper function for plotting the mandelbrot set
583 # from the specified position with the specified Magnification.
584 def mandel(realstart imagstart realmag imagmag)
585 mandelhelp(realstart, realstart+realmag*78, realmag,
586 imagstart, imagstart+imagmag*40, imagmag);
587
Hans Wennborg1d8b31b2016-06-14 16:05:12 +0000588Given this, we can try plotting out the mandelbrot set! Lets try it out:
Sean Silvad7fb3962012-12-05 00:26:32 +0000589
590::
591
592 ready> mandel(-2.3, -1.3, 0.05, 0.07);
593 *******************************+++++++++++*************************************
594 *************************+++++++++++++++++++++++*******************************
595 **********************+++++++++++++++++++++++++++++****************************
596 *******************+++++++++++++++++++++.. ...++++++++*************************
597 *****************++++++++++++++++++++++.... ...+++++++++***********************
598 ***************+++++++++++++++++++++++..... ...+++++++++*********************
599 **************+++++++++++++++++++++++.... ....+++++++++********************
600 *************++++++++++++++++++++++...... .....++++++++*******************
601 ************+++++++++++++++++++++....... .......+++++++******************
602 ***********+++++++++++++++++++.... ... .+++++++*****************
603 **********+++++++++++++++++....... .+++++++****************
604 *********++++++++++++++........... ...+++++++***************
605 ********++++++++++++............ ...++++++++**************
606 ********++++++++++... .......... .++++++++**************
607 *******+++++++++..... .+++++++++*************
608 *******++++++++...... ..+++++++++*************
609 *******++++++....... ..+++++++++*************
610 *******+++++...... ..+++++++++*************
611 *******.... .... ...+++++++++*************
612 *******.... . ...+++++++++*************
613 *******+++++...... ...+++++++++*************
614 *******++++++....... ..+++++++++*************
615 *******++++++++...... .+++++++++*************
616 *******+++++++++..... ..+++++++++*************
617 ********++++++++++... .......... .++++++++**************
618 ********++++++++++++............ ...++++++++**************
619 *********++++++++++++++.......... ...+++++++***************
620 **********++++++++++++++++........ .+++++++****************
621 **********++++++++++++++++++++.... ... ..+++++++****************
622 ***********++++++++++++++++++++++....... .......++++++++*****************
623 ************+++++++++++++++++++++++...... ......++++++++******************
624 **************+++++++++++++++++++++++.... ....++++++++********************
625 ***************+++++++++++++++++++++++..... ...+++++++++*********************
626 *****************++++++++++++++++++++++.... ...++++++++***********************
627 *******************+++++++++++++++++++++......++++++++*************************
628 *********************++++++++++++++++++++++.++++++++***************************
629 *************************+++++++++++++++++++++++*******************************
630 ******************************+++++++++++++************************************
631 *******************************************************************************
632 *******************************************************************************
633 *******************************************************************************
634 Evaluated to 0.000000
635 ready> mandel(-2, -1, 0.02, 0.04);
636 **************************+++++++++++++++++++++++++++++++++++++++++++++++++++++
637 ***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++
638 *********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
639 *******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
640 *****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.....
641 ***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........
642 **************++++++++++++++++++++++++++++++++++++++++++++++++++++++...........
643 ************+++++++++++++++++++++++++++++++++++++++++++++++++++++..............
644 ***********++++++++++++++++++++++++++++++++++++++++++++++++++........ .
645 **********++++++++++++++++++++++++++++++++++++++++++++++.............
646 ********+++++++++++++++++++++++++++++++++++++++++++..................
647 *******+++++++++++++++++++++++++++++++++++++++.......................
648 ******+++++++++++++++++++++++++++++++++++...........................
649 *****++++++++++++++++++++++++++++++++............................
650 *****++++++++++++++++++++++++++++...............................
651 ****++++++++++++++++++++++++++...... .........................
652 ***++++++++++++++++++++++++......... ...... ...........
653 ***++++++++++++++++++++++............
654 **+++++++++++++++++++++..............
655 **+++++++++++++++++++................
656 *++++++++++++++++++.................
657 *++++++++++++++++............ ...
658 *++++++++++++++..............
659 *+++....++++................
660 *.......... ...........
661 *
662 *.......... ...........
663 *+++....++++................
664 *++++++++++++++..............
665 *++++++++++++++++............ ...
666 *++++++++++++++++++.................
667 **+++++++++++++++++++................
668 **+++++++++++++++++++++..............
669 ***++++++++++++++++++++++............
670 ***++++++++++++++++++++++++......... ...... ...........
671 ****++++++++++++++++++++++++++...... .........................
672 *****++++++++++++++++++++++++++++...............................
673 *****++++++++++++++++++++++++++++++++............................
674 ******+++++++++++++++++++++++++++++++++++...........................
675 *******+++++++++++++++++++++++++++++++++++++++.......................
676 ********+++++++++++++++++++++++++++++++++++++++++++..................
677 Evaluated to 0.000000
678 ready> mandel(-0.9, -1.4, 0.02, 0.03);
679 *******************************************************************************
680 *******************************************************************************
681 *******************************************************************************
682 **********+++++++++++++++++++++************************************************
683 *+++++++++++++++++++++++++++++++++++++++***************************************
684 +++++++++++++++++++++++++++++++++++++++++++++**********************************
685 ++++++++++++++++++++++++++++++++++++++++++++++++++*****************************
686 ++++++++++++++++++++++++++++++++++++++++++++++++++++++*************************
687 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++**********************
688 +++++++++++++++++++++++++++++++++.........++++++++++++++++++*******************
689 +++++++++++++++++++++++++++++++.... ......+++++++++++++++++++****************
690 +++++++++++++++++++++++++++++....... ........+++++++++++++++++++**************
691 ++++++++++++++++++++++++++++........ ........++++++++++++++++++++************
692 +++++++++++++++++++++++++++......... .. ...+++++++++++++++++++++**********
693 ++++++++++++++++++++++++++........... ....++++++++++++++++++++++********
694 ++++++++++++++++++++++++............. .......++++++++++++++++++++++******
695 +++++++++++++++++++++++............. ........+++++++++++++++++++++++****
696 ++++++++++++++++++++++........... ..........++++++++++++++++++++++***
697 ++++++++++++++++++++........... .........++++++++++++++++++++++*
698 ++++++++++++++++++............ ...........++++++++++++++++++++
699 ++++++++++++++++............... .............++++++++++++++++++
700 ++++++++++++++................. ...............++++++++++++++++
701 ++++++++++++.................. .................++++++++++++++
702 +++++++++.................. .................+++++++++++++
703 ++++++........ . ......... ..++++++++++++
704 ++............ ...... ....++++++++++
705 .............. ...++++++++++
706 .............. ....+++++++++
707 .............. .....++++++++
708 ............. ......++++++++
709 ........... .......++++++++
710 ......... ........+++++++
711 ......... ........+++++++
712 ......... ....+++++++
713 ........ ...+++++++
714 ....... ...+++++++
715 ....+++++++
716 .....+++++++
717 ....+++++++
718 ....+++++++
719 ....+++++++
720 Evaluated to 0.000000
721 ready> ^D
722
723At this point, you may be starting to realize that Kaleidoscope is a
724real and powerful language. It may not be self-similar :), but it can be
725used to plot things that are!
726
727With this, we conclude the "adding user-defined operators" chapter of
728the tutorial. We have successfully augmented our language, adding the
729ability to extend the language in the library, and we have shown how
730this can be used to build a simple but interesting end-user application
731in Kaleidoscope. At this point, Kaleidoscope can build a variety of
732applications that are functional and can call functions with
733side-effects, but it can't actually define and mutate a variable itself.
734
735Strikingly, variable mutation is an important feature of some languages,
736and it is not at all obvious how to `add support for mutable
737variables <LangImpl7.html>`_ without having to add an "SSA construction"
738phase to your front-end. In the next chapter, we will describe how you
739can add variable mutation without building SSA in your front-end.
740
741Full Code Listing
742=================
743
744Here is the complete code listing for our running example, enhanced with
745the if/then/else and for expressions.. To build this example, use:
746
747.. code-block:: bash
748
749 # Compile
Eric Christophera8c6a0a2015-01-08 19:07:01 +0000750 clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy
Sean Silvad7fb3962012-12-05 00:26:32 +0000751 # Run
752 ./toy
753
754On some platforms, you will need to specify -rdynamic or
755-Wl,--export-dynamic when linking. This ensures that symbols defined in
756the main executable are exported to the dynamic linker and so are
757available for symbol resolution at run time. This is not needed if you
758compile your support code into a shared library, although doing that
759will cause problems on Windows.
760
761Here is the code:
762
Logan Chien855b17d2013-06-08 09:03:03 +0000763.. literalinclude:: ../../examples/Kaleidoscope/Chapter6/toy.cpp
764 :language: c++
Sean Silvad7fb3962012-12-05 00:26:32 +0000765
766`Next: Extending the language: mutable variables / SSA
767construction <LangImpl7.html>`_
768