aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <ginger.bill.22@gmail.com>2016-08-02 01:08:36 +0100
committergingerBill <ginger.bill.22@gmail.com>2016-08-02 01:08:36 +0100
commitbf3283c889ce387fd252b48e12e090fab7446048 (patch)
tree564b43bddda6b290009da46c730b937b299e477b /src
parente5665a190d196dc6f2a9bb45be737325eaf12cf5 (diff)
Massive Refactor and If statements
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.cpp62
-rw-r--r--src/checker/expression.cpp411
-rw-r--r--src/checker/statements.cpp254
-rw-r--r--src/codegen/print.cpp64
-rw-r--r--src/codegen/ssa.cpp679
-rw-r--r--src/parser.cpp706
-rw-r--r--src/printer.cpp128
-rw-r--r--src/tokenizer.cpp7
8 files changed, 1207 insertions, 1104 deletions
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");
-
- 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);
-
- } break;
-
- case AstNode_AssignStmt:
- switch (node->assign_stmt.op.kind) {
+ ast_node(bl, BasicLit, &basic_lit);
+ *bl = ids->op;
+ bl->kind = Token_Integer;
+ bl->string = make_string("1");
+
+ 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;
+
+ 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<ssaValue *> 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;
@@ -94,10 +111,22 @@ struct ssaInstruction {
} 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));
-
-/*
- 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;
-*/
-
-#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);
-
- ssaLvalue val = {ssaLvalue_Address};
- val.address.value = value;
- val.address.expr = expr;
- return val;
- } break;
-#endif
-
- case AstNode_SelectorExpr:
- break;
- case AstNode_IndexExpr: {
+ 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;
+
+ case_ast_node(cl, CompoundLit, expr);
+ case_end;
+
+ case_ast_node(pe, ParenExpr, expr);
+ return ssa_build_addr(proc, unparen_expr(expr));
+ case_end;
+
+ case_ast_node(de, DerefExpr, expr);
+ ssaValue *v = ssa_build_expr(proc, de->expr);
+ return ssa_make_lvalue_address(v, expr);
+ case_end;
+
+ case_ast_node(se, SelectorExpr, expr);
+ case_end;
+
+ 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(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(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(_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 == '=') {