434 lines
9.7 KiB
C++
434 lines
9.7 KiB
C++
|
|
// Lexer::interns::map::allocator - array allocator, resizing
|
|
// Lexer::tokens - array allocator, resizing
|
|
//
|
|
// Parser::ast_arena - arena for asts
|
|
// Lexer::interns::string_allocator - arena for interns
|
|
//
|
|
Intern_String keyword_struct;
|
|
Intern_String keyword_union;
|
|
Intern_String keyword_return;
|
|
Intern_String keyword_if;
|
|
Intern_String keyword_else;
|
|
Intern_String keyword_for;
|
|
Intern_String keyword_cast;
|
|
Intern_String keyword_enum;
|
|
|
|
Intern_String intern_void;
|
|
Intern_String intern_int;
|
|
Intern_String intern_str;
|
|
Intern_String intern_unsigned;
|
|
|
|
struct Ast_Package;
|
|
struct Sym;
|
|
struct Parse_Ctx:Lexer{
|
|
Allocator *perm; // Stores: AST, tokens, interns
|
|
Allocator *heap;
|
|
|
|
U64 unique_ids;
|
|
Map type_map;
|
|
|
|
Ast_Package *resolving_package;
|
|
Map resolved;
|
|
Map syms;
|
|
S32 scope;
|
|
Array<Sym *> local_syms;
|
|
|
|
Token empty_token;
|
|
S64 indent;
|
|
|
|
String_Builder gen;
|
|
|
|
Intern_String intern(String string){
|
|
return intern_string(&interns, string);
|
|
}
|
|
|
|
void init(Allocator *perm_allocator, Allocator *heap_allocator){
|
|
perm = perm_allocator;
|
|
heap = heap_allocator;
|
|
|
|
gen = {perm};
|
|
resolved = {heap};
|
|
syms = {heap};
|
|
type_map = {heap};
|
|
local_syms = {heap};
|
|
|
|
lex_init(perm, heap, this);
|
|
keyword_struct= intern("struct"_s);
|
|
keyword_union = intern("union"_s);
|
|
keyword_cast = intern("cast"_s);
|
|
keyword_return = intern("return"_s);
|
|
keyword_if = intern("if"_s);
|
|
keyword_else = intern("else"_s);
|
|
keyword_for = intern("for"_s);
|
|
keyword_enum = intern_string(&interns, "enum"_s);
|
|
interns.first_keyword = keyword_struct.str;
|
|
interns.last_keyword = keyword_enum.str;
|
|
|
|
intern_void = intern_string(&interns, "void"_s);
|
|
intern_int = intern_string(&interns, "int"_s);
|
|
intern_str = intern_string(&interns, "String"_s);
|
|
intern_unsigned = intern_string(&interns, "unsigned"_s);
|
|
}
|
|
};
|
|
|
|
thread_local Parse_Ctx *pctx;
|
|
//-----------------------------------------------------------------------------
|
|
// AST
|
|
//-----------------------------------------------------------------------------
|
|
enum Ast_Kind{
|
|
AST_NONE,
|
|
|
|
AST_PACKAGE,
|
|
|
|
AST_STR,
|
|
AST_INT,
|
|
AST_CAST,
|
|
AST_IDENT,
|
|
AST_INDEX,
|
|
AST_UNARY,
|
|
AST_BINARY,
|
|
AST_COMPOUND_ITEM,
|
|
AST_COMPOUND,
|
|
|
|
AST_INIT,
|
|
AST_IF,
|
|
AST_IF_NODE,
|
|
AST_RETURN,
|
|
AST_BLOCK,
|
|
AST_LAMBDA,
|
|
AST_LAMBDA_ARG,
|
|
AST_CONST,
|
|
AST_VAR,
|
|
|
|
AST_TYPESPEC_IDENT,
|
|
AST_TYPESPEC_POINTER,
|
|
AST_TYPESPEC_ARRAY,
|
|
AST_TYPESPEC_LAMBDA
|
|
};
|
|
|
|
struct Ast{
|
|
U64 id;
|
|
Token *pos;
|
|
|
|
Ast_Kind kind;
|
|
// @todo?
|
|
// bool is_atom: 1;
|
|
// bool is_stmt: 1;
|
|
// bool is_expr: 1;
|
|
// bool is_decl: 1;
|
|
// bool is_named: 1;
|
|
};
|
|
|
|
struct Ast_Resolved_Type;
|
|
struct Ast_Typespec;
|
|
struct Ast_Expr:Ast{};
|
|
|
|
struct Ast_Atom: Ast_Expr{
|
|
union{
|
|
Intern_String intern_val;
|
|
U64 int_val;
|
|
};
|
|
};
|
|
|
|
struct Ast_Compound_Item: Ast_Expr{
|
|
Ast_Atom *name; // index | name
|
|
Ast_Expr *index;
|
|
Ast_Expr *item;
|
|
};
|
|
|
|
struct Ast_Compound: Ast_Expr{
|
|
Ast_Resolved_Type *type;
|
|
Ast_Typespec *typespec;
|
|
Array<Ast_Compound_Item *> exprs;
|
|
};
|
|
|
|
struct Ast_Unary: Ast_Expr{
|
|
Token_Kind op;
|
|
Ast_Expr *expr;
|
|
};
|
|
|
|
struct Ast_Cast: Ast_Expr{
|
|
Ast_Expr *expr;
|
|
Ast_Typespec *typespec;
|
|
};
|
|
|
|
struct Ast_Index: Ast_Expr{
|
|
Ast_Expr *expr;
|
|
Ast_Expr *index;
|
|
};
|
|
|
|
struct Ast_Binary: Ast_Expr{
|
|
Token_Kind op;
|
|
Ast_Expr *left;
|
|
Ast_Expr *right;
|
|
};
|
|
|
|
struct Ast_Block : Ast {
|
|
Array<Ast *> stmts;
|
|
};
|
|
|
|
struct Ast_Return: Ast{
|
|
Ast_Expr *expr;
|
|
};
|
|
|
|
struct Ast_Init: Ast{
|
|
Token_Kind op;
|
|
Ast_Atom *ident;
|
|
Ast_Expr *expr;
|
|
};
|
|
|
|
struct Ast_If_Node: Ast{
|
|
Ast_Expr *expr ;
|
|
Ast_Block *block;
|
|
Ast_Init *init;
|
|
};
|
|
|
|
struct Ast_If: Ast{
|
|
Array<Ast_If_Node *> ifs;
|
|
};
|
|
|
|
struct Ast_Lambda_Arg: Ast_Expr{
|
|
Intern_String name;
|
|
Ast_Typespec *typespec;
|
|
};
|
|
|
|
struct Ast_Lambda : Ast_Expr {
|
|
Array<Ast_Lambda_Arg *> args;
|
|
Ast_Typespec *ret;
|
|
Ast_Block *block;
|
|
};
|
|
|
|
struct Ast_Resolved_Type;
|
|
struct Ast_Typespec:Ast{
|
|
union{
|
|
Ast_Typespec *base;
|
|
Intern_String name;
|
|
struct{
|
|
Ast_Typespec *base;
|
|
Ast_Expr *expr;
|
|
}arr;
|
|
Ast_Lambda *lambda;
|
|
};
|
|
};
|
|
|
|
struct Ast_Named:Ast{
|
|
Intern_String name;
|
|
};
|
|
|
|
struct Ast_Var: Ast_Named{
|
|
Ast_Typespec *typespec;
|
|
Ast_Expr *expr;
|
|
};
|
|
|
|
struct Ast_Const: Ast_Named{
|
|
Ast_Expr *expr;
|
|
};
|
|
|
|
struct Ast_Package:Ast{
|
|
Intern_String name;
|
|
Array<Ast_Named *> decls;
|
|
Array<Ast_Named *> ordered;
|
|
};
|
|
|
|
function Ast_Typespec *ast_typespec_name(Token *pos, Intern_String name);
|
|
//-----------------------------------------------------------------------------
|
|
// AST Constructors beginning with expressions
|
|
//-----------------------------------------------------------------------------
|
|
#define AST_NEW(T,ikind,ipos) \
|
|
Ast_##T *result = exp_alloc_type(pctx->perm, Ast_##T, AF_ZeroMemory);\
|
|
result->kind = AST_##ikind; \
|
|
result->pos = ipos; \
|
|
result->id = ++pctx->unique_ids
|
|
|
|
function Ast_Atom *
|
|
ast_expr_string(Token *pos, Intern_String string){
|
|
AST_NEW(Atom, STR, pos);
|
|
result->intern_val = string;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Atom *
|
|
ast_expr_identifier(Token *pos, Intern_String string){
|
|
AST_NEW(Atom, IDENT, pos);
|
|
result->intern_val = string;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Atom *
|
|
ast_expr_integer(Token *pos, S64 integer){
|
|
AST_NEW(Atom, INT, pos);
|
|
result->int_val = integer;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Expr *
|
|
ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
|
|
AST_NEW(Binary, BINARY, op);
|
|
result->op = op->kind;
|
|
result->left = left;
|
|
result->right = right;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Compound *
|
|
ast_expr_compound(Token *pos, Ast_Typespec *typespec, Array<Ast_Compound_Item *> exprs){
|
|
AST_NEW(Compound, COMPOUND, pos);
|
|
result->typespec = typespec;
|
|
result->exprs = exprs.tight_copy(pctx->perm);
|
|
return result;
|
|
}
|
|
|
|
function Ast_Compound_Item *
|
|
ast_expr_compound_item(Token *pos, Ast_Expr *index, Ast_Atom *name, Ast_Expr *item){
|
|
AST_NEW(Compound_Item, COMPOUND_ITEM, pos);
|
|
result->name = name;
|
|
result->index = index;
|
|
result->item = item;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Expr *
|
|
ast_expr_cast(Token *pos, Ast_Expr *expr, Ast_Typespec *typespec){
|
|
AST_NEW(Cast, CAST, pos);
|
|
result->expr = expr;
|
|
result->typespec = typespec;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Expr *
|
|
ast_expr_unary(Token *pos, Token_Kind op, Ast_Expr *expr){
|
|
AST_NEW(Unary, UNARY, pos);
|
|
result->expr = expr;
|
|
result->op = op;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Expr *
|
|
ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
|
|
AST_NEW(Index, INDEX, pos);
|
|
result->expr = expr;
|
|
result->index = index;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Lambda *
|
|
ast_lambda(Token *pos, Array<Ast_Lambda_Arg *> params, Ast_Typespec *ret, Ast_Block *block){
|
|
AST_NEW(Lambda, LAMBDA, pos);
|
|
result->args = params.tight_copy(pctx->perm);
|
|
result->ret = ret;
|
|
result->block = block;
|
|
if(!ret){
|
|
result->ret = ast_typespec_name(0, intern_void);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function Ast_Expr *
|
|
ast_expr_lambda_empty(Token *pos){
|
|
AST_NEW(Expr, LAMBDA, pos);
|
|
return result;
|
|
}
|
|
|
|
function Ast_Lambda_Arg *
|
|
ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Typespec *typespec){
|
|
AST_NEW(Lambda_Arg, LAMBDA_ARG, pos);
|
|
result->name = name;
|
|
result->typespec = typespec;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Block *
|
|
ast_block(Token *pos, Array<Ast *> stmts){
|
|
AST_NEW(Block, BLOCK, pos);
|
|
result->stmts = stmts.tight_copy(pctx->perm);
|
|
return result;
|
|
}
|
|
|
|
function Ast_If *
|
|
ast_if(Token *pos, Array<Ast_If_Node *> ifs){
|
|
AST_NEW(If, IF, pos);
|
|
result->ifs = ifs.tight_copy(pctx->perm);
|
|
return result;
|
|
}
|
|
|
|
function Ast_If_Node *
|
|
ast_if_node(Token *pos, Ast_Init *init, Ast_Expr *expr, Ast_Block *block){
|
|
AST_NEW(If_Node, IF_NODE, pos);
|
|
result->block = block;
|
|
result->expr = expr;
|
|
result->init = init;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Init *
|
|
ast_init(Token *pos, Token_Kind op, Ast_Atom *ident, Ast_Expr *expr){
|
|
AST_NEW(Init, INIT, pos);
|
|
result->op = op;
|
|
result->ident = ident;
|
|
result->expr = expr;
|
|
return result;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Typespecs
|
|
//-----------------------------------------------------------------------------
|
|
function Ast_Typespec *
|
|
ast_typespec_name(Token *pos, Intern_String name){
|
|
AST_NEW(Typespec, TYPESPEC_IDENT, pos);
|
|
result->name = name;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Typespec *
|
|
ast_typespec_pointer(Token *pos, Ast_Typespec *base){
|
|
AST_NEW(Typespec, TYPESPEC_POINTER, pos);
|
|
result->base = base;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Typespec *
|
|
ast_typespec_array(Token *pos, Ast_Typespec *base, Ast_Expr *expr){
|
|
AST_NEW(Typespec, TYPESPEC_ARRAY, pos);
|
|
result->arr.base = base;
|
|
result->arr.expr = expr;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Typespec *
|
|
ast_typespec_lambda(Token *pos, Ast_Lambda *lambda){
|
|
AST_NEW(Typespec, TYPESPEC_LAMBDA, pos);
|
|
result->lambda = lambda;
|
|
return result;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Declarations
|
|
//-----------------------------------------------------------------------------
|
|
|
|
function Ast_Var *
|
|
ast_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *expr){
|
|
AST_NEW(Var, VAR, pos);
|
|
result->expr = expr;
|
|
result->typespec = typespec;
|
|
result->name = name;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Const *
|
|
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
|
AST_NEW(Const, CONST, pos);
|
|
result->expr = expr;
|
|
result->name = name;
|
|
return result;
|
|
}
|
|
|
|
function Ast_Package *
|
|
ast_package(Token *pos, String name, Array<Ast_Named *> decls){
|
|
AST_NEW(Package, PACKAGE, pos);
|
|
result->decls = decls.tight_copy(pctx->perm);
|
|
result->ordered = array_make<Ast_Named *>(pctx->perm, decls.len);
|
|
result->name = intern_string(&pctx->interns, name);
|
|
return result;
|
|
}
|