Files
corelang/new_ast.cpp
2022-05-24 23:35:49 +02:00

374 lines
8.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 Sym;
struct Parse_Ctx:Lexer{
Allocator *perm; // Stores: AST, tokens, interns
Allocator *heap;
U64 unique_ids;
Map global_syms;
Map type_map;
Array<Sym *> local_syms;
Token empty_token;
S64 indent;
Intern_String intern(String string){
return intern_string(&interns, string);
}
void init(Allocator *perm_allocator, Allocator *heap_allocator){
perm = perm_allocator;
heap = heap_allocator;
global_syms = {heap};
type_map = {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_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;
Ast_Kind kind;
Token *pos;
};
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{
// @todo: Ast_Expr to Ast_Atom
Ast_Expr *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_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{
Ast_Resolved_Type *resolved_type;
union{
Ast_Typespec *base;
Intern_String name;
struct{
Ast_Typespec *base;
Ast_Expr *expr;
}arr;
Ast_Lambda *lambda;
};
};
struct Ast_Decl:Ast{
Intern_String name;
union{
struct{
Ast_Typespec *typespec;
Ast_Expr *expr;
}var;
};
};
struct Ast_Package:Ast{
Intern_String name;
Array<Ast_Decl *> decls;
};
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); \
result->kind = ikind; \
result->pos = ipos; \
result->id = ++pctx->unique_ids
function Ast_Atom *
ast_expr_string(Token *pos, Intern_String string){
AST_NEW(Atom, AST_STR, pos);
result->intern_val = string;
return result;
}
function Ast_Atom *
ast_expr_identifier(Token *pos, Intern_String string){
AST_NEW(Atom, AST_IDENT, pos);
result->intern_val = string;
return result;
}
function Ast_Atom *
ast_expr_integer(Token *pos, S64 integer){
AST_NEW(Atom, AST_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, AST_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, AST_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_Expr *name, Ast_Expr *item){
AST_NEW(Compound_Item, AST_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, AST_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, AST_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, AST_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, AST_LAMBDA, pos);
result->args = params.tight_copy(pctx->perm);
result->ret = ret;
if(!ret){
result->ret = ast_typespec_name(0, intern_void);
}
return result;
}
function Ast_Expr *
ast_expr_lambda_empty(Token *pos){
AST_NEW(Expr, AST_LAMBDA, pos);
return result;
}
function Ast_Lambda_Arg *
ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Typespec *typespec){
AST_NEW(Lambda_Arg, AST_LAMBDA_ARG, pos);
result->name = name;
result->typespec = typespec;
return result;
}
function Ast_Block *
ast_block(Token *pos, Array<Ast *> stmts){
AST_NEW(Block, AST_BLOCK, pos);
result->stmts = stmts.tight_copy(pctx->perm);
return result;
}
//-----------------------------------------------------------------------------
// Typespecs
//-----------------------------------------------------------------------------
function Ast_Typespec *
ast_typespec_name(Token *pos, Intern_String name){
AST_NEW(Typespec, AST_TYPESPEC_IDENT, pos);
result->name = name;
return result;
}
function Ast_Typespec *
ast_typespec_pointer(Token *pos, Ast_Typespec *base){
AST_NEW(Typespec, AST_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, AST_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, AST_TYPESPEC_LAMBDA, pos);
result->lambda = lambda;
return result;
}
//-----------------------------------------------------------------------------
// Declarations
//-----------------------------------------------------------------------------
function Ast_Decl *
ast_decl_func(Token *pos, Intern_String name){
AST_NEW(Decl, AST_LAMBDA, pos);
result->name = name;
return result;
}
function Ast_Decl *
ast_decl_var(Token *pos, Ast_Typespec *typespec, Intern_String name, Ast_Expr *expr){
AST_NEW(Decl, AST_VAR, pos);
result->var.expr = expr;
result->var.typespec = typespec;
result->name = name;
return result;
}
function Ast_Decl *
ast_decl_const(Token *pos, Intern_String name, Ast_Expr *expr){
Ast_Decl *result = ast_decl_var(pos, 0, name, expr);
result->kind = AST_CONST;
return result;
}
function Ast_Package *
ast_package(Token *pos, String name, Array<Ast_Decl *> decls){
AST_NEW(Package, AST_PACKAGE, pos);
result->decls = decls.tight_copy(pctx->perm);
result->name = intern_string(&pctx->interns, name);
return result;
}