1f4a2713aSLionel Sambuc============================================================ 2f4a2713aSLionel SambucKaleidoscope: Extending the Language: User-defined Operators 3f4a2713aSLionel Sambuc============================================================ 4f4a2713aSLionel Sambuc 5f4a2713aSLionel Sambuc.. contents:: 6f4a2713aSLionel Sambuc :local: 7f4a2713aSLionel Sambuc 8f4a2713aSLionel SambucChapter 6 Introduction 9f4a2713aSLionel Sambuc====================== 10f4a2713aSLionel Sambuc 11f4a2713aSLionel SambucWelcome to Chapter 6 of the "`Implementing a language with 12f4a2713aSLionel SambucLLVM <index.html>`_" tutorial. At this point in our tutorial, we now 13f4a2713aSLionel Sambuchave a fully functional language that is fairly minimal, but also 14f4a2713aSLionel Sambucuseful. There is still one big problem with it, however. Our language 15f4a2713aSLionel Sambucdoesn't have many useful operators (like division, logical negation, or 16f4a2713aSLionel Sambuceven any comparisons besides less-than). 17f4a2713aSLionel Sambuc 18f4a2713aSLionel SambucThis chapter of the tutorial takes a wild digression into adding 19f4a2713aSLionel Sambucuser-defined operators to the simple and beautiful Kaleidoscope 20f4a2713aSLionel Sambuclanguage. This digression now gives us a simple and ugly language in 21f4a2713aSLionel Sambucsome ways, but also a powerful one at the same time. One of the great 22f4a2713aSLionel Sambucthings about creating your own language is that you get to decide what 23f4a2713aSLionel Sambucis good or bad. In this tutorial we'll assume that it is okay to use 24f4a2713aSLionel Sambucthis as a way to show some interesting parsing techniques. 25f4a2713aSLionel Sambuc 26f4a2713aSLionel SambucAt the end of this tutorial, we'll run through an example Kaleidoscope 27f4a2713aSLionel Sambucapplication that `renders the Mandelbrot set <#example>`_. This gives an 28f4a2713aSLionel Sambucexample of what you can build with Kaleidoscope and its feature set. 29f4a2713aSLionel Sambuc 30f4a2713aSLionel SambucUser-defined Operators: the Idea 31f4a2713aSLionel Sambuc================================ 32f4a2713aSLionel Sambuc 33f4a2713aSLionel SambucThe "operator overloading" that we will add to Kaleidoscope is more 34f4a2713aSLionel Sambucgeneral than languages like C++. In C++, you are only allowed to 35f4a2713aSLionel Sambucredefine existing operators: you can't programatically change the 36f4a2713aSLionel Sambucgrammar, introduce new operators, change precedence levels, etc. In this 37f4a2713aSLionel Sambucchapter, we will add this capability to Kaleidoscope, which will let the 38f4a2713aSLionel Sambucuser round out the set of operators that are supported. 39f4a2713aSLionel Sambuc 40f4a2713aSLionel SambucThe point of going into user-defined operators in a tutorial like this 41f4a2713aSLionel Sambucis to show the power and flexibility of using a hand-written parser. 42f4a2713aSLionel SambucThus far, the parser we have been implementing uses recursive descent 43f4a2713aSLionel Sambucfor most parts of the grammar and operator precedence parsing for the 44f4a2713aSLionel Sambucexpressions. See `Chapter 2 <LangImpl2.html>`_ for details. Without 45f4a2713aSLionel Sambucusing operator precedence parsing, it would be very difficult to allow 46f4a2713aSLionel Sambucthe programmer to introduce new operators into the grammar: the grammar 47f4a2713aSLionel Sambucis dynamically extensible as the JIT runs. 48f4a2713aSLionel Sambuc 49f4a2713aSLionel SambucThe two specific features we'll add are programmable unary operators 50f4a2713aSLionel Sambuc(right now, Kaleidoscope has no unary operators at all) as well as 51f4a2713aSLionel Sambucbinary operators. An example of this is: 52f4a2713aSLionel Sambuc 53f4a2713aSLionel Sambuc:: 54f4a2713aSLionel Sambuc 55f4a2713aSLionel Sambuc # Logical unary not. 56f4a2713aSLionel Sambuc def unary!(v) 57f4a2713aSLionel Sambuc if v then 58f4a2713aSLionel Sambuc 0 59f4a2713aSLionel Sambuc else 60f4a2713aSLionel Sambuc 1; 61f4a2713aSLionel Sambuc 62f4a2713aSLionel Sambuc # Define > with the same precedence as <. 63f4a2713aSLionel Sambuc def binary> 10 (LHS RHS) 64f4a2713aSLionel Sambuc RHS < LHS; 65f4a2713aSLionel Sambuc 66f4a2713aSLionel Sambuc # Binary "logical or", (note that it does not "short circuit") 67f4a2713aSLionel Sambuc def binary| 5 (LHS RHS) 68f4a2713aSLionel Sambuc if LHS then 69f4a2713aSLionel Sambuc 1 70f4a2713aSLionel Sambuc else if RHS then 71f4a2713aSLionel Sambuc 1 72f4a2713aSLionel Sambuc else 73f4a2713aSLionel Sambuc 0; 74f4a2713aSLionel Sambuc 75f4a2713aSLionel Sambuc # Define = with slightly lower precedence than relationals. 76f4a2713aSLionel Sambuc def binary= 9 (LHS RHS) 77f4a2713aSLionel Sambuc !(LHS < RHS | LHS > RHS); 78f4a2713aSLionel Sambuc 79f4a2713aSLionel SambucMany languages aspire to being able to implement their standard runtime 80f4a2713aSLionel Sambuclibrary in the language itself. In Kaleidoscope, we can implement 81f4a2713aSLionel Sambucsignificant parts of the language in the library! 82f4a2713aSLionel Sambuc 83f4a2713aSLionel SambucWe will break down implementation of these features into two parts: 84f4a2713aSLionel Sambucimplementing support for user-defined binary operators and adding unary 85f4a2713aSLionel Sambucoperators. 86f4a2713aSLionel Sambuc 87f4a2713aSLionel SambucUser-defined Binary Operators 88f4a2713aSLionel Sambuc============================= 89f4a2713aSLionel Sambuc 90f4a2713aSLionel SambucAdding support for user-defined binary operators is pretty simple with 91f4a2713aSLionel Sambucour current framework. We'll first add support for the unary/binary 92f4a2713aSLionel Sambuckeywords: 93f4a2713aSLionel Sambuc 94f4a2713aSLionel Sambuc.. code-block:: c++ 95f4a2713aSLionel Sambuc 96f4a2713aSLionel Sambuc enum Token { 97f4a2713aSLionel Sambuc ... 98f4a2713aSLionel Sambuc // operators 99f4a2713aSLionel Sambuc tok_binary = -11, tok_unary = -12 100f4a2713aSLionel Sambuc }; 101f4a2713aSLionel Sambuc ... 102f4a2713aSLionel Sambuc static int gettok() { 103f4a2713aSLionel Sambuc ... 104f4a2713aSLionel Sambuc if (IdentifierStr == "for") return tok_for; 105f4a2713aSLionel Sambuc if (IdentifierStr == "in") return tok_in; 106f4a2713aSLionel Sambuc if (IdentifierStr == "binary") return tok_binary; 107f4a2713aSLionel Sambuc if (IdentifierStr == "unary") return tok_unary; 108f4a2713aSLionel Sambuc return tok_identifier; 109f4a2713aSLionel Sambuc 110f4a2713aSLionel SambucThis just adds lexer support for the unary and binary keywords, like we 111f4a2713aSLionel Sambucdid in `previous chapters <LangImpl5.html#iflexer>`_. One nice thing 112f4a2713aSLionel Sambucabout our current AST, is that we represent binary operators with full 113f4a2713aSLionel Sambucgeneralisation by using their ASCII code as the opcode. For our extended 114f4a2713aSLionel Sambucoperators, we'll use this same representation, so we don't need any new 115f4a2713aSLionel SambucAST or parser support. 116f4a2713aSLionel Sambuc 117f4a2713aSLionel SambucOn the other hand, we have to be able to represent the definitions of 118f4a2713aSLionel Sambucthese new operators, in the "def binary\| 5" part of the function 119f4a2713aSLionel Sambucdefinition. In our grammar so far, the "name" for the function 120f4a2713aSLionel Sambucdefinition is parsed as the "prototype" production and into the 121f4a2713aSLionel Sambuc``PrototypeAST`` AST node. To represent our new user-defined operators 122f4a2713aSLionel Sambucas prototypes, we have to extend the ``PrototypeAST`` AST node like 123f4a2713aSLionel Sambucthis: 124f4a2713aSLionel Sambuc 125f4a2713aSLionel Sambuc.. code-block:: c++ 126f4a2713aSLionel Sambuc 127f4a2713aSLionel Sambuc /// PrototypeAST - This class represents the "prototype" for a function, 128f4a2713aSLionel Sambuc /// which captures its argument names as well as if it is an operator. 129f4a2713aSLionel Sambuc class PrototypeAST { 130f4a2713aSLionel Sambuc std::string Name; 131f4a2713aSLionel Sambuc std::vector<std::string> Args; 132f4a2713aSLionel Sambuc bool isOperator; 133f4a2713aSLionel Sambuc unsigned Precedence; // Precedence if a binary op. 134f4a2713aSLionel Sambuc public: 135f4a2713aSLionel Sambuc PrototypeAST(const std::string &name, const std::vector<std::string> &args, 136f4a2713aSLionel Sambuc bool isoperator = false, unsigned prec = 0) 137f4a2713aSLionel Sambuc : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} 138f4a2713aSLionel Sambuc 139f4a2713aSLionel Sambuc bool isUnaryOp() const { return isOperator && Args.size() == 1; } 140f4a2713aSLionel Sambuc bool isBinaryOp() const { return isOperator && Args.size() == 2; } 141f4a2713aSLionel Sambuc 142f4a2713aSLionel Sambuc char getOperatorName() const { 143f4a2713aSLionel Sambuc assert(isUnaryOp() || isBinaryOp()); 144f4a2713aSLionel Sambuc return Name[Name.size()-1]; 145f4a2713aSLionel Sambuc } 146f4a2713aSLionel Sambuc 147f4a2713aSLionel Sambuc unsigned getBinaryPrecedence() const { return Precedence; } 148f4a2713aSLionel Sambuc 149f4a2713aSLionel Sambuc Function *Codegen(); 150f4a2713aSLionel Sambuc }; 151f4a2713aSLionel Sambuc 152f4a2713aSLionel SambucBasically, in addition to knowing a name for the prototype, we now keep 153f4a2713aSLionel Sambuctrack of whether it was an operator, and if it was, what precedence 154f4a2713aSLionel Sambuclevel the operator is at. The precedence is only used for binary 155f4a2713aSLionel Sambucoperators (as you'll see below, it just doesn't apply for unary 156f4a2713aSLionel Sambucoperators). Now that we have a way to represent the prototype for a 157f4a2713aSLionel Sambucuser-defined operator, we need to parse it: 158f4a2713aSLionel Sambuc 159f4a2713aSLionel Sambuc.. code-block:: c++ 160f4a2713aSLionel Sambuc 161f4a2713aSLionel Sambuc /// prototype 162f4a2713aSLionel Sambuc /// ::= id '(' id* ')' 163f4a2713aSLionel Sambuc /// ::= binary LETTER number? (id, id) 164f4a2713aSLionel Sambuc static PrototypeAST *ParsePrototype() { 165f4a2713aSLionel Sambuc std::string FnName; 166f4a2713aSLionel Sambuc 167f4a2713aSLionel Sambuc unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. 168f4a2713aSLionel Sambuc unsigned BinaryPrecedence = 30; 169f4a2713aSLionel Sambuc 170f4a2713aSLionel Sambuc switch (CurTok) { 171f4a2713aSLionel Sambuc default: 172f4a2713aSLionel Sambuc return ErrorP("Expected function name in prototype"); 173f4a2713aSLionel Sambuc case tok_identifier: 174f4a2713aSLionel Sambuc FnName = IdentifierStr; 175f4a2713aSLionel Sambuc Kind = 0; 176f4a2713aSLionel Sambuc getNextToken(); 177f4a2713aSLionel Sambuc break; 178f4a2713aSLionel Sambuc case tok_binary: 179f4a2713aSLionel Sambuc getNextToken(); 180f4a2713aSLionel Sambuc if (!isascii(CurTok)) 181f4a2713aSLionel Sambuc return ErrorP("Expected binary operator"); 182f4a2713aSLionel Sambuc FnName = "binary"; 183f4a2713aSLionel Sambuc FnName += (char)CurTok; 184f4a2713aSLionel Sambuc Kind = 2; 185f4a2713aSLionel Sambuc getNextToken(); 186f4a2713aSLionel Sambuc 187f4a2713aSLionel Sambuc // Read the precedence if present. 188f4a2713aSLionel Sambuc if (CurTok == tok_number) { 189f4a2713aSLionel Sambuc if (NumVal < 1 || NumVal > 100) 190f4a2713aSLionel Sambuc return ErrorP("Invalid precedecnce: must be 1..100"); 191f4a2713aSLionel Sambuc BinaryPrecedence = (unsigned)NumVal; 192f4a2713aSLionel Sambuc getNextToken(); 193f4a2713aSLionel Sambuc } 194f4a2713aSLionel Sambuc break; 195f4a2713aSLionel Sambuc } 196f4a2713aSLionel Sambuc 197f4a2713aSLionel Sambuc if (CurTok != '(') 198f4a2713aSLionel Sambuc return ErrorP("Expected '(' in prototype"); 199f4a2713aSLionel Sambuc 200f4a2713aSLionel Sambuc std::vector<std::string> ArgNames; 201f4a2713aSLionel Sambuc while (getNextToken() == tok_identifier) 202f4a2713aSLionel Sambuc ArgNames.push_back(IdentifierStr); 203f4a2713aSLionel Sambuc if (CurTok != ')') 204f4a2713aSLionel Sambuc return ErrorP("Expected ')' in prototype"); 205f4a2713aSLionel Sambuc 206f4a2713aSLionel Sambuc // success. 207f4a2713aSLionel Sambuc getNextToken(); // eat ')'. 208f4a2713aSLionel Sambuc 209f4a2713aSLionel Sambuc // Verify right number of names for operator. 210f4a2713aSLionel Sambuc if (Kind && ArgNames.size() != Kind) 211f4a2713aSLionel Sambuc return ErrorP("Invalid number of operands for operator"); 212f4a2713aSLionel Sambuc 213f4a2713aSLionel Sambuc return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); 214f4a2713aSLionel Sambuc } 215f4a2713aSLionel Sambuc 216f4a2713aSLionel SambucThis is all fairly straightforward parsing code, and we have already 217f4a2713aSLionel Sambucseen a lot of similar code in the past. One interesting part about the 218f4a2713aSLionel Sambuccode above is the couple lines that set up ``FnName`` for binary 219f4a2713aSLionel Sambucoperators. This builds names like "binary@" for a newly defined "@" 220f4a2713aSLionel Sambucoperator. This then takes advantage of the fact that symbol names in the 221f4a2713aSLionel SambucLLVM symbol table are allowed to have any character in them, including 222f4a2713aSLionel Sambucembedded nul characters. 223f4a2713aSLionel Sambuc 224f4a2713aSLionel SambucThe next interesting thing to add, is codegen support for these binary 225f4a2713aSLionel Sambucoperators. Given our current structure, this is a simple addition of a 226f4a2713aSLionel Sambucdefault case for our existing binary operator node: 227f4a2713aSLionel Sambuc 228f4a2713aSLionel Sambuc.. code-block:: c++ 229f4a2713aSLionel Sambuc 230f4a2713aSLionel Sambuc Value *BinaryExprAST::Codegen() { 231f4a2713aSLionel Sambuc Value *L = LHS->Codegen(); 232f4a2713aSLionel Sambuc Value *R = RHS->Codegen(); 233f4a2713aSLionel Sambuc if (L == 0 || R == 0) return 0; 234f4a2713aSLionel Sambuc 235f4a2713aSLionel Sambuc switch (Op) { 236f4a2713aSLionel Sambuc case '+': return Builder.CreateFAdd(L, R, "addtmp"); 237f4a2713aSLionel Sambuc case '-': return Builder.CreateFSub(L, R, "subtmp"); 238f4a2713aSLionel Sambuc case '*': return Builder.CreateFMul(L, R, "multmp"); 239f4a2713aSLionel Sambuc case '<': 240f4a2713aSLionel Sambuc L = Builder.CreateFCmpULT(L, R, "cmptmp"); 241f4a2713aSLionel Sambuc // Convert bool 0/1 to double 0.0 or 1.0 242f4a2713aSLionel Sambuc return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), 243f4a2713aSLionel Sambuc "booltmp"); 244f4a2713aSLionel Sambuc default: break; 245f4a2713aSLionel Sambuc } 246f4a2713aSLionel Sambuc 247f4a2713aSLionel Sambuc // If it wasn't a builtin binary operator, it must be a user defined one. Emit 248f4a2713aSLionel Sambuc // a call to it. 249f4a2713aSLionel Sambuc Function *F = TheModule->getFunction(std::string("binary")+Op); 250f4a2713aSLionel Sambuc assert(F && "binary operator not found!"); 251f4a2713aSLionel Sambuc 252f4a2713aSLionel Sambuc Value *Ops[2] = { L, R }; 253f4a2713aSLionel Sambuc return Builder.CreateCall(F, Ops, "binop"); 254f4a2713aSLionel Sambuc } 255f4a2713aSLionel Sambuc 256f4a2713aSLionel SambucAs you can see above, the new code is actually really simple. It just 257f4a2713aSLionel Sambucdoes a lookup for the appropriate operator in the symbol table and 258f4a2713aSLionel Sambucgenerates a function call to it. Since user-defined operators are just 259f4a2713aSLionel Sambucbuilt as normal functions (because the "prototype" boils down to a 260f4a2713aSLionel Sambucfunction with the right name) everything falls into place. 261f4a2713aSLionel Sambuc 262f4a2713aSLionel SambucThe final piece of code we are missing, is a bit of top-level magic: 263f4a2713aSLionel Sambuc 264f4a2713aSLionel Sambuc.. code-block:: c++ 265f4a2713aSLionel Sambuc 266f4a2713aSLionel Sambuc Function *FunctionAST::Codegen() { 267f4a2713aSLionel Sambuc NamedValues.clear(); 268f4a2713aSLionel Sambuc 269f4a2713aSLionel Sambuc Function *TheFunction = Proto->Codegen(); 270f4a2713aSLionel Sambuc if (TheFunction == 0) 271f4a2713aSLionel Sambuc return 0; 272f4a2713aSLionel Sambuc 273f4a2713aSLionel Sambuc // If this is an operator, install it. 274f4a2713aSLionel Sambuc if (Proto->isBinaryOp()) 275f4a2713aSLionel Sambuc BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); 276f4a2713aSLionel Sambuc 277f4a2713aSLionel Sambuc // Create a new basic block to start insertion into. 278f4a2713aSLionel Sambuc BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); 279f4a2713aSLionel Sambuc Builder.SetInsertPoint(BB); 280f4a2713aSLionel Sambuc 281f4a2713aSLionel Sambuc if (Value *RetVal = Body->Codegen()) { 282f4a2713aSLionel Sambuc ... 283f4a2713aSLionel Sambuc 284f4a2713aSLionel SambucBasically, before codegening a function, if it is a user-defined 285f4a2713aSLionel Sambucoperator, we register it in the precedence table. This allows the binary 286f4a2713aSLionel Sambucoperator parsing logic we already have in place to handle it. Since we 287f4a2713aSLionel Sambucare working on a fully-general operator precedence parser, this is all 288f4a2713aSLionel Sambucwe need to do to "extend the grammar". 289f4a2713aSLionel Sambuc 290f4a2713aSLionel SambucNow we have useful user-defined binary operators. This builds a lot on 291f4a2713aSLionel Sambucthe previous framework we built for other operators. Adding unary 292f4a2713aSLionel Sambucoperators is a bit more challenging, because we don't have any framework 293f4a2713aSLionel Sambucfor it yet - lets see what it takes. 294f4a2713aSLionel Sambuc 295f4a2713aSLionel SambucUser-defined Unary Operators 296f4a2713aSLionel Sambuc============================ 297f4a2713aSLionel Sambuc 298f4a2713aSLionel SambucSince we don't currently support unary operators in the Kaleidoscope 299f4a2713aSLionel Sambuclanguage, we'll need to add everything to support them. Above, we added 300f4a2713aSLionel Sambucsimple support for the 'unary' keyword to the lexer. In addition to 301f4a2713aSLionel Sambucthat, we need an AST node: 302f4a2713aSLionel Sambuc 303f4a2713aSLionel Sambuc.. code-block:: c++ 304f4a2713aSLionel Sambuc 305f4a2713aSLionel Sambuc /// UnaryExprAST - Expression class for a unary operator. 306f4a2713aSLionel Sambuc class UnaryExprAST : public ExprAST { 307f4a2713aSLionel Sambuc char Opcode; 308f4a2713aSLionel Sambuc ExprAST *Operand; 309f4a2713aSLionel Sambuc public: 310f4a2713aSLionel Sambuc UnaryExprAST(char opcode, ExprAST *operand) 311f4a2713aSLionel Sambuc : Opcode(opcode), Operand(operand) {} 312f4a2713aSLionel Sambuc virtual Value *Codegen(); 313f4a2713aSLionel Sambuc }; 314f4a2713aSLionel Sambuc 315f4a2713aSLionel SambucThis AST node is very simple and obvious by now. It directly mirrors the 316f4a2713aSLionel Sambucbinary operator AST node, except that it only has one child. With this, 317f4a2713aSLionel Sambucwe need to add the parsing logic. Parsing a unary operator is pretty 318f4a2713aSLionel Sambucsimple: we'll add a new function to do it: 319f4a2713aSLionel Sambuc 320f4a2713aSLionel Sambuc.. code-block:: c++ 321f4a2713aSLionel Sambuc 322f4a2713aSLionel Sambuc /// unary 323f4a2713aSLionel Sambuc /// ::= primary 324f4a2713aSLionel Sambuc /// ::= '!' unary 325f4a2713aSLionel Sambuc static ExprAST *ParseUnary() { 326f4a2713aSLionel Sambuc // If the current token is not an operator, it must be a primary expr. 327f4a2713aSLionel Sambuc if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') 328f4a2713aSLionel Sambuc return ParsePrimary(); 329f4a2713aSLionel Sambuc 330f4a2713aSLionel Sambuc // If this is a unary operator, read it. 331f4a2713aSLionel Sambuc int Opc = CurTok; 332f4a2713aSLionel Sambuc getNextToken(); 333f4a2713aSLionel Sambuc if (ExprAST *Operand = ParseUnary()) 334f4a2713aSLionel Sambuc return new UnaryExprAST(Opc, Operand); 335f4a2713aSLionel Sambuc return 0; 336f4a2713aSLionel Sambuc } 337f4a2713aSLionel Sambuc 338f4a2713aSLionel SambucThe grammar we add is pretty straightforward here. If we see a unary 339f4a2713aSLionel Sambucoperator when parsing a primary operator, we eat the operator as a 340f4a2713aSLionel Sambucprefix and parse the remaining piece as another unary operator. This 341f4a2713aSLionel Sambucallows us to handle multiple unary operators (e.g. "!!x"). Note that 342f4a2713aSLionel Sambucunary operators can't have ambiguous parses like binary operators can, 343f4a2713aSLionel Sambucso there is no need for precedence information. 344f4a2713aSLionel Sambuc 345f4a2713aSLionel SambucThe problem with this function, is that we need to call ParseUnary from 346f4a2713aSLionel Sambucsomewhere. To do this, we change previous callers of ParsePrimary to 347f4a2713aSLionel Sambuccall ParseUnary instead: 348f4a2713aSLionel Sambuc 349f4a2713aSLionel Sambuc.. code-block:: c++ 350f4a2713aSLionel Sambuc 351f4a2713aSLionel Sambuc /// binoprhs 352f4a2713aSLionel Sambuc /// ::= ('+' unary)* 353f4a2713aSLionel Sambuc static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { 354f4a2713aSLionel Sambuc ... 355f4a2713aSLionel Sambuc // Parse the unary expression after the binary operator. 356f4a2713aSLionel Sambuc ExprAST *RHS = ParseUnary(); 357f4a2713aSLionel Sambuc if (!RHS) return 0; 358f4a2713aSLionel Sambuc ... 359f4a2713aSLionel Sambuc } 360f4a2713aSLionel Sambuc /// expression 361f4a2713aSLionel Sambuc /// ::= unary binoprhs 362f4a2713aSLionel Sambuc /// 363f4a2713aSLionel Sambuc static ExprAST *ParseExpression() { 364f4a2713aSLionel Sambuc ExprAST *LHS = ParseUnary(); 365f4a2713aSLionel Sambuc if (!LHS) return 0; 366f4a2713aSLionel Sambuc 367f4a2713aSLionel Sambuc return ParseBinOpRHS(0, LHS); 368f4a2713aSLionel Sambuc } 369f4a2713aSLionel Sambuc 370f4a2713aSLionel SambucWith these two simple changes, we are now able to parse unary operators 371f4a2713aSLionel Sambucand build the AST for them. Next up, we need to add parser support for 372f4a2713aSLionel Sambucprototypes, to parse the unary operator prototype. We extend the binary 373f4a2713aSLionel Sambucoperator code above with: 374f4a2713aSLionel Sambuc 375f4a2713aSLionel Sambuc.. code-block:: c++ 376f4a2713aSLionel Sambuc 377f4a2713aSLionel Sambuc /// prototype 378f4a2713aSLionel Sambuc /// ::= id '(' id* ')' 379f4a2713aSLionel Sambuc /// ::= binary LETTER number? (id, id) 380f4a2713aSLionel Sambuc /// ::= unary LETTER (id) 381f4a2713aSLionel Sambuc static PrototypeAST *ParsePrototype() { 382f4a2713aSLionel Sambuc std::string FnName; 383f4a2713aSLionel Sambuc 384f4a2713aSLionel Sambuc unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. 385f4a2713aSLionel Sambuc unsigned BinaryPrecedence = 30; 386f4a2713aSLionel Sambuc 387f4a2713aSLionel Sambuc switch (CurTok) { 388f4a2713aSLionel Sambuc default: 389f4a2713aSLionel Sambuc return ErrorP("Expected function name in prototype"); 390f4a2713aSLionel Sambuc case tok_identifier: 391f4a2713aSLionel Sambuc FnName = IdentifierStr; 392f4a2713aSLionel Sambuc Kind = 0; 393f4a2713aSLionel Sambuc getNextToken(); 394f4a2713aSLionel Sambuc break; 395f4a2713aSLionel Sambuc case tok_unary: 396f4a2713aSLionel Sambuc getNextToken(); 397f4a2713aSLionel Sambuc if (!isascii(CurTok)) 398f4a2713aSLionel Sambuc return ErrorP("Expected unary operator"); 399f4a2713aSLionel Sambuc FnName = "unary"; 400f4a2713aSLionel Sambuc FnName += (char)CurTok; 401f4a2713aSLionel Sambuc Kind = 1; 402f4a2713aSLionel Sambuc getNextToken(); 403f4a2713aSLionel Sambuc break; 404f4a2713aSLionel Sambuc case tok_binary: 405f4a2713aSLionel Sambuc ... 406f4a2713aSLionel Sambuc 407f4a2713aSLionel SambucAs with binary operators, we name unary operators with a name that 408f4a2713aSLionel Sambucincludes the operator character. This assists us at code generation 409f4a2713aSLionel Sambuctime. Speaking of, the final piece we need to add is codegen support for 410f4a2713aSLionel Sambucunary operators. It looks like this: 411f4a2713aSLionel Sambuc 412f4a2713aSLionel Sambuc.. code-block:: c++ 413f4a2713aSLionel Sambuc 414f4a2713aSLionel Sambuc Value *UnaryExprAST::Codegen() { 415f4a2713aSLionel Sambuc Value *OperandV = Operand->Codegen(); 416f4a2713aSLionel Sambuc if (OperandV == 0) return 0; 417f4a2713aSLionel Sambuc 418f4a2713aSLionel Sambuc Function *F = TheModule->getFunction(std::string("unary")+Opcode); 419f4a2713aSLionel Sambuc if (F == 0) 420f4a2713aSLionel Sambuc return ErrorV("Unknown unary operator"); 421f4a2713aSLionel Sambuc 422f4a2713aSLionel Sambuc return Builder.CreateCall(F, OperandV, "unop"); 423f4a2713aSLionel Sambuc } 424f4a2713aSLionel Sambuc 425f4a2713aSLionel SambucThis code is similar to, but simpler than, the code for binary 426f4a2713aSLionel Sambucoperators. It is simpler primarily because it doesn't need to handle any 427f4a2713aSLionel Sambucpredefined operators. 428f4a2713aSLionel Sambuc 429f4a2713aSLionel SambucKicking the Tires 430f4a2713aSLionel Sambuc================= 431f4a2713aSLionel Sambuc 432f4a2713aSLionel SambucIt is somewhat hard to believe, but with a few simple extensions we've 433f4a2713aSLionel Sambuccovered in the last chapters, we have grown a real-ish language. With 434f4a2713aSLionel Sambucthis, we can do a lot of interesting things, including I/O, math, and a 435f4a2713aSLionel Sambucbunch of other things. For example, we can now add a nice sequencing 436f4a2713aSLionel Sambucoperator (printd is defined to print out the specified value and a 437f4a2713aSLionel Sambucnewline): 438f4a2713aSLionel Sambuc 439f4a2713aSLionel Sambuc:: 440f4a2713aSLionel Sambuc 441f4a2713aSLionel Sambuc ready> extern printd(x); 442f4a2713aSLionel Sambuc Read extern: 443f4a2713aSLionel Sambuc declare double @printd(double) 444f4a2713aSLionel Sambuc 445f4a2713aSLionel Sambuc ready> def binary : 1 (x y) 0; # Low-precedence operator that ignores operands. 446f4a2713aSLionel Sambuc .. 447f4a2713aSLionel Sambuc ready> printd(123) : printd(456) : printd(789); 448f4a2713aSLionel Sambuc 123.000000 449f4a2713aSLionel Sambuc 456.000000 450f4a2713aSLionel Sambuc 789.000000 451f4a2713aSLionel Sambuc Evaluated to 0.000000 452f4a2713aSLionel Sambuc 453f4a2713aSLionel SambucWe can also define a bunch of other "primitive" operations, such as: 454f4a2713aSLionel Sambuc 455f4a2713aSLionel Sambuc:: 456f4a2713aSLionel Sambuc 457f4a2713aSLionel Sambuc # Logical unary not. 458f4a2713aSLionel Sambuc def unary!(v) 459f4a2713aSLionel Sambuc if v then 460f4a2713aSLionel Sambuc 0 461f4a2713aSLionel Sambuc else 462f4a2713aSLionel Sambuc 1; 463f4a2713aSLionel Sambuc 464f4a2713aSLionel Sambuc # Unary negate. 465f4a2713aSLionel Sambuc def unary-(v) 466f4a2713aSLionel Sambuc 0-v; 467f4a2713aSLionel Sambuc 468f4a2713aSLionel Sambuc # Define > with the same precedence as <. 469f4a2713aSLionel Sambuc def binary> 10 (LHS RHS) 470f4a2713aSLionel Sambuc RHS < LHS; 471f4a2713aSLionel Sambuc 472f4a2713aSLionel Sambuc # Binary logical or, which does not short circuit. 473f4a2713aSLionel Sambuc def binary| 5 (LHS RHS) 474f4a2713aSLionel Sambuc if LHS then 475f4a2713aSLionel Sambuc 1 476f4a2713aSLionel Sambuc else if RHS then 477f4a2713aSLionel Sambuc 1 478f4a2713aSLionel Sambuc else 479f4a2713aSLionel Sambuc 0; 480f4a2713aSLionel Sambuc 481f4a2713aSLionel Sambuc # Binary logical and, which does not short circuit. 482f4a2713aSLionel Sambuc def binary& 6 (LHS RHS) 483f4a2713aSLionel Sambuc if !LHS then 484f4a2713aSLionel Sambuc 0 485f4a2713aSLionel Sambuc else 486f4a2713aSLionel Sambuc !!RHS; 487f4a2713aSLionel Sambuc 488f4a2713aSLionel Sambuc # Define = with slightly lower precedence than relationals. 489f4a2713aSLionel Sambuc def binary = 9 (LHS RHS) 490f4a2713aSLionel Sambuc !(LHS < RHS | LHS > RHS); 491f4a2713aSLionel Sambuc 492f4a2713aSLionel Sambuc # Define ':' for sequencing: as a low-precedence operator that ignores operands 493f4a2713aSLionel Sambuc # and just returns the RHS. 494f4a2713aSLionel Sambuc def binary : 1 (x y) y; 495f4a2713aSLionel Sambuc 496f4a2713aSLionel SambucGiven the previous if/then/else support, we can also define interesting 497f4a2713aSLionel Sambucfunctions for I/O. For example, the following prints out a character 498f4a2713aSLionel Sambucwhose "density" reflects the value passed in: the lower the value, the 499f4a2713aSLionel Sambucdenser the character: 500f4a2713aSLionel Sambuc 501f4a2713aSLionel Sambuc:: 502f4a2713aSLionel Sambuc 503f4a2713aSLionel Sambuc ready> 504f4a2713aSLionel Sambuc 505f4a2713aSLionel Sambuc extern putchard(char) 506f4a2713aSLionel Sambuc def printdensity(d) 507f4a2713aSLionel Sambuc if d > 8 then 508f4a2713aSLionel Sambuc putchard(32) # ' ' 509f4a2713aSLionel Sambuc else if d > 4 then 510f4a2713aSLionel Sambuc putchard(46) # '.' 511f4a2713aSLionel Sambuc else if d > 2 then 512f4a2713aSLionel Sambuc putchard(43) # '+' 513f4a2713aSLionel Sambuc else 514f4a2713aSLionel Sambuc putchard(42); # '*' 515f4a2713aSLionel Sambuc ... 516f4a2713aSLionel Sambuc ready> printdensity(1): printdensity(2): printdensity(3): 517f4a2713aSLionel Sambuc printdensity(4): printdensity(5): printdensity(9): 518f4a2713aSLionel Sambuc putchard(10); 519f4a2713aSLionel Sambuc **++. 520f4a2713aSLionel Sambuc Evaluated to 0.000000 521f4a2713aSLionel Sambuc 522f4a2713aSLionel SambucBased on these simple primitive operations, we can start to define more 523f4a2713aSLionel Sambucinteresting things. For example, here's a little function that solves 524f4a2713aSLionel Sambucfor the number of iterations it takes a function in the complex plane to 525f4a2713aSLionel Sambucconverge: 526f4a2713aSLionel Sambuc 527f4a2713aSLionel Sambuc:: 528f4a2713aSLionel Sambuc 529f4a2713aSLionel Sambuc # Determine whether the specific location diverges. 530f4a2713aSLionel Sambuc # Solve for z = z^2 + c in the complex plane. 531f4a2713aSLionel Sambuc def mandleconverger(real imag iters creal cimag) 532f4a2713aSLionel Sambuc if iters > 255 | (real*real + imag*imag > 4) then 533f4a2713aSLionel Sambuc iters 534f4a2713aSLionel Sambuc else 535f4a2713aSLionel Sambuc mandleconverger(real*real - imag*imag + creal, 536f4a2713aSLionel Sambuc 2*real*imag + cimag, 537f4a2713aSLionel Sambuc iters+1, creal, cimag); 538f4a2713aSLionel Sambuc 539f4a2713aSLionel Sambuc # Return the number of iterations required for the iteration to escape 540f4a2713aSLionel Sambuc def mandleconverge(real imag) 541f4a2713aSLionel Sambuc mandleconverger(real, imag, 0, real, imag); 542f4a2713aSLionel Sambuc 543f4a2713aSLionel SambucThis "``z = z2 + c``" function is a beautiful little creature that is 544f4a2713aSLionel Sambucthe basis for computation of the `Mandelbrot 545f4a2713aSLionel SambucSet <http://en.wikipedia.org/wiki/Mandelbrot_set>`_. Our 546f4a2713aSLionel Sambuc``mandelconverge`` function returns the number of iterations that it 547f4a2713aSLionel Sambuctakes for a complex orbit to escape, saturating to 255. This is not a 548f4a2713aSLionel Sambucvery useful function by itself, but if you plot its value over a 549f4a2713aSLionel Sambuctwo-dimensional plane, you can see the Mandelbrot set. Given that we are 550f4a2713aSLionel Sambuclimited to using putchard here, our amazing graphical output is limited, 551f4a2713aSLionel Sambucbut we can whip together something using the density plotter above: 552f4a2713aSLionel Sambuc 553f4a2713aSLionel Sambuc:: 554f4a2713aSLionel Sambuc 555f4a2713aSLionel Sambuc # Compute and plot the mandlebrot set with the specified 2 dimensional range 556f4a2713aSLionel Sambuc # info. 557f4a2713aSLionel Sambuc def mandelhelp(xmin xmax xstep ymin ymax ystep) 558f4a2713aSLionel Sambuc for y = ymin, y < ymax, ystep in ( 559f4a2713aSLionel Sambuc (for x = xmin, x < xmax, xstep in 560f4a2713aSLionel Sambuc printdensity(mandleconverge(x,y))) 561f4a2713aSLionel Sambuc : putchard(10) 562f4a2713aSLionel Sambuc ) 563f4a2713aSLionel Sambuc 564f4a2713aSLionel Sambuc # mandel - This is a convenient helper function for plotting the mandelbrot set 565f4a2713aSLionel Sambuc # from the specified position with the specified Magnification. 566f4a2713aSLionel Sambuc def mandel(realstart imagstart realmag imagmag) 567f4a2713aSLionel Sambuc mandelhelp(realstart, realstart+realmag*78, realmag, 568f4a2713aSLionel Sambuc imagstart, imagstart+imagmag*40, imagmag); 569f4a2713aSLionel Sambuc 570f4a2713aSLionel SambucGiven this, we can try plotting out the mandlebrot set! Lets try it out: 571f4a2713aSLionel Sambuc 572f4a2713aSLionel Sambuc:: 573f4a2713aSLionel Sambuc 574f4a2713aSLionel Sambuc ready> mandel(-2.3, -1.3, 0.05, 0.07); 575f4a2713aSLionel Sambuc *******************************+++++++++++************************************* 576f4a2713aSLionel Sambuc *************************+++++++++++++++++++++++******************************* 577f4a2713aSLionel Sambuc **********************+++++++++++++++++++++++++++++**************************** 578f4a2713aSLionel Sambuc *******************+++++++++++++++++++++.. ...++++++++************************* 579f4a2713aSLionel Sambuc *****************++++++++++++++++++++++.... ...+++++++++*********************** 580f4a2713aSLionel Sambuc ***************+++++++++++++++++++++++..... ...+++++++++********************* 581f4a2713aSLionel Sambuc **************+++++++++++++++++++++++.... ....+++++++++******************** 582f4a2713aSLionel Sambuc *************++++++++++++++++++++++...... .....++++++++******************* 583f4a2713aSLionel Sambuc ************+++++++++++++++++++++....... .......+++++++****************** 584f4a2713aSLionel Sambuc ***********+++++++++++++++++++.... ... .+++++++***************** 585f4a2713aSLionel Sambuc **********+++++++++++++++++....... .+++++++**************** 586f4a2713aSLionel Sambuc *********++++++++++++++........... ...+++++++*************** 587f4a2713aSLionel Sambuc ********++++++++++++............ ...++++++++************** 588f4a2713aSLionel Sambuc ********++++++++++... .......... .++++++++************** 589f4a2713aSLionel Sambuc *******+++++++++..... .+++++++++************* 590f4a2713aSLionel Sambuc *******++++++++...... ..+++++++++************* 591f4a2713aSLionel Sambuc *******++++++....... ..+++++++++************* 592f4a2713aSLionel Sambuc *******+++++...... ..+++++++++************* 593f4a2713aSLionel Sambuc *******.... .... ...+++++++++************* 594f4a2713aSLionel Sambuc *******.... . ...+++++++++************* 595f4a2713aSLionel Sambuc *******+++++...... ...+++++++++************* 596f4a2713aSLionel Sambuc *******++++++....... ..+++++++++************* 597f4a2713aSLionel Sambuc *******++++++++...... .+++++++++************* 598f4a2713aSLionel Sambuc *******+++++++++..... ..+++++++++************* 599f4a2713aSLionel Sambuc ********++++++++++... .......... .++++++++************** 600f4a2713aSLionel Sambuc ********++++++++++++............ ...++++++++************** 601f4a2713aSLionel Sambuc *********++++++++++++++.......... ...+++++++*************** 602f4a2713aSLionel Sambuc **********++++++++++++++++........ .+++++++**************** 603f4a2713aSLionel Sambuc **********++++++++++++++++++++.... ... ..+++++++**************** 604f4a2713aSLionel Sambuc ***********++++++++++++++++++++++....... .......++++++++***************** 605f4a2713aSLionel Sambuc ************+++++++++++++++++++++++...... ......++++++++****************** 606f4a2713aSLionel Sambuc **************+++++++++++++++++++++++.... ....++++++++******************** 607f4a2713aSLionel Sambuc ***************+++++++++++++++++++++++..... ...+++++++++********************* 608f4a2713aSLionel Sambuc *****************++++++++++++++++++++++.... ...++++++++*********************** 609f4a2713aSLionel Sambuc *******************+++++++++++++++++++++......++++++++************************* 610f4a2713aSLionel Sambuc *********************++++++++++++++++++++++.++++++++*************************** 611f4a2713aSLionel Sambuc *************************+++++++++++++++++++++++******************************* 612f4a2713aSLionel Sambuc ******************************+++++++++++++************************************ 613f4a2713aSLionel Sambuc ******************************************************************************* 614f4a2713aSLionel Sambuc ******************************************************************************* 615f4a2713aSLionel Sambuc ******************************************************************************* 616f4a2713aSLionel Sambuc Evaluated to 0.000000 617f4a2713aSLionel Sambuc ready> mandel(-2, -1, 0.02, 0.04); 618f4a2713aSLionel Sambuc **************************+++++++++++++++++++++++++++++++++++++++++++++++++++++ 619f4a2713aSLionel Sambuc ***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 620f4a2713aSLionel Sambuc *********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++. 621f4a2713aSLionel Sambuc *******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++... 622f4a2713aSLionel Sambuc *****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++..... 623f4a2713aSLionel Sambuc ***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........ 624f4a2713aSLionel Sambuc **************++++++++++++++++++++++++++++++++++++++++++++++++++++++........... 625f4a2713aSLionel Sambuc ************+++++++++++++++++++++++++++++++++++++++++++++++++++++.............. 626f4a2713aSLionel Sambuc ***********++++++++++++++++++++++++++++++++++++++++++++++++++........ . 627f4a2713aSLionel Sambuc **********++++++++++++++++++++++++++++++++++++++++++++++............. 628f4a2713aSLionel Sambuc ********+++++++++++++++++++++++++++++++++++++++++++.................. 629f4a2713aSLionel Sambuc *******+++++++++++++++++++++++++++++++++++++++....................... 630f4a2713aSLionel Sambuc ******+++++++++++++++++++++++++++++++++++........................... 631f4a2713aSLionel Sambuc *****++++++++++++++++++++++++++++++++............................ 632f4a2713aSLionel Sambuc *****++++++++++++++++++++++++++++............................... 633f4a2713aSLionel Sambuc ****++++++++++++++++++++++++++...... ......................... 634f4a2713aSLionel Sambuc ***++++++++++++++++++++++++......... ...... ........... 635f4a2713aSLionel Sambuc ***++++++++++++++++++++++............ 636f4a2713aSLionel Sambuc **+++++++++++++++++++++.............. 637f4a2713aSLionel Sambuc **+++++++++++++++++++................ 638f4a2713aSLionel Sambuc *++++++++++++++++++................. 639f4a2713aSLionel Sambuc *++++++++++++++++............ ... 640f4a2713aSLionel Sambuc *++++++++++++++.............. 641f4a2713aSLionel Sambuc *+++....++++................ 642f4a2713aSLionel Sambuc *.......... ........... 643f4a2713aSLionel Sambuc * 644f4a2713aSLionel Sambuc *.......... ........... 645f4a2713aSLionel Sambuc *+++....++++................ 646f4a2713aSLionel Sambuc *++++++++++++++.............. 647f4a2713aSLionel Sambuc *++++++++++++++++............ ... 648f4a2713aSLionel Sambuc *++++++++++++++++++................. 649f4a2713aSLionel Sambuc **+++++++++++++++++++................ 650f4a2713aSLionel Sambuc **+++++++++++++++++++++.............. 651f4a2713aSLionel Sambuc ***++++++++++++++++++++++............ 652f4a2713aSLionel Sambuc ***++++++++++++++++++++++++......... ...... ........... 653f4a2713aSLionel Sambuc ****++++++++++++++++++++++++++...... ......................... 654f4a2713aSLionel Sambuc *****++++++++++++++++++++++++++++............................... 655f4a2713aSLionel Sambuc *****++++++++++++++++++++++++++++++++............................ 656f4a2713aSLionel Sambuc ******+++++++++++++++++++++++++++++++++++........................... 657f4a2713aSLionel Sambuc *******+++++++++++++++++++++++++++++++++++++++....................... 658f4a2713aSLionel Sambuc ********+++++++++++++++++++++++++++++++++++++++++++.................. 659f4a2713aSLionel Sambuc Evaluated to 0.000000 660f4a2713aSLionel Sambuc ready> mandel(-0.9, -1.4, 0.02, 0.03); 661f4a2713aSLionel Sambuc ******************************************************************************* 662f4a2713aSLionel Sambuc ******************************************************************************* 663f4a2713aSLionel Sambuc ******************************************************************************* 664f4a2713aSLionel Sambuc **********+++++++++++++++++++++************************************************ 665f4a2713aSLionel Sambuc *+++++++++++++++++++++++++++++++++++++++*************************************** 666f4a2713aSLionel Sambuc +++++++++++++++++++++++++++++++++++++++++++++********************************** 667f4a2713aSLionel Sambuc ++++++++++++++++++++++++++++++++++++++++++++++++++***************************** 668f4a2713aSLionel Sambuc ++++++++++++++++++++++++++++++++++++++++++++++++++++++************************* 669f4a2713aSLionel Sambuc +++++++++++++++++++++++++++++++++++++++++++++++++++++++++********************** 670f4a2713aSLionel Sambuc +++++++++++++++++++++++++++++++++.........++++++++++++++++++******************* 671f4a2713aSLionel Sambuc +++++++++++++++++++++++++++++++.... ......+++++++++++++++++++**************** 672f4a2713aSLionel Sambuc +++++++++++++++++++++++++++++....... ........+++++++++++++++++++************** 673f4a2713aSLionel Sambuc ++++++++++++++++++++++++++++........ ........++++++++++++++++++++************ 674f4a2713aSLionel Sambuc +++++++++++++++++++++++++++......... .. ...+++++++++++++++++++++********** 675f4a2713aSLionel Sambuc ++++++++++++++++++++++++++........... ....++++++++++++++++++++++******** 676f4a2713aSLionel Sambuc ++++++++++++++++++++++++............. .......++++++++++++++++++++++****** 677f4a2713aSLionel Sambuc +++++++++++++++++++++++............. ........+++++++++++++++++++++++**** 678f4a2713aSLionel Sambuc ++++++++++++++++++++++........... ..........++++++++++++++++++++++*** 679f4a2713aSLionel Sambuc ++++++++++++++++++++........... .........++++++++++++++++++++++* 680f4a2713aSLionel Sambuc ++++++++++++++++++............ ...........++++++++++++++++++++ 681f4a2713aSLionel Sambuc ++++++++++++++++............... .............++++++++++++++++++ 682f4a2713aSLionel Sambuc ++++++++++++++................. ...............++++++++++++++++ 683f4a2713aSLionel Sambuc ++++++++++++.................. .................++++++++++++++ 684f4a2713aSLionel Sambuc +++++++++.................. .................+++++++++++++ 685f4a2713aSLionel Sambuc ++++++........ . ......... ..++++++++++++ 686f4a2713aSLionel Sambuc ++............ ...... ....++++++++++ 687f4a2713aSLionel Sambuc .............. ...++++++++++ 688f4a2713aSLionel Sambuc .............. ....+++++++++ 689f4a2713aSLionel Sambuc .............. .....++++++++ 690f4a2713aSLionel Sambuc ............. ......++++++++ 691f4a2713aSLionel Sambuc ........... .......++++++++ 692f4a2713aSLionel Sambuc ......... ........+++++++ 693f4a2713aSLionel Sambuc ......... ........+++++++ 694f4a2713aSLionel Sambuc ......... ....+++++++ 695f4a2713aSLionel Sambuc ........ ...+++++++ 696f4a2713aSLionel Sambuc ....... ...+++++++ 697f4a2713aSLionel Sambuc ....+++++++ 698f4a2713aSLionel Sambuc .....+++++++ 699f4a2713aSLionel Sambuc ....+++++++ 700f4a2713aSLionel Sambuc ....+++++++ 701f4a2713aSLionel Sambuc ....+++++++ 702f4a2713aSLionel Sambuc Evaluated to 0.000000 703f4a2713aSLionel Sambuc ready> ^D 704f4a2713aSLionel Sambuc 705f4a2713aSLionel SambucAt this point, you may be starting to realize that Kaleidoscope is a 706f4a2713aSLionel Sambucreal and powerful language. It may not be self-similar :), but it can be 707f4a2713aSLionel Sambucused to plot things that are! 708f4a2713aSLionel Sambuc 709f4a2713aSLionel SambucWith this, we conclude the "adding user-defined operators" chapter of 710f4a2713aSLionel Sambucthe tutorial. We have successfully augmented our language, adding the 711f4a2713aSLionel Sambucability to extend the language in the library, and we have shown how 712f4a2713aSLionel Sambucthis can be used to build a simple but interesting end-user application 713f4a2713aSLionel Sambucin Kaleidoscope. At this point, Kaleidoscope can build a variety of 714f4a2713aSLionel Sambucapplications that are functional and can call functions with 715f4a2713aSLionel Sambucside-effects, but it can't actually define and mutate a variable itself. 716f4a2713aSLionel Sambuc 717f4a2713aSLionel SambucStrikingly, variable mutation is an important feature of some languages, 718f4a2713aSLionel Sambucand it is not at all obvious how to `add support for mutable 719f4a2713aSLionel Sambucvariables <LangImpl7.html>`_ without having to add an "SSA construction" 720f4a2713aSLionel Sambucphase to your front-end. In the next chapter, we will describe how you 721f4a2713aSLionel Sambuccan add variable mutation without building SSA in your front-end. 722f4a2713aSLionel Sambuc 723f4a2713aSLionel SambucFull Code Listing 724f4a2713aSLionel Sambuc================= 725f4a2713aSLionel Sambuc 726f4a2713aSLionel SambucHere is the complete code listing for our running example, enhanced with 727f4a2713aSLionel Sambucthe if/then/else and for expressions.. To build this example, use: 728f4a2713aSLionel Sambuc 729f4a2713aSLionel Sambuc.. code-block:: bash 730f4a2713aSLionel Sambuc 731f4a2713aSLionel Sambuc # Compile 732*0a6a1f1dSLionel Sambuc clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy 733f4a2713aSLionel Sambuc # Run 734f4a2713aSLionel Sambuc ./toy 735f4a2713aSLionel Sambuc 736f4a2713aSLionel SambucOn some platforms, you will need to specify -rdynamic or 737f4a2713aSLionel Sambuc-Wl,--export-dynamic when linking. This ensures that symbols defined in 738f4a2713aSLionel Sambucthe main executable are exported to the dynamic linker and so are 739f4a2713aSLionel Sambucavailable for symbol resolution at run time. This is not needed if you 740f4a2713aSLionel Sambuccompile your support code into a shared library, although doing that 741f4a2713aSLionel Sambucwill cause problems on Windows. 742f4a2713aSLionel Sambuc 743f4a2713aSLionel SambucHere is the code: 744f4a2713aSLionel Sambuc 745f4a2713aSLionel Sambuc.. literalinclude:: ../../examples/Kaleidoscope/Chapter6/toy.cpp 746f4a2713aSLionel Sambuc :language: c++ 747f4a2713aSLionel Sambuc 748f4a2713aSLionel Sambuc`Next: Extending the language: mutable variables / SSA 749f4a2713aSLionel Sambucconstruction <LangImpl7.html>`_ 750f4a2713aSLionel Sambuc 751