#ifndef _AST_H #define _AST_H // LLVM includes #include "llvm/ADT/STLExtras.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/DIBuilder.h" // Local includes #include "Lexer.h" using namespace llvm; //===----------------------------------------------------------------------===// // Abstract Syntax Tree (aka Parse Tree) //===----------------------------------------------------------------------===// namespace ast { // struct instantiated by the 'main' to access data structures if llvm IR. struct AstObjects { public: static std::unique_ptr TheModule; static IRBuilder<> Builder; static std::map NamedValues; }; raw_ostream &indent(raw_ostream &O, int size) { return O << std::string(size, ' '); } /// ExprAST - Base class for all expression nodes. class ExprAST { lexer::SourceLocation Loc; public: ExprAST(lexer::SourceLocation Loc = lexer::CurLoc) : Loc(Loc) {} virtual ~ExprAST() {} virtual Value *codegen() = 0; int getLine() const { return Loc.Line; } int getCol() const { return Loc.Col; } virtual raw_ostream &dump(raw_ostream &out, int ind) { return out << ':' << getLine() << ':' << getCol() << '\n'; } }; /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; public: NumberExprAST(double Val) : Val(Val) {} raw_ostream &dump(raw_ostream &out, int ind) override { return ExprAST::dump(out << Val, ind); } Value *codegen() override; }; /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; public: VariableExprAST(lexer::SourceLocation Loc, const std::string &Name) : ExprAST(Loc), Name(Name) {} const std::string &getName() const { return Name; } Value *codegen() override; raw_ostream &dump(raw_ostream &out, int ind) override { return ExprAST::dump(out << Name, ind); } }; /// UnaryExprAST - Expression class for a unary operator. class UnaryExprAST : public ExprAST { char Opcode; std::unique_ptr Operand; public: UnaryExprAST(char Opcode, std::unique_ptr Operand) : Opcode(Opcode), Operand(std::move(Operand)) {} Value *codegen() override; raw_ostream &dump(raw_ostream &out, int ind) override { ExprAST::dump(out << "unary" << Opcode, ind); Operand->dump(out, ind + 1); return out; } }; /// BinaryExprAST - Expression class for a binary operator. class BinaryExprAST : public ExprAST { char Op; std::unique_ptr LHS, RHS; public: BinaryExprAST(lexer::SourceLocation Loc, char Op, std::unique_ptr LHS, std::unique_ptr RHS) : ExprAST(Loc), Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} Value *codegen() override; raw_ostream &dump(raw_ostream &out, int ind) override { ExprAST::dump(out << "binary" << Op, ind); LHS->dump(indent(out, ind) << "LHS:", ind + 1); RHS->dump(indent(out, ind) << "RHS:", ind + 1); return out; } }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; std::vector> Args; public: CallExprAST(lexer::SourceLocation Loc, const std::string &Callee, std::vector> Args) : ExprAST(Loc), Callee(Callee), Args(std::move(Args)) {} Value *codegen() override; raw_ostream &dump(raw_ostream &out, int ind) override { ExprAST::dump(out << "call " << Callee, ind); for (const auto &Arg : Args) Arg->dump(indent(out, ind + 1), ind + 1); return out; } }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { std::unique_ptr Cond, Then, Else; public: IfExprAST(lexer::SourceLocation Loc, std::unique_ptr Cond, std::unique_ptr Then, std::unique_ptr Else) : ExprAST(Loc), Cond(std::move(Cond)), Then(std::move(Then)), Else(std::move(Else)) {} Value *codegen() override; raw_ostream &dump(raw_ostream &out, int ind) override { ExprAST::dump(out << "if", ind); Cond->dump(indent(out, ind) << "Cond:", ind + 1); Then->dump(indent(out, ind) << "Then:", ind + 1); Else->dump(indent(out, ind) << "Else:", ind + 1); return out; } }; /// ForExprAST - Expression class for for/in. class ForExprAST : public ExprAST { std::string VarName; std::unique_ptr Start, End, Step, Body; public: ForExprAST(const std::string &VarName, std::unique_ptr Start, std::unique_ptr End, std::unique_ptr Step, std::unique_ptr Body) : VarName(VarName), Start(std::move(Start)), End(std::move(End)), Step(std::move(Step)), Body(std::move(Body)) {} Value *codegen() override; raw_ostream &dump(raw_ostream &out, int ind) override { ExprAST::dump(out << "for", ind); Start->dump(indent(out, ind) << "Cond:", ind + 1); End->dump(indent(out, ind) << "End:", ind + 1); Step->dump(indent(out, ind) << "Step:", ind + 1); Body->dump(indent(out, ind) << "Body:", ind + 1); return out; } }; /// VarExprAST - Expression class for var/in class VarExprAST : public ExprAST { std::vector>> VarNames; std::unique_ptr Body; public: VarExprAST( std::vector>> VarNames, std::unique_ptr Body) : VarNames(std::move(VarNames)), Body(std::move(Body)) {} Value *codegen() override; raw_ostream &dump(raw_ostream &out, int ind) override { ExprAST::dump(out << "var", ind); for (const auto &NamedVar : VarNames) NamedVar.second->dump(indent(out, ind) << NamedVar.first << ':', ind + 1); Body->dump(indent(out, ind) << "Body:", ind + 1); return out; } }; /// PrototypeAST - This class represents the "prototype" for a function, /// which captures its name, and its argument names (thus implicitly the number /// of arguments the function takes), as well as if it is an operator. class PrototypeAST { std::string Name; std::vector Args; bool IsOperator; unsigned Precedence; // Precedence if a binary op. int Line; public: PrototypeAST(lexer::SourceLocation Loc, const std::string &Name, std::vector Args, bool IsOperator = false, unsigned Prec = 0) : Name(Name), Args(std::move(Args)), IsOperator(IsOperator), Precedence(Prec), Line(Loc.Line) {} Function *codegen(); const std::string &getName() const { return Name; } bool isUnaryOp() const { return IsOperator && Args.size() == 1; } bool isBinaryOp() const { return IsOperator && Args.size() == 2; } char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); return Name[Name.size() - 1]; } unsigned getBinaryPrecedence() const { return Precedence; } int getLine() const { return Line; } }; /// FunctionAST - This class represents a function definition itself. class FunctionAST { std::unique_ptr Proto; std::unique_ptr Body; public: FunctionAST(std::unique_ptr Proto, std::unique_ptr Body) : Proto(std::move(Proto)), Body(std::move(Body)) {} Function *codegen(); raw_ostream &dump(raw_ostream &out, int ind) { indent(out, ind) << "FunctionAST\n"; ++ind; indent(out, ind) << "Body:"; return Body ? Body->dump(out, ind) : out << "null\n"; } }; #endif