.. code-block:: c++
- Value *VariableExprAST::Codegen() {
+ Value *VariableExprAST::codegen() {
// Look this variable up in the function.
Value *V = NamedValues[Name];
- if (V == 0) return ErrorV("Unknown variable name");
+ if (!V)
+ return ErrorV("Unknown variable name");
// Load the value.
return Builder.CreateLoad(V, Name.c_str());
As you can see, this is pretty straightforward. Now we need to update
the things that define the variables to set up the alloca. We'll start
-with ``ForExprAST::Codegen`` (see the `full code listing <#code>`_ for
+with ``ForExprAST::codegen()`` (see the `full code listing <#code>`_ for
the unabridged code):
.. code-block:: c++
AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
// Emit the start code first, without 'variable' in scope.
- Value *StartVal = Start->Codegen();
- if (StartVal == 0) return 0;
+ Value *StartVal = Start->codegen();
+ if (!StartVal)
+ return nullptr;
// Store the value into the alloca.
Builder.CreateStore(StartVal, Alloca);
...
// Compute the end condition.
- Value *EndCond = End->Codegen();
- if (EndCond == 0) return EndCond;
+ Value *EndCond = End->codegen();
+ if (!EndCond)
+ return nullptr;
// Reload, increment, and restore the alloca. This handles the case where
// the body of the loop mutates the variable.
For each argument, we make an alloca, store the input value to the
function into the alloca, and register the alloca as the memory location
-for the argument. This method gets invoked by ``FunctionAST::Codegen``
+for the argument. This method gets invoked by ``FunctionAST::codegen()``
right after it sets up the entry block for the function.
The final missing piece is adding the mem2reg pass, which allows us to
.. code-block:: c++
- Value *BinaryExprAST::Codegen() {
+ Value *BinaryExprAST::codegen() {
// Special case '=' because we don't want to emit the LHS as an expression.
if (Op == '=') {
// Assignment requires the LHS to be an identifier.
- VariableExprAST *LHSE = dynamic_cast<VariableExprAST*>(LHS);
+ VariableExprAST *LHSE = dynamic_cast<VariableExprAST*>(LHS.get());
if (!LHSE)
return ErrorV("destination of '=' must be a variable");
.. code-block:: c++
// Codegen the RHS.
- Value *Val = RHS->Codegen();
- if (Val == 0) return 0;
+ Value *Val = RHS->codegen();
+ if (!Val)
+ return nullptr;
// Look up the name.
Value *Variable = NamedValues[LHSE->getName()];
- if (Variable == 0) return ErrorV("Unknown variable name");
+ if (!Variable)
+ return ErrorV("Unknown variable name");
Builder.CreateStore(Val, Variable);
return Val;
User-defined Local Variables
============================
-Adding var/in is just like any other other extensions we made to
+Adding var/in is just like any other extension we made to
Kaleidoscope: we extend the lexer, the parser, the AST and the code
generator. The first step for adding our new 'var/in' construct is to
extend the lexer. As before, this is pretty trivial, the code looks like
...
static int gettok() {
...
- if (IdentifierStr == "in") return tok_in;
- if (IdentifierStr == "binary") return tok_binary;
- if (IdentifierStr == "unary") return tok_unary;
- if (IdentifierStr == "var") return tok_var;
+ if (IdentifierStr == "in")
+ return tok_in;
+ if (IdentifierStr == "binary")
+ return tok_binary;
+ if (IdentifierStr == "unary")
+ return tok_unary;
+ if (IdentifierStr == "var")
+ return tok_var;
return tok_identifier;
...
/// VarExprAST - Expression class for var/in
class VarExprAST : public ExprAST {
- std::vector<std::pair<std::string, ExprAST*> > VarNames;
- ExprAST *Body;
+ std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames;
+ std::unique_ptr<ExprAST> Body;
+
public:
- VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames,
- ExprAST *body)
- : VarNames(varnames), Body(body) {}
+ VarExprAST(std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames,
+ std::unique_ptr<ExprAST> body)
+ : VarNames(std::move(VarNames)), Body(std::move(Body)) {}
- virtual Value *Codegen();
+ virtual Value *codegen();
};
var/in allows a list of names to be defined all at once, and each name
/// ::= ifexpr
/// ::= forexpr
/// ::= varexpr
- 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();
- case tok_for: return ParseForExpr();
- case tok_var: return ParseVarExpr();
+ 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();
+ case tok_for:
+ return ParseForExpr();
+ case tok_var:
+ return ParseVarExpr();
}
}
/// varexpr ::= 'var' identifier ('=' expression)?
// (',' identifier ('=' expression)?)* 'in' expression
- static ExprAST *ParseVarExpr() {
+ static std::unique_ptr<ExprAST> ParseVarExpr() {
getNextToken(); // eat the var.
- std::vector<std::pair<std::string, ExprAST*> > VarNames;
+ std::vector<std::pair<std::string, std::unique_ptr<ExprAST>>> VarNames;
// At least one variable name is required.
if (CurTok != tok_identifier)
getNextToken(); // eat identifier.
// Read the optional initializer.
- ExprAST *Init = 0;
+ std::unique_ptr<ExprAST> Init;
if (CurTok == '=') {
getNextToken(); // eat the '='.
Init = ParseExpression();
- if (Init == 0) return 0;
+ if (!Init) return nullptr;
}
- VarNames.push_back(std::make_pair(Name, Init));
+ VarNames.push_back(std::make_pair(Name, std::move(Init)));
// End of var list, exit loop.
if (CurTok != ',') break;
return Error("expected 'in' keyword after 'var'");
getNextToken(); // eat 'in'.
- ExprAST *Body = ParseExpression();
- if (Body == 0) return 0;
+ auto Body = ParseExpression();
+ if (!Body)
+ return nullptr;
- return new VarExprAST(VarNames, Body);
+ return llvm::make_unique<VarExprAST>(std::move(VarNames),
+ std::move(Body));
}
Now that we can parse and represent the code, we need to support
.. code-block:: c++
- Value *VarExprAST::Codegen() {
+ Value *VarExprAST::codegen() {
std::vector<AllocaInst *> OldBindings;
Function *TheFunction = Builder.GetInsertBlock()->getParent();
// Register all variables and emit their initializer.
for (unsigned i = 0, e = VarNames.size(); i != e; ++i) {
const std::string &VarName = VarNames[i].first;
- ExprAST *Init = VarNames[i].second;
+ ExprAST *Init = VarNames[i].second.get();
Basically it loops over all the variables, installing them one at a
time. For each variable we put into the symbol table, we remember the
// var a = a in ... # refers to outer 'a'.
Value *InitVal;
if (Init) {
- InitVal = Init->Codegen();
- if (InitVal == 0) return 0;
+ InitVal = Init->codegen();
+ if (!InitVal)
+ return nullptr;
} else { // If not specified, use 0.0.
InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));
}
.. code-block:: c++
// Codegen the body, now that all vars are in scope.
- Value *BodyVal = Body->Codegen();
- if (BodyVal == 0) return 0;
+ Value *BodyVal = Body->codegen();
+ if (!BodyVal)
+ return nullptr;
Finally, before returning, we restore the previous variable bindings: