From bf3283c889ce387fd252b48e12e090fab7446048 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 2 Aug 2016 01:08:36 +0100 Subject: [PATCH] Massive Refactor and If statements --- examples/test.c | 11 +- examples/test.ll | 13 + examples/test.odin | 6 + run.bat | 4 +- src/checker/checker.cpp | 62 ++-- src/checker/expression.cpp | 411 +++++++++++---------- src/checker/statements.cpp | 250 ++++++------- src/codegen/print.cpp | 64 ++-- src/codegen/ssa.cpp | 669 +++++++++++++++++++++-------------- src/parser.cpp | 706 +++++++++++++++++-------------------- src/printer.cpp | 128 +++---- src/tokenizer.cpp | 7 +- 12 files changed, 1229 insertions(+), 1102 deletions(-) diff --git a/examples/test.c b/examples/test.c index 84a4f9a08..bf1d9fafe 100644 --- a/examples/test.c +++ b/examples/test.c @@ -1,6 +1,11 @@ int main() { - float a = 0.5; - float b = 1.5; - int c = a < b; + int x = 15; + int y = 4; + x = x & (~y); + if (x > 0) { + x = 123; + } else { + x = 321; + } return 0; } diff --git a/examples/test.ll b/examples/test.ll index 82af5a836..c8d5f46ee 100644 --- a/examples/test.ll +++ b/examples/test.ll @@ -1,4 +1,17 @@ define void @main() { entry: + %0 = alloca i64, align 8 ; x + store i64 zeroinitializer, i64* %0 + store i64 15, i64* %0 + %1 = load i64, i64* %0 + %2 = icmp sgt i64 %1, 0 + br i1 %2, label %if-then, label %if-else +if-then: + store i64 123, i64* %0 + br label %if-end +if-else: + store i64 321, i64* %0 + br label %if-end +if-end: ret void } diff --git a/examples/test.odin b/examples/test.odin index fd7194210..1f1de7750 100644 --- a/examples/test.odin +++ b/examples/test.odin @@ -1,2 +1,8 @@ main :: proc() { + x : int = 15; + if x > 0 { + x = 123; + } else { + x = 321; + } } diff --git a/run.bat b/run.bat index 418b2e059..3f25c6ca1 100644 --- a/run.bat +++ b/run.bat @@ -5,5 +5,5 @@ rem del "..\examples\test.bc" call ..\bin\odin.exe ..\examples/test.odin call lli ..\examples/test.ll rem call opt -mem2reg ..\examples/test.ll > ..\examples/test.bc -rem call llvm-dis ..\examples/test.bc -o..\examples/test.ll -rem call clang ..\examples/test.c -O1 -S -emit-llvm -o ..\examples/test-c.ll +rem call llvm-dis ..\examples/test.bc -o ..\examples/test.ll +call clang ..\examples/test.c -O0 -S -emit-llvm -o ..\examples/test-c.ll diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 62e3b9019..e6bf8b2ff 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -63,7 +63,8 @@ b32 has_init(DeclInfo *d) { if (d->init_expr != NULL) return true; if (d->proc_decl != NULL) { - if (d->proc_decl->proc_decl.body != NULL) + ast_node(pd, ProcDecl, d->proc_decl); + if (pd->body != NULL) return true; } @@ -466,7 +467,7 @@ void add_entity_use(CheckerInfo *i, AstNode *identifier, Entity *entity) { void add_file_entity(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) { - GB_ASSERT(are_strings_equal(identifier->ident.token.string, e->token.string)); + GB_ASSERT(are_strings_equal(identifier->Ident.token.string, e->token.string)); add_entity(c, c->global_scope, identifier, e); map_set(&c->info.entities, hash_pointer(e), d); @@ -537,20 +538,18 @@ void check_parsed_files(Checker *c) { continue; switch (decl->kind) { - case AstNode_BadDecl: - break; - - case AstNode_VarDecl: { - auto *vd = &decl->var_decl; + case_ast_node(bd, BadDecl, decl); + case_end; + case_ast_node(vd, VarDecl, decl); switch (vd->kind) { case Declaration_Immutable: { for (AstNode *name = vd->name_list, *value = vd->value_list; name != NULL && value != NULL; name = name->next, value = value->next) { - GB_ASSERT(name->kind == AstNode_Ident); + ast_node(n, Ident, name); ExactValue v = {ExactValue_Invalid}; - Entity *e = make_entity_constant(c->allocator, c->context.scope, name->ident.token, NULL, v); + Entity *e = make_entity_constant(c->allocator, c->context.scope, n->token, NULL, v); DeclInfo *di = make_declaration_info(c->allocator, c->global_scope); di->type_expr = vd->type; di->init_expr = value; @@ -582,7 +581,8 @@ void check_parsed_files(Checker *c) { AstNode *value = vd->value_list; for (AstNode *name = vd->name_list; name != NULL; name = name->next) { - Entity *e = make_entity_variable(c->allocator, c->global_scope, name->ident.token, NULL); + ast_node(n, Ident, name); + Entity *e = make_entity_variable(c->allocator, c->global_scope, n->token, NULL); entities[entity_index++] = e; DeclInfo *d = di; @@ -600,41 +600,39 @@ void check_parsed_files(Checker *c) { } } break; } + case_end; - - } break; - - case AstNode_TypeDecl: { - AstNode *identifier = decl->type_decl.name; - Entity *e = make_entity_type_name(c->allocator, c->global_scope, identifier->ident.token, NULL); + case_ast_node(td, TypeDecl, decl); + ast_node(n, Ident, td->name); + Entity *e = make_entity_type_name(c->allocator, c->global_scope, n->token, NULL); DeclInfo *d = make_declaration_info(c->allocator, e->parent); - d->type_expr = decl->type_decl.type; - add_file_entity(c, identifier, e, d); - } break; + d->type_expr = td->type; + add_file_entity(c, td->name, e, d); + case_end; - case AstNode_AliasDecl: { - AstNode *identifier = decl->alias_decl.name; - Entity *e = make_entity_alias_name(c->allocator, c->global_scope, identifier->ident.token, NULL); + case_ast_node(ad, AliasDecl, decl); + ast_node(n, Ident, ad->name); + Entity *e = make_entity_alias_name(c->allocator, c->global_scope, n->token, NULL); DeclInfo *d = make_declaration_info(c->allocator, e->parent); - d->type_expr = decl->alias_decl.type; - add_file_entity(c, identifier, e, d); - } break; + d->type_expr = ad->type; + add_file_entity(c, ad->name, e, d); + case_end; - case AstNode_ProcDecl: { - AstNode *identifier = decl->proc_decl.name; - Token token = identifier->ident.token; + case_ast_node(pd, ProcDecl, decl); + ast_node(n, Ident, pd->name); + Token token = n->token; Entity *e = make_entity_procedure(c->allocator, c->global_scope, token, NULL); - add_entity(c, c->global_scope, identifier, e); + add_entity(c, c->global_scope, pd->name, e); DeclInfo *d = make_declaration_info(c->allocator, e->parent); d->proc_decl = decl; map_set(&c->info.entities, hash_pointer(e), d); e->order = gb_array_count(c->info.entities.entries); - } break; + case_end; - case AstNode_ImportDecl: + case_ast_node(id, ImportDecl, decl); // NOTE(bill): ignore - break; + case_end; default: error(&c->error_collector, ast_node_token(decl), "Only declarations are allowed at file scope"); diff --git a/src/checker/expression.cpp b/src/checker/expression.cpp index 9a9ad4c7f..2fe95a8e3 100644 --- a/src/checker/expression.cpp +++ b/src/checker/expression.cpp @@ -16,7 +16,7 @@ void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { GB_ASSERT(node->kind == AstNode_StructType); GB_ASSERT(struct_type->kind == Type_Structure); - auto *st = &node->struct_type; + ast_node(st, StructType, node); if (st->field_count == 0) { error(&c->error_collector, ast_node_token(node), "Empty struct{} definition"); return; @@ -28,7 +28,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { isize field_count = 0; for (AstNode *field = st->field_list; field != NULL; field = field->next) { - for (AstNode *name = field->field.name_list; name != NULL; name = name->next) { + for (AstNode *name = field->Field.name_list; name != NULL; name = name->next) { GB_ASSERT(name->kind == AstNode_Ident); field_count++; } @@ -37,10 +37,11 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { Entity **fields = gb_alloc_array(c->allocator, Entity *, st->field_count); isize field_index = 0; for (AstNode *field = st->field_list; field != NULL; field = field->next) { - Type *type = check_type(c, field->field.type); - for (AstNode *name = field->field.name_list; name != NULL; name = name->next) { - GB_ASSERT(name->kind == AstNode_Ident); - Token name_token = name->ident.token; + ast_node(f, Field, field); + Type *type = check_type(c, f->type); + for (AstNode *name = f->name_list; name != NULL; name = name->next) { + ast_node(i, Ident, name); + Token name_token = i->token; // TODO(bill): is the curr_scope correct? Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type); u64 key = hash_string(name_token.string); @@ -67,13 +68,14 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel Entity **variables = gb_alloc_array(c->allocator, Entity *, field_count); isize variable_index = 0; for (AstNode *field = field_list; field != NULL; field = field->next) { - GB_ASSERT(field->kind == AstNode_Field); - AstNode *type_expr = field->field.type; + ast_node(f, Field, field); + AstNode *type_expr = f->type; if (type_expr) { Type *type = check_type(c, type_expr); - for (AstNode *name = field->field.name_list; name != NULL; name = name->next) { + for (AstNode *name = f->name_list; name != NULL; name = name->next) { if (name->kind == AstNode_Ident) { - Entity *param = make_entity_param(c->allocator, scope, name->ident.token, type); + ast_node(i, Ident, name); + Entity *param = make_entity_param(c->allocator, scope, i->token, type); add_entity(c, scope, name, param); variables[variable_index++] = param; } else { @@ -117,19 +119,21 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) { - isize param_count = proc_type_node->proc_type.param_count; - isize result_count = proc_type_node->proc_type.result_count; + ast_node(pt, ProcType, proc_type_node); + + isize param_count = pt->param_count; + isize result_count = pt->result_count; // gb_printf("%td -> %td\n", param_count, result_count); - Type *params = check_get_params(c, c->context.scope, proc_type_node->proc_type.param_list, param_count); - Type *results = check_get_results(c, c->context.scope, proc_type_node->proc_type.result_list, result_count); + Type *params = check_get_params(c, c->context.scope, pt->param_list, param_count); + Type *results = check_get_results(c, c->context.scope, pt->result_list, result_count); type->procedure.scope = c->context.scope; type->procedure.params = params; - type->procedure.param_count = proc_type_node->proc_type.param_count; + type->procedure.param_count = pt->param_count; type->procedure.results = results; - type->procedure.result_count = proc_type_node->proc_type.result_count; + type->procedure.result_count = pt->result_count; } @@ -137,10 +141,11 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) { GB_ASSERT(n->kind == AstNode_Ident); o->mode = Addressing_Invalid; o->expr = n; - Entity *e = scope_lookup_entity(c->context.scope, n->ident.token.string); + ast_node(i, Ident, n); + Entity *e = scope_lookup_entity(c->context.scope, i->token.string); if (e == NULL) { - error(&c->error_collector, n->ident.token, - "Undeclared type or identifier `%.*s`", LIT(n->ident.token.string)); + error(&c->error_collector, i->token, + "Undeclared type or identifier `%.*s`", LIT(i->token.string)); return; } add_entity_use(&c->info, n, e); @@ -155,7 +160,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) { } if (e->type == NULL) { - GB_PANIC("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(n->ident.token.string)); + GB_PANIC("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(i->token.string)); return; } @@ -230,7 +235,7 @@ Type *check_type_expr_extra(Checker *c, AstNode *e, Type *named_type) { defer (gb_string_free(err_str)); switch (e->kind) { - case AstNode_Ident: { + case_ast_node(i, Ident, e); Operand o = {}; check_identifier(c, &o, e, named_type); switch (o.mode) { @@ -252,46 +257,48 @@ Type *check_type_expr_extra(Checker *c, AstNode *e, Type *named_type) { error(&c->error_collector, ast_node_token(e), "`%s` used as a type when not a type", err_str); break; } - } break; + case_end; - case AstNode_ParenExpr: - return check_type(c, e->paren_expr.expr, named_type); + case_ast_node(pe, ParenExpr, e); + return check_type(c, pe->expr, named_type); + case_end; - case AstNode_ArrayType: - if (e->array_type.count != NULL) { + + case_ast_node(at, ArrayType, e); + if (at->count != NULL) { Type *t = make_type_array(c->allocator, - check_type(c, e->array_type.elem), - check_array_count(c, e->array_type.count)); + check_type(c, at->elem), + check_array_count(c, at->count)); set_base_type(named_type, t); return t; } else { - Type *t = make_type_slice(c->allocator, check_type(c, e->array_type.elem)); + Type *t = make_type_slice(c->allocator, check_type(c, at->elem)); set_base_type(named_type, t); return t; } - break; + case_end; - case AstNode_StructType: { + case_ast_node(st, StructType, e); Type *t = make_type_structure(c->allocator); set_base_type(named_type, t); check_struct_type(c, t, e); return t; - } break; + case_end; - case AstNode_PointerType: { - Type *t = make_type_pointer(c->allocator, check_type(c, e->pointer_type.type)); + case_ast_node(pt, PointerType, e); + Type *t = make_type_pointer(c->allocator, check_type(c, pt->type)); set_base_type(named_type, t); return t; - } break; + case_end; - case AstNode_ProcType: { + case_ast_node(pt, ProcType, e); Type *t = alloc_type(c->allocator, Type_Procedure); set_base_type(named_type, t); check_open_scope(c, e); check_procedure_type(c, t, e); check_close_scope(c); return t; - } break; + case_end; default: err_str = expr_to_string(e); @@ -312,7 +319,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { defer (gb_string_free(err_str)); switch (e->kind) { - case AstNode_Ident: { + case_ast_node(i, Ident, e); Operand operand = {}; check_identifier(c, &operand, e, named_type); switch (operand.mode) { @@ -334,9 +341,9 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { error(&c->error_collector, ast_node_token(e), "`%s` used as a type when not a type", err_str); break; } - } break; + case_end; - case AstNode_SelectorExpr: { + case_ast_node(se, SelectorExpr, e); Operand o = {}; check_selector(c, &o, e); @@ -344,43 +351,44 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) { set_base_type(type, o.type); return o.type; } - } break; + case_end; - case AstNode_ParenExpr: - return check_type(c, e->paren_expr.expr, named_type); + case_ast_node(pe, ParenExpr, e); + return check_type(c, pe->expr, named_type); + case_end; - case AstNode_ArrayType: { - if (e->array_type.count != NULL) { + case_ast_node(at, ArrayType, e); + if (at->count != NULL) { type = make_type_array(c->allocator, - check_type(c, e->array_type.elem), - check_array_count(c, e->array_type.count)); + check_type(c, at->elem), + check_array_count(c, at->count)); set_base_type(named_type, type); } else { - type = make_type_slice(c->allocator, check_type(c, e->array_type.elem)); + type = make_type_slice(c->allocator, check_type(c, at->elem)); set_base_type(named_type, type); } goto end; - } break; + case_end; - case AstNode_StructType: { + case_ast_node(st, StructType, e); type = make_type_structure(c->allocator); set_base_type(named_type, type); check_struct_type(c, type, e); goto end; - } break; + case_end; - case AstNode_PointerType: { - type = make_type_pointer(c->allocator, check_type(c, e->pointer_type.type)); + case_ast_node(pt, PointerType, e); + type = make_type_pointer(c->allocator, check_type(c, pt->type)); set_base_type(named_type, type); goto end; - } break; + case_end; - case AstNode_ProcType: { + case_ast_node(pt, ProcType, e); type = alloc_type(c->allocator, Type_Procedure); set_base_type(named_type, type); check_procedure_type(c, type, e); goto end; - } break; + case_end; default: err_str = expr_to_string(e); @@ -581,7 +589,8 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) { void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { if (op.kind == Token_Pointer) { // Pointer address if (o->mode != Addressing_Variable) { - gbString str = expr_to_string(node->unary_expr.expr); + ast_node(ue, UnaryExpr, node); + gbString str = expr_to_string(ue->expr); defer (gb_string_free(str)); error(&c->error_collector, op, "Cannot take the pointer address of `%s`", str); o->mode = Addressing_Invalid; @@ -672,8 +681,10 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { gbString err_str = NULL; defer (gb_string_free(err_str)); - check_expr(c, x, node->binary_expr.left); - check_expr(c, y, node->binary_expr.right); + ast_node(be, BinaryExpr, node); + + check_expr(c, x, be->left); + check_expr(c, y, be->right); if (x->mode == Addressing_Invalid) return; if (y->mode == Addressing_Invalid) { x->mode = Addressing_Invalid; @@ -689,7 +700,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { return; } - Token op = node->binary_expr.op; + Token op = be->op; if (token_is_comparison(op)) { check_comparison(c, x, y, op); return; @@ -770,19 +781,21 @@ void update_expr_type(Checker *c, AstNode *e, Type *type) { return; switch (e->kind) { - case AstNode_UnaryExpr: + case_ast_node(ue, UnaryExpr, e); if (found->value.kind != ExactValue_Invalid) break; - update_expr_type(c, e->unary_expr.expr, type); + update_expr_type(c, ue->expr, type); break; + case_end; - case AstNode_BinaryExpr: + case_ast_node(be, BinaryExpr, e); if (found->value.kind != ExactValue_Invalid) break; - if (!token_is_comparison(e->binary_expr.op)) { - update_expr_type(c, e->binary_expr.left, type); - update_expr_type(c, e->binary_expr.right, type); + if (!token_is_comparison(be->op)) { + update_expr_type(c, be->left, type); + update_expr_type(c, be->right, type); } + case_end; } if (is_type_untyped(type)) { @@ -946,7 +959,8 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) { if (type->kind == Type_Pointer) type = get_base_type(type->pointer.element); - String field_str = field_node->ident.token.string; + ast_node(i, Ident, field_node); + String field_str = i->token.string; switch (type->kind) { case Type_Structure: for (isize i = 0; i < type->structure.field_count; i++) { @@ -970,8 +984,9 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) { void check_selector(Checker *c, Operand *operand, AstNode *node) { GB_ASSERT(node->kind == AstNode_SelectorExpr); - AstNode *op_expr = node->selector_expr.expr; - AstNode *selector = node->selector_expr.selector; + ast_node(se, SelectorExpr, node); + AstNode *op_expr = se->expr; + AstNode *selector = se->selector; if (selector) { Entity *entity = lookup_field(operand->type, selector); if (entity == NULL) { @@ -999,7 +1014,7 @@ void check_selector(Checker *c, Operand *operand, AstNode *node) { b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) { GB_ASSERT(call->kind == AstNode_CallExpr); - auto *ce = &call->call_expr; + ast_node(ce, CallExpr, call); BuiltinProcedure *bp = &builtin_procedures[id]; { char *err = NULL; @@ -1008,8 +1023,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (ce->arg_list_count > bp->arg_count && !bp->variadic) err = "Too many"; if (err) { + ast_node(proc, Ident, ce->proc); error(&c->error_collector, ce->close, "`%s` arguments for `%.*s`, expected %td, got %td", - err, LIT(call->call_expr.proc->ident.token.string), + err, LIT(proc->token.string), bp->arg_count, ce->arg_list_count); return false; } @@ -1093,9 +1109,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) isize index = 0; Entity *entity = lookup_field(type, field_arg, &index); if (entity == NULL) { + ast_node(arg, Ident, field_arg); gbString type_str = type_to_string(type); error(&c->error_collector, ast_node_token(ce->arg_list), - "`%s` has no field named `%.*s`", type_str, LIT(field_arg->ident.token.string)); + "`%s` has no field named `%.*s`", type_str, LIT(arg->token.string)); return false; } @@ -1112,7 +1129,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) error(&c->error_collector, ast_node_token(arg), "`%s` is not a selector expression", str); return false; } - auto *s = &arg->selector_expr; + ast_node(s, SelectorExpr, arg); check_expr(c, operand, s->expr); if (operand->mode == Addressing_Invalid) @@ -1128,9 +1145,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) isize index = 0; Entity *entity = lookup_field(type, s->selector, &index); if (entity == NULL) { + ast_node(i, Ident, s->selector); gbString type_str = type_to_string(type); error(&c->error_collector, ast_node_token(arg), - "`%s` has no field named `%.*s`", type_str, LIT(s->selector->ident.token.string)); + "`%s` has no field named `%.*s`", type_str, LIT(i->token.string)); return false; } @@ -1267,7 +1285,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) { GB_ASSERT(call->kind == AstNode_CallExpr); GB_ASSERT(proc_type->kind == Type_Procedure); - auto *ce = &call->call_expr; + ast_node(ce, CallExpr, call); isize error_code = 0; isize param_index = 0; isize param_count = 0; @@ -1341,7 +1359,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode ExpressionKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { GB_ASSERT(call->kind == AstNode_CallExpr); - auto *ce = &call->call_expr; + ast_node(ce, CallExpr, call); check_expr_or_type(c, operand, ce->proc); if (operand->mode == Addressing_Invalid) { @@ -1492,16 +1510,17 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ o->type = &basic_types[Basic_Invalid]; switch (node->kind) { - case AstNode_BadExpr: + case_ast_node(be, BadExpr, node) goto error; + case_end; - case AstNode_Ident: + case_ast_node(i, Ident, node); check_identifier(c, o, node, type_hint); - break; - case AstNode_BasicLit: { + case_end; + + case_ast_node(bl, BasicLit, node); BasicKind basic_kind = Basic_Invalid; - Token lit = node->basic_lit; - switch (lit.kind) { + switch (bl->kind) { case Token_Integer: basic_kind = Basic_UntypedInteger; break; case Token_Float: basic_kind = Basic_UntypedFloat; break; case Token_String: basic_kind = Basic_UntypedString; break; @@ -1510,14 +1529,14 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ } o->mode = Addressing_Constant; o->type = &basic_types[basic_kind]; - o->value = make_exact_value_from_basic_literal(lit); - } break; + o->value = make_exact_value_from_basic_literal(*bl); + case_end; - case AstNode_ProcLit: { + case_ast_node(pl, ProcLit, node); Scope *origin_curr_scope = c->context.scope; - Type *proc_type = check_type(c, node->proc_lit.type); + Type *proc_type = check_type(c, pl->type); if (proc_type != NULL) { - check_proc_body(c, empty_token, c->context.decl, proc_type, node->proc_lit.body); + check_proc_body(c, empty_token, c->context.decl, proc_type, pl->body); o->mode = Addressing_Value; o->type = proc_type; } else { @@ -1526,10 +1545,9 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ gb_string_free(str); goto error; } - } break; + case_end; - case AstNode_CompoundLit: { - auto *cl = &node->compound_lit; + case_ast_node(cl, CompoundLit, node); Type *type = type_hint; if (cl->type != NULL) { type = check_type(c, cl->type); @@ -1562,7 +1580,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ check_assignment(c, o, field->type, make_string("structure literal")); } if (cl->elem_count < field_count) { - error(&c->error_collector, node->compound_lit.close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elem_count); + error(&c->error_collector, cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elem_count); } } @@ -1610,43 +1628,48 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ o->mode = Addressing_Value; o->type = type; - } break; + case_end; - case AstNode_ParenExpr: - kind = check_expr_base(c, o, node->paren_expr.expr, type_hint); + case_ast_node(pe, ParenExpr, node); + kind = check_expr_base(c, o, pe->expr, type_hint); o->expr = node; - break; + case_end; - case AstNode_TagExpr: + + case_ast_node(te, TagExpr, node); // TODO(bill): Tag expressions error(&c->error_collector, ast_node_token(node), "Tag expressions are not supported yet"); - kind = check_expr_base(c, o, node->tag_expr.expr, type_hint); + kind = check_expr_base(c, o, te->expr, type_hint); o->expr = node; - break; + case_end; - case AstNode_UnaryExpr: - check_expr(c, o, node->unary_expr.expr); + + case_ast_node(ue, UnaryExpr, node); + check_expr(c, o, ue->expr); if (o->mode == Addressing_Invalid) goto error; - check_unary_expr(c, o, node->unary_expr.op, node); + check_unary_expr(c, o, ue->op, node); if (o->mode == Addressing_Invalid) goto error; - break; + case_end; - case AstNode_BinaryExpr: + + case_ast_node(be, BinaryExpr, node); check_binary_expr(c, o, node); if (o->mode == Addressing_Invalid) goto error; - break; + case_end; - case AstNode_SelectorExpr: - check_expr_base(c, o, node->selector_expr.expr); + + case_ast_node(se, SelectorExpr, node); + check_expr_base(c, o, se->expr); check_selector(c, o, node); - break; + case_end; - case AstNode_IndexExpr: { - check_expr(c, o, node->index_expr.expr); + + case_ast_node(ie, IndexExpr, node); + check_expr(c, o, ie->expr); if (o->mode == Addressing_Invalid) goto error; @@ -1693,19 +1716,19 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ goto error; } - if (node->index_expr.index == NULL) { + if (ie->index == NULL) { gbString str = expr_to_string(o->expr); error(&c->error_collector, ast_node_token(o->expr), "Missing index for `%s`", str); gb_string_free(str); goto error; } - check_index_value(c, node->index_expr.index, max_count, NULL); - } break; + check_index_value(c, ie->index, max_count, NULL); + case_end; - case AstNode_SliceExpr: { - auto *se = &node->slice_expr; + + case_ast_node(se, SliceExpr, node); check_expr(c, o, se->expr); if (o->mode == Addressing_Invalid) goto error; @@ -1784,21 +1807,24 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ } } - } break; + case_end; - case AstNode_CastExpr: { - Type *cast_type = check_type(c, node->cast_expr.type); - check_expr_or_type(c, o, node->cast_expr.expr); + + case_ast_node(ce, CastExpr, node); + Type *cast_type = check_type(c, ce->type); + check_expr_or_type(c, o, ce->expr); if (o->mode != Addressing_Invalid) check_cast_expr(c, o, cast_type); - } break; + case_end; - case AstNode_CallExpr: + + case_ast_node(ce, CallExpr, node); return check_call_expr(c, o, node); + case_end; - case AstNode_DerefExpr: - check_expr_or_type(c, o, node->deref_expr.expr); + case_ast_node(de, DerefExpr, node); + check_expr_or_type(c, o, de->expr); if (o->mode == Addressing_Invalid) { goto error; } else { @@ -1813,7 +1839,7 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ goto error; } } - break; + case_end; case AstNode_ProcType: case AstNode_PointerType: @@ -1925,12 +1951,12 @@ gbString write_expr_to_string(gbString str, AstNode *node); gbString write_field_list_to_string(gbString str, AstNode *field_list, char *sep) { isize i = 0; for (AstNode *field = field_list; field != NULL; field = field->next) { - GB_ASSERT(field->kind == AstNode_Field); + ast_node(f, Field, field); if (i > 0) str = gb_string_appendc(str, sep); isize j = 0; - for (AstNode *name = field->field.name_list; name != NULL; name = name->next) { + for (AstNode *name = f->name_list; name != NULL; name = name->next) { if (j > 0) str = gb_string_appendc(str, ", "); str = write_expr_to_string(str, name); @@ -1938,7 +1964,7 @@ gbString write_field_list_to_string(gbString str, AstNode *field_list, char *sep } str = gb_string_appendc(str, ": "); - str = write_expr_to_string(str, field->field.type); + str = write_expr_to_string(str, f->type); i++; } @@ -1959,115 +1985,118 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, "(bad expression)"); break; - case AstNode_Ident: - str = string_append_token(str, node->ident.token); - break; - case AstNode_BasicLit: - str = string_append_token(str, node->basic_lit); - break; - case AstNode_ProcLit: - str = write_expr_to_string(str, node->proc_lit.type); - break; - case AstNode_CompoundLit: + case_ast_node(i, Ident, node); + str = string_append_token(str, i->token); + case_end; + + case_ast_node(bl, BasicLit, node); + str = string_append_token(str, *bl); + case_end; + + case_ast_node(pl, ProcLit, node); + str = write_expr_to_string(str, pl->type); + case_end; + + case_ast_node(cl, CompoundLit, node); str = gb_string_appendc(str, "("); - str = write_expr_to_string(str, node->compound_lit.type); + str = write_expr_to_string(str, cl->type); str = gb_string_appendc(str, " literal)"); - break; + case_end; - case AstNode_TagExpr: + case_ast_node(te, TagExpr, node); str = gb_string_appendc(str, "#"); - str = string_append_token(str, node->tag_expr.name); - str = write_expr_to_string(str, node->tag_expr.expr); - break; + str = string_append_token(str, te->name); + str = write_expr_to_string(str, te->expr); + case_end; - case AstNode_UnaryExpr: - str = string_append_token(str, node->unary_expr.op); - str = write_expr_to_string(str, node->unary_expr.expr); - break; + case_ast_node(ue, UnaryExpr, node); + str = string_append_token(str, ue->op); + str = write_expr_to_string(str, ue->expr); + case_end; - case AstNode_BinaryExpr: - str = write_expr_to_string(str, node->binary_expr.left); + case_ast_node(be, BinaryExpr, node); + str = write_expr_to_string(str, be->left); str = gb_string_appendc(str, " "); - str = string_append_token(str, node->binary_expr.op); + str = string_append_token(str, be->op); str = gb_string_appendc(str, " "); - str = write_expr_to_string(str, node->binary_expr.right); - break; + str = write_expr_to_string(str, be->right); + case_end; - case AstNode_ParenExpr: + case_ast_node(pe, ParenExpr, node); str = gb_string_appendc(str, "("); - str = write_expr_to_string(str, node->paren_expr.expr); + str = write_expr_to_string(str, pe->expr); str = gb_string_appendc(str, ")"); - break; + case_end; - case AstNode_SelectorExpr: - str = write_expr_to_string(str, node->selector_expr.expr); + case_ast_node(se, SelectorExpr, node); + str = write_expr_to_string(str, se->expr); str = gb_string_appendc(str, "."); - str = write_expr_to_string(str, node->selector_expr.selector); - break; + str = write_expr_to_string(str, se->selector); + case_end; - case AstNode_IndexExpr: - str = write_expr_to_string(str, node->index_expr.expr); + case_ast_node(ie, IndexExpr, node); + str = write_expr_to_string(str, ie->expr); str = gb_string_appendc(str, "["); - str = write_expr_to_string(str, node->index_expr.index); + str = write_expr_to_string(str, ie->index); str = gb_string_appendc(str, "]"); - break; + case_end; - case AstNode_SliceExpr: - str = write_expr_to_string(str, node->slice_expr.expr); + case_ast_node(se, SliceExpr, node); + str = write_expr_to_string(str, se->expr); str = gb_string_appendc(str, "["); - str = write_expr_to_string(str, node->slice_expr.low); + str = write_expr_to_string(str, se->low); str = gb_string_appendc(str, ":"); - str = write_expr_to_string(str, node->slice_expr.high); - if (node->slice_expr.triple_indexed) { + str = write_expr_to_string(str, se->high); + if (se->triple_indexed) { str = gb_string_appendc(str, ":"); - str = write_expr_to_string(str, node->slice_expr.max); + str = write_expr_to_string(str, se->max); } str = gb_string_appendc(str, "]"); - break; + case_end; - - case AstNode_CastExpr: + case_ast_node(ce, CastExpr, node); str = gb_string_appendc(str, "cast("); - str = write_expr_to_string(str, node->cast_expr.type); + str = write_expr_to_string(str, ce->type); str = gb_string_appendc(str, ")"); - str = write_expr_to_string(str, node->cast_expr.expr); - break; + str = write_expr_to_string(str, ce->expr); + case_end; - case AstNode_PointerType: + case_ast_node(pt, PointerType, node); str = gb_string_appendc(str, "^"); - str = write_expr_to_string(str, node->pointer_type.type); - break; - case AstNode_ArrayType: + str = write_expr_to_string(str, pt->type); + case_end; + + case_ast_node(at, ArrayType, node); str = gb_string_appendc(str, "["); - str = write_expr_to_string(str, node->array_type.count); + str = write_expr_to_string(str, at->count); str = gb_string_appendc(str, "]"); - str = write_expr_to_string(str, node->array_type.elem); - break; + str = write_expr_to_string(str, at->elem); + case_end; - - case AstNode_CallExpr: { - str = write_expr_to_string(str, node->call_expr.proc); + case_ast_node(ce, CallExpr, node); + str = write_expr_to_string(str, ce->proc); str = gb_string_appendc(str, "("); isize i = 0; - for (AstNode *arg = node->call_expr.arg_list; arg != NULL; arg = arg->next) { + for (AstNode *arg = ce->arg_list; arg != NULL; arg = arg->next) { if (i > 0) gb_string_appendc(str, ", "); str = write_expr_to_string(str, arg); i++; } str = gb_string_appendc(str, ")"); - } break; + case_end; - case AstNode_ProcType: + case_ast_node(pt, ProcType, node); str = gb_string_appendc(str, "proc("); - str = write_field_list_to_string(str, node->proc_type.param_list, ", "); + str = write_field_list_to_string(str, pt->param_list, ", "); str = gb_string_appendc(str, ")"); + case_end; - break; - case AstNode_StructType: + case_ast_node(st, StructType, node); str = gb_string_appendc(str, "struct{"); + str = write_field_list_to_string(str, st->field_list, ", "); str = gb_string_appendc(str, "}"); - break; + case_end; } diff --git a/src/checker/statements.cpp b/src/checker/statements.cpp index 364a1de69..bf6f0d87b 100644 --- a/src/checker/statements.cpp +++ b/src/checker/statements.cpp @@ -39,29 +39,32 @@ b32 check_is_terminating_list(Checker *c, AstNode *list) { // TODO(bill): Warn/err against code after `return` that it won't be executed b32 check_is_terminating(Checker *c, AstNode *node) { switch (node->kind) { - case AstNode_ReturnStmt: + case_ast_node(rs, ReturnStmt, node); return true; + case_end; - case AstNode_BlockStmt: - return check_is_terminating_list(c, node->block_stmt.list); + case_ast_node(bs, BlockStmt, node); + return check_is_terminating_list(c, bs->list); + case_end; - case AstNode_ExprStmt: - return check_is_terminating(c, node->expr_stmt.expr); + case_ast_node(es, ExprStmt, node); + return check_is_terminating(c, es->expr); + case_end; - case AstNode_IfStmt: - if (node->if_stmt.else_stmt != NULL) { - if (check_is_terminating(c, node->if_stmt.body) && - check_is_terminating(c, node->if_stmt.else_stmt)) { + case_ast_node(is, IfStmt, node); + if (is->else_stmt != NULL) { + if (check_is_terminating(c, is->body) && + check_is_terminating(c, is->else_stmt)) { return true; } } - break; + case_end; - case AstNode_ForStmt: - if (node->for_stmt.cond == NULL) { + case_ast_node(fs, ForStmt, node); + if (fs->cond == NULL) { return true; } - break; + case_end; } return false; @@ -170,19 +173,22 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) { AstNode *node = unparen_expr(lhs); // NOTE(bill): Ignore assignments to `_` - if (node->kind == AstNode_Ident && - are_strings_equal(node->ident.token.string, make_string("_"))) { - add_entity_definition(&c->info, node, NULL); - check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier")); - if (op_a->mode == Addressing_Invalid) - return NULL; - return op_a->type; - } + if (node->kind == AstNode_Ident) { + ast_node(i, Ident, node); + if (are_strings_equal(i->token.string, make_string("_"))) { + add_entity_definition(&c->info, node, NULL); + check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier")); + if (op_a->mode == Addressing_Invalid) + return NULL; + return op_a->type; + } + } Entity *e = NULL; b32 used = false; if (node->kind == AstNode_Ident) { - e = scope_lookup_entity(c->context.scope, node->ident.token.string); + ast_node(i, Ident, node); + e = scope_lookup_entity(c->context.scope, i->token.string); if (e != NULL && e->kind == Entity_Variable) { used = e->variable.used; // TODO(bill): Make backup just in case } @@ -207,7 +213,8 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) { if (op_b.expr->kind == AstNode_SelectorExpr) { // NOTE(bill): Extra error checks Operand op_c = {Addressing_Invalid}; - check_expr(c, &op_c, op_b.expr->selector_expr.expr); + ast_node(se, SelectorExpr, op_b.expr); + check_expr(c, &op_c, se->expr); } gbString str = expr_to_string(op_b.expr); @@ -379,10 +386,11 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod c->context.decl = decl; push_procedure(c, type); - check_stmt_list(c, body->block_stmt.list, 0); + ast_node(bs, BlockStmt, body); + check_stmt_list(c, bs->list, 0); if (type->procedure.result_count > 0) { if (!check_is_terminating(c, body)) { - error(&c->error_collector, body->block_stmt.close, "Missing return statement at the end of the procedure"); + error(&c->error_collector, bs->close, "Missing return statement at the end of the procedure"); } } pop_procedure(c); @@ -395,7 +403,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { Type *proc_type = make_type_procedure(c->allocator, e->parent, NULL, 0, NULL, 0); e->type = proc_type; - auto *pd = &d->proc_decl->proc_decl; + ast_node(pd, ProcDecl, d->proc_decl); #if 1 Scope *original_curr_scope = c->context.scope; @@ -409,7 +417,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { for (AstNode *tag = pd->tag_list; tag != NULL; tag = tag->next) { GB_ASSERT(tag->kind == AstNode_TagExpr); - String tag_name = tag->tag_expr.name.string; + ast_node(te, TagExpr, tag); + String tag_name = te->name.string; if (are_strings_equal(tag_name, make_string("foreign"))) { is_foreign = true; } else if (are_strings_equal(tag_name, make_string("inline"))) { @@ -516,13 +525,13 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { void check_stmt(Checker *c, AstNode *node, u32 flags) { switch (node->kind) { - case AstNode_EmptyStmt: break; - case AstNode_BadStmt: break; - case AstNode_BadDecl: break; + case_ast_node(_, EmptyStmt, node); case_end; + case_ast_node(_, BadStmt, node); case_end; + case_ast_node(_, BadDecl, node); case_end; - case AstNode_ExprStmt: { + case_ast_node(es, ExprStmt, node) Operand operand = {Addressing_Invalid}; - ExpressionKind kind = check_expr_base(c, &operand, node->expr_stmt.expr); + ExpressionKind kind = check_expr_base(c, &operand, es->expr); switch (operand.mode) { case Addressing_Type: error(&c->error_collector, ast_node_token(node), "Is not an expression"); @@ -533,19 +542,18 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { error(&c->error_collector, ast_node_token(node), "Expression is not used"); break; } - } break; + case_end; - case AstNode_TagStmt: + case_ast_node(ts, TagStmt, node); // TODO(bill): Tag Statements error(&c->error_collector, ast_node_token(node), "Tag statements are not supported yet"); - check_stmt(c, node->tag_stmt.stmt, flags); - break; + check_stmt(c, ts->stmt, flags); + case_end; - case AstNode_IncDecStmt: { + case_ast_node(ids, IncDecStmt, node); Token op = {}; - auto *s = &node->inc_dec_stmt; - op = s->op; - switch (s->op.kind) { + op = ids->op; + switch (ids->op.kind) { case Token_Increment: op.kind = Token_Add; op.string.len = 1; @@ -555,44 +563,45 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { op.string.len = 1; break; default: - error(&c->error_collector, s->op, "Unknown inc/dec operation %.*s", LIT(s->op.string)); + error(&c->error_collector, ids->op, "Unknown inc/dec operation %.*s", LIT(ids->op.string)); return; } Operand operand = {Addressing_Invalid}; - check_expr(c, &operand, s->expr); + check_expr(c, &operand, ids->expr); if (operand.mode == Addressing_Invalid) return; if (!is_type_numeric(operand.type)) { - error(&c->error_collector, s->op, "Non numeric type"); + error(&c->error_collector, ids->op, "Non numeric type"); return; } AstNode basic_lit = {AstNode_BasicLit}; - basic_lit.basic_lit = s->op; - basic_lit.basic_lit.kind = Token_Integer; - basic_lit.basic_lit.string = make_string("1"); + ast_node(bl, BasicLit, &basic_lit); + *bl = ids->op; + bl->kind = Token_Integer; + bl->string = make_string("1"); - AstNode be = {AstNode_BinaryExpr}; - be.binary_expr.op = op; - be.binary_expr.left = s->expr;; - be.binary_expr.right = &basic_lit; - check_binary_expr(c, &operand, &be); + AstNode binary_expr = {AstNode_BinaryExpr}; + ast_node(be, BinaryExpr, &binary_expr); + be->op = op; + be->left = ids->expr; + be->right = &basic_lit; + check_binary_expr(c, &operand, &binary_expr); + case_end; - } break; - - case AstNode_AssignStmt: - switch (node->assign_stmt.op.kind) { + case_ast_node(as, AssignStmt, node); + switch (as->op.kind) { case Token_Eq: { // a, b, c = 1, 2, 3; // Multisided - if (node->assign_stmt.lhs_count == 0) { - error(&c->error_collector, node->assign_stmt.op, "Missing lhs in assignment statement"); + if (as->lhs_count == 0) { + error(&c->error_collector, as->op, "Missing lhs in assignment statement"); return; } Operand operand = {}; - AstNode *lhs = node->assign_stmt.lhs_list; - AstNode *rhs = node->assign_stmt.rhs_list; + AstNode *lhs = as->lhs_list; + AstNode *rhs = as->rhs_list; isize i = 0; for (; lhs != NULL && rhs != NULL; @@ -615,7 +624,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { } } - if (i < node->assign_stmt.lhs_count && i < node->assign_stmt.rhs_count) { + if (i < as->lhs_count && i < as->rhs_count) { if (lhs == NULL) error(&c->error_collector, ast_node_token(lhs), "Too few values on the right hand side of the declaration"); } else if (rhs != NULL) { @@ -625,9 +634,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { default: { // a += 1; // Single-sided - Token op = node->assign_stmt.op; - if (node->assign_stmt.lhs_count != 1 || - node->assign_stmt.rhs_count != 1) { + Token op = as->op; + if (as->lhs_count != 1 || as->rhs_count != 1) { error(&c->error_collector, op, "Assignment operation `%.*s` requires single-valued expressions", LIT(op.string)); return; } @@ -637,61 +645,60 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { } // TODO(bill): Check if valid assignment operator Operand operand = {Addressing_Invalid}; - AstNode be = {AstNode_BinaryExpr}; - be.binary_expr.op = op; + AstNode binary_expr = {AstNode_BinaryExpr}; + ast_node(be, BinaryExpr, &binary_expr); + be->op = op; // NOTE(bill): Only use the first one will be used - be.binary_expr.left = node->assign_stmt.lhs_list; - be.binary_expr.right = node->assign_stmt.rhs_list; + be->left = as->lhs_list; + be->right = as->rhs_list; - check_binary_expr(c, &operand, &be); + check_binary_expr(c, &operand, &binary_expr); if (operand.mode == Addressing_Invalid) return; // NOTE(bill): Only use the first one will be used - check_assignment_variable(c, &operand, node->assign_stmt.lhs_list); + check_assignment_variable(c, &operand, as->lhs_list); } break; } - break; + case_end; - case AstNode_BlockStmt: + case_ast_node(bs, BlockStmt, node); check_open_scope(c, node); - check_stmt_list(c, node->block_stmt.list, flags); + check_stmt_list(c, bs->list, flags); check_close_scope(c); - break; + case_end; - case AstNode_IfStmt: { + case_ast_node(is, IfStmt, node); check_open_scope(c, node); defer (check_close_scope(c)); - auto *is = &node->if_stmt; if (is->init != NULL) check_stmt(c, is->init, 0); Operand operand = {Addressing_Invalid}; - check_expr(c, &operand, node->if_stmt.cond); + check_expr(c, &operand, is->cond); if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) { - error(&c->error_collector, ast_node_token(node->if_stmt.cond), + error(&c->error_collector, ast_node_token(is->cond), "Non-boolean condition in `if` statement"); } - check_stmt(c, node->if_stmt.body, flags); + check_stmt(c, is->body, flags); - if (node->if_stmt.else_stmt) { - switch (node->if_stmt.else_stmt->kind) { + if (is->else_stmt) { + switch (is->else_stmt->kind) { case AstNode_IfStmt: case AstNode_BlockStmt: - check_stmt(c, node->if_stmt.else_stmt, flags); + check_stmt(c, is->else_stmt, flags); break; default: - error(&c->error_collector, ast_node_token(node->if_stmt.else_stmt), + error(&c->error_collector, ast_node_token(is->else_stmt), "Invalid `else` statement in `if` statement"); break; } } - } break; + case_end; - case AstNode_ReturnStmt: { - auto *rs = &node->return_stmt; + case_ast_node(rs, ReturnStmt, node); GB_ASSERT(gb_array_count(c->procedure_stack) > 0); if (c->in_defer) { @@ -714,31 +721,30 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { check_init_variables(c, tuple->variables, tuple->variable_count, rs->result_list, rs->result_count, make_string("return statement")); } - } break; + case_end; - case AstNode_ForStmt: { + case_ast_node(fs, ForStmt, node); flags |= Statement_BreakAllowed | Statement_ContinueAllowed; check_open_scope(c, node); defer (check_close_scope(c)); - if (node->for_stmt.init != NULL) - check_stmt(c, node->for_stmt.init, 0); - if (node->for_stmt.cond) { + if (fs->init != NULL) + check_stmt(c, fs->init, 0); + if (fs->cond) { Operand operand = {Addressing_Invalid}; - check_expr(c, &operand, node->for_stmt.cond); + check_expr(c, &operand, fs->cond); if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) { - error(&c->error_collector, ast_node_token(node->for_stmt.cond), + error(&c->error_collector, ast_node_token(fs->cond), "Non-boolean condition in `for` statement"); } } - if (node->for_stmt.end != NULL) - check_stmt(c, node->for_stmt.end, 0); - check_stmt(c, node->for_stmt.body, flags); - } break; + if (fs->end != NULL) + check_stmt(c, fs->end, 0); + check_stmt(c, fs->body, flags); + case_end; - case AstNode_DeferStmt: { - auto *ds = &node->defer_stmt; + case_ast_node(ds, DeferStmt, node); if (is_ast_node_decl(ds->stmt)) { error(&c->error_collector, ds->token, "You cannot defer a declaration"); } else { @@ -747,10 +753,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { check_stmt(c, ds->stmt, 0); c->in_defer = out_in_defer; } - } break; + case_end; - case AstNode_BranchStmt: { - Token token = node->branch_stmt.token; + case_ast_node(bs, BranchStmt, node); + Token token = bs->token; switch (token.kind) { case Token_break: if ((flags & Statement_BreakAllowed) == 0) @@ -764,12 +770,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { error(&c->error_collector, token, "Invalid AST: Branch Statement `%.*s`", LIT(token.string)); break; } - } break; + case_end; // Declarations - case AstNode_VarDecl: { - auto *vd = &node->var_decl; + case_ast_node(vd, VarDecl, node); isize entity_count = vd->name_count; isize entity_index = 0; Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count); @@ -780,7 +785,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { for (AstNode *name = vd->name_list; name != NULL; name = name->next) { Entity *entity = NULL; - Token token = name->ident.token; + Token token = name->Ident.token; if (name->kind == AstNode_Ident) { String str = token.string; Entity *found = NULL; @@ -841,7 +846,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { name = name->next, value = value->next) { GB_ASSERT(name->kind == AstNode_Ident); ExactValue v = {ExactValue_Invalid}; - Entity *e = make_entity_constant(c->allocator, c->context.scope, name->ident.token, NULL, v); + ast_node(i, Ident, name); + Entity *e = make_entity_constant(c->allocator, c->context.scope, i->token, NULL, v); entities[entity_index++] = e; check_const_decl(c, e, vd->type, value); } @@ -866,11 +872,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { error(&c->error_collector, ast_node_token(node), "Unknown variable declaration kind. Probably an invalid AST."); return; } - } break; + case_end; - case AstNode_ProcDecl: { - auto *pd = &node->proc_decl; - Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->ident.token, NULL); + case_ast_node(pd, ProcDecl, node); + ast_node(name, Ident, pd->name); + Entity *e = make_entity_procedure(c->allocator, c->context.scope, name->token, NULL); add_entity(c, c->context.scope, pd->name, e); DeclInfo decl = {}; @@ -878,22 +884,20 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { decl.proc_decl = node; check_proc_decl(c, e, &decl, false); destroy_declaration_info(&decl); - } break; + case_end; - case AstNode_TypeDecl: { - auto *td = &node->type_decl; - AstNode *name = td->name; - Entity *e = make_entity_type_name(c->allocator, c->context.scope, name->ident.token, NULL); - add_entity(c, c->context.scope, name, e); + case_ast_node(td, TypeDecl, node); + ast_node(name, Ident, td->name); + Entity *e = make_entity_type_name(c->allocator, c->context.scope, name->token, NULL); + add_entity(c, c->context.scope, td->name, e); check_type_decl(c, e, td->type, NULL); - } break; + case_end; - case AstNode_AliasDecl: { - auto *ad = &node->alias_decl; - AstNode *name = ad->name; - Entity *e = make_entity_alias_name(c->allocator, c->context.scope, name->ident.token, NULL); - add_entity(c, c->context.scope, name, e); + case_ast_node(ad, AliasDecl, node); + ast_node(name, Ident, ad->name); + Entity *e = make_entity_alias_name(c->allocator, c->context.scope, name->token, NULL); + add_entity(c, c->context.scope, ad->name, e); check_alias_decl(c, e, ad->type, NULL); - } break; + case_end; } } diff --git a/src/codegen/print.cpp b/src/codegen/print.cpp index d8c76d034..c51a88de5 100644 --- a/src/codegen/print.cpp +++ b/src/codegen/print.cpp @@ -215,24 +215,24 @@ void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint) ssa_print_encoded_global(f, value->global.entity->token.string); break; case ssaValue_Procedure: - ssa_print_encoded_global(f, value->procedure.entity->token.string); + ssa_print_encoded_global(f, value->proc.entity->token.string); break; case ssaValue_Constant: { ssa_print_exact_value(f, m, value->constant.value, type_hint); } break; - case ssaValue_Instruction: + case ssaValue_Instr: ssa_fprintf(f, "%%%d", value->id); break; } } -void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) { - GB_ASSERT(value->kind == ssaValue_Instruction); - ssaInstruction *instr = &value->instruction; +void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) { + GB_ASSERT(value->kind == ssaValue_Instr); + ssaInstr *instr = &value->instr; ssa_fprintf(f, "\t"); switch (instr->kind) { - case ssaInstruction_Local: { + case ssaInstr_Local: { Type *type = instr->local.entity->type; ssa_fprintf(f, "%%%d = alloca ", value->id); ssa_print_type(f, m->sizes, type); @@ -246,7 +246,7 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "* %%%d\n", value->id); } break; - case ssaInstruction_Store: { + case ssaInstr_Store: { Type *type = ssa_value_type(instr->store.address); ssa_fprintf(f, "store "); ssa_print_type(f, m->sizes, type); @@ -259,7 +259,7 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "\n"); } break; - case ssaInstruction_Load: { + case ssaInstr_Load: { Type *type = instr->load.type; ssa_fprintf(f, "%%%d = load ", value->id); ssa_print_type(f, m->sizes, type); @@ -270,8 +270,7 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) { ssa_fprintf(f, "\n"); } break; - case ssaInstruction_GetElementPtr: { - Type *rt = instr->get_element_ptr.result_type; + case ssaInstr_GetElementPtr: { Type *et = instr->get_element_ptr.element_type; Type *t_int = &basic_types[Basic_int]; ssa_fprintf(f, "%%%d = getelementptr ", value->id); @@ -283,22 +282,35 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) { ssa_print_type(f, m->sizes, et); ssa_fprintf(f, "* "); ssa_print_value(f, m, instr->get_element_ptr.address, et); - ssa_fprintf(f, ", "); - ssa_print_type(f, m->sizes, t_int); - ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->get_element_ptr.indices[0], t_int); - if (instr->get_element_ptr.index_count == 2) { + for (isize i = 0; i < instr->get_element_ptr.index_count; i++) { ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, t_int); ssa_fprintf(f, " "); - ssa_print_value(f, m, instr->get_element_ptr.indices[1], t_int); + ssa_print_value(f, m, instr->get_element_ptr.indices[i], t_int); } ssa_fprintf(f, "\n"); } break; + case ssaInstr_Br: { + ssa_fprintf(f, "br "); + if (instr->br.cond != NULL) { + Type *t_bool = &basic_types[Basic_bool]; + ssa_print_type(f, m->sizes, t_bool); + ssa_fprintf(f, " "); + ssa_print_value(f, m, instr->br.cond, t_bool); + ssa_fprintf(f, ", ", instr->br.cond->id); + } + ssa_fprintf(f, "label "); + ssa_print_encoded_local(f, instr->br.true_block->label); + if (instr->br.false_block != NULL) { + ssa_fprintf(f, ", label "); + ssa_print_encoded_local(f, instr->br.false_block->label); + } + ssa_fprintf(f, "\n"); + } break; - case ssaInstruction_BinaryOp: { - auto *bo = &value->instruction.binary_op; + case ssaInstr_BinaryOp: { + auto *bo = &value->instr.binary_op; Type *type = ssa_value_type(bo->left); ssa_fprintf(f, "%%%d = ", value->id); @@ -319,9 +331,9 @@ void ssa_print_instruction(gbFile *f, ssaModule *m, ssaValue *value) { if (bo->op.kind != Token_CmpEq && bo->op.kind != Token_NotEq) { if (is_type_unsigned(type)) { - ssa_fprintf(f, "s"); - } else { ssa_fprintf(f, "u"); + } else { + ssa_fprintf(f, "s"); } } switch (bo->op.kind) { @@ -401,7 +413,7 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) { } break; case ssaValue_Procedure: { - ssaProcedure *proc = &v->procedure; + ssaProcedure *proc = &v->proc; if (proc->body == NULL) { ssa_fprintf(f, "declare "); } else { @@ -438,12 +450,12 @@ void ssa_print_llvm_ir(gbFile *f, ssaModule *m) { ssa_fprintf(f, "\n"); } else { ssa_fprintf(f, "{\n"); - gb_for_array(i, proc->blocks) { - ssaBlock *block = &proc->blocks[i]->block; + gb_for_array(i, proc->blocks.entries) { + ssaBlock *block = &proc->blocks.entries[i].value->block; ssa_fprintf(f, "%.*s:\n", LIT(block->label)); - gb_for_array(j, block->instructions) { - ssaValue *value = block->instructions[j]; - ssa_print_instruction(f, m, value); + gb_for_array(j, block->instrs) { + ssaValue *value = block->instrs[j]; + ssa_print_instr(f, m, value); } } diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index bb1f51b81..a21d8fd67 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -22,7 +22,7 @@ struct ssaBlock { String label; ssaProcedure *parent; - gbArray(ssaValue *) instructions; + gbArray(ssaValue *) instrs; gbArray(ssaValue *) values; }; @@ -35,37 +35,54 @@ struct ssaProcedure { AstNode *type_expr; AstNode *body; - gbArray(ssaValue *) blocks; + Map blocks; ssaBlock *curr_block; gbArray(ssaValue *) anonymous_procedures; }; -#define SSA_INSTRUCTION_KINDS \ - SSA_INSTRUCTION_KIND(Invalid), \ - SSA_INSTRUCTION_KIND(Local), \ - SSA_INSTRUCTION_KIND(Store), \ - SSA_INSTRUCTION_KIND(Load), \ - SSA_INSTRUCTION_KIND(GetElementPtr), \ - SSA_INSTRUCTION_KIND(Convert), \ - SSA_INSTRUCTION_KIND(BinaryOp), \ - SSA_INSTRUCTION_KIND(Count), +#define SSA_INSTR_KINDS \ + SSA_INSTR_KIND(Invalid), \ + SSA_INSTR_KIND(Local), \ + SSA_INSTR_KIND(Store), \ + SSA_INSTR_KIND(Load), \ + SSA_INSTR_KIND(GetElementPtr), \ + SSA_INSTR_KIND(Convert), \ + SSA_INSTR_KIND(Br), \ + SSA_INSTR_KIND(BinaryOp), \ + SSA_INSTR_KIND(Count), -enum ssaInstructionKind { -#define SSA_INSTRUCTION_KIND(x) GB_JOIN2(ssaInstruction_, x) - SSA_INSTRUCTION_KINDS -#undef SSA_INSTRUCTION_KIND +enum ssaInstrKind { +#define SSA_INSTR_KIND(x) GB_JOIN2(ssaInstr_, x) + SSA_INSTR_KINDS +#undef SSA_INSTR_KIND }; -String const ssa_instruction_strings[] = { -#define SSA_INSTRUCTION_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1} - SSA_INSTRUCTION_KINDS -#undef SSA_INSTRUCTION_KIND +String const ssa_instr_strings[] = { +#define SSA_INSTR_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1} + SSA_INSTR_KINDS +#undef SSA_INSTR_KIND }; -struct ssaInstruction { - ssaInstructionKind kind; +enum ssaConversionKind { + ssaConversion_Invalid, + + ssaConversion_ZExt, + ssaConversion_FPExt, + ssaConversion_FPToUI, + ssaConversion_FPToSI, + ssaConversion_UIToFP, + ssaConversion_SIToFP, + ssaConversion_PtrToInt, + ssaConversion_IntToPtr, + ssaConversion_BitCast, + + ssaConversion_Count, +}; + +struct ssaInstr { + ssaInstrKind kind; ssaBlock *parent; Type *type; @@ -93,11 +110,23 @@ struct ssaInstruction { b32 inbounds; } get_element_ptr; + struct { + ssaValue *cond; + ssaBlock *true_block; + ssaBlock *false_block; + } br; + struct { Type *type; Token op; ssaValue *left, *right; } binary_op; + + struct { + ssaConversionKind kind; + ssaValue *value; + Type *from, *to; + } conversion; }; }; @@ -111,7 +140,7 @@ enum ssaValueKind { ssaValue_Procedure, ssaValue_Block, - ssaValue_Instruction, + ssaValue_Instr, ssaValue_Count, }; @@ -130,14 +159,14 @@ struct ssaValue { Type * type; } type_name; struct { - b32 generated; + b32 is_gen; Entity * entity; Type * type; ssaValue *value; } global; - ssaProcedure procedure; + ssaProcedure proc; ssaBlock block; - ssaInstruction instruction; + ssaInstr instr; }; }; @@ -159,6 +188,13 @@ struct ssaLvalue { }; }; +ssaLvalue ssa_make_lvalue_address(ssaValue *value, AstNode *expr) { + ssaLvalue lval = {ssaLvalue_Address}; + lval.address.value = value; + lval.address.expr = expr; + return lval; +} + void ssa_module_init(ssaModule *m, Checker *c) { m->allocator = gb_heap_allocator(); @@ -182,37 +218,37 @@ void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v) { Type *ssa_value_type(ssaValue *value); void ssa_value_set_type(ssaValue *value, Type *type); -Type *ssa_instruction_type(ssaInstruction *instr) { +Type *ssa_instr_type(ssaInstr *instr) { switch (instr->kind) { - case ssaInstruction_Local: + case ssaInstr_Local: return instr->local.type; - case ssaInstruction_Store: + case ssaInstr_Store: return ssa_value_type(instr->store.address); - case ssaInstruction_Load: + case ssaInstr_Load: return instr->load.type; - case ssaInstruction_GetElementPtr: + case ssaInstr_GetElementPtr: return instr->get_element_ptr.result_type; - case ssaInstruction_BinaryOp: + case ssaInstr_BinaryOp: return instr->binary_op.type; } return NULL; } -void ssa_instruction_set_type(ssaInstruction *instr, Type *type) { +void ssa_instr_set_type(ssaInstr *instr, Type *type) { switch (instr->kind) { - case ssaInstruction_Local: + case ssaInstr_Local: instr->local.type = type; break; - case ssaInstruction_Store: + case ssaInstr_Store: ssa_value_set_type(instr->store.value, type); break; - case ssaInstruction_Load: + case ssaInstr_Load: instr->load.type = type; break; - case ssaInstruction_GetElementPtr: + case ssaInstr_GetElementPtr: instr->get_element_ptr.result_type = type; break; - case ssaInstruction_BinaryOp: + case ssaInstr_BinaryOp: instr->binary_op.type = type; break; } @@ -225,11 +261,11 @@ Type *ssa_value_type(ssaValue *value) { case ssaValue_Global: return value->global.type; case ssaValue_Procedure: - return value->procedure.type; + return value->proc.type; case ssaValue_Constant: return value->constant.type; - case ssaValue_Instruction: - return ssa_instruction_type(&value->instruction); + case ssaValue_Instr: + return ssa_instr_type(&value->instr); } return NULL; } @@ -244,13 +280,13 @@ void ssa_value_set_type(ssaValue *value, Type *type) { value->global.type = type; break; case ssaValue_Procedure: - value->procedure.type = type; + value->proc.type = type; break; case ssaValue_Constant: value->constant.type = type; break; - case ssaValue_Instruction: - ssa_instruction_set_type(&value->instruction, type); + case ssaValue_Instr: + ssa_instr_set_type(&value->instr, type); break; } } @@ -259,8 +295,8 @@ void ssa_value_set_type(ssaValue *value, Type *type) { ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr); ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv); -ssaLvalue ssa_build_address(ssaProcedure *proc, AstNode *expr); -ssaValue *ssa_emit_conversion(ssaProcedure *proc, ssaValue *value, Type *a_type); +ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr); +ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *a_type); @@ -273,9 +309,9 @@ ssaValue *ssa_alloc_value(gbAllocator a, ssaValueKind kind) { return v; } -ssaValue *ssa_alloc_instruction(gbAllocator a, ssaInstructionKind kind) { - ssaValue *v = ssa_alloc_value(a, ssaValue_Instruction); - v->instruction.kind = kind; +ssaValue *ssa_alloc_instr(gbAllocator a, ssaInstrKind kind) { + ssaValue *v = ssa_alloc_value(a, ssaValue_Instr); + v->instr.kind = kind; return v; } @@ -296,9 +332,9 @@ ssaValue *ssa_make_value_global(gbAllocator a, Entity *e, ssaValue *value) { -ssaValue *ssa_make_instruction_local(ssaProcedure *p, Entity *e) { - ssaValue *v = ssa_alloc_instruction(p->module->allocator, ssaInstruction_Local); - ssaInstruction *i = &v->instruction; +ssaValue *ssa_make_instr_local(ssaProcedure *p, Entity *e) { + ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Local); + ssaInstr *i = &v->instr; i->local.entity = e; i->local.type = e->type; if (p->curr_block) { @@ -309,9 +345,9 @@ ssaValue *ssa_make_instruction_local(ssaProcedure *p, Entity *e) { } -ssaValue *ssa_make_instruction_store(ssaProcedure *p, ssaValue *address, ssaValue *value) { - ssaValue *v = ssa_alloc_instruction(p->module->allocator, ssaInstruction_Store); - ssaInstruction *i = &v->instruction; +ssaValue *ssa_make_instr_store(ssaProcedure *p, ssaValue *address, ssaValue *value) { + ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Store); + ssaInstr *i = &v->instr; i->store.address = address; i->store.value = value; if (p->curr_block) { @@ -320,9 +356,9 @@ ssaValue *ssa_make_instruction_store(ssaProcedure *p, ssaValue *address, ssaValu return v; } -ssaValue *ssa_make_instruction_load(ssaProcedure *p, ssaValue *address) { - ssaValue *v = ssa_alloc_instruction(p->module->allocator, ssaInstruction_Load); - ssaInstruction *i = &v->instruction; +ssaValue *ssa_make_instr_load(ssaProcedure *p, ssaValue *address) { + ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Load); + ssaInstr *i = &v->instr; i->load.address = address; i->load.type = ssa_value_type(address); if (p->curr_block) { @@ -331,11 +367,11 @@ ssaValue *ssa_make_instruction_load(ssaProcedure *p, ssaValue *address) { return v; } -ssaValue *ssa_make_instruction_get_element_ptr(ssaProcedure *p, ssaValue *address, +ssaValue *ssa_make_instr_get_element_ptr(ssaProcedure *p, ssaValue *address, ssaValue *index0, ssaValue *index1, isize index_count, b32 inbounds) { - ssaValue *v = ssa_alloc_instruction(p->module->allocator, ssaInstruction_GetElementPtr); - ssaInstruction *i = &v->instruction; + ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_GetElementPtr); + ssaInstr *i = &v->instr; i->get_element_ptr.address = address; i->get_element_ptr.indices[0] = index0; i->get_element_ptr.indices[1] = index1; @@ -348,9 +384,9 @@ ssaValue *ssa_make_instruction_get_element_ptr(ssaProcedure *p, ssaValue *addres return v; } -ssaValue *ssa_make_instruction_binary_op(ssaProcedure *p, Token op, ssaValue *left, ssaValue *right) { - ssaValue *v = ssa_alloc_instruction(p->module->allocator, ssaInstruction_BinaryOp); - ssaInstruction *i = &v->instruction; +ssaValue *ssa_make_instr_binary_op(ssaProcedure *p, Token op, ssaValue *left, ssaValue *right) { + ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_BinaryOp); + ssaInstr *i = &v->instr; i->binary_op.op = op; i->binary_op.left = left; i->binary_op.right = right; @@ -360,6 +396,17 @@ ssaValue *ssa_make_instruction_binary_op(ssaProcedure *p, Token op, ssaValue *le return v; } +ssaValue *ssa_make_instr_br(ssaProcedure *p, ssaValue *cond, ssaBlock *true_block, ssaBlock *false_block) { + ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_Br); + ssaInstr *i = &v->instr; + i->br.cond = cond; + i->br.true_block = true_block; + i->br.false_block = false_block; + if (p->curr_block) { + gb_array_append(p->curr_block->values, v); + } + return v; +} ssaValue *ssa_make_value_constant(gbAllocator a, Type *type, ExactValue value) { ssaValue *v = ssa_alloc_value(a, ssaValue_Constant); @@ -370,22 +417,22 @@ ssaValue *ssa_make_value_constant(gbAllocator a, Type *type, ExactValue value) { ssaValue *ssa_make_value_procedure(gbAllocator a, Entity *e, DeclInfo *decl, ssaModule *m) { ssaValue *v = ssa_alloc_value(a, ssaValue_Procedure); - v->procedure.module = m; - v->procedure.entity = e; - v->procedure.type = e->type; - v->procedure.decl = decl; - v->procedure.name = e->token.string; + v->proc.module = m; + v->proc.entity = e; + v->proc.type = e->type; + v->proc.decl = decl; + v->proc.name = e->token.string; return v; } -ssaValue *ssa_make_value_block(gbAllocator a, ssaProcedure *proc, AstNode *node, Scope *scope, String label) { - ssaValue *v = ssa_alloc_value(a, ssaValue_Block); +ssaValue *ssa_make_value_block(ssaProcedure *proc, AstNode *node, Scope *scope, String label) { + ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block); v->block.label = label; v->block.node = node; v->block.scope = scope; v->block.parent = proc; - gb_array_init(v->block.instructions, gb_heap_allocator()); + gb_array_init(v->block.instrs, gb_heap_allocator()); gb_array_init(v->block.values, gb_heap_allocator()); return v; @@ -412,7 +459,7 @@ ssaValue *ssa_add_global_string(ssaProcedure *proc, ExactValue value) { ssaValue *g = ssa_make_value_global(a, entity, v); - g->global.generated = true; + g->global.is_gen = true; map_set(&proc->module->values, hash_pointer(entity), g); map_set(&proc->module->members, hash_string(name), g); @@ -420,36 +467,40 @@ ssaValue *ssa_add_global_string(ssaProcedure *proc, ExactValue value) { return g; } - ssaValue *ssa_add_block(ssaProcedure *proc, AstNode *node, String label) { - gbAllocator a = proc->module->allocator; Scope *scope = NULL; Scope **found = map_get(&proc->module->info->scopes, hash_pointer(node)); if (found) scope = *found; - ssaValue *block = ssa_make_value_block(a, proc, node, scope, label); - gb_array_append(proc->blocks, block); + + // IMPORTANT TODO(bill): Check for duplicate labels and replace in a sane way + // if (map_get(&proc->blocks, hash_string(label)) != NULL) { + // GB_PANIC("Block of name `%.*s` already exists", LIT(label)); + // } + + ssaValue *block = ssa_make_value_block(proc, node, scope, label); + map_set(&proc->blocks, hash_string(label), block); return block; } - void ssa_begin_procedure_body(ssaProcedure *proc) { - gb_array_init(proc->blocks, gb_heap_allocator()); + map_init(&proc->blocks, gb_heap_allocator()); ssaValue *b = ssa_add_block(proc, proc->body, make_string("entry")); proc->curr_block = &b->block; } void ssa_end_procedure_body(ssaProcedure *proc) { - // Number registers i32 reg_id = 0; - gb_for_array(i, proc->blocks) { - ssaBlock *b = &proc->blocks[i]->block; - gb_for_array(j, b->instructions) { - ssaValue *value = b->instructions[j]; - ssaInstruction *instr = &value->instruction; - if (instr->kind == ssaInstruction_Store) { + gb_for_array(i, proc->blocks.entries) { + ssaBlock *b = &proc->blocks.entries[i].value->block; + gb_for_array(j, b->instrs) { + ssaValue *value = b->instrs[j]; + ssaInstr *instr = &value->instr; + switch (instr->kind) { + case ssaInstr_Store: + case ssaInstr_Br: continue; } value->id = reg_id; @@ -459,15 +510,18 @@ void ssa_end_procedure_body(ssaProcedure *proc) { } -b32 ssa_is_blank_identifier(AstNode *i) { - GB_ASSERT(i->kind == AstNode_Ident); - return are_strings_equal(i->ident.token.string, make_string("_")); +b32 ssa_is_blank_ident(AstNode *node) { + if (node->kind == AstNode_Ident) { + ast_node(i, Ident, node); + return are_strings_equal(i->token.string, make_string("_")); + } + return false; } ssaValue *ssa_block_emit(ssaBlock *b, ssaValue *instr) { - instr->instruction.parent = b; - gb_array_append(b->instructions, instr); + instr->instr.parent = b; + gb_array_append(b->instrs, instr); return instr; } @@ -477,9 +531,7 @@ ssaValue *ssa_emit(ssaProcedure *proc, ssaValue *instr) { ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e) { - ssaValue *instr = ssa_make_instruction_local(proc, e); - ssa_emit(proc, instr); - return instr; + return ssa_emit(proc, ssa_make_instr_local(proc, e)); } ssaValue *ssa_add_local_for_identifier(ssaProcedure *proc, AstNode *name) { @@ -492,15 +544,11 @@ ssaValue *ssa_add_local_for_identifier(ssaProcedure *proc, AstNode *name) { ssaValue *ssa_emit_store(ssaProcedure *p, ssaValue *address, ssaValue *value) { - ssaValue *store = ssa_make_instruction_store(p, address, value); - ssa_emit(p, store); - return store; + return ssa_emit(p, ssa_make_instr_store(p, address, value)); } ssaValue *ssa_emit_load(ssaProcedure *p, ssaValue *address) { - ssaValue *v = ssa_make_instruction_load(p, address); - ssa_emit(p, v); - return v; + return ssa_emit(p, ssa_make_instr_load(p, address)); } ssaValue *ssa_lvalue_store(ssaLvalue lval, ssaProcedure *p, ssaValue *value) { @@ -508,7 +556,6 @@ ssaValue *ssa_lvalue_store(ssaLvalue lval, ssaProcedure *p, ssaValue *value) { case ssaLvalue_Address: return ssa_emit_store(p, lval.address.value, value); } - GB_PANIC("Illegal lvalue store"); return NULL; } @@ -538,7 +585,7 @@ Type *ssa_lvalue_type(ssaLvalue lval) { return NULL; } -ssaValue *ssa_emit_conversion(ssaProcedure *proc, ssaValue *value, Type *t) { +ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { Type *src_type = ssa_value_type(value); if (are_types_identical(t, src_type)) return value; @@ -552,13 +599,22 @@ ssaValue *ssa_emit_conversion(ssaProcedure *proc, ssaValue *value, Type *t) { } - GB_PANIC("TODO(bill): ssa_emit_conversion"); + GB_PANIC("TODO(bill): ssa_emit_conv"); return NULL; } ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *right, Type *type) { switch (op.kind) { + case Token_AndNot: { + // NOTE(bill): x &~ y == x & (~y) == x & (y ~ -1) + // NOTE(bill): "not" `x` == `x` "xor" `-1` + ssaValue *neg = ssa_make_value_constant(proc->module->allocator, type, make_exact_value_integer(-1)); + op.kind = Token_Xor; + right = ssa_emit_arith(proc, op, right, neg, type); + ssa_value_set_type(right, type); + op.kind = Token_And; + } /* fallthrough */ case Token_Add: case Token_Sub: case Token_Mul: @@ -567,13 +623,12 @@ ssaValue *ssa_emit_arith(ssaProcedure *proc, Token op, ssaValue *left, ssaValue case Token_And: case Token_Or: case Token_Xor: - case Token_AndNot: - left = ssa_emit_conversion(proc, left, type); - right = ssa_emit_conversion(proc, right, type); + left = ssa_emit_conv(proc, left, type); + right = ssa_emit_conv(proc, right, type); break; } - ssaValue *v = ssa_make_instruction_binary_op(proc, op, left, right); + ssaValue *v = ssa_make_instr_binary_op(proc, op, left, right); return ssa_emit(proc, v); } @@ -592,19 +647,41 @@ ssaValue *ssa_emit_compare(ssaProcedure *proc, Token op, ssaValue *left, ssaValu if (are_types_identical(a, b)) { // NOTE(bill): No need for a conversion } else if (left->kind == ssaValue_Constant) { - left = ssa_emit_conversion(proc, left, ssa_value_type(right)); + left = ssa_emit_conv(proc, left, ssa_value_type(right)); } else if (right->kind == ssaValue_Constant) { - right = ssa_emit_conversion(proc, right, ssa_value_type(left)); + right = ssa_emit_conv(proc, right, ssa_value_type(left)); } - ssaValue *v = ssa_make_instruction_binary_op(proc, op, left, right); + ssaValue *v = ssa_make_instr_binary_op(proc, op, left, right); ssa_value_set_type(v, &basic_types[Basic_bool]); return ssa_emit(proc, v); } + +void ssa_emit_jump(ssaProcedure *proc, ssaBlock *block) { + ssaValue *br = ssa_make_instr_br(proc, NULL, block, NULL); + ssa_emit(proc, br); + proc->curr_block = NULL; +} + +void ssa_emit_if(ssaProcedure *proc, ssaValue *cond, ssaBlock *true_block, ssaBlock *false_block) { + ssaValue *br = ssa_make_instr_br(proc, cond, true_block, false_block); + ssa_emit(proc, br); + proc->curr_block = NULL; +} + + + + + + ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv) { switch (expr->kind) { - case AstNode_Ident: { + case_ast_node(bl, BasicLit, expr); + GB_PANIC("Non-constant basic literal"); + case_end; + + case_ast_node(i, Ident, expr); Entity *e = *map_get(&proc->module->info->uses, hash_pointer(expr)); if (e->kind == Entity_Builtin) { GB_PANIC("TODO(bill): Entity_Builtin"); @@ -615,23 +692,22 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue if (found) { return ssa_emit_load(proc, *found); } - } break; + case_end; - case AstNode_ParenExpr: + case_ast_node(pe, ParenExpr, expr); return ssa_build_single_expr(proc, unparen_expr(expr), tv); + case_end; - case AstNode_DerefExpr: { - ssaLvalue addr = ssa_build_address(proc, expr); - ssaValue *load = ssa_lvalue_load(addr, proc); + case_ast_node(de, DerefExpr, expr); + ssaValue *load = ssa_lvalue_load(ssa_build_addr(proc, expr), proc); ssa_value_set_type(load, type_deref(ssa_value_type(load))); return load; - } break; + case_end; - case AstNode_UnaryExpr: { - auto *ue = &expr->unary_expr; + case_ast_node(ue, UnaryExpr, expr); switch (ue->op.kind) { case Token_Pointer: - return ssa_lvalue_address(ssa_build_address(proc, ue->expr), proc); + return ssa_lvalue_address(ssa_build_addr(proc, ue->expr), proc); case Token_Add: return ssa_build_expr(proc, ue->expr); case Token_Sub: { @@ -653,10 +729,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue return NULL; } - } break; + case_end; - case AstNode_BinaryExpr: { - auto *be = &expr->binary_expr; + case_ast_node(be, BinaryExpr, expr); switch (be->op.kind) { case Token_Add: case Token_Sub: @@ -666,22 +741,12 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case Token_And: case Token_Or: case Token_Xor: + case Token_AndNot: return ssa_emit_arith(proc, be->op, ssa_build_expr(proc, be->left), ssa_build_expr(proc, be->right), tv->type); - case Token_AndNot: { - AstNode ue = {AstNode_UnaryExpr}; - ue.unary_expr.op = be->op; - ue.unary_expr.op.kind = Token_Xor; - ue.unary_expr.expr = be->right; - ssaValue *left = ssa_build_expr(proc, be->left); - ssaValue *right = ssa_build_expr(proc, &ue); - Token op = be->op; - op.kind = Token_And; - return ssa_emit_arith(proc, op, left, right, tv->type); - } break; case Token_CmpEq: case Token_NotEq: @@ -692,23 +757,31 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *cmp = ssa_emit_compare(proc, be->op, ssa_build_expr(proc, be->left), ssa_build_expr(proc, be->right)); - return ssa_emit_conversion(proc, cmp, default_type(tv->type)); + return ssa_emit_conv(proc, cmp, default_type(tv->type)); } break; default: GB_PANIC("Invalid binary expression"); } - } break; - case AstNode_ProcLit: - break; - case AstNode_CastExpr: - break; - case AstNode_CallExpr: - break; - case AstNode_SliceExpr: - break; - case AstNode_IndexExpr: { - auto *ie = &expr->index_expr; + case_end; + + case_ast_node(se, ProcLit, expr); + GB_PANIC("TODO(bill): ssa_build_single_expr ProcLit"); + case_end; + + case_ast_node(se, CastExpr, expr); + GB_PANIC("TODO(bill): ssa_build_single_expr CastExpr"); + case_end; + + case_ast_node(se, CallExpr, expr); + GB_PANIC("TODO(bill): ssa_build_single_expr CallExpr"); + case_end; + + case_ast_node(se, SliceExpr, expr); + GB_PANIC("TODO(bill): ssa_build_single_expr SliceExpr"); + case_end; + + case_ast_node(ie, IndexExpr, expr); Type *t = type_of_expr(proc->module->info, ie->expr); t = get_base_type(t); switch (t->kind) { @@ -716,27 +789,25 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // TODO(bill): Strings AstNode_IndexExpression } break; - case Type_Array: { - Type *t_int = &basic_types[Basic_int]; - ssaValue *e = ssa_lvalue_address(ssa_build_address(proc, ie->expr), proc); - ssaValue *i0 = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(0)); - ssaValue *i1 = ssa_emit_conversion(proc, ssa_build_expr(proc, ie->index), t_int); - ssaValue *gep = ssa_make_instruction_get_element_ptr(proc, e, - i0, i1, 2, - true); - ssa_value_set_type(gep, t->array.element); - return ssa_emit_load(proc, ssa_emit(proc, gep)); + case Type_Slice: { + ssaValue *v = ssa_lvalue_address(ssa_build_addr(proc, expr), proc); + return ssa_emit_load(proc, v); } break; - case Type_Slice: - break; + case Type_Array: { + ssaValue *v = ssa_lvalue_address(ssa_build_addr(proc, expr), proc); + return ssa_emit_load(proc, v); + } break; - case Type_Pointer: - break; + case Type_Pointer: { + ssaValue *v = ssa_lvalue_address(ssa_build_addr(proc, expr), proc); + return ssa_emit_load(proc, v); + } break; } - } break; - case AstNode_SelectorExpr: - break; + case_end; + + case_ast_node(se, SelectorExpr, expr); + case_end; } GB_PANIC("Unexpected expression"); @@ -759,8 +830,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { ssaValue *value = NULL; if (tv->mode == Addressing_Variable) { - gb_printf("!Addressable!\n"); - // TODO(bill): Addressing_Variable + value = ssa_lvalue_load(ssa_build_addr(proc, expr), proc); } else { value = ssa_build_single_expr(proc, expr, tv); } @@ -771,81 +841,70 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { } -ssaLvalue ssa_build_address(ssaProcedure *proc, AstNode *expr) { +ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) { switch (expr->kind) { - case AstNode_Ident: { - if (!ssa_is_blank_identifier(expr)) { - Entity *e = entity_of_ident(proc->module->info, expr); - - ssaLvalue val = {ssaLvalue_Address}; - val.address.expr = expr; - ssaValue **found = map_get(&proc->module->values, hash_pointer(e)); - if (found) { - val.address.value = *found; - } - return val; + case_ast_node(i, Ident, expr); + if (ssa_is_blank_ident(expr)) { + ssaLvalue val = {ssaLvalue_Blank}; } - } break; - case AstNode_ParenExpr: - return ssa_build_address(proc, unparen_expr(expr)); + Entity *e = entity_of_ident(proc->module->info, expr); + ssaValue *v = NULL; + ssaValue **found = map_get(&proc->module->values, hash_pointer(e)); + if (found) v = *found; + return ssa_make_lvalue_address(v, expr); + case_end; -/* - ssaLvalue addr = ssa_build_address(proc, expr->dereference_expr.operand); - ssaValue *load = ssa_lvalue_load(addr, proc); - ssaValue *deref = ssa_emit_load(proc, load); - ssa_value_set_type(deref, type_deref(ssa_value_type(deref))); - return deref; -*/ + case_ast_node(cl, CompoundLit, expr); + case_end; -#if 1 - case AstNode_DerefExpr: { - AstNode *operand = expr->deref_expr.expr; - ssaLvalue addr = ssa_build_address(proc, operand); - ssaValue *value = ssa_lvalue_load(addr, proc); + case_ast_node(pe, ParenExpr, expr); + return ssa_build_addr(proc, unparen_expr(expr)); + case_end; - ssaLvalue val = {ssaLvalue_Address}; - val.address.value = value; - val.address.expr = expr; - return val; - } break; -#endif + case_ast_node(de, DerefExpr, expr); + ssaValue *v = ssa_build_expr(proc, de->expr); + return ssa_make_lvalue_address(v, expr); + case_end; - case AstNode_SelectorExpr: - break; + case_ast_node(se, SelectorExpr, expr); + case_end; - case AstNode_IndexExpr: { + case_ast_node(ie, IndexExpr, expr); + Type *t_int = &basic_types[Basic_int]; ssaValue *v = NULL; Type *element_type = NULL; - auto *ie = &expr->index_expr; - Type *t = type_of_expr(proc->module->info, expr->index_expr.expr); + Type *t = type_of_expr(proc->module->info, ie->expr); t = get_base_type(t); switch (t->kind) { case Type_Array: { - Type *t_int = &basic_types[Basic_int]; - ssaValue *e = ssa_lvalue_address(ssa_build_address(proc, ie->expr), proc); + ssaValue *e = ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc); ssaValue *i0 = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(0)); - ssaValue *i1 = ssa_emit_conversion(proc, ssa_build_expr(proc, ie->index), t_int); - ssaValue *gep = ssa_make_instruction_get_element_ptr(proc, e, - i0, i1, 2, - true); + ssaValue *i1 = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); + ssaValue *gep = ssa_make_instr_get_element_ptr(proc, e, + i0, i1, 2, true); element_type = t->array.element; v = gep; } break; - case Type_Pointer: - GB_PANIC("ssa_build_address AstNode_IndexExpression Type_Slice"); - break; - case Type_Slice: - GB_PANIC("ssa_build_address AstNode_IndexExpression Type_Slice"); - break; + case Type_Pointer: { + ssaValue *e = ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc); + ssaValue *load = ssa_emit_load(proc, e); + ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int); + ssaValue *gep = ssa_make_instr_get_element_ptr(proc, load, + index, NULL, 1, false); + element_type = t->pointer.element; + gep->instr.get_element_ptr.result_type = t->pointer.element; + gep->instr.get_element_ptr.element_type = t->pointer.element; + v = gep; + } break; + case Type_Slice: { + GB_PANIC("ssa_build_addr AstNode_IndexExpression Type_Slice"); + } break; } ssa_value_set_type(v, element_type); - ssaLvalue val = {ssaLvalue_Address}; - val.address.value = ssa_emit(proc, v); - val.address.expr = expr; - return val; - } break; + return ssa_make_lvalue_address(ssa_emit(proc, v), expr); + case_end; // TODO(bill): Others address } @@ -858,11 +917,48 @@ ssaLvalue ssa_build_address(ssaProcedure *proc, AstNode *expr) { void ssa_build_assign_op(ssaProcedure *proc, ssaLvalue lhs, ssaValue *value, Token op) { ssaValue *old_value = ssa_lvalue_load(lhs, proc); - ssaValue *change = ssa_emit_conversion(proc, value, ssa_value_type(old_value)); + ssaValue *change = ssa_emit_conv(proc, value, ssa_value_type(old_value)); ssaValue *new_value = ssa_emit_arith(proc, op, old_value, change, ssa_lvalue_type(lhs)); ssa_lvalue_store(lhs, proc, new_value); } +void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssaBlock *false_block) { + switch (cond->kind) { + case_ast_node(pe, ParenExpr, cond); + ssa_build_cond(proc, pe->expr, true_block, false_block); + return; + case_end; + + case_ast_node(ue, UnaryExpr, cond); + if (ue->op.kind == Token_Not) { + ssa_build_cond(proc, ue->expr, false_block, true_block); + return; + } + case_end; + + case_ast_node(be, BinaryExpr, cond); + if (be->op.kind == Token_CmpAnd) { + ssaValue *b = ssa_add_block(proc, NULL, make_string("logical-true")); + ssaBlock *block = &b->block; + ssa_build_cond(proc, be->left, block, false_block); + proc->curr_block = block; + ssa_build_cond(proc, be->right, true_block, false_block); + return; + } else if (be->op.kind == Token_CmpOr) { + ssaValue *b = ssa_add_block(proc, NULL, make_string("logical-false")); + ssaBlock *block = &b->block; + ssa_build_cond(proc, be->left, true_block, block); + proc->curr_block = block; + ssa_build_cond(proc, be->right, true_block, false_block); + return; + } + case_end; + } + + ssaValue *expr = ssa_build_expr(proc, cond); + ssa_emit_if(proc, expr, true_block, false_block); +} + void ssa_build_stmt(ssaProcedure *proc, AstNode *s); @@ -873,10 +969,10 @@ void ssa_build_stmt_list(ssaProcedure *proc, AstNode *list) { void ssa_build_stmt(ssaProcedure *proc, AstNode *s) { switch (s->kind) { - case AstNode_EmptyStmt: - break; - case AstNode_VarDecl: { - auto *vd = &s->var_decl; + case_ast_node(bs, EmptyStmt, s); + case_end; + + case_ast_node(vd, VarDecl, s); if (vd->kind == Declaration_Mutable) { if (vd->name_count == vd->value_count) { // 1:1 assigment gbArray(ssaLvalue) lvals; @@ -888,9 +984,9 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *s) { for (AstNode *name = vd->name_list; name != NULL; name = name->next) { ssaLvalue lval = {ssaLvalue_Blank}; - if (!ssa_is_blank_identifier(name)) { + if (!ssa_is_blank_ident(name)) { ssa_add_local_for_identifier(proc, name); - lval = ssa_build_address(proc, name); + lval = ssa_build_addr(proc, name); } gb_array_append(lvals, lval); @@ -908,7 +1004,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *s) { } else if (vd->value_count == 0) { // declared and zero-initialized for (AstNode *name = vd->name_list; name != NULL; name = name->next) { - if (!ssa_is_blank_identifier(name)) { + if (!ssa_is_blank_ident(name)) { // TODO(bill): add local ssa_add_local_for_identifier(proc, name); } @@ -917,44 +1013,43 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *s) { GB_PANIC("TODO(bill): tuple assignment variable declaration"); } } - } break; + case_end; - case AstNode_IncDecStmt: { - Token op = s->inc_dec_stmt.op; + case_ast_node(ids, IncDecStmt, s); + Token op = ids->op; if (op.kind == Token_Increment) { op.kind = Token_Add; } else if (op.kind == Token_Decrement) { op.kind = Token_Sub; } - ssaLvalue lval = ssa_build_address(proc, s->inc_dec_stmt.expr); + ssaLvalue lval = ssa_build_addr(proc, ids->expr); ssaValue *one = ssa_make_value_constant(proc->module->allocator, ssa_lvalue_type(lval), make_exact_value_integer(1)); ssa_build_assign_op(proc, lval, one, op); - } break; + case_end; - case AstNode_AssignStmt: { - auto *assign = &s->assign_stmt; - switch (assign->op.kind) { + case_ast_node(as, AssignStmt, s); + switch (as->op.kind) { case Token_Eq: { gbArray(ssaLvalue) lvals; gb_array_init(lvals, gb_heap_allocator()); defer (gb_array_free(lvals)); - for (AstNode *lhs = assign->lhs_list; + for (AstNode *lhs = as->lhs_list; lhs != NULL; lhs = lhs->next) { ssaLvalue lval = {}; - if (!ssa_is_blank_identifier(lhs)) { - lval = ssa_build_address(proc, lhs); + if (!ssa_is_blank_ident(lhs)) { + lval = ssa_build_addr(proc, lhs); } gb_array_append(lvals, lval); } - if (assign->lhs_count == assign->rhs_count) { - if (assign->lhs_count == 1) { - AstNode *lhs = assign->lhs_list; - AstNode *rhs = assign->rhs_list; + if (as->lhs_count == as->rhs_count) { + if (as->lhs_count == 1) { + AstNode *lhs = as->lhs_list; + AstNode *rhs = as->rhs_list; ssaValue *init = ssa_build_expr(proc, rhs); ssa_lvalue_store(lvals[0], proc, init); } else { @@ -962,7 +1057,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *s) { gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals)); defer (gb_array_free(inits)); - for (AstNode *rhs = assign->rhs_list; rhs != NULL; rhs = rhs->next) { + for (AstNode *rhs = as->rhs_list; rhs != NULL; rhs = rhs->next) { ssaValue *init = ssa_build_expr(proc, rhs); gb_array_append(inits, init); } @@ -980,57 +1075,85 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *s) { default: { // NOTE(bill): Only 1 += 1 is allowed, no tuples // +=, -=, etc - Token op = assign->op; + Token op = as->op; i32 kind = op.kind; kind += Token_Add - Token_AddEq; // Convert += to + op.kind = cast(TokenKind)kind; - ssaLvalue lhs = ssa_build_address(proc, assign->lhs_list); - ssaValue *value = ssa_build_expr(proc, assign->rhs_list); + ssaLvalue lhs = ssa_build_addr(proc, as->lhs_list); + ssaValue *value = ssa_build_expr(proc, as->rhs_list); ssa_build_assign_op(proc, lhs, value, op); } break; } - } break; + case_end; - case AstNode_ExprStmt: - ssa_build_expr(proc, s->expr_stmt.expr); - break; + case_ast_node(es, ExprStmt, s); + ssa_build_expr(proc, es->expr); + case_end; - case AstNode_BlockStmt: - ssa_build_stmt_list(proc, s->block_stmt.list); - break; + case_ast_node(bs, BlockStmt, s); + ssa_build_stmt_list(proc, bs->list); + case_end; - case AstNode_IfStmt: - GB_PANIC("AstNode_IfStatement"); - break; - case AstNode_ReturnStmt: - GB_PANIC("AstNode_ReturnStatement"); - break; - case AstNode_ForStmt: - GB_PANIC("AstNode_ForStatement"); - break; - case AstNode_DeferStmt: - GB_PANIC("AstNode_DeferStatement"); - break; - case AstNode_BranchStmt: - GB_PANIC("AstNode_BranchStatement"); - break; + case_ast_node(is, IfStmt, s); + if (is->init != NULL) { + ssa_build_stmt(proc, is->init); + } + ssaValue *then_block = ssa_add_block(proc, is->body, make_string("if-then")); + ssaValue *else_block = NULL; + if (is->else_stmt != NULL) { + else_block = ssa_add_block(proc, is->else_stmt, make_string("if-else")); + } + ssaValue *end_block = ssa_add_block(proc, is->body, make_string("if-end")); + if (else_block == NULL) { + else_block = end_block; + } + + ssa_build_cond(proc, is->cond, &then_block->block, &else_block->block); + proc->curr_block = &then_block->block; + ssa_build_stmt(proc, is->body); + ssa_emit_jump(proc, &end_block->block); + + if (is->else_stmt != NULL) { + proc->curr_block = &else_block->block; + ssa_build_stmt(proc, is->else_stmt); + ssa_emit_jump(proc, &end_block->block); + } + + proc->curr_block = &end_block->block; + case_end; + + case_ast_node(rs, ReturnStmt, s); + GB_PANIC("AstNode_ReturnStmt"); + case_end; + + case_ast_node(fs, ForStmt, s); + GB_PANIC("AstNode_ForStmt"); + case_end; + + case_ast_node(bs, DeferStmt, s); + GB_PANIC("AstNode_DeferStmt"); + case_end; + + case_ast_node(bs, BranchStmt, s); + GB_PANIC("AstNode_BranchStmt"); + case_end; } } void ssa_build_procedure(ssaValue *value) { - ssaProcedure *proc = &value->procedure; + ssaProcedure *proc = &value->proc; // gb_printf("Building %.*s: %.*s\n", LIT(entity_strings[proc->entity->kind]), LIT(proc->name)); AstNode *proc_decl = proc->decl->proc_decl; switch (proc_decl->kind) { - case AstNode_ProcDecl: - proc->type_expr = proc_decl->proc_decl.type; - proc->body = proc_decl->proc_decl.body; - break; + case_ast_node(pd, ProcDecl, proc_decl); + proc->type_expr = pd->type; + proc->body = pd->body; + case_end; default: return; } diff --git a/src/parser.cpp b/src/parser.cpp index 33e2c0abc..39c7a4fe7 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -43,7 +43,6 @@ struct AstFile { TokenPos fix_prev_pos; }; - // NOTE(bill): Just used to quickly check if there is double declaration in the same scope // No type checking actually happens // TODO(bill): Should this be completely handled in the semantic checker or is it better here? @@ -64,244 +63,177 @@ struct Parser { isize import_index; }; +enum DeclKind { + Declaration_Invalid, + Declaration_Mutable, + Declaration_Immutable, + Declaration_Count, +}; + #define AST_NODE_KINDS \ - AST_NODE_KIND(Invalid), \ + AST_NODE_KIND(Invalid, struct{}) \ + AST_NODE_KIND(BasicLit, Token) \ + AST_NODE_KIND(Ident, struct { \ + Token token; \ + AstEntity *entity; \ + }) \ + AST_NODE_KIND(ProcLit, struct { \ + AstNode *type; \ + AstNode *body; \ + }) \ + AST_NODE_KIND(CompoundLit, struct { \ + AstNode *type; \ + AstNode *elem_list; \ + isize elem_count; \ + Token open, close; \ + }) \ +AST_NODE_KIND(_ExprBegin, struct{}) \ + AST_NODE_KIND(BadExpr, struct { Token begin, end; }) \ + AST_NODE_KIND(TagExpr, struct { Token token, name; AstNode *expr; }) \ + AST_NODE_KIND(UnaryExpr, struct { Token op; AstNode *expr; }) \ + AST_NODE_KIND(BinaryExpr, struct { Token op; AstNode *left, *right; } ) \ + AST_NODE_KIND(ParenExpr, struct { AstNode *expr; Token open, close; }) \ + AST_NODE_KIND(SelectorExpr, struct { Token token; AstNode *expr, *selector; }) \ + AST_NODE_KIND(IndexExpr, struct { AstNode *expr, *index; Token open, close; }) \ + AST_NODE_KIND(CastExpr, struct { Token token; AstNode *type, *expr; }) \ + AST_NODE_KIND(DerefExpr, struct { Token op; AstNode *expr; }) \ + AST_NODE_KIND(CallExpr, struct { \ + AstNode *proc, *arg_list; \ + isize arg_list_count; \ + Token open, close; \ + }) \ + AST_NODE_KIND(SliceExpr, struct { \ + AstNode *expr; \ + Token open, close; \ + AstNode *low, *high, *max; \ + b32 triple_indexed; \ + }) \ +AST_NODE_KIND(_ExprEnd, struct{}) \ +AST_NODE_KIND(_StmtBegin, struct{}) \ + AST_NODE_KIND(BadStmt, struct { Token begin, end; }) \ + AST_NODE_KIND(EmptyStmt, struct { Token token; }) \ + AST_NODE_KIND(ExprStmt, struct { AstNode *expr; } ) \ + AST_NODE_KIND(IncDecStmt, struct { Token op; AstNode *expr; }) \ + AST_NODE_KIND(TagStmt, struct { \ + Token token; \ + Token name; \ + AstNode *stmt; \ + }) \ + AST_NODE_KIND(AssignStmt, struct { \ + Token op; \ + AstNode *lhs_list, *rhs_list; \ + isize lhs_count, rhs_count; \ + }) \ +AST_NODE_KIND(_ComplexStmtBegin, struct{}) \ + AST_NODE_KIND(BlockStmt, struct { \ + AstNode *list; \ + isize list_count; \ + Token open, close; \ + }) \ + AST_NODE_KIND(IfStmt, struct { \ + Token token; \ + AstNode *init; \ + AstNode *cond; \ + AstNode *body; \ + AstNode *else_stmt; \ + }) \ + AST_NODE_KIND(ReturnStmt, struct { \ + Token token; \ + AstNode *result_list; \ + isize result_count; \ + }) \ + AST_NODE_KIND(ForStmt, struct { \ + Token token; \ + AstNode *init, *cond, *end; \ + AstNode *body; \ + }) \ + AST_NODE_KIND(DeferStmt, struct { Token token; AstNode *stmt; }) \ + AST_NODE_KIND(BranchStmt, struct { Token token; }) \ \ - AST_NODE_KIND(BasicLit), \ - AST_NODE_KIND(Ident), \ - AST_NODE_KIND(ProcLit), \ - AST_NODE_KIND(CompoundLit), \ -\ -AST_NODE_KIND(_ExprBegin), \ - AST_NODE_KIND(BadExpr), \ - AST_NODE_KIND(TagExpr), \ - AST_NODE_KIND(UnaryExpr), \ - AST_NODE_KIND(BinaryExpr), \ - AST_NODE_KIND(ParenExpr), \ - AST_NODE_KIND(CallExpr), \ - AST_NODE_KIND(SelectorExpr), \ - AST_NODE_KIND(IndexExpr), \ - AST_NODE_KIND(SliceExpr), \ - AST_NODE_KIND(CastExpr), \ - AST_NODE_KIND(DerefExpr), \ -AST_NODE_KIND(_ExprEnd), \ -\ -AST_NODE_KIND(_stmtBegin), \ - AST_NODE_KIND(BadStmt), \ - AST_NODE_KIND(EmptyStmt), \ - AST_NODE_KIND(TagStmt), \ - AST_NODE_KIND(ExprStmt), \ - AST_NODE_KIND(IncDecStmt), \ - AST_NODE_KIND(AssignStmt), \ -\ -AST_NODE_KIND(_ComplexStmtBegin), \ - AST_NODE_KIND(BlockStmt), \ - AST_NODE_KIND(IfStmt), \ - AST_NODE_KIND(ReturnStmt), \ - AST_NODE_KIND(ForStmt), \ - AST_NODE_KIND(DeferStmt), \ - AST_NODE_KIND(BranchStmt), \ -\ -AST_NODE_KIND(_ComplexStmtEnd), \ -\ -AST_NODE_KIND(_stmtEnd), \ -\ -AST_NODE_KIND(_DeclBegin), \ - AST_NODE_KIND(BadDecl), \ - AST_NODE_KIND(VarDecl), \ - AST_NODE_KIND(ProcDecl), \ - AST_NODE_KIND(TypeDecl), \ - AST_NODE_KIND(AliasDecl), \ - AST_NODE_KIND(ImportDecl), \ -AST_NODE_KIND(_DeclEnd), \ -\ -AST_NODE_KIND(_TypeBegin), \ - AST_NODE_KIND(Field), \ - AST_NODE_KIND(ProcType), \ - AST_NODE_KIND(PointerType), \ - AST_NODE_KIND(ArrayType), \ - AST_NODE_KIND(StructType), \ -AST_NODE_KIND(_TypeEnd), \ -\ - AST_NODE_KIND(Count), +AST_NODE_KIND(_ComplexStmtEnd, struct{}) \ +AST_NODE_KIND(_StmtEnd, struct{}) \ +AST_NODE_KIND(_DeclBegin, struct{}) \ + AST_NODE_KIND(BadDecl, struct { Token begin, end; }) \ + AST_NODE_KIND(VarDecl, struct { \ + DeclKind kind; \ + AstNode *name_list; \ + AstNode *type; \ + AstNode *value_list; \ + isize name_count, value_count; \ + }) \ + AST_NODE_KIND(ProcDecl, struct { \ + DeclKind kind; \ + AstNode *name; \ + AstNode *type; \ + AstNode *body; \ + AstNode *tag_list; \ + isize tag_count; \ + }) \ + AST_NODE_KIND(TypeDecl, struct { Token token; AstNode *name, *type; }) \ + AST_NODE_KIND(AliasDecl, struct { Token token; AstNode *name, *type; }) \ + AST_NODE_KIND(ImportDecl, struct { Token token, filepath; }) \ +AST_NODE_KIND(_DeclEnd, struct{}) \ +AST_NODE_KIND(_TypeBegin, struct{}) \ + AST_NODE_KIND(Field, struct { \ + AstNode *name_list; \ + isize name_count; \ + AstNode *type; \ + }) \ + AST_NODE_KIND(ProcType, struct { \ + Token token; \ + AstNode *param_list; \ + AstNode *result_list; \ + isize param_count; \ + isize result_count; \ + }) \ + AST_NODE_KIND(PointerType, struct { \ + Token token; \ + AstNode *type; \ + }) \ + AST_NODE_KIND(ArrayType, struct { \ + Token token; \ + AstNode *count; \ + AstNode *elem; \ + }) \ + AST_NODE_KIND(StructType, struct { \ + Token token; \ + AstNode *field_list; \ + isize field_count; \ + }) \ +AST_NODE_KIND(_TypeEnd, struct{}) \ + AST_NODE_KIND(Count, struct{}) enum AstNodeKind { -#define AST_NODE_KIND(x) GB_JOIN2(AstNode_, x) +#define AST_NODE_KIND(name, ...) GB_JOIN2(AstNode_, name), AST_NODE_KINDS #undef AST_NODE_KIND }; String const ast_node_strings[] = { -#define AST_NODE_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1} +#define AST_NODE_KIND(name, ...) {cast(u8 *)#name, gb_size_of(#name)-1}, AST_NODE_KINDS #undef AST_NODE_KIND }; -enum DeclKind { - Declaration_Invalid, - - Declaration_Mutable, - Declaration_Immutable, - - Declaration_Count, -}; - - struct AstNode { AstNodeKind kind; AstNode *prev, *next; // NOTE(bill): allow for Linked list union { - // NOTE(bill): open/close for debugging/errors - Token basic_lit; - struct { - Token token; - AstEntity *entity; - } ident; - struct { - AstNode *type; // AstNode_ProcType - AstNode *body; // AstNode_BlockStmt - } proc_lit; - struct { - AstNode *type; - AstNode *elem_list; - isize elem_count; - Token open, close; - } compound_lit; - - struct { - Token token; - Token name; - AstNode *expr; - } tag_expr; - - struct { Token begin, end; } bad_expr; - struct { Token op; AstNode *expr; } unary_expr; - struct { Token op; AstNode *left, *right; } binary_expr; - struct { AstNode *expr; Token open, close; } paren_expr; - struct { Token token; AstNode *expr, *selector; } selector_expr; - struct { AstNode *expr, *index; Token open, close; } index_expr; - struct { Token token; AstNode *type, *expr; } cast_expr; - struct { - AstNode *proc, *arg_list; - isize arg_list_count; - Token open, close; - } call_expr; - struct { Token op; AstNode *expr; } deref_expr; - struct { - AstNode *expr; - Token open, close; - AstNode *low, *high, *max; - b32 triple_indexed; // [(1st):2nd:3rd] - } slice_expr; - - struct { Token begin, end; } bad_stmt; - struct { Token token; } empty_stmt; - struct { AstNode *expr; } expr_stmt; - struct { Token op; AstNode *expr; } inc_dec_stmt; - struct { - Token token; - Token name; - AstNode *stmt; - } tag_stmt; - struct { - Token op; - AstNode *lhs_list, *rhs_list; - isize lhs_count, rhs_count; - } assign_stmt; - struct { - AstNode *list; - isize list_count; - Token open, close; - } block_stmt; - struct { - Token token; - AstNode *init; - AstNode *cond; - AstNode *body; - AstNode *else_stmt; - } if_stmt; - struct { - Token token; - AstNode *result_list; - isize result_count; - } return_stmt; - struct { - Token token; - AstNode *init, *cond, *end; - AstNode *body; - } for_stmt; - struct { - Token token; - AstNode *stmt; - } defer_stmt; - struct { - Token token; - } branch_stmt; - - struct { Token begin, end; } bad_decl; - struct { - DeclKind kind; - AstNode *name_list; - AstNode *type; - AstNode *value_list; - isize name_count, value_count; - } var_decl; - - struct { - AstNode *name_list; - isize name_count; - AstNode *type; - } field; - - // TODO(bill): Unify Procedure Declarations and Literals - struct { - DeclKind kind; - AstNode *name; // AstNode_Ident - AstNode *type; // AstNode_ProcType - AstNode *body; // AstNode_BlockStmt - AstNode *tag_list; // AstNode_TagExpr - isize tag_count; - } proc_decl; - struct { - Token token; - AstNode *name; // AstNode_Ident - AstNode *type; - } type_decl; - struct { - Token token; - AstNode *name; // AstNode_Ident - AstNode *type; - } alias_decl; - struct { - Token token; - Token filepath; - } import_decl; - - - struct { - Token token; - AstNode *type; - } pointer_type; - struct { - Token token; - AstNode *count; // NOTE(bill): Zero/NULL is probably a slice - AstNode *elem; - } array_type; - struct { - Token token; - AstNode *field_list; // AstNode_Field - isize field_count; - } struct_type; - struct { - Token token; - AstNode *param_list; // AstNode_Field list - AstNode *result_list; // type expression list - isize param_count; - isize result_count; - } proc_type; +#define AST_NODE_KIND(_kind_name_, ...) __VA_ARGS__ _kind_name_; + AST_NODE_KINDS +#undef AST_NODE_KIND }; }; + +#define ast_node(n_, Kind_, node_) auto *n_ = &(node_)->Kind_; GB_ASSERT((node_)->kind == GB_JOIN2(AstNode_, Kind_)) +#define case_ast_node(n_, Kind_, node_) case GB_JOIN2(AstNode_, Kind_): { ast_node(n_, Kind_, node_); +#define case_end } break; + + + + + gb_inline AstScope *make_ast_scope(AstFile *f, AstScope *parent) { AstScope *scope = gb_alloc_item(gb_arena_allocator(&f->arena), AstScope); map_init(&scope->entities, gb_heap_allocator()); @@ -314,7 +246,7 @@ gb_inline b32 is_ast_node_expr(AstNode *node) { return gb_is_between(node->kind, AstNode__ExprBegin+1, AstNode__ExprEnd-1); } gb_inline b32 is_ast_node_stmt(AstNode *node) { - return gb_is_between(node->kind, AstNode__stmtBegin+1, AstNode__stmtEnd-1); + return gb_is_between(node->kind, AstNode__StmtBegin+1, AstNode__StmtEnd-1); } gb_inline b32 is_ast_node_complex_stmt(AstNode *node) { return gb_is_between(node->kind, AstNode__ComplexStmtBegin+1, AstNode__ComplexStmtEnd-1); @@ -330,85 +262,85 @@ gb_inline b32 is_ast_node_type(AstNode *node) { Token ast_node_token(AstNode *node) { switch (node->kind) { case AstNode_BasicLit: - return node->basic_lit; + return node->BasicLit; case AstNode_Ident: - return node->ident.token; + return node->Ident.token; case AstNode_ProcLit: - return ast_node_token(node->proc_lit.type); + return ast_node_token(node->ProcLit.type); case AstNode_CompoundLit: - return ast_node_token(node->compound_lit.type); + return ast_node_token(node->CompoundLit.type); case AstNode_TagExpr: - return node->tag_expr.token; + return node->TagExpr.token; case AstNode_BadExpr: - return node->bad_expr.begin; + return node->BadExpr.begin; case AstNode_UnaryExpr: - return node->unary_expr.op; + return node->UnaryExpr.op; case AstNode_BinaryExpr: - return ast_node_token(node->binary_expr.left); + return ast_node_token(node->BinaryExpr.left); case AstNode_ParenExpr: - return node->paren_expr.open; + return node->ParenExpr.open; case AstNode_CallExpr: - return ast_node_token(node->call_expr.proc); + return ast_node_token(node->CallExpr.proc); case AstNode_SelectorExpr: - return ast_node_token(node->selector_expr.selector); + return ast_node_token(node->SelectorExpr.selector); case AstNode_IndexExpr: - return node->index_expr.open; + return node->IndexExpr.open; case AstNode_SliceExpr: - return node->slice_expr.open; + return node->SliceExpr.open; case AstNode_CastExpr: - return node->cast_expr.token; + return node->CastExpr.token; case AstNode_DerefExpr: - return node->deref_expr.op; + return node->DerefExpr.op; case AstNode_BadStmt: - return node->bad_stmt.begin; + return node->BadStmt.begin; case AstNode_EmptyStmt: - return node->empty_stmt.token; + return node->EmptyStmt.token; case AstNode_ExprStmt: - return ast_node_token(node->expr_stmt.expr); + return ast_node_token(node->ExprStmt.expr); case AstNode_TagStmt: - return node->tag_stmt.token; + return node->TagStmt.token; case AstNode_IncDecStmt: - return node->inc_dec_stmt.op; + return node->IncDecStmt.op; case AstNode_AssignStmt: - return node->assign_stmt.op; + return node->AssignStmt.op; case AstNode_BlockStmt: - return node->block_stmt.open; + return node->BlockStmt.open; case AstNode_IfStmt: - return node->if_stmt.token; + return node->IfStmt.token; case AstNode_ReturnStmt: - return node->return_stmt.token; + return node->ReturnStmt.token; case AstNode_ForStmt: - return node->for_stmt.token; + return node->ForStmt.token; case AstNode_DeferStmt: - return node->defer_stmt.token; + return node->DeferStmt.token; case AstNode_BranchStmt: - return node->branch_stmt.token; + return node->BranchStmt.token; case AstNode_BadDecl: - return node->bad_decl.begin; + return node->BadDecl.begin; case AstNode_VarDecl: - return ast_node_token(node->var_decl.name_list); + return ast_node_token(node->VarDecl.name_list); case AstNode_ProcDecl: - return node->proc_decl.name->ident.token; + return node->ProcDecl.name->Ident.token; case AstNode_TypeDecl: - return node->type_decl.token; + return node->TypeDecl.token; case AstNode_AliasDecl: - return node->alias_decl.token; + return node->AliasDecl.token; case AstNode_ImportDecl: - return node->import_decl.token; + return node->ImportDecl.token; case AstNode_Field: { - if (node->field.name_list) - return ast_node_token(node->field.name_list); + if (node->Field.name_list) + return ast_node_token(node->Field.name_list); else - return ast_node_token(node->field.type); + return ast_node_token(node->Field.type); } case AstNode_ProcType: - return node->proc_type.token; + return node->ProcType.token; case AstNode_PointerType: - return node->pointer_type.token; + return node->PointerType.token; case AstNode_ArrayType: - return node->array_type.token; + return node->ArrayType.token; case AstNode_StructType: - return node->struct_type.token; + return node->StructType.token; } return empty_token; @@ -500,31 +432,31 @@ gb_inline AstNode *make_node(AstFile *f, AstNodeKind kind) { gb_inline AstNode *make_bad_expr(AstFile *f, Token begin, Token end) { AstNode *result = make_node(f, AstNode_BadExpr); - result->bad_expr.begin = begin; - result->bad_expr.end = end; + result->BadExpr.begin = begin; + result->BadExpr.end = end; return result; } gb_inline AstNode *make_tag_expr(AstFile *f, Token token, Token name, AstNode *expr) { AstNode *result = make_node(f, AstNode_TagExpr); - result->tag_expr.token = token; - result->tag_expr.name = name; - result->tag_expr.expr = expr; + result->TagExpr.token = token; + result->TagExpr.name = name; + result->TagExpr.expr = expr; return result; } gb_inline AstNode *make_tag_stmt(AstFile *f, Token token, Token name, AstNode *stmt) { AstNode *result = make_node(f, AstNode_TagStmt); - result->tag_stmt.token = token; - result->tag_stmt.name = name; - result->tag_stmt.stmt = stmt; + result->TagStmt.token = token; + result->TagStmt.name = name; + result->TagStmt.stmt = stmt; return result; } gb_inline AstNode *make_unary_expr(AstFile *f, Token op, AstNode *expr) { AstNode *result = make_node(f, AstNode_UnaryExpr); - result->unary_expr.op = op; - result->unary_expr.expr = expr; + result->UnaryExpr.op = op; + result->UnaryExpr.expr = expr; return result; } @@ -540,94 +472,94 @@ gb_inline AstNode *make_binary_expr(AstFile *f, Token op, AstNode *left, AstNode right = make_bad_expr(f, op, op); } - result->binary_expr.op = op; - result->binary_expr.left = left; - result->binary_expr.right = right; + result->BinaryExpr.op = op; + result->BinaryExpr.left = left; + result->BinaryExpr.right = right; return result; } gb_inline AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token close) { AstNode *result = make_node(f, AstNode_ParenExpr); - result->paren_expr.expr = expr; - result->paren_expr.open = open; - result->paren_expr.close = close; + result->ParenExpr.expr = expr; + result->ParenExpr.open = open; + result->ParenExpr.close = close; return result; } gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNode *arg_list, isize arg_list_count, Token open, Token close) { AstNode *result = make_node(f, AstNode_CallExpr); - result->call_expr.proc = proc; - result->call_expr.arg_list = arg_list; - result->call_expr.arg_list_count = arg_list_count; - result->call_expr.open = open; - result->call_expr.close = close; + result->CallExpr.proc = proc; + result->CallExpr.arg_list = arg_list; + result->CallExpr.arg_list_count = arg_list_count; + result->CallExpr.open = open; + result->CallExpr.close = close; return result; } gb_inline AstNode *make_selector_expr(AstFile *f, Token token, AstNode *expr, AstNode *selector) { AstNode *result = make_node(f, AstNode_SelectorExpr); - result->selector_expr.expr = expr; - result->selector_expr.selector = selector; + result->SelectorExpr.expr = expr; + result->SelectorExpr.selector = selector; return result; } gb_inline AstNode *make_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, Token close) { AstNode *result = make_node(f, AstNode_IndexExpr); - result->index_expr.expr = expr; - result->index_expr.index = index; - result->index_expr.open = open; - result->index_expr.close = close; + result->IndexExpr.expr = expr; + result->IndexExpr.index = index; + result->IndexExpr.open = open; + result->IndexExpr.close = close; return result; } gb_inline AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, AstNode *low, AstNode *high, AstNode *max, b32 triple_indexed) { AstNode *result = make_node(f, AstNode_SliceExpr); - result->slice_expr.expr = expr; - result->slice_expr.open = open; - result->slice_expr.close = close; - result->slice_expr.low = low; - result->slice_expr.high = high; - result->slice_expr.max = max; - result->slice_expr.triple_indexed = triple_indexed; + result->SliceExpr.expr = expr; + result->SliceExpr.open = open; + result->SliceExpr.close = close; + result->SliceExpr.low = low; + result->SliceExpr.high = high; + result->SliceExpr.max = max; + result->SliceExpr.triple_indexed = triple_indexed; return result; } gb_inline AstNode *make_cast_expr(AstFile *f, Token token, AstNode *type, AstNode *expr) { AstNode *result = make_node(f, AstNode_CastExpr); - result->cast_expr.token = token; - result->cast_expr.type = type; - result->cast_expr.expr = expr; + result->CastExpr.token = token; + result->CastExpr.type = type; + result->CastExpr.expr = expr; return result; } gb_inline AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) { AstNode *result = make_node(f, AstNode_DerefExpr); - result->deref_expr.expr = expr; - result->deref_expr.op = op; + result->DerefExpr.expr = expr; + result->DerefExpr.op = op; return result; } gb_inline AstNode *make_basic_lit(AstFile *f, Token basic_lit) { AstNode *result = make_node(f, AstNode_BasicLit); - result->basic_lit = basic_lit; + result->BasicLit = basic_lit; return result; } gb_inline AstNode *make_identifier(AstFile *f, Token token, AstEntity *entity = NULL) { AstNode *result = make_node(f, AstNode_Ident); - result->ident.token = token; - result->ident.entity = entity; + result->Ident.token = token; + result->Ident.entity = entity; return result; } gb_inline AstNode *make_procedure_literal(AstFile *f, AstNode *type, AstNode *body) { AstNode *result = make_node(f, AstNode_ProcLit); - result->proc_lit.type = type; - result->proc_lit.body = body; + result->ProcLit.type = type; + result->ProcLit.body = body; return result; } @@ -635,191 +567,191 @@ gb_inline AstNode *make_procedure_literal(AstFile *f, AstNode *type, AstNode *bo gb_inline AstNode *make_compound_literal(AstFile *f, AstNode *type, AstNode *elem_list, isize elem_count, Token open, Token close) { AstNode *result = make_node(f, AstNode_CompoundLit); - result->compound_lit.type = type; - result->compound_lit.elem_list = elem_list; - result->compound_lit.elem_count = elem_count; - result->compound_lit.open = open; - result->compound_lit.close = close; + result->CompoundLit.type = type; + result->CompoundLit.elem_list = elem_list; + result->CompoundLit.elem_count = elem_count; + result->CompoundLit.open = open; + result->CompoundLit.close = close; return result; } gb_inline AstNode *make_bad_stmt(AstFile *f, Token begin, Token end) { AstNode *result = make_node(f, AstNode_BadStmt); - result->bad_stmt.begin = begin; - result->bad_stmt.end = end; + result->BadStmt.begin = begin; + result->BadStmt.end = end; return result; } gb_inline AstNode *make_empty_stmt(AstFile *f, Token token) { AstNode *result = make_node(f, AstNode_EmptyStmt); - result->empty_stmt.token = token; + result->EmptyStmt.token = token; return result; } gb_inline AstNode *make_expr_stmt(AstFile *f, AstNode *expr) { AstNode *result = make_node(f, AstNode_ExprStmt); - result->expr_stmt.expr = expr; + result->ExprStmt.expr = expr; return result; } gb_inline AstNode *make_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) { AstNode *result = make_node(f, AstNode_IncDecStmt); - result->inc_dec_stmt.op = op; - result->inc_dec_stmt.expr = expr; + result->IncDecStmt.op = op; + result->IncDecStmt.expr = expr; return result; } gb_inline AstNode *make_assign_stmt(AstFile *f, Token op, AstNode *lhs_list, isize lhs_count, AstNode *rhs_list, isize rhs_count) { AstNode *result = make_node(f, AstNode_AssignStmt); - result->assign_stmt.op = op; - result->assign_stmt.lhs_list = lhs_list; - result->assign_stmt.lhs_count = lhs_count; - result->assign_stmt.rhs_list = rhs_list; - result->assign_stmt.rhs_count = rhs_count; + result->AssignStmt.op = op; + result->AssignStmt.lhs_list = lhs_list; + result->AssignStmt.lhs_count = lhs_count; + result->AssignStmt.rhs_list = rhs_list; + result->AssignStmt.rhs_count = rhs_count; return result; } gb_inline AstNode *make_block_stmt(AstFile *f, AstNode *list, isize list_count, Token open, Token close) { AstNode *result = make_node(f, AstNode_BlockStmt); - result->block_stmt.list = list; - result->block_stmt.list_count = list_count; - result->block_stmt.open = open; - result->block_stmt.close = close; + result->BlockStmt.list = list; + result->BlockStmt.list_count = list_count; + result->BlockStmt.open = open; + result->BlockStmt.close = close; return result; } gb_inline AstNode *make_if_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body, AstNode *else_stmt) { AstNode *result = make_node(f, AstNode_IfStmt); - result->if_stmt.token = token; - result->if_stmt.init = init; - result->if_stmt.cond = cond; - result->if_stmt.body = body; - result->if_stmt.else_stmt = else_stmt; + result->IfStmt.token = token; + result->IfStmt.init = init; + result->IfStmt.cond = cond; + result->IfStmt.body = body; + result->IfStmt.else_stmt = else_stmt; return result; } gb_inline AstNode *make_return_stmt(AstFile *f, Token token, AstNode *result_list, isize result_count) { AstNode *result = make_node(f, AstNode_ReturnStmt); - result->return_stmt.token = token; - result->return_stmt.result_list = result_list; - result->return_stmt.result_count = result_count; + result->ReturnStmt.token = token; + result->ReturnStmt.result_list = result_list; + result->ReturnStmt.result_count = result_count; return result; } gb_inline AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *end, AstNode *body) { AstNode *result = make_node(f, AstNode_ForStmt); - result->for_stmt.token = token; - result->for_stmt.init = init; - result->for_stmt.cond = cond; - result->for_stmt.end = end; - result->for_stmt.body = body; + result->ForStmt.token = token; + result->ForStmt.init = init; + result->ForStmt.cond = cond; + result->ForStmt.end = end; + result->ForStmt.body = body; return result; } gb_inline AstNode *make_defer_stmt(AstFile *f, Token token, AstNode *stmt) { AstNode *result = make_node(f, AstNode_DeferStmt); - result->defer_stmt.token = token; - result->defer_stmt.stmt = stmt; + result->DeferStmt.token = token; + result->DeferStmt.stmt = stmt; return result; } gb_inline AstNode *make_branch_stmt(AstFile *f, Token token) { AstNode *result = make_node(f, AstNode_BranchStmt); - result->branch_stmt.token = token; + result->BranchStmt.token = token; return result; } gb_inline AstNode *make_bad_decl(AstFile *f, Token begin, Token end) { AstNode *result = make_node(f, AstNode_BadDecl); - result->bad_decl.begin = begin; - result->bad_decl.end = end; + result->BadDecl.begin = begin; + result->BadDecl.end = end; return result; } gb_inline AstNode *make_variable_decl(AstFile *f, DeclKind kind, AstNode *name_list, isize name_count, AstNode *type, AstNode *value_list, isize value_count) { AstNode *result = make_node(f, AstNode_VarDecl); - result->var_decl.kind = kind; - result->var_decl.name_list = name_list; - result->var_decl.name_count = name_count; - result->var_decl.type = type; - result->var_decl.value_list = value_list; - result->var_decl.value_count = value_count; + result->VarDecl.kind = kind; + result->VarDecl.name_list = name_list; + result->VarDecl.name_count = name_count; + result->VarDecl.type = type; + result->VarDecl.value_list = value_list; + result->VarDecl.value_count = value_count; return result; } gb_inline AstNode *make_field(AstFile *f, AstNode *name_list, isize name_count, AstNode *type) { AstNode *result = make_node(f, AstNode_Field); - result->field.name_list = name_list; - result->field.name_count = name_count; - result->field.type = type; + result->Field.name_list = name_list; + result->Field.name_count = name_count; + result->Field.type = type; return result; } gb_inline AstNode *make_proc_type(AstFile *f, Token token, AstNode *param_list, isize param_count, AstNode *result_list, isize result_count) { AstNode *result = make_node(f, AstNode_ProcType); - result->proc_type.token = token; - result->proc_type.param_list = param_list; - result->proc_type.param_count = param_count; - result->proc_type.result_list = result_list; - result->proc_type.result_count = result_count; + result->ProcType.token = token; + result->ProcType.param_list = param_list; + result->ProcType.param_count = param_count; + result->ProcType.result_list = result_list; + result->ProcType.result_count = result_count; return result; } gb_inline AstNode *make_procedure_decl(AstFile *f, DeclKind kind, AstNode *name, AstNode *proc_type, AstNode *body, AstNode *tag_list, isize tag_count) { AstNode *result = make_node(f, AstNode_ProcDecl); - result->proc_decl.kind = kind; - result->proc_decl.name = name; - result->proc_decl.type = proc_type; - result->proc_decl.body = body; - result->proc_decl.tag_list = tag_list; - result->proc_decl.tag_count = tag_count; + result->ProcDecl.kind = kind; + result->ProcDecl.name = name; + result->ProcDecl.type = proc_type; + result->ProcDecl.body = body; + result->ProcDecl.tag_list = tag_list; + result->ProcDecl.tag_count = tag_count; return result; } gb_inline AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type) { AstNode *result = make_node(f, AstNode_PointerType); - result->pointer_type.token = token; - result->pointer_type.type = type; + result->PointerType.token = token; + result->PointerType.type = type; return result; } gb_inline AstNode *make_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) { AstNode *result = make_node(f, AstNode_ArrayType); - result->array_type.token = token; - result->array_type.count = count; - result->array_type.elem = elem; + result->ArrayType.token = token; + result->ArrayType.count = count; + result->ArrayType.elem = elem; return result; } gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNode *field_list, isize field_count) { AstNode *result = make_node(f, AstNode_StructType); - result->struct_type.token = token; - result->struct_type.field_list = field_list; - result->struct_type.field_count = field_count; + result->StructType.token = token; + result->StructType.field_list = field_list; + result->StructType.field_count = field_count; return result; } gb_inline AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) { AstNode *result = make_node(f, AstNode_TypeDecl); - result->type_decl.token = token; - result->type_decl.name = name; - result->type_decl.type = type; + result->TypeDecl.token = token; + result->TypeDecl.name = name; + result->TypeDecl.type = type; return result; } gb_inline AstNode *make_alias_decl(AstFile *f, Token token, AstNode *name, AstNode *type) { AstNode *result = make_node(f, AstNode_AliasDecl); - result->alias_decl.token = token; - result->alias_decl.name = name; - result->alias_decl.type = type; + result->AliasDecl.token = token; + result->AliasDecl.name = name; + result->AliasDecl.type = type; return result; } gb_inline AstNode *make_import_decl(AstFile *f, Token token, Token filepath) { AstNode *result = make_node(f, AstNode_ImportDecl); - result->import_decl.token = token; - result->import_decl.filepath = filepath; + result->ImportDecl.token = token; + result->ImportDecl.filepath = filepath; return result; } @@ -882,8 +814,8 @@ gb_internal void add_ast_entity(AstFile *f, AstScope *scope, AstNode *declaratio continue; } - AstEntity *entity = make_ast_entity(f, n->ident.token, declaration, scope); - n->ident.entity = entity; + AstEntity *entity = make_ast_entity(f, n->Ident.token, declaration, scope); + n->Ident.entity = entity; AstEntity *insert_entity = ast_scope_insert(scope, *entity); if (insert_entity != NULL && @@ -969,7 +901,7 @@ AstNode *unparen_expr(AstNode *node) { for (;;) { if (node->kind != AstNode_ParenExpr) return node; - node = node->paren_expr.expr; + node = node->ParenExpr.expr; } } @@ -1054,7 +986,7 @@ AstNode *parse_operand(AstFile *f, b32 lhs) { case Token_Hash: { operand = parse_tag_expr(f, NULL); - operand->tag_expr.expr = parse_expr(f, false); + operand->TagExpr.expr = parse_expr(f, false); return operand; } @@ -1403,7 +1335,7 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { return NULL; if (statement->kind == AstNode_ExprStmt) - return statement->expr_stmt.expr; + return statement->ExprStmt.expr; ast_file_err(f, f->cursor[0], "Expected `%.*s`, found a simple statement.", LIT(kind)); return make_bad_expr(f, f->cursor[0], f->cursor[1]); @@ -1492,7 +1424,7 @@ AstNode *parse_parameter_list(AstFile *f, AstScope *scope, isize *param_count_) while (f->cursor[0].kind == Token_Identifier) { AstNode *field = parse_field_decl(f, scope); DLIST_APPEND(param_list, param_list_curr, field); - param_count += field->field.name_count; + param_count += field->Field.name_count; if (f->cursor[0].kind != Token_Comma) break; next_token(f); @@ -1670,7 +1602,7 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) { AstNode *name = name_list; if (name_count != 1) { ast_file_err(f, proc_token, "You can only declare one procedure at a time (at the moment)"); - return make_bad_decl(f, name->ident.token, proc_token); + return make_bad_decl(f, name->Ident.token, proc_token); } AstNode *procedure_decl = parse_procedure_decl(f, proc_token, name, declaration_kind); @@ -1946,7 +1878,7 @@ AstNode *parse_stmt(AstFile *f) { case Token_Hash: s = parse_tag_stmt(f, NULL); - s->tag_stmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument + s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument return s; case Token_OpenBrace: return parse_block_stmt(f); @@ -2128,7 +2060,7 @@ void parse_file(Parser *p, AstFile *f) { ast_file_err(f, ast_node_token(node), "Only declarations are allowed at file scope"); } else { if (node->kind == AstNode_ImportDecl) { - auto *id = &node->import_decl; + auto *id = &node->ImportDecl; String file = id->filepath.string; String file_str = {}; if (file.text[0] == '"') diff --git a/src/printer.cpp b/src/printer.cpp index 31a86fe99..143635cf7 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -12,24 +12,24 @@ void print_ast(AstNode *node, isize indent) { switch (node->kind) { case AstNode_BasicLit: print_indent(indent); - print_token(node->basic_lit); + print_token(node->BasicLit); break; case AstNode_Ident: print_indent(indent); - print_token(node->ident.token); + print_token(node->Ident.token); break; case AstNode_ProcLit: print_indent(indent); gb_printf("(proc lit)\n"); - print_ast(node->proc_lit.type, indent+1); - print_ast(node->proc_lit.body, indent+1); + print_ast(node->ProcLit.type, indent+1); + print_ast(node->ProcLit.body, indent+1); break; case AstNode_CompoundLit: print_indent(indent); gb_printf("(compound lit)\n"); - print_ast(node->compound_lit.type, indent+1); - print_ast(node->compound_lit.elem_list, indent+1); + print_ast(node->CompoundLit.type, indent+1); + print_ast(node->CompoundLit.elem_list, indent+1); break; @@ -37,168 +37,168 @@ void print_ast(AstNode *node, isize indent) { print_indent(indent); gb_printf("(tag)\n"); print_indent(indent+1); - print_token(node->tag_expr.name); - print_ast(node->tag_expr.expr, indent+1); + print_token(node->TagExpr.name); + print_ast(node->TagExpr.expr, indent+1); break; case AstNode_UnaryExpr: print_indent(indent); - print_token(node->unary_expr.op); - print_ast(node->unary_expr.expr, indent+1); + print_token(node->UnaryExpr.op); + print_ast(node->UnaryExpr.expr, indent+1); break; case AstNode_BinaryExpr: print_indent(indent); - print_token(node->binary_expr.op); - print_ast(node->binary_expr.left, indent+1); - print_ast(node->binary_expr.right, indent+1); + print_token(node->BinaryExpr.op); + print_ast(node->BinaryExpr.left, indent+1); + print_ast(node->BinaryExpr.right, indent+1); break; case AstNode_CallExpr: print_indent(indent); gb_printf("(call)\n"); - print_ast(node->call_expr.proc, indent+1); - print_ast(node->call_expr.arg_list, indent+1); + print_ast(node->CallExpr.proc, indent+1); + print_ast(node->CallExpr.arg_list, indent+1); break; case AstNode_SelectorExpr: print_indent(indent); gb_printf(".\n"); - print_ast(node->selector_expr.expr, indent+1); - print_ast(node->selector_expr.selector, indent+1); + print_ast(node->SelectorExpr.expr, indent+1); + print_ast(node->SelectorExpr.selector, indent+1); break; case AstNode_IndexExpr: print_indent(indent); gb_printf("([])\n"); - print_ast(node->index_expr.expr, indent+1); - print_ast(node->index_expr.index, indent+1); + print_ast(node->IndexExpr.expr, indent+1); + print_ast(node->IndexExpr.index, indent+1); break; case AstNode_CastExpr: print_indent(indent); gb_printf("(cast)\n"); - print_ast(node->cast_expr.type, indent+1); - print_ast(node->cast_expr.expr, indent+1); + print_ast(node->CastExpr.type, indent+1); + print_ast(node->CastExpr.expr, indent+1); break; case AstNode_DerefExpr: print_indent(indent); gb_printf("(deref)\n"); - print_ast(node->deref_expr.expr, indent+1); + print_ast(node->DerefExpr.expr, indent+1); break; case AstNode_ExprStmt: - print_ast(node->expr_stmt.expr, indent); + print_ast(node->ExprStmt.expr, indent); break; case AstNode_IncDecStmt: print_indent(indent); - print_token(node->inc_dec_stmt.op); - print_ast(node->inc_dec_stmt.expr, indent+1); + print_token(node->IncDecStmt.op); + print_ast(node->IncDecStmt.expr, indent+1); break; case AstNode_AssignStmt: print_indent(indent); - print_token(node->assign_stmt.op); - print_ast(node->assign_stmt.lhs_list, indent+1); - print_ast(node->assign_stmt.rhs_list, indent+1); + print_token(node->AssignStmt.op); + print_ast(node->AssignStmt.lhs_list, indent+1); + print_ast(node->AssignStmt.rhs_list, indent+1); break; case AstNode_BlockStmt: print_indent(indent); gb_printf("(block)\n"); - print_ast(node->block_stmt.list, indent+1); + print_ast(node->BlockStmt.list, indent+1); break; case AstNode_IfStmt: print_indent(indent); gb_printf("(if)\n"); - print_ast(node->if_stmt.cond, indent+1); - print_ast(node->if_stmt.body, indent+1); - if (node->if_stmt.else_stmt) { + print_ast(node->IfStmt.cond, indent+1); + print_ast(node->IfStmt.body, indent+1); + if (node->IfStmt.else_stmt) { print_indent(indent); gb_printf("(else)\n"); - print_ast(node->if_stmt.else_stmt, indent+1); + print_ast(node->IfStmt.else_stmt, indent+1); } break; case AstNode_ReturnStmt: print_indent(indent); gb_printf("(return)\n"); - print_ast(node->return_stmt.result_list, indent+1); + print_ast(node->ReturnStmt.result_list, indent+1); break; case AstNode_ForStmt: print_indent(indent); gb_printf("(for)\n"); - print_ast(node->for_stmt.init, indent+1); - print_ast(node->for_stmt.cond, indent+1); - print_ast(node->for_stmt.end, indent+1); - print_ast(node->for_stmt.body, indent+1); + print_ast(node->ForStmt.init, indent+1); + print_ast(node->ForStmt.cond, indent+1); + print_ast(node->ForStmt.end, indent+1); + print_ast(node->ForStmt.body, indent+1); break; case AstNode_DeferStmt: print_indent(indent); gb_printf("(defer)\n"); - print_ast(node->defer_stmt.stmt, indent+1); + print_ast(node->DeferStmt.stmt, indent+1); break; case AstNode_VarDecl: print_indent(indent); - if (node->var_decl.kind == Declaration_Mutable) + if (node->VarDecl.kind == Declaration_Mutable) gb_printf("(decl:var,mutable)\n"); - else if (node->var_decl.kind == Declaration_Immutable) + else if (node->VarDecl.kind == Declaration_Immutable) gb_printf("(decl:var,immutable)\n"); - print_ast(node->var_decl.name_list, indent+1); - print_ast(node->var_decl.type, indent+1); - print_ast(node->var_decl.value_list, indent+1); + print_ast(node->VarDecl.name_list, indent+1); + print_ast(node->VarDecl.type, indent+1); + print_ast(node->VarDecl.value_list, indent+1); break; case AstNode_ProcDecl: print_indent(indent); - if (node->proc_decl.kind == Declaration_Mutable) + if (node->ProcDecl.kind == Declaration_Mutable) gb_printf("(decl:proc,mutable)\n"); - else if (node->proc_decl.kind == Declaration_Immutable) + else if (node->ProcDecl.kind == Declaration_Immutable) gb_printf("(decl:proc,immutable)\n"); - print_ast(node->proc_decl.type, indent+1); - print_ast(node->proc_decl.body, indent+1); - print_ast(node->proc_decl.tag_list, indent+1); + print_ast(node->ProcDecl.type, indent+1); + print_ast(node->ProcDecl.body, indent+1); + print_ast(node->ProcDecl.tag_list, indent+1); break; case AstNode_TypeDecl: print_indent(indent); gb_printf("(type)\n"); - print_ast(node->type_decl.name, indent+1); - print_ast(node->type_decl.type, indent+1); + print_ast(node->TypeDecl.name, indent+1); + print_ast(node->TypeDecl.type, indent+1); break; case AstNode_AliasDecl: print_indent(indent); gb_printf("(alias)\n"); - print_ast(node->alias_decl.name, indent+1); - print_ast(node->alias_decl.type, indent+1); + print_ast(node->AliasDecl.name, indent+1); + print_ast(node->AliasDecl.type, indent+1); break; case AstNode_ProcType: print_indent(indent); - gb_printf("(type:proc)(%td -> %td)\n", node->proc_type.param_count, node->proc_type.result_count); - print_ast(node->proc_type.param_list, indent+1); - if (node->proc_type.result_list) { + gb_printf("(type:proc)(%td -> %td)\n", node->ProcType.param_count, node->ProcType.result_count); + print_ast(node->ProcType.param_list, indent+1); + if (node->ProcType.result_list) { print_indent(indent+1); gb_printf("->\n"); - print_ast(node->proc_type.result_list, indent+1); + print_ast(node->ProcType.result_list, indent+1); } break; case AstNode_Field: - print_ast(node->field.name_list, indent); - print_ast(node->field.type, indent); + print_ast(node->Field.name_list, indent); + print_ast(node->Field.type, indent); break; case AstNode_PointerType: print_indent(indent); - print_token(node->pointer_type.token); - print_ast(node->pointer_type.type, indent+1); + print_token(node->PointerType.token); + print_ast(node->PointerType.type, indent+1); break; case AstNode_ArrayType: print_indent(indent); gb_printf("[]\n"); - print_ast(node->array_type.count, indent+1); - print_ast(node->array_type.elem, indent+1); + print_ast(node->ArrayType.count, indent+1); + print_ast(node->ArrayType.elem, indent+1); break; case AstNode_StructType: print_indent(indent); gb_printf("(struct)\n"); - print_ast(node->struct_type.field_list, indent+1); + print_ast(node->StructType.field_list, indent+1); break; } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index c03c9ce7a..aa59cf319 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -705,7 +705,12 @@ Token tokenizer_get_token(Tokenizer *t) { case '&': token.kind = Token_And; if (t->curr_rune == '~') { - token.kind = token_type_variant2(t, Token_AndNot, Token_AndNotEq); + token.kind = Token_AndNot; + advance_to_next_rune(t); + if (t->curr_rune == '=') { + token.kind = Token_AndNotEq; + advance_to_next_rune(t); + } } else { token.kind = token_type_variant3(t, Token_And, Token_AndEq, '&', Token_CmpAnd); if (t->curr_rune == '=') {