.. code-block:: c++
// control
- tok_if = -6, tok_then = -7, tok_else = -8,
+ tok_if = -6,
+ tok_then = -7,
+ tok_else = -8,
Once we have that, we recognize the new keywords in the lexer. This is
pretty simple stuff:
.. code-block:: c++
...
- if (IdentifierStr == "def") return tok_def;
- if (IdentifierStr == "extern") return tok_extern;
- if (IdentifierStr == "if") return tok_if;
- if (IdentifierStr == "then") return tok_then;
- if (IdentifierStr == "else") return tok_else;
+ if (IdentifierStr == "def")
+ return tok_def;
+ if (IdentifierStr == "extern")
+ return tok_extern;
+ if (IdentifierStr == "if")
+ return tok_if;
+ if (IdentifierStr == "then")
+ return tok_then;
+ if (IdentifierStr == "else")
+ return tok_else;
return tok_identifier;
AST Extensions for If/Then/Else
/// IfExprAST - Expression class for if/then/else.
class IfExprAST : public ExprAST {
- ExprAST *Cond, *Then, *Else;
+ std::unique<ExprAST> Cond, Then, Else;
+
public:
- IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
- : Cond(cond), Then(then), Else(_else) {}
+ IfExprAST(std::unique_ptr<ExprAST> Cond, std::unique_ptr<ExprAST> Then,
+ std::unique_ptr<ExprAST> Else)
+ : Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {}
virtual Value *Codegen();
};
.. code-block:: c++
/// ifexpr ::= 'if' expression 'then' expression 'else' expression
- static ExprAST *ParseIfExpr() {
+ static std::unique_ptr<ExprAST> ParseIfExpr() {
getNextToken(); // eat the if.
// condition.
- ExprAST *Cond = ParseExpression();
- if (!Cond) return 0;
+ auto Cond = ParseExpression();
+ if (!Cond)
+ return nullptr;
if (CurTok != tok_then)
return Error("expected then");
getNextToken(); // eat the then
- ExprAST *Then = ParseExpression();
- if (Then == 0) return 0;
+ auto Then = ParseExpression();
+ if (!Then)
+ return nullptr;
if (CurTok != tok_else)
return Error("expected else");
getNextToken();
- ExprAST *Else = ParseExpression();
- if (!Else) return 0;
+ auto Else = ParseExpression();
+ if (!Else)
+ return nullptr;
- return new IfExprAST(Cond, Then, Else);
+ return llvm::make_unique<IfExprAST>(std::move(Cond), std::move(Then),
+ std::move(Else));
}
Next we hook it up as a primary expression:
.. code-block:: c++
- static ExprAST *ParsePrimary() {
+ static std::unique_ptr<ExprAST> ParsePrimary() {
switch (CurTok) {
- default: return Error("unknown token when expecting an expression");
- case tok_identifier: return ParseIdentifierExpr();
- case tok_number: return ParseNumberExpr();
- case '(': return ParseParenExpr();
- case tok_if: return ParseIfExpr();
+ default:
+ return Error("unknown token when expecting an expression");
+ case tok_identifier:
+ return ParseIdentifierExpr();
+ case tok_number:
+ return ParseNumberExpr();
+ case '(':
+ return ParseParenExpr();
+ case tok_if:
+ return ParseIfExpr();
}
}
Value *IfExprAST::Codegen() {
Value *CondV = Cond->Codegen();
- if (CondV == 0) return 0;
+ if (!CondV)
+ return nullptr;
// Convert condition to a bool by comparing equal to 0.0.
- CondV = Builder.CreateFCmpONE(CondV,
- ConstantFP::get(getGlobalContext(), APFloat(0.0)),
- "ifcond");
+ CondV = Builder.CreateFCmpONE(
+ CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond");
This code is straightforward and similar to what we saw before. We emit
the expression for the condition, then compare that value to zero to get
// Create blocks for the then and else cases. Insert the 'then' block at the
// end of the function.
- BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
+ BasicBlock *ThenBB =
+ BasicBlock::Create(getGlobalContext(), "then", TheFunction);
BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
Builder.SetInsertPoint(ThenBB);
Value *ThenV = Then->Codegen();
- if (ThenV == 0) return 0;
+ if (!ThenV)
+ return nullptr;
Builder.CreateBr(MergeBB);
// Codegen of 'Then' can change the current block, update ThenBB for the PHI.
Builder.SetInsertPoint(ElseBB);
Value *ElseV = Else->Codegen();
- if (ElseV == 0) return 0;
+ if (!ElseV)
+ return nullptr;
Builder.CreateBr(MergeBB);
// Codegen of 'Else' can change the current block, update ElseBB for the PHI.
// Emit merge block.
TheFunction->getBasicBlockList().push_back(MergeBB);
Builder.SetInsertPoint(MergeBB);
- PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2,
- "iftmp");
+ PHINode *PN =
+ Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp");
PN->addIncoming(ThenV, ThenBB);
PN->addIncoming(ElseV, ElseBB);
tok_for = -9, tok_in = -10
... in gettok ...
- if (IdentifierStr == "def") return tok_def;
- if (IdentifierStr == "extern") return tok_extern;
- if (IdentifierStr == "if") return tok_if;
- if (IdentifierStr == "then") return tok_then;
- if (IdentifierStr == "else") return tok_else;
- if (IdentifierStr == "for") return tok_for;
- if (IdentifierStr == "in") return tok_in;
+ if (IdentifierStr == "def")
+ return tok_def;
+ if (IdentifierStr == "extern")
+ return tok_extern;
+ if (IdentifierStr == "if")
+ return tok_if;
+ if (IdentifierStr == "then")
+ return tok_then;
+ if (IdentifierStr == "else")
+ return tok_else;
+ if (IdentifierStr == "for")
+ return tok_for;
+ if (IdentifierStr == "in")
+ return tok_in;
return tok_identifier;
AST Extensions for the 'for' Loop
/// ForExprAST - Expression class for for/in.
class ForExprAST : public ExprAST {
std::string VarName;
- ExprAST *Start, *End, *Step, *Body;
+ std::unique_ptr<ExprAST> Start, End, Step, Body;
+
public:
- ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
- ExprAST *step, ExprAST *body)
- : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
+ ForExprAST(const std::string &VarName, std::unique_ptr<ExprAST> Start,
+ std::unique_ptr<ExprAST> End, std::unique_ptr<ExprAST> Step,
+ std::unique_ptr<ExprAST> Body)
+ : VarName(VarName), Start(std::move(Start)), End(std::move(End)),
+ Step(std::move(Step)), Body(std::move(Body)) {}
virtual Value *Codegen();
};
.. code-block:: c++
/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
- static ExprAST *ParseForExpr() {
+ static std::unique_ptr<ExprAST> ParseForExpr() {
getNextToken(); // eat the for.
if (CurTok != tok_identifier)
getNextToken(); // eat '='.
- ExprAST *Start = ParseExpression();
- if (Start == 0) return 0;
+ auto Start = ParseExpression();
+ if (!Start)
+ return nullptr;
if (CurTok != ',')
return Error("expected ',' after for start value");
getNextToken();
- ExprAST *End = ParseExpression();
- if (End == 0) return 0;
+ auto End = ParseExpression();
+ if (!End)
+ return nullptr;
// The step value is optional.
- ExprAST *Step = 0;
+ std::unique_ptr<ExprAST> Step;
if (CurTok == ',') {
getNextToken();
Step = ParseExpression();
- if (Step == 0) return 0;
+ if (!Step)
+ return nullptr;
}
if (CurTok != tok_in)
return Error("expected 'in' after for");
getNextToken(); // eat 'in'.
- ExprAST *Body = ParseExpression();
- if (Body == 0) return 0;
+ auto Body = ParseExpression();
+ if (!Body)
+ return nullptr;
- return new ForExprAST(IdName, Start, End, Step, Body);
+ return llvm::make_unique<ForExprAST>(IdName, std::move(Start),
+ std::move(End), std::move(Step),
+ std::move(Body));
}
LLVM IR for the 'for' Loop
// block.
Function *TheFunction = Builder.GetInsertBlock()->getParent();
BasicBlock *PreheaderBB = Builder.GetInsertBlock();
- BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
+ BasicBlock *LoopBB =
+ BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
// Insert an explicit fall through from the current block to the LoopBB.
Builder.CreateBr(LoopBB);
Builder.SetInsertPoint(LoopBB);
// Start the PHI node with an entry for Start.
- PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str());
+ PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
+ 2, VarName.c_str());
Variable->addIncoming(StartVal, PreheaderBB);
Now that the "preheader" for the loop is set up, we switch to emitting
// Emit the body of the loop. This, like any other expr, can change the
// current BB. Note that we ignore the value computed by the body, but don't
// allow an error.
- if (Body->Codegen() == 0)
- return 0;
+ if (!Body->Codegen())
+ return nullptr;
Now the code starts to get more interesting. Our 'for' loop introduces a
new variable to the symbol table. This means that our symbol table can
.. code-block:: c++
// Emit the step value.
- Value *StepVal;
+ Value *StepVal = nullptr;
if (Step) {
StepVal = Step->Codegen();
- if (StepVal == 0) return 0;
+ if (!StepVal)
+ return nullptr;
} else {
// If not specified, use 1.0.
StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
// Compute the end condition.
Value *EndCond = End->Codegen();
- if (EndCond == 0) return EndCond;
+ if (!EndCond)
+ return nullptr;
// Convert condition to a bool by comparing equal to 0.0.
- EndCond = Builder.CreateFCmpONE(EndCond,
- ConstantFP::get(getGlobalContext(), APFloat(0.0)),
- "loopcond");
+ EndCond = Builder.CreateFCmpONE(
+ EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond");
Finally, we evaluate the exit value of the loop, to determine whether
the loop should exit. This mirrors the condition evaluation for the
// Create the "after loop" block and insert it.
BasicBlock *LoopEndBB = Builder.GetInsertBlock();
- BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
+ BasicBlock *AfterBB =
+ BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
// Insert the conditional branch into the end of LoopEndBB.
Builder.CreateCondBr(EndCond, LoopBB, AfterBB);