This document describes the internal APIs of the Dana compiler.
class AstNode {
public:
SourceLoc loc; // Source location
virtual void accept(AstVisitor&); // Visitor pattern
virtual void print(std::ostream&, int indent = 0);
};class AstVisitor {
public:
virtual void visit(Type& n) = 0;
virtual void visit(FParType& n) = 0;
virtual void visit(Program& n) = 0;
virtual void visit(FParDef& n) = 0;
virtual void visit(Header& n) = 0;
virtual void visit(VarDef& n) = 0;
virtual void visit(FuncDecl& n) = 0;
virtual void visit(FuncDef& n) = 0;
virtual void visit(Block& n) = 0;
// ... all statement types
// ... all expression types
// ... all condition types
};Represents a type declaration in source code.
class Type : public AstNode {
public:
DataType data_type() const; // INT or BYTE
const vec<optional<int>>& dimensions() const;
};Represents a parameter type (may have pass-by-reference).
class FParType : public Type {
public:
bool isByRef() const;
};class VarDef : public Def {
public:
const vec<std::string>& identifiers() const;
Type* declaredType() const;
vec<VarSymbol*>& symbols(); // Set by semantic analysis
};class FuncDef : public Def {
public:
Header* funcHeader() const;
vec<up<Def>>& localDefs();
Block* funcBody() const;
bool isEntrypoint() const;
void setEntrypoint(bool);
};class FuncDecl : public Def {
public:
Header* funcHeader() const;
};class AssignStmt : public Stmt {
public:
Lval* left() const;
Expr* right() const;
};class IfStmt : public Stmt {
public:
Cond* conditionExpr() const;
Block* thenBlock() const;
vec<pair<up<Cond>, up<Block>>>& elifs();
Block* elseBlock() const;
};class LoopStmt : public Stmt {
public:
const optional<string>& loopLabel() const;
Block* loopBody() const;
};class Expr : public AstNode {
public:
SemaTypePtr type() const; // Computed type
void setType(SemaTypePtr);
bool isLValue() const;
void setLValue(bool);
bool isAssignable() const;
void setAssignable(bool);
bool isConstExpr() const;
void setConstExpr(bool);
};class FuncCall : public Expr {
public:
const string& identifier() const;
vec<up<Expr>>& arguments();
FuncSymbol* funcSymbol() const; // Set by semantic analysis
void setFuncSymbol(FuncSymbol*);
};class RelCond : public Cond {
public:
RelOp opKind() const; // Eq, Ne, Lt, Gt, Le, Ge
Expr* leftExpr() const;
Expr* rightExpr() const;
};class BinaryCond : public Cond {
public:
LogicOp opKind() const; // And, Or
Cond* leftCond() const;
Cond* rightCond() const;
};class Symbol {
public:
enum class SymKind { VAR, PARAM, FUNC };
enum class ParamPass { BY_VAL, BY_REF };
const string& getName() const;
SemaTypePtr getType() const;
SymKind getKind() const;
const SourceLoc& getLocation() const;
bool isVariable() const;
bool isParameter() const;
bool isFunction() const;
bool isDefined() const;
void markDefined();
};class VarSymbol : public Symbol {
public:
VarSymbol(const string& name, SemaTypePtr type, const SourceLoc& loc);
FuncSymbol* getDefiningFunc() const;
void setDefiningFunc(FuncSymbol*);
};class ParamSymbol : public Symbol {
public:
ParamSymbol(const string& name, SemaTypePtr type, ParamPass pass, const SourceLoc& loc);
ParamPass getPass() const;
};class FuncSymbol : public Symbol {
public:
FuncSymbol(const string& name, SemaTypePtr sig, bool isProcedure, const SourceLoc& loc);
bool isProcedure() const;
const vector<ParamSymbol*>& getParams() const;
void addParam(ParamSymbol* param);
void clearParams();
void markForwardDeclaration();
bool isForwardDeclared() const;
};class SemaType {
public:
enum class TypeKind { INT, BYTE, VOID, ARRAY, FUNC };
TypeKind getKind() const;
virtual bool equals(const SemaType& other) const = 0;
};
using SemaTypePtr = shared_ptr<const SemaType>;// Create singleton types
SemaTypePtr makeIntType();
SemaTypePtr makeByteType();
SemaTypePtr makeVoidType();
// Create composite types
SemaTypePtr makeArrayType(SemaTypePtr elementType, optional<size_t> size);
SemaTypePtr makeFuncType(SemaTypePtr returnType, vector<SemaTypePtr> paramTypes);class ArrayType : public SemaType {
public:
SemaTypePtr elementType() const;
optional<size_t> size() const; // nullopt for unsized
};class FuncType : public SemaType {
public:
SemaTypePtr returnType() const;
const vector<SemaTypePtr>& paramTypes() const;
};class SemContext {
public:
struct FunctionFrame {
FuncSymbol* symbol;
bool isProcedure;
SemaTypePtr returnType;
};
SemContext(SymbolTable& symtab, Diagnostics& diags);
// Scope management
void openScope();
void closeScope();
// Symbol operations
struct LookupResult { Symbol* symbol; int scopeLevel; };
LookupResult lookupSymbol(const string& name);
LookupResult lookupLocalSymbol(const string& name);
LookupResult declareSymbol(unique_ptr<Symbol> sym);
// Function context
void enterFunction(FunctionFrame& frame);
void leaveFunction();
FunctionFrame* currentFunction();
// Diagnostics
Diagnostics& diags();
bool hasErrors() const;
};class SemanticPass : public AstVisitor {
public:
explicit SemanticPass(SemContext& context);
// Type utilities
static bool isIntType(const SemaTypePtr& t);
static bool isByteType(const SemaTypePtr& t);
static bool isArrayType(const SemaTypePtr& t);
static bool typesEqual(const SemaTypePtr& a, const SemaTypePtr& b);
static bool typesCompatible(const SemaTypePtr& actual, const SemaTypePtr& expected);
};
void runSemanticPass(Program& program, SemContext& context);class ControlFlowPass : public AstVisitor {
public:
explicit ControlFlowPass(SemContext& context);
};
void runControlFlowPass(Program& program, SemContext& context);class CodegenContext {
public:
CodegenContext(const string& moduleName);
llvm::LLVMContext& llvmContext();
llvm::Module& llvmModule();
llvm::IRBuilder<>& builder();
// Value mapping
void mapSymbol(Symbol* sym, llvm::Value* val);
llvm::Value* lookupSymbol(Symbol* sym);
// Function context
void enterFunction(llvm::Function* func, FuncSymbol* sym);
void leaveFunction();
llvm::Function* currentFunction();
// Loop context (for break/continue)
void pushLoop(llvm::BasicBlock* breakTarget, llvm::BasicBlock* continueTarget,
const optional<string>& label);
void popLoop();
pair<llvm::BasicBlock*, llvm::BasicBlock*> getLoopTargets(const optional<string>& label);
};class Codegen : public AstVisitor {
public:
explicit Codegen(CodegenContext& ctx);
// Expression evaluation returns llvm::Value*
llvm::Value* lastValue() const;
};class Diagnostics {
public:
enum class Severity { Error, Warning, Note };
enum class Phase { Lexer, Parser, Semantic };
void setFilename(const string& filename);
void report(Severity sev, Phase phase, const SourceLoc& loc, const string& msg);
void report(Severity sev, int line, int col, const char* fmt, ...);
void printAll();
bool hasErrors() const;
};struct SourceLoc {
int line;
int col;
static SourceLoc builtin(); // For built-in symbols
};template<class T> using up = std::unique_ptr<T>;
template<class T> using vec = std::vector<T>;