Skip to content

Commit

Permalink
feat: add hash-consed types
Browse files Browse the repository at this point in the history
  • Loading branch information
jsilll committed Oct 23, 2024
1 parent 7d9f6f1 commit 91d7e23
Show file tree
Hide file tree
Showing 25 changed files with 394 additions and 150 deletions.
1 change: 1 addition & 0 deletions include/ADT/NonOwningList.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ template <typename T> class NonOwningList {
struct Node {
T data;
Node *next;

explicit Node(const T &data) noexcept : data(data), next(nullptr) {}
};

Expand Down
30 changes: 25 additions & 5 deletions include/AST/AST.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct ExprAST {
ExprASTKind kind;
std::string_view span;
Type *type;

ExprAST(ExprASTKind kind, std::string_view span)
: kind(kind), span(span), type(nullptr) {}
};
Expand All @@ -74,6 +75,7 @@ enum class StmtASTKind {
struct StmtAST {
StmtASTKind kind;
std::string_view span;

StmtAST(StmtASTKind kind, std::string_view span) : kind(kind), span(span) {}
};

Expand All @@ -86,6 +88,7 @@ enum class DeclASTKind {
struct DeclAST {
DeclASTKind kind;
std::string_view ident;

DeclAST(DeclASTKind kind, std::string_view ident)
: kind(kind), ident(ident) {}
};
Expand All @@ -95,6 +98,7 @@ struct DeclAST {
struct ModuleAST {
std::string_view ident;
NonOwningList<DeclAST *> decls;

ModuleAST(std::string_view ident, NonOwningList<DeclAST *> decls)
: ident(ident), decls(decls) {}
};
Expand All @@ -109,6 +113,7 @@ struct NumberExprAST : public ExprAST {
struct UnaryExprAST : public ExprAST {
UnOpKind op;
ExprAST *expr;

UnaryExprAST(std::string_view span, UnOpKind op, ExprAST *expr)
: ExprAST(ExprASTKind::Unary, span), op(op), expr(expr) {}
};
Expand All @@ -117,29 +122,33 @@ struct BinaryExprAST : public ExprAST {
BinOpKind op;
ExprAST *lhs;
ExprAST *rhs;

BinaryExprAST(std::string_view span, BinOpKind op, ExprAST *lhs,
ExprAST *rhs)
: ExprAST(ExprASTKind::Binary, span), op(op), lhs(lhs), rhs(rhs) {}
};

struct CallExprAST : public ExprAST {
ExprAST *callee;
ExprAST *arg; // TODO: support multiple arguments
// NOLINTNEXTLINE
CallExprAST(std::string_view span, ExprAST *callee, ExprAST *arg)
: ExprAST(ExprASTKind::Call, span), callee(callee), arg(arg) {}
NonOwningList<ExprAST *> args;

CallExprAST(std::string_view span, ExprAST *callee,
NonOwningList<ExprAST *> args)
: ExprAST(ExprASTKind::Call, span), callee(callee), args(args) {}
};

struct IndexExprAST : public ExprAST {
ExprAST *base;
ExprAST *index;

// NOLINTNEXTLINE
IndexExprAST(std::string_view span, ExprAST *base, ExprAST *index)
: ExprAST(ExprASTKind::Index, span), base(base), index(index) {}
};

struct GroupedExprAST : public ExprAST {
ExprAST *expr;

GroupedExprAST(std::string_view span, ExprAST *expr)
: ExprAST(ExprASTKind::Grouped, span), expr(expr) {}
};
Expand All @@ -148,18 +157,21 @@ struct GroupedExprAST : public ExprAST {

struct ExprStmtAST : public StmtAST {
ExprAST *expr;

ExprStmtAST(std::string_view span, ExprAST *expr)
: StmtAST(StmtASTKind::Expr, span), expr(expr) {}
};

struct BreakStmtAST : public StmtAST {
StmtAST *target;

explicit BreakStmtAST(std::string_view span)
: StmtAST(StmtASTKind::Break, span), target(nullptr) {}
};

struct ReturnStmtAST : public StmtAST {
ExprAST *expr;

ReturnStmtAST(std::string_view span, ExprAST *expr)
: StmtAST(StmtASTKind::Return, span), expr(expr) {}
};
Expand All @@ -168,6 +180,7 @@ struct LocalStmtAST : public StmtAST {
bool isConst;
Type *type;
ExprAST *init;

LocalStmtAST(bool isConst, std::string_view ident, Type *type,
ExprAST *init)
: StmtAST(StmtASTKind::Local, ident), isConst(isConst), type(type),
Expand All @@ -177,12 +190,14 @@ struct LocalStmtAST : public StmtAST {
struct AssignStmtAST : public StmtAST {
ExprAST *lhs;
ExprAST *rhs;

AssignStmtAST(std::string_view span, ExprAST *lhs, ExprAST *rhs)
: StmtAST(StmtASTKind::Assign, span), lhs(lhs), rhs(rhs) {}
};

struct BlockStmtAST : public StmtAST {
NonOwningList<StmtAST *> stmts;

BlockStmtAST(std::string_view span, NonOwningList<StmtAST *> stmts)
: StmtAST(StmtASTKind::Block, span), stmts(stmts) {}
};
Expand All @@ -191,6 +206,7 @@ struct IfStmtAST : public StmtAST {
ExprAST *cond;
BlockStmtAST *thenStmt;
StmtAST *elseStmt;

IfStmtAST(std::string_view span, ExprAST *cond, BlockStmtAST *thenStmt,
StmtAST *elseStmt)
: StmtAST(StmtASTKind::If, span), cond(cond), thenStmt(thenStmt),
Expand All @@ -200,6 +216,7 @@ struct IfStmtAST : public StmtAST {
struct WhileStmtAST : public StmtAST {
ExprAST *cond;
BlockStmtAST *body;

WhileStmtAST(std::string_view span, ExprAST *cond, BlockStmtAST *body)
: StmtAST(StmtASTKind::While, span), cond(cond), body(body) {}
};
Expand All @@ -210,11 +227,13 @@ struct FunctionDeclAST : public DeclAST {
NonOwningList<LocalStmtAST *> params;
Type *retType;
BlockStmtAST *body;
Type *type;

FunctionDeclAST(std::string_view ident,
NonOwningList<LocalStmtAST *> params, Type *retType,
BlockStmtAST *body)
: DeclAST(DeclASTKind::Function, ident), params(params),
retType(retType), body(body) {}
retType(retType), body(body), type(nullptr) {}
};

/// === Identifier Expressions ===
Expand All @@ -224,6 +243,7 @@ using IdentifierDecl =

struct IdentifierExprAST : public ExprAST {
IdentifierDecl decl;

explicit IdentifierExprAST(std::string_view span)
: ExprAST(ExprASTKind::Identifier, span) {}
};
Expand Down
31 changes: 23 additions & 8 deletions include/Alloc/Arena.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef LANG_ARENA_H
#define LANG_ARENA_H

#include <cstddef>
#include <list>
#include <memory>

Expand All @@ -21,15 +22,17 @@ constexpr std::size_t gigaBytes(const std::size_t bytes) {
class Arena {
public:
explicit Arena(std::size_t bytes)
: allocations(0), defaultSize(bytes), allocSize(0) {}
: defaultSize(bytes), numAllocations(0), allocSize(0) {}

Arena(const Arena &) = delete;
Arena &operator=(const Arena &) = delete;

Arena(Arena &&) = default;
Arena &operator=(Arena &&) = default;

[[nodiscard]] std::size_t totalAllocations() const { return allocations; }
[[nodiscard]] std::size_t totalAllocations() const {
return numAllocations;
}

[[nodiscard]] std::size_t totalAllocated() const {
std::size_t total = allocSize;
Expand All @@ -50,23 +53,35 @@ class Arena {
template <typename T, typename... Args> T *alloc(Args &&...args) {
static_assert(std::is_trivially_destructible_v<T>,
"T must be trivially destructible");
++allocations;
++numAllocations;
return new (allocInternal(sizeof(T))) T(std::forward<Args>(args)...);
}

template <typename T> void dealloc(T *ptr) {
static_assert(std::is_trivially_destructible_v<T>,
"T must be trivially destructible");
std::byte *start = block.data.get() + allocSize - sizeof(T);
assert(reinterpret_cast<T *>(start) == ptr);
allocSize -= sizeof(T);
}

private:
struct Block {
std::unique_ptr<std::byte[]> data;
std::size_t size;
Block() : data(nullptr), size(0) {}
std::unique_ptr<std::byte[]> data;

Block() : size(0), data(nullptr) {}

Block(std::size_t size)
: data(std::make_unique<std::byte[]>(size)), size(size) {}
: size(size), data(std::make_unique<std::byte[]>(size)) {}
};

std::size_t allocations;
std::size_t defaultSize;
std::size_t allocSize;
std::size_t numAllocations;

Block block;
std::size_t allocSize;

std::list<Block> used;
std::list<Block> avail;

Expand Down
8 changes: 8 additions & 0 deletions include/Analysis/CFA.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,29 @@
namespace lang {

enum class CFAErrorKind {
EarlyBreakStmt,
EarlyReturnStmt,
InvalidBreakStmt,
};

struct CFAError {
CFAErrorKind kind;
std::string_view span;

CFAError(CFAErrorKind kind, std::string_view span)
: kind(kind), span(span) {}

TextError toTextError() const;

JSONError toJSONError() const;
};

struct CFAResult {
std::vector<CFAError> errors;

CFAResult(std::vector<CFAError> errors) : errors(std::move(errors)) {}

[[nodiscard]] bool hasErrors() const { return !errors.empty(); }
};

class CFA : public MutableASTVisitor<CFA> {
Expand Down
8 changes: 8 additions & 0 deletions include/Analysis/Resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,22 @@ enum class ResolveErrorKind {
struct ResolveError {
ResolveErrorKind kind;
std::string_view span;

ResolveError(ResolveErrorKind kind, std::string_view span)
: kind(kind), span(span) {}

TextError toTextError() const;

JSONError toJSONError() const;
};

struct ResolveResult {
std::vector<ResolveError> errors;

ResolveResult(std::vector<ResolveError> errors)
: errors(std::move(errors)) {}

[[nodiscard]] bool hasErrors() const { return !errors.empty(); }
};

class Resolver : public MutableASTVisitor<Resolver> {
Expand Down
19 changes: 16 additions & 3 deletions include/Analysis/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,45 @@
namespace lang {

enum class TypeCheckerErrorKind {
InvalidReturn,
InvalidReturnStmt,
InvalidAssignment,
InvalidBinaryOperation,
};

struct TypeCheckerError {
TypeCheckerErrorKind kind;
std::string_view span;

TypeCheckerError(TypeCheckerErrorKind kind, std::string_view span)
: kind(kind), span(span) {}

TextError toTextError() const;

JSONError toJSONError() const;
};

struct TypeCheckerResult {
std::vector<TypeCheckerError> errors;

TypeCheckerResult(std::vector<TypeCheckerError> errors)
: errors(std::move(errors)) {}

[[nodiscard]] bool hasErrors() const { return !errors.empty(); }
};

class TypeChecker : public MutableASTVisitor<TypeChecker> {
friend class ASTVisitor<TypeChecker, false>;

public:
TypeChecker(TypeContext &typeCtx) : typeCtx(typeCtx), currentFunction(nullptr) {}
TypeChecker(TypeContext &typeCtx)
: typeCtx(&typeCtx), arena(typeCtx.getArena()),
currentFunction(nullptr) {}

TypeCheckerResult analyzeModuleAST(ModuleAST &module);

private:
TypeContext &typeCtx;
TypeContext *typeCtx;
Arena *arena;
FunctionDeclAST *currentFunction;
std::vector<TypeCheckerError> errors;

Expand Down
2 changes: 1 addition & 1 deletion include/Codegen/Codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Codegen : public ConstASTVisitor<Codegen> {
: deepCodegen(false), context(std::make_unique<llvm::LLVMContext>()),
builder(std::make_unique<llvm::IRBuilder<>>(*context)) {}

llvm::Module *generate(const ModuleAST &module);
llvm::Module *generateFromModuleAST(const ModuleAST &module);

private:
bool deepCodegen = false;
Expand Down
7 changes: 7 additions & 0 deletions include/Lex/Lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,22 @@ enum class LexErrorKind {
struct LexError {
LexErrorKind kind;
std::string_view span;

LexError(LexErrorKind kind, std::string_view span)
: kind(kind), span(span) {}

TextError toTextError() const;

JSONError toJSONError() const;
};

struct LexResult {
std::vector<Token> tokens;
std::vector<LexError> errors;

LexResult() = default;

[[nodiscard]] bool hasErrors() const { return !errors.empty(); }
};

class Lexer {
Expand Down
3 changes: 3 additions & 0 deletions include/Lex/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ std::string tokenKindToString(TokenKind kind);
struct Token {
TokenKind kind;
std::string_view span;

Token(TokenKind kind, std::string_view span) : kind(kind), span(span) {}

std::string toString() const;
};

Expand Down
Loading

0 comments on commit 91d7e23

Please sign in to comment.