Files
corelang/new_ast.c
Krzosa Karol feae74b0b9 Almost works
2022-05-07 20:56:03 +02:00

1014 lines
22 KiB
C

typedef struct Expr Expr;
typedef struct Note Note;
typedef struct Decl Decl;
typedef struct Stmt Stmt;
typedef struct Stmt_If Stmt_If;
typedef struct Typespec Typespec;
typedef struct Decl_Enum_Child Decl_Enum_Child;
typedef struct Decl_Function_Arg Decl_Function_Arg;
typedef struct Expr_Compound_Field Expr_Compound_Field;
typedef struct AST AST;
typedef struct AST_Parent AST_Parent;
//-----------------------------------------------------------------------------
// Expressions
//-----------------------------------------------------------------------------
typedef enum Expr_Sizeof_Kind{
SIZEOF_Expr,
SIZEOF_Type,
}Expr_Sizeof_Kind;
typedef enum Expr_Kind{
EK_None,
EK_Int,
EK_String,
EK_Identifier,
EK_Compound,
EK_Paren,
EK_PostfixUnary,
EK_Unary,
EK_Binary,
EK_Ternary,
EK_Cast,
EK_Field,
EK_Call,
EK_Index,
EK_SizeType,
EK_SizeExpr,
} Expr_Kind;
typedef enum Expr_Compound_Kind{
COMPOUND_None,
COMPOUND_Default,
COMPOUND_Named,
COMPOUND_Index,
}Expr_Compound_Kind;
struct Expr_Compound_Field{
Expr_Compound_Field *next;
Expr_Compound_Kind kind;
Token *pos;
Expr *init;
union{
Expr *index;
Intern_String name;
};
};
struct Expr {
Expr_Kind kind;
Token *token;
Expr *next;
union {
U64 int_val;
Intern_String intern_val;
double float_val;
struct {
Expr *expr;
} paren;
struct {
Typespec *typespec;
Expr* expr;
} cast;
struct{
Intern_String name;
Expr *expr;
}field;
struct{
Typespec *typespec;
Expr_Compound_Field *first;
Expr_Compound_Field *last;
}compound;
struct {
Expr *atom;
Expr_Compound_Field *first;
Expr_Compound_Field *last;
} call;
struct{
}arg;
struct {
Expr *atom;
Expr *index;
} index;
struct {
Token_Kind op;
Expr* expr;
} unary;
struct {
Token_Kind op;
Expr *expr;
} postfix_unary;
struct {
Token_Kind op;
Expr* left;
Expr* right;
} binary;
struct {
Expr* cond;
Expr* on_true;
Expr* on_false;
} ternary;
struct{
Typespec *typespec;
} size_type;
struct{
Expr *expr;
} size_expr;
};
};
//-----------------------------------------------------------------------------
// Type specifiers
//-----------------------------------------------------------------------------
typedef enum Typespec_Kind{
TS_None,
TS_Name,
TS_Pointer,
TS_Array,
TS_Function,
TS_NamedArgument,
}Typespec_Kind;
struct Typespec{
Typespec *next;
Typespec_Kind kind;
Token *pos;
union{
Typespec *base;
Intern_String name;
struct{
Intern_String name;
Typespec *base;
}named;
struct{
Typespec *first;
Typespec *last;
Typespec *ret;
}func;
struct{
Typespec *base;
Expr *size;
}arr;
};
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
typedef enum AST_Kind{
AST_None,
AST_Decl_Enum_Child,
AST_Decl_Var,
AST_Decl_Const,
AST_Decl_Typedef,
AST_Decl_Func_Arg,
AST_Decl_Variable,
AST_Decl_Struct, // //
AST_Decl_SubStruct,
AST_Decl_SubUnion,
AST_Decl_Union, //
AST_Decl_Enum,
AST_Decl_Func,
AST_Program,
AST_Note,
AST_Note_List,
AST_Stmt_If,
AST_Stmt_Decl,
AST_Stmt_Expr,
AST_Stmt_Return,
AST_Stmt_For,
AST_FirstParent = AST_Decl_Struct,
AST_LastParent = AST_Stmt_For,
AST_FirstStruct = AST_Decl_Struct,
AST_LastStruct = AST_Decl_Union,
}AST_Kind;
#define AST_FIELDS AST *next, *prev; AST_Parent *notes; AST_Parent *parent; Token *pos; AST_Kind kind
#define AST_PARENT_FIELDS AST *first, *last
#define AST_UNION union{ struct{ AST_FIELDS; }; AST ast; }
#define AST_PARENT_UNION union{ struct{ AST_FIELDS; AST_PARENT_FIELDS; }; AST_Parent child; }
struct AST{
AST_FIELDS;
};
typedef struct AST_Parent{
AST_UNION;
AST_PARENT_FIELDS;
} AST_Parent;
typedef AST_Parent Note_List;
typedef AST_Parent Program;
typedef struct Note{
AST_PARENT_UNION;
Intern_String name;
Expr *expr;
}Note;
typedef struct Decl_Struct{
AST_PARENT_UNION;
Intern_String name;
}Decl_Struct;
typedef struct Decl_Func_Arg{
AST_UNION;
Intern_String name;
Typespec *typespec;
}Decl_Func_Arg;
typedef struct Decl_Enum_Child{
AST_UNION;
Intern_String name;
Expr *expr;
}Decl_Enum_Child;
typedef struct Decl_Enum{
AST_PARENT_UNION;
Typespec *typespec;
Intern_String name;
}Decl_Enum;
typedef struct Decl_Func{
AST_PARENT_UNION;
Intern_String name;
Typespec *ret;
AST *body;
}Decl_Func;
typedef struct Decl_Typedef{
AST_PARENT_UNION;
Typespec *typespec;
Intern_String name;
}Decl_Typedef;
typedef struct Decl_Var{
AST_PARENT_UNION;
Typespec *typespec;
Intern_String name;
Expr *expr;
}Decl_Var;
typedef struct Decl_Const{
AST_PARENT_UNION;
Typespec *typespec;
Intern_String name;
Expr *expr;
}Decl_Const;
/*
//-----------------------------------------------------------------------------
// Declarations
//-----------------------------------------------------------------------------
typedef enum Decl_Kind{
DECL_None,
DECL_Struct,
DECL_Union,
DECL_SubStruct,
DECL_SubUnion,
DECL_Enum,
DECL_Variable,
DECL_Const,
DECL_Typedef,
DECL_Function,
DECL_List,
}Decl_Kind;
struct Decl{
Decl_Kind kind;
Decl *next;
B32 is_incomplete;
Decl *prev; // Doubly linked list?
Decl *parent; // ?
Intern_String name;
Token *pos;
Note *first_note;
Note *last_note;
union{
struct{
Decl_Enum_Child *first;
Decl_Enum_Child *last;
Typespec *typespec;
}enum_decl;
struct{
Decl *first;
Decl *last;
}struct_decl;
struct{
Typespec *typespec;
Expr *expr;
}var_decl;
struct{
Typespec *typespec;
}typedef_decl;
struct{
Decl_Function_Arg *first;
Decl_Function_Arg *last;
Typespec *ret;
Stmt *body;
}func_decl;
struct{
Decl *first;
Decl *last;
}list_decl;
};
};
*/
/*
struct Note{
Token *pos;
Intern_String name;
Expr *expr;
Note *next;
Note *first;
Note *last;
};
struct Decl_Function_Arg{
Decl_Function_Arg *next;
Token *pos;
Intern_String name;
Typespec *typespec;
};
struct Decl_Enum_Child{
Decl_Enum_Child *next;
Intern_String name;
Token *pos;
Expr *expr;
Note *first_note;
Note *last_note;
};
*/
/*
//-----------------------------------------------------------------------------
// Statements
//-----------------------------------------------------------------------------
typedef enum Stmt_Kind{
STMT_None,
STMT_Decl,
STMT_Expr,
STMT_List,
STMT_Return,
STMT_If,
STMT_For,
}Stmt_Kind;
struct Stmt_If{
Stmt_If *next;
Expr *cond;
Stmt *body;
};
struct Stmt{
Stmt_Kind kind;
Stmt *next;
Token *pos;
union{
Stmt_If stmt_if;
Decl *decl;
Expr *expr;
struct{
Stmt *first;
Stmt *last;
}list;
struct{
Expr *expr;
}ret;
};
};
*/
//-----------------------------------------------------------------------------
// Expression constructors
//-----------------------------------------------------------------------------
function Expr *
expr_new(Arena *p, Expr_Kind kind, Token *token){
Expr *expr = arena_push_struct(p, Expr);
expr->kind = kind;
expr->token = token;
return expr;
}
function Expr *
expr_int(Arena *p, Token *token){
assert(token->kind == TK_Int);
Expr *expr = expr_new(p, EK_Int, token);
expr->int_val = token->int_val;
return expr;
}
function Expr *
expr_str(Arena *p, Token *token){
assert(token->kind == TK_StringLit);
Expr *expr = expr_new(p, EK_String, token);
expr->intern_val = token->intern_val;
return expr;
}
function Expr *
expr_identifier(Arena *p, Token *token){
assert(token->kind == TK_Identifier);
Expr *expr = expr_new(p, EK_Identifier, token);
expr->intern_val = token->intern_val;
return expr;
}
function Expr *
expr_field(Arena *p, Token *token, Expr *inexpr){
assert(token->kind == TK_Identifier);
Expr *expr = expr_new(p, EK_Field, token);
expr->field.expr = inexpr;
expr->field.name = token->intern_val;
return expr;
}
function Expr *
expr_paren(Arena *p, Token *token, Expr *inexpr){
Expr *expr = expr_new(p, EK_Paren, token);
expr->paren.expr = inexpr;
return expr;
}
function Expr *
expr_postfix_unary(Arena *p, Token *op, Expr *exp){
Expr *expr = expr_new(p, EK_PostfixUnary, op);
expr->unary.op = op->kind;
expr->unary.expr = exp;
return expr;
}
function Expr *
expr_unary(Arena *p, Token *op, Expr *exp){
Expr *expr = expr_new(p, EK_Unary, op);
expr->unary.op = op->kind;
expr->unary.expr = exp;
return expr;
}
function Expr *
expr_binary(Arena *p, Token *op, Expr *left, Expr *right){
Expr *expr = expr_new(p, EK_Binary, op);
expr->binary.op = op->kind;
expr->binary.left = left;
expr->binary.right = right;
return expr;
}
function Expr *
expr_ternary(Arena *p, Token *op, Expr *cond, Expr *on_true, Expr *on_false){
Expr *expr = expr_new(p, EK_Ternary, op);
expr->ternary.cond = cond;
expr->ternary.on_true = on_true;
expr->ternary.on_false = on_false;
return expr;
}
function Expr *
expr_call(Arena *p, Token *token, Expr *atom){
Expr *expr = expr_new(p, EK_Call, token);
expr->call.atom = atom;
return expr;
}
function Expr *
expr_index(Arena *p, Token *token, Expr *atom, Expr *index){
Expr *expr = expr_new(p, EK_Index, token);
expr->index.atom = atom;
expr->index.index = index;
return expr;
}
function Expr *
expr_cast(Arena *p, Token *token, Typespec *type, Expr *exp){
Expr *expr = expr_new(p, EK_Cast, token);
expr->cast.typespec = type;
expr->cast.expr = exp;
return expr;
}
function Expr *
expr_size_type(Arena *p, Token *token, Typespec *type){
Expr *expr = expr_new(p, EK_SizeType, token);
expr->size_type.typespec = type;
return expr;
}
function Expr *
expr_sizeof_expr(Arena *p, Token *token, Expr *in_expr){
Expr *expr = expr_new(p, EK_SizeExpr, token);
expr->size_expr.expr = in_expr;
return expr;
}
function Expr *
expr_compound(Arena *arena, Token *pos, Typespec *typespec){
Expr *result = expr_new(arena, EK_Compound, pos);
result->compound.typespec = typespec;
return result;
}
function Expr_Compound_Field *
expr_compound_new(Arena *arena, Expr_Compound_Kind kind, Token *pos, Expr *init){
Expr_Compound_Field *result = arena_push_struct(arena, Expr_Compound_Field);
result->kind = kind;
result->pos = pos;
result->init = init;
return result;
}
function Expr_Compound_Field *
expr_compound_default(Arena *arena, Token *pos, Expr *init){
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Default, pos, init);
return result;
}
function Expr_Compound_Field *
expr_compound_named(Arena *arena, Token *pos, Intern_String name, Expr *init){
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Named, pos, init);
result->name = name;
return result;
}
function Expr_Compound_Field *
expr_compound_index(Arena *arena, Token *pos, Expr *index, Expr *init){
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Index, pos, init);
result->index = index;
return result;
}
function void
expr_call_push(Expr *list, Expr_Compound_Field *field){
SLLQueuePush(list->call.first, list->call.last, field);
}
function void
expr_compound_push(Expr *list, Expr_Compound_Field *field){
SLLQueuePush(list->compound.first, list->compound.last, field);
}
//-----------------------------------------------------------------------------
// Type specifier constructors
//-----------------------------------------------------------------------------
function Typespec *
typespec_new(Arena *p, Typespec_Kind kind, Token *pos){
Typespec *result = arena_push_struct(p, Typespec);
result->kind = kind;
result->pos = pos;
return result;
}
function Typespec *
typespec_name(Arena *p, Token *pos, Intern_String name){
Typespec *result = typespec_new(p, TS_Name, pos);
result->name = name;
return result;
}
function Typespec *
typespec_pointer(Arena *p, Token *pos, Typespec *base){
Typespec *result = typespec_new(p, TS_Pointer, pos);
result->base = base;
return result;
}
function Typespec *
typespec_array(Arena *p, Token *pos, Typespec *base, Expr *size){
Typespec *result = typespec_new(p, TS_Array, pos);
result->arr.base = base;
result->arr.size = size;
return result;
}
function Typespec *
typespec_function(Arena *p, Token *pos, Typespec *ret){
Typespec *result = typespec_new(p, TS_Function, pos);
result->func.ret = ret;
return result;
}
function Typespec *
typespec_named_argument(Arena *arena, Token *pos, Typespec *typespec, Intern_String name){
Typespec *result = typespec_new(arena, TS_NamedArgument, pos);
result->named.base = typespec;
result->named.name = name;
return result;
}
function void
typespec_function_push(Typespec *func, Typespec *arg){
SLLQueuePush(func->func.first, func->func.last, arg);
}
//-----------------------------------------------------------------------------
// Double linked list
//-----------------------------------------------------------------------------
function void
ast_remove(AST *node){
AST_Parent *l = node->parent;
assert(l);
if (l->first==l->last){
assert(node==l->last);
l->first=l->last=0;
}
else if (l->last==node){
l->last=l->last->prev;
l->last->next=0;
}
else if (l->first==node){
l->first=l->first->next;
l->first->prev=0;
}
else {
node->prev->next=node->next;
node->next->prev=node->prev;
}
node->parent=0;
node->prev=0;
node->next=0;
}
function void
ast_push_first(AST_Parent *l, AST *node){
if (l->first==0){
l->first=l->last=node;
node->prev=0;
node->next=0;
}
else {
l->last->next=node;
node->prev=l->last;
node->next=0;
l->last=node;
}
node->parent=l;
}
function void
ast_push_last(AST_Parent *l, AST *node){
if(l->first == 0){
l->first = l->last = node;
node->prev = 0;
node->next = 0;
}
else {
node->next = l->first;
l->first->prev = node;
node->prev = 0;
l->first = node;
}
node->parent = l;
}
function void
ast_push_after(AST *in_list, AST *node){
AST_Parent *parent = in_list->parent;
assert(parent);
assert(parent->first && parent->last);
node->prev = in_list;
if(in_list == parent->last){
in_list->next = node;
parent->last = node;
}
else {
node->next = in_list->next;
in_list->next = node;
node->next->prev = node;
}
node->parent=parent;
}
function void
ast_push_before(AST *in_list, AST *node){
AST_Parent *parent = in_list->parent;
assert(parent);
assert(parent->first && parent->last);
node->next = in_list;
if(parent->first == in_list){
in_list->prev = node;
parent->first = node;
}
else{
node->prev = in_list->prev;
in_list->prev = node;
node->prev->next = node;
}
node->parent = parent;
}
//-----------------------------------------------------------------------------
// Notes
//-----------------------------------------------------------------------------
/*
function Note *
find_note(Note *first, String string){
for(Note *n = first; n; n=n->next){
if(string_compare(string, n->name.s)){
return n;
}
}
return 0;
}
*/
/*
function String
find_string_note(Note *first, String string, String default_string){
Note *note = find_note(first, string);
if(note){
return note->expr->token->intern_val.s;
}
return default_string;
}
function Note *
decl_find_note(Decl *decl, String string){
return find_note(decl->first_note, string);
}
function String
decl_find_string_note(Decl *decl, String string, String default_string){
return find_string_note(decl->first_note, string, default_string);
}
*/
//-----------------------------------------------------------------------------
// Declarations
//-----------------------------------------------------------------------------
#define ast_parent_new(arena, T, pos) (T *)ast__parent_new(arena, sizeof(T), AST_##T, pos)
#define ast_new(arena, T, pos) (T *)ast__new(arena, sizeof(T), AST_##T, pos)
function B32
ast_kind_is_parent(AST_Kind kind){
B32 result = kind >= AST_FirstParent && kind <= AST_LastParent;
return result;
}
function B32
ast_kind_is_struct(AST_Kind kind){
B32 result = kind >= AST_FirstStruct && kind <= AST_LastStruct;
return result;
}
function AST *
ast__new(Arena *p, SizeU size, AST_Kind kind, Token *pos){
assert(!ast_kind_is_parent(kind));
AST *result = arena_push_size(p, size);
result->pos = pos;
result->kind = kind;
return result;
}
function AST_Parent *
ast__parent_new(Arena *p, SizeU size, AST_Kind kind, Token *pos){
assert(ast_kind_is_parent(kind));
AST_Parent *result = arena_push_size(p, size);
result->pos = pos;
result->kind = kind;
return result;
}
function Note *
note_push_new(Arena *p, AST_Parent *parent, Token *pos, Intern_String name, Expr *expr){
Note *result = ast_parent_new(p, Note, pos);
result->name = name;
result->expr = expr;
ast_push_last(parent, (AST *)result);
return result;
}
function Note_List *
note_list(Arena *p, Token *pos){
Note_List *result = ast_parent_new(p, Note_List, pos);
return result;
}
function Decl_Struct *
decl_struct(Arena *p, AST_Kind kind, Token *pos, Intern_String name){
assert(ast_kind_is_struct(kind));
Decl_Struct *result = ast_parent_new(p, Decl_Struct, pos);
result->name = name;
return result;
}
function Decl_Typedef *
decl_typedef(Arena *p, Token *pos, Intern_String name, Typespec *type){
Decl_Typedef *result = ast_new(p, Decl_Typedef, pos);
result->typespec = type;
result->name = name;
return result;
}
function Decl_Const *
decl_const(Arena *arena, Token *pos, Intern_String name, Expr *expr, Typespec *typespec){
Decl_Const *result = ast_new(arena, Decl_Const, pos);
result->expr = expr;
result->name = name;
result->typespec = typespec;
return result;
}
function Decl_Enum *
decl_enum(Arena *p, Token *pos, Intern_String name, Typespec *typespec){
Decl_Enum *result = ast_parent_new(p, Decl_Enum, pos);
result->typespec = typespec;
return result;
}
function Decl_Var *
decl_variable(Arena *arena, Token *pos, Intern_String name, Expr *expr, Typespec *typespec, Note_List *notes){
Decl_Var *result = ast_new(arena, Decl_Var, pos);
result->expr = expr;
result->name = name;
result->typespec = typespec;
result->notes = notes;
return result;
}
function Decl_Func *
decl_function(Arena *p, Token *pos, Intern_String name, Typespec *ret){
Decl_Func *result = ast_parent_new(p, Decl_Func, pos);
result->ret = ret;
return result;
}
function Decl_Func_Arg *
decl_func_arg(Arena *arena, Token *pos, Intern_String name, Typespec *type){
Decl_Func_Arg *result = ast_new(arena, Decl_Func_Arg, pos);
result->name = name;
result->typespec = type;
return result;
}
function Decl_Enum_Child *
decl_enum_child(Arena *p, Token *pos, Intern_String name, Expr *expr, Note_List *note){
Decl_Enum_Child *result = ast_new(p, Decl_Enum_Child, pos);
result->name = name;
result->expr = expr;
result->notes = (AST_Parent *)note;
return result;
}
function void
decl_func_push(Arena *p, Decl_Func *parent, Token *pos, Intern_String name, Typespec *type){
assert(parent->kind == AST_Decl_Func);
Decl_Func_Arg *func_arg = decl_func_arg(p, pos, name, type);
ast_push_last((AST_Parent *)parent, (AST *)func_arg);
}
function void
decl_enum_push(Arena *p, Decl_Enum *parent, Token *pos, Intern_String name, Expr *expr, Note_List *notes){
assert(parent->kind == AST_Decl_Enum);
Decl_Enum_Child *child = decl_enum_child(p, pos, name, expr, notes);
ast_push_last((AST_Parent *)parent, (AST *)child);
}
function void
decl_struct_push(Decl_Struct *parent, AST *child){
assert(ast_kind_is_struct(parent->kind));
ast_push_last((AST_Parent *)parent, child);
}
function Program *
ast_program(Arena *arena, Token *token){
Program *result = ast_parent_new(arena, Program, token);
return result;
}
function void
ast_program_push(AST_Parent *parent, AST *child){
assert(parent->kind == AST_Program);
ast_push_last((AST_Parent *)parent, child);
}
//-----------------------------------------------------------------------------
// Statements
//-----------------------------------------------------------------------------
/*
function Stmt *
stmt_new(Arena *p, Stmt_Kind kind, Token *pos){
Stmt *result = arena_push_struct(p, Stmt);
result->kind = kind;
result->pos = pos;
return result;
}
function Stmt *
stmt_decl(Arena *p, Token *pos, Decl *decl){
Stmt *result = stmt_new(p, STMT_Decl, pos);
result->decl = decl;
return result;
}
function Stmt *
stmt_expr(Arena *p, Token *pos, Expr *expr){
Stmt *result = stmt_new(p, STMT_Expr, pos);
result->expr = expr;
return result;
}
function Stmt *
stmt_list(Arena *p, Token *pos){
Stmt *result = stmt_new(p, STMT_List, pos);
return result;
}
function Stmt *
stmt_return(Arena *p, Token *pos, Expr *expr){
Stmt *result = stmt_new(p, STMT_Return, pos);
result->ret.expr = expr;
return result;
}
function Stmt *
stmt_if(Arena *p, Token *pos, Stmt *body, Expr *cond){
Stmt *result = stmt_new(p, STMT_If, pos);
result->stmt_if.cond = cond;
result->stmt_if.body = body;
return result;
}
function void
stmt_push(Stmt *stmt, Stmt *child){
SLLQueuePush(stmt->list.first, stmt->list.last, child);
}
*/
//-----------------------------------------------------------------------------
// Test stuff
//-----------------------------------------------------------------------------
function void
list_print(AST_Parent *decls){
printf("\n");
printf("next:");
for(AST *n = decls->first; n; n=n->next){
printf("%d", n->kind);
}
printf("prev:");
for(AST *n = decls->last; n; n=n->prev){
printf("%d", n->kind);
}
printf("parent:");
for(AST *n = decls->first; n; n=n->next){
printf("%d", n->parent->kind);
}
}
function void
ast_test(){
printf("\nAST_Size = %u", (U32)sizeof(AST));
printf("\nAST_Struct_Size = %u", (U32)sizeof(Decl_Struct));
AST_Parent parent = {0};
AST decls[16] = {0};
parent.kind = 0;
for(int i = 0; i < buff_cap(decls); i++){
decls[i].kind = i+1;
}
ast_push_first(&parent, decls);
ast_push_first(&parent, decls+1);
ast_push_first(&parent, decls+2);
ast_push_before(decls, decls+3);
ast_push_before(decls, decls+4);
ast_push_after(decls, decls+5);
ast_push_after(decls+5, decls+6);
//list_print(&parent);
ast_remove(decls);
ast_remove(decls+1);
ast_remove(decls+2);
ast_remove(decls+3);
ast_remove(decls+4);
ast_remove(decls+5);
ast_remove(decls+6);
assert(parent.first == 0);
assert(parent.last == 0);
}