From 50aeea1c2e11ed1413ca29bf5993b80dff38fa62 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Wed, 7 Sep 2016 21:59:03 +0100 Subject: [PATCH] Remove AstNode linked lists and replace with arrays --- src/checker/checker.cpp | 30 +-- src/checker/expr.cpp | 293 +++++++++++++----------- src/checker/stmt.cpp | 151 ++++++------ src/codegen/ssa.cpp | 220 +++++++++--------- src/main.cpp | 5 +- src/parser.cpp | 492 ++++++++++++++++++---------------------- src/printer.cpp | 61 +++-- 7 files changed, 620 insertions(+), 632 deletions(-) diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 877f6e461..65b2e4a6f 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -741,7 +741,8 @@ void check_parsed_files(Checker *c) { gb_for_array(i, c->parser->files) { AstFile *f = &c->parser->files[i]; add_curr_ast_file(c, f); - for (AstNode *decl = f->decls; decl != NULL; decl = decl->next) { + gb_for_array(decl_index, f->decls) { + AstNode *decl = f->decls[decl_index]; if (!is_ast_node_decl(decl)) continue; @@ -752,9 +753,9 @@ void check_parsed_files(Checker *c) { 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_for_array(i, vd->values) { + AstNode *name = vd->names[i]; + AstNode *value = vd->values[i]; ExactValue v = {ExactValue_Invalid}; Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v); DeclInfo *di = make_declaration_info(c->allocator, c->global_scope); @@ -763,8 +764,8 @@ void check_parsed_files(Checker *c) { add_file_entity(c, name, e, di); } - isize lhs_count = vd->name_count; - isize rhs_count = vd->value_count; + isize lhs_count = gb_array_count(vd->names); + isize rhs_count = gb_array_count(vd->values); if (rhs_count == 0 && vd->type == NULL) { error(&c->error_collector, ast_node_token(decl), "Missing type or initial expression"); @@ -774,20 +775,24 @@ void check_parsed_files(Checker *c) { } break; case Declaration_Mutable: { - isize entity_count = vd->name_count; + isize entity_count = gb_array_count(vd->names); isize entity_index = 0; Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count); DeclInfo *di = NULL; - if (vd->value_count > 0) { + if (gb_array_count(vd->values) > 0) { di = make_declaration_info(gb_heap_allocator(), c->global_scope); di->entities = entities; di->entity_count = entity_count; di->type_expr = vd->type; - di->init_expr = vd->value_list; + di->init_expr = vd->values[0]; // TODO(bill): Is this correct? } - AstNode *value = vd->value_list; - for (AstNode *name = vd->name_list; name != NULL; name = name->next) { + gb_for_array(i, vd->names) { + AstNode *name = vd->names[i]; + AstNode *value = NULL; + if (i < gb_array_count(vd->values)) { + value = vd->values[i]; + } Entity *e = make_entity_variable(c->allocator, c->global_scope, name->Ident, NULL); entities[entity_index++] = e; @@ -801,9 +806,6 @@ void check_parsed_files(Checker *c) { } add_file_entity(c, name, e, d); - - if (value != NULL) - value = value->next; } } break; } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index b5fb1249f..13d367acd 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -250,7 +250,7 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr); -void check_fields(Checker *c, AstNode *node, AstNode *decl_list, +void check_fields(Checker *c, AstNode *node, AstNodeArray decls, Entity **fields, isize field_count, Entity **other_fields, isize other_field_count, CycleChecker *cycle_checker, String context) { @@ -268,19 +268,21 @@ void check_fields(Checker *c, AstNode *node, AstNode *decl_list, DeclInfo *d;d check_entity_decl(c, e, d, NULL); #endif - for (AstNode *decl = decl_list; decl != NULL; decl = decl->next) { + gb_for_array(decl_index, decls) { + AstNode *decl = decls[decl_index]; if (decl->kind == AstNode_VarDecl) { ast_node(vd, VarDecl, decl); if (vd->kind != Declaration_Immutable) continue; - isize entity_count = vd->name_count; + isize entity_count = gb_array_count(vd->names); isize entity_index = 0; Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count); - for (AstNode *name = vd->name_list, *value = vd->value_list; - name != NULL && value != NULL; - name = name->next, value = value->next) { + gb_for_array(i, vd->values) { + AstNode *name = vd->names[i]; + AstNode *value = vd->values[i]; + GB_ASSERT(name->kind == AstNode_Ident); ExactValue v = {ExactValue_Invalid}; Token name_token = name->Ident; @@ -289,8 +291,8 @@ void check_fields(Checker *c, AstNode *node, AstNode *decl_list, check_const_decl(c, e, vd->type, value); } - isize lhs_count = vd->name_count; - isize rhs_count = vd->value_count; + isize lhs_count = gb_array_count(vd->names); + isize rhs_count = gb_array_count(vd->values); // TODO(bill): Better error messages or is this good enough? if (rhs_count == 0 && vd->type == NULL) { @@ -299,8 +301,8 @@ void check_fields(Checker *c, AstNode *node, AstNode *decl_list, error(&c->error_collector, ast_node_token(node), "Extra initial expression"); } - AstNode *name = vd->name_list; - for (isize i = 0; i < entity_count; i++, name = name->next) { + gb_for_array(i, vd->names) { + AstNode *name = vd->names[i]; Entity *e = entities[i]; Token name_token = name->Ident; HashKey key = hash_string(name_token.string); @@ -337,15 +339,20 @@ void check_fields(Checker *c, AstNode *node, AstNode *decl_list, if (node->kind == AstNode_UnionType) { isize field_index = 0; fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL); - for (AstNode *decl = decl_list; decl != NULL; decl = decl->next) { - if (decl->kind != AstNode_VarDecl) + gb_for_array(decl_index, decls) { + AstNode *decl = decls[decl_index]; + if (decl->kind != AstNode_VarDecl) { continue; + } + ast_node(vd, VarDecl, decl); - if (vd->kind != Declaration_Mutable) + if (vd->kind != Declaration_Mutable) { continue; + } Type *base_type = check_type(c, vd->type, NULL, cycle_checker); - for (AstNode *name = vd->name_list; name != NULL; name = name->next) { + gb_for_array(name_index, vd->names) { + AstNode *name = vd->names[name_index]; Token name_token = name->Ident; Type *type = make_type_named(c->allocator, name_token.string, base_type, NULL); @@ -366,22 +373,26 @@ void check_fields(Checker *c, AstNode *node, AstNode *decl_list, } } else { isize field_index = 0; - for (AstNode *decl = decl_list; decl != NULL; decl = decl->next) { - if (decl->kind != AstNode_VarDecl) + gb_for_array(decl_index, decls) { + AstNode *decl = decls[decl_index]; + if (decl->kind != AstNode_VarDecl) { continue; + } ast_node(vd, VarDecl, decl); - if (vd->kind != Declaration_Mutable) + if (vd->kind != Declaration_Mutable) { continue; + } Type *type = check_type(c, vd->type, NULL, cycle_checker); if (vd->is_using) { - if (vd->name_count > 1) { - error(&c->error_collector, ast_node_token(vd->name_list), + if (gb_array_count(vd->names) > 1) { + error(&c->error_collector, ast_node_token(vd->names[0]), "Cannot apply `using` to more than one of the same type"); } } - for (AstNode *name = vd->name_list; name != NULL; name = name->next) { + gb_for_array(name_index, vd->names) { + AstNode *name = vd->names[name_index]; Token name_token = name->Ident; Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using); @@ -401,7 +412,7 @@ void check_fields(Checker *c, AstNode *node, AstNode *decl_list, if (vd->is_using) { Type *t = get_base_type(type_deref(type)); if (!is_type_struct(t) && !is_type_raw_union(t)) { - Token name_token = vd->name_list->Ident; + Token name_token = vd->names[0]->Ident; error(&c->error_collector, name_token, "`using` on a field `%.*s` must be a type", LIT(name_token.string)); continue; } @@ -419,13 +430,14 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke isize field_count = 0; isize other_field_count = 0; - for (AstNode *decl = st->decl_list; decl != NULL; decl = decl->next) { + gb_for_array(decl_index, st->decls) { + AstNode *decl = st->decls[decl_index]; switch (decl->kind) { case_ast_node(vd, VarDecl, decl); if (vd->kind == Declaration_Mutable) { - field_count += vd->name_count; + field_count += gb_array_count(vd->names); } else { - other_field_count += vd->name_count; + other_field_count += gb_array_count(vd->names); } case_end; @@ -438,7 +450,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count); - check_fields(c, node, st->decl_list, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("struct")); + check_fields(c, node, st->decls, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("struct")); struct_type->Record.struct_is_packed = st->is_packed; struct_type->Record.fields = fields; @@ -453,13 +465,14 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker isize field_count = 1; isize other_field_count = 0; - for (AstNode *decl = ut->decl_list; decl != NULL; decl = decl->next) { + gb_for_array(decl_index, ut->decls) { + AstNode *decl = ut->decls[decl_index]; switch (decl->kind) { case_ast_node(vd, VarDecl, decl); if (vd->kind == Declaration_Mutable) { - field_count += vd->name_count; + field_count += gb_array_count(vd->names); } else { - other_field_count += vd->name_count; + other_field_count += gb_array_count(vd->names); } case_end; @@ -472,7 +485,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count); - check_fields(c, node, ut->decl_list, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("union")); + check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("union")); union_type->Record.fields = fields; union_type->Record.field_count = field_count; @@ -487,13 +500,14 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChec isize field_count = 0; isize other_field_count = 0; - for (AstNode *decl = ut->decl_list; decl != NULL; decl = decl->next) { + gb_for_array(decl_index, ut->decls) { + AstNode *decl = ut->decls[decl_index]; switch (decl->kind) { case_ast_node(vd, VarDecl, decl); if (vd->kind == Declaration_Mutable) { - field_count += vd->name_count; + field_count += gb_array_count(vd->names); } else { - other_field_count += vd->name_count; + other_field_count += gb_array_count(vd->names); } case_end; @@ -506,7 +520,7 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChec Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count); - check_fields(c, node, ut->decl_list, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("raw union")); + check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("raw union")); union_type->Record.fields = fields; union_type->Record.field_count = field_count; @@ -538,10 +552,12 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod } enum_type->Record.enum_base = base_type; - Entity **fields = gb_alloc_array(c->allocator, Entity *, et->field_count); + Entity **fields = gb_alloc_array(c->allocator, Entity *, gb_array_count(et->fields)); isize field_index = 0; ExactValue iota = make_exact_value_integer(-1); - for (AstNode *field = et->field_list; field != NULL; field = field->next) { + gb_for_array(i, et->fields) { + AstNode *field = et->fields[i]; + ast_node(f, FieldValue, field); Token name_token = f->field->Ident; @@ -583,26 +599,34 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod add_entity_use(&c->info, f->field, e); } enum_type->Record.other_fields = fields; - enum_type->Record.other_field_count = et->field_count; + enum_type->Record.other_field_count = gb_array_count(et->fields); } -Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize field_count, b32 *is_variadic_) { - if (field_list == NULL || field_count == 0) +Type *check_get_params(Checker *c, Scope *scope, AstNodeArray fields, b32 *is_variadic_) { + if (fields == NULL || gb_array_count(fields) == 0) return NULL; b32 is_variadic = false; Type *tuple = make_type_tuple(c->allocator); - Entity **variables = gb_alloc_array(c->allocator, Entity *, field_count); + isize variable_count = 0; + gb_for_array(i, fields) { + AstNode *field = fields[i]; + ast_node(f, Field, field); + variable_count += gb_array_count(f->names); + } + + Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count); isize variable_index = 0; - for (AstNode *field = field_list; field != NULL; field = field->next) { + gb_for_array(i, fields) { + AstNode *field = fields[i]; ast_node(f, Field, field); AstNode *type_expr = f->type; if (type_expr) { if (type_expr->kind == AstNode_Ellipsis) { type_expr = type_expr->Ellipsis.expr; - if (field->next == NULL) { + if (i+1 == gb_array_count(fields)) { is_variadic = true; } else { error(&c->error_collector, ast_node_token(field), "Invalid AST: Invalid variadic parameter"); @@ -610,7 +634,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel } Type *type = check_type(c, type_expr); - for (AstNode *name = f->name_list; name != NULL; name = name->next) { + gb_for_array(j, f->names) { + AstNode *name = f->names[j]; if (name->kind == AstNode_Ident) { Entity *param = make_entity_param(c->allocator, scope, name->Ident, type, f->is_using); add_entity(c, scope, name, param); @@ -622,29 +647,31 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel } } - if (is_variadic && field_count > 0) { + if (is_variadic && gb_array_count(fields) > 0) { // NOTE(bill): Change last variadic parameter to be a slice // Custom Calling convention for variadic parameters - Entity *end = variables[field_count-1]; + Entity *end = variables[gb_array_count(fields)-1]; end->type = make_type_slice(c->allocator, end->type); } tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = field_count; + tuple->Tuple.variable_count = variable_count; if (is_variadic_) *is_variadic_ = is_variadic; return tuple; } -Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_count) { - if (list == NULL) +Type *check_get_results(Checker *c, Scope *scope, AstNodeArray results) { + if (results == NULL || gb_array_count(results) == 0) { return NULL; + } Type *tuple = make_type_tuple(c->allocator); - Entity **variables = gb_alloc_array(c->allocator, Entity *, list_count); + Entity **variables = gb_alloc_array(c->allocator, Entity *, gb_array_count(results)); isize variable_index = 0; - for (AstNode *item = list; item != NULL; item = item->next) { + gb_for_array(i, results) { + AstNode *item = results[i]; Type *type = check_type(c, item); Token token = ast_node_token(item); token.string = make_string(""); // NOTE(bill): results are not named @@ -654,7 +681,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun variables[variable_index++] = param; } tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = list_count; + tuple->Tuple.variable_count = gb_array_count(results); return tuple; } @@ -663,20 +690,23 @@ 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) { 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); b32 variadic = false; - Type *params = check_get_params(c, c->context.scope, pt->param_list, param_count, &variadic); - Type *results = check_get_results(c, c->context.scope, pt->result_list, result_count); + Type *params = check_get_params(c, c->context.scope, pt->params, &variadic); + Type *results = check_get_results(c, c->context.scope, pt->results); + + isize param_count = 0; + isize result_count = 0; + if (params) param_count = params ->Tuple.variable_count; + if (results) result_count = results->Tuple.variable_count; type->Proc.scope = c->context.scope; type->Proc.params = params; - type->Proc.param_count = pt->param_count; + type->Proc.param_count = param_count; type->Proc.results = results; - type->Proc.result_count = pt->result_count; + type->Proc.result_count = result_count; type->Proc.variadic = variadic; } @@ -1953,15 +1983,15 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) BuiltinProc *bp = &builtin_procs[id]; { char *err = NULL; - if (ce->arg_list_count < bp->arg_count) + if (gb_array_count(ce->args) < bp->arg_count) err = "Too few"; - if (ce->arg_list_count > bp->arg_count && !bp->variadic) + if (gb_array_count(ce->args) > 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(proc->string), - bp->arg_count, ce->arg_list_count); + bp->arg_count, gb_array_count(ce->args)); return false; } } @@ -1975,17 +2005,17 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) // NOTE(bill): The first arg is a Type, this will be checked case by case break; default: - check_multi_expr(c, operand, ce->arg_list); + check_multi_expr(c, operand, ce->args[0]); } switch (id) { case BuiltinProc_new: { // new :: proc(Type) -> ^Type Operand op = {}; - check_expr_or_type(c, &op, ce->arg_list); + check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; if (op.mode != Addressing_Type && type == NULL || type == t_invalid) { - error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a type for `new`"); + error(&c->error_collector, ast_node_token(ce->args[0]), "Expected a type for `new`"); return false; } operand->mode = Addressing_Value; @@ -1994,15 +2024,15 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_new_slice: { // new_slice :: proc(Type, len: int[, cap: int]) -> []Type Operand op = {}; - check_expr_or_type(c, &op, ce->arg_list); + check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; if (op.mode != Addressing_Type && type == NULL || type == t_invalid) { - error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a type for `new_slice`"); + error(&c->error_collector, ast_node_token(ce->args[0]), "Expected a type for `new_slice`"); return false; } - AstNode *len = ce->arg_list->next; - AstNode *cap = len->next; + AstNode *len = ce->args[1]; + AstNode *cap = ce->args[2]; check_expr(c, &op, len); if (op.mode == Addressing_Invalid) @@ -2028,7 +2058,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) type_str); return false; } - if (cap->next != NULL) { + if (ce->args[3] != NULL) { error(&c->error_collector, ast_node_token(call), "Too many arguments to `new_slice`, expected either 2 or 3"); return false; @@ -2057,10 +2087,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_size_of: { // size_of :: proc(Type) -> int Operand op = {}; - check_expr_or_type(c, &op, ce->arg_list); + check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; if (!type) { - error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a type for `size_of`"); + error(&c->error_collector, ast_node_token(ce->args[0]), "Expected a type for `size_of`"); return false; } @@ -2084,10 +2114,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_align_of: { // align_of :: proc(Type) -> int Operand op = {}; - check_expr_or_type(c, &op, ce->arg_list); + check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; if (!type) { - error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a type for `align_of`"); + error(&c->error_collector, ast_node_token(ce->args[0]), "Expected a type for `align_of`"); return false; } operand->mode = Addressing_Constant; @@ -2109,15 +2139,15 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_offset_of: { // offset_val :: proc(Type, field) -> int Operand op = {}; - check_expr_or_type(c, &op, ce->arg_list); + check_expr_or_type(c, &op, ce->args[0]); Type *type = get_base_type(op.type); - AstNode *field_arg = unparen_expr(ce->arg_list->next); + AstNode *field_arg = unparen_expr(ce->args[1]); if (type != NULL) { - error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a type for `offset_of`"); + error(&c->error_collector, ast_node_token(ce->args[0]), "Expected a type for `offset_of`"); return false; } if (!is_type_struct(type)) { - error(&c->error_collector, ast_node_token(ce->arg_list), "Expected a structure type for `offset_of`"); + error(&c->error_collector, ast_node_token(ce->args[0]), "Expected a structure type for `offset_of`"); return false; } if (field_arg == NULL || @@ -2131,7 +2161,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Selection sel = lookup_field(type, arg->string, operand->mode == Addressing_Type); if (sel.entity == NULL) { gbString type_str = type_to_string(type); - error(&c->error_collector, ast_node_token(ce->arg_list), + error(&c->error_collector, ast_node_token(ce->args[0]), "`%s` has no field named `%.*s`", type_str, LIT(arg->string)); return false; } @@ -2144,7 +2174,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_offset_of_val: { // offset_val :: proc(val: expression) -> int - AstNode *arg = unparen_expr(ce->arg_list); + AstNode *arg = unparen_expr(ce->args[0]); if (arg->kind != AstNode_SelectorExpr) { gbString str = expr_to_string(arg); error(&c->error_collector, ast_node_token(arg), "`%s` is not a selector expression", str); @@ -2192,7 +2222,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) // assert :: proc(cond: bool) if (!is_type_boolean(operand->type)) { - gbString str = expr_to_string(ce->arg_list); + gbString str = expr_to_string(ce->args[0]); defer (gb_string_free(str)); error(&c->error_collector, ast_node_token(call), "`%s` is not a boolean", str); @@ -2200,7 +2230,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (operand->mode == Addressing_Constant && !operand->value.value_bool) { - gbString str = expr_to_string(ce->arg_list); + gbString str = expr_to_string(ce->args[0]); defer (gb_string_free(str)); error(&c->error_collector, ast_node_token(call), "Compile time assertion: `%s`", str); @@ -2272,7 +2302,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) dest_type = d->Slice.elem; Operand op = {}; - check_expr(c, &op, ce->arg_list->next); + check_expr(c, &op, ce->args[1]); if (op.mode == Addressing_Invalid) return false; Type *s = get_base_type(op.type); @@ -2285,8 +2315,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (!are_types_identical(dest_type, src_type)) { - gbString d_arg = expr_to_string(ce->arg_list); - gbString s_arg = expr_to_string(ce->arg_list->next); + gbString d_arg = expr_to_string(ce->args[0]); + gbString s_arg = expr_to_string(ce->args[1]); gbString d_str = type_to_string(dest_type); gbString s_str = type_to_string(src_type); defer (gb_string_free(d_arg)); @@ -2309,7 +2339,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) x_type = get_base_type(operand->type); Operand op = {}; - check_expr(c, &op, ce->arg_list->next); + check_expr(c, &op, ce->args[1]); if (op.mode == Addressing_Invalid) return false; y_type = get_base_type(op.type); @@ -2321,8 +2351,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *elem_type = x_type->Pointer.elem->Slice.elem; if (!check_is_assignable_to(c, &op, elem_type)) { - gbString d_arg = expr_to_string(ce->arg_list); - gbString s_arg = expr_to_string(ce->arg_list->next); + gbString d_arg = expr_to_string(ce->args[0]); + gbString s_arg = expr_to_string(ce->args[1]); gbString d_str = type_to_string(elem_type); gbString s_str = type_to_string(y_type); defer (gb_string_free(d_arg)); @@ -2353,7 +2383,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) isize max_count = vector_type->Vector.count; isize arg_count = 0; - for (AstNode *arg = ce->arg_list->next; arg != NULL; arg = arg->next) { + gb_for_array(i, ce->args) { + if (i == 0) continue; + AstNode *arg = ce->args[i]; Operand op = {}; check_expr(c, &op, arg); if (op.mode == Addressing_Invalid) @@ -2406,7 +2438,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; } - AstNode *offset = ce->arg_list->next; + AstNode *offset = ce->args[1]; Operand op = {}; check_expr(c, &op, offset); if (op.mode == Addressing_Invalid) @@ -2447,7 +2479,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) "`rawptr` cannot have pointer arithmetic"); return false; } - AstNode *offset = ce->arg_list->next; + AstNode *offset = ce->args[1]; Operand op = {}; check_expr(c, &op, offset); if (op.mode == Addressing_Invalid) @@ -2509,8 +2541,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; } - AstNode *len = ce->arg_list->next; - AstNode *cap = len->next; + AstNode *len = ce->args[1]; + AstNode *cap = ce->args[2]; Operand op = {}; check_expr(c, &op, len); @@ -2537,7 +2569,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) type_str); return false; } - if (cap->next != NULL) { + if (ce->args[2] != NULL) { error(&c->error_collector, ast_node_token(call), "Too many arguments to `slice_ptr`, expected either 2 or 3"); return false; @@ -2560,7 +2592,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; } - AstNode *other_arg = ce->arg_list->next; + AstNode *other_arg = ce->args[1]; Operand a = *operand; Operand b = {}; check_expr(c, &b, other_arg); @@ -2620,7 +2652,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; } - AstNode *other_arg = ce->arg_list->next; + AstNode *other_arg = ce->args[1]; Operand a = *operand; Operand b = {}; check_expr(c, &b, other_arg); @@ -2710,6 +2742,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return true; } + 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_Proc); @@ -2734,21 +2767,22 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode } } - if (ce->arg_list_count == 0) { + if (gb_array_count(ce->args) == 0) { if (variadic && param_count-1 == 0) return; if (param_count == 0) return; } + // TODO(bill): Completely redo this entire code. + // It's from when I used linked lists instead of arrays in the parser - - if (ce->arg_list_count > param_count && !variadic) { + if (gb_array_count(ce->args) > param_count && !variadic) { error_code = +1; } else { Entity **sig_params = proc_type->Proc.params->Tuple.variables; - AstNode *call_arg = ce->arg_list; - for (; call_arg != NULL; call_arg = call_arg->next) { + gb_for_array(arg_index, ce->args) { + AstNode *call_arg = ce->args[arg_index]; check_multi_expr(c, operand, call_arg); if (operand->mode == Addressing_Invalid) continue; @@ -2804,8 +2838,6 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode if ((!variadic && param_index < param_count) || (variadic && param_index < param_count-1)) { error_code = -1; - } else if (call_arg != NULL && call_arg->next != NULL) { - error_code = +1; } } @@ -2832,8 +2864,8 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { check_expr_or_type(c, operand, ce->proc); if (operand->mode == Addressing_Invalid) { - for (AstNode *arg = ce->arg_list; arg != NULL; arg = arg->next) { - check_expr_base(c, operand, arg); + gb_for_array(i, ce->args) { + check_expr_base(c, operand, ce->args[i]); } operand->mode = Addressing_Invalid; operand->expr = call; @@ -2977,17 +3009,16 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case Type_Record: { if (!is_type_struct(t)) break; - if (cl->elem_count == 0) + if (gb_array_count(cl->elems) == 0) { break; // NOTE(bill): No need to init + } { // Checker values - AstNode *elem = cl->elem_list; isize field_count = t->Record.field_count; - if (elem->kind == AstNode_FieldValue) { + if (cl->elems[0]->kind == AstNode_FieldValue) { b32 *fields_visited = gb_alloc_array(c->allocator, b32, field_count); - for (; - elem != NULL; - elem = elem->next) { + gb_for_array(i, cl->elems) { + AstNode *elem = cl->elems[i]; if (elem->kind != AstNode_FieldValue) { error(&c->error_collector, ast_node_token(elem), "Mixture of `field = value` and value elements in a structure literal is not allowed"); @@ -3030,10 +3061,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint check_assignment(c, o, field->type, make_string("structure literal")); } } else { - isize index = 0; - for (; - elem != NULL; - elem = elem->next, index++) { + gb_for_array(index, cl->elems) { + AstNode *elem = cl->elems[index]; if (elem->kind == AstNode_FieldValue) { error(&c->error_collector, ast_node_token(elem), "Mixture of `field = value` and value elements in a structure literal is not allowed"); @@ -3048,8 +3077,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } check_assignment(c, o, field->type, make_string("structure literal")); } - if (cl->elem_count < field_count) { - error(&c->error_collector, cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elem_count); + if (gb_array_count(cl->elems) < field_count) { + error(&c->error_collector, cl->close, "Too few values in structure literal, expected %td, got %td", field_count, gb_array_count(cl->elems)); } } } @@ -3074,10 +3103,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } - i64 index = 0; i64 max = 0; - for (AstNode *elem = cl->elem_list; elem != NULL; elem = elem->next, index++) { - AstNode *e = elem; + isize index = 0; + for (; index < gb_array_count(cl->elems); index++) { + AstNode *e = cl->elems[index]; if (e->kind == AstNode_FieldValue) { error(&c->error_collector, ast_node_token(e), "`field = value` is only allowed in structure literals"); @@ -3088,12 +3117,12 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint if (t->kind == Type_Array && t->Array.count >= 0 && index >= t->Array.count) { - error(&c->error_collector, ast_node_token(elem), "Index %lld is out of bounds (>= %lld) for array literal", index, t->Array.count); + error(&c->error_collector, ast_node_token(e), "Index %lld is out of bounds (>= %lld) for array literal", index, t->Array.count); } if (t->kind == Type_Vector && t->Vector.count >= 0 && index >= t->Vector.count) { - error(&c->error_collector, ast_node_token(elem), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count); + error(&c->error_collector, ast_node_token(e), "Index %lld is out of bounds (>= %lld) for vector literal", index, t->Vector.count); } Operand o = {}; @@ -3105,7 +3134,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint if (t->kind == Type_Vector) { if (t->Vector.count > 1 && gb_is_between(index, 2, t->Vector.count-1)) { - error(&c->error_collector, ast_node_token(cl->elem_list), + error(&c->error_collector, ast_node_token(cl->elems[0]), "Expected either 1 (broadcast) or %td elements in vector literal, got %td", t->Vector.count, index); } } @@ -3454,15 +3483,14 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) { 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) { +gbString write_fields_to_string(gbString str, AstNodeArray fields, char *sep) { + gb_for_array(i, fields) { + AstNode *field = fields[i]; ast_node(f, Field, field); if (i > 0) str = gb_string_appendc(str, sep); str = write_expr_to_string(str, field); - i++; } return str; } @@ -3594,12 +3622,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) { if (f->is_using) { str = gb_string_appendc(str, "using "); } - isize i = 0; - for (AstNode *name = f->name_list; name != NULL; name = name->next) { + gb_for_array(i, f->names) { + AstNode *name = f->names[i]; if (i > 0) str = gb_string_appendc(str, ", "); str = write_expr_to_string(str, name); - i++; } str = gb_string_appendc(str, ": "); @@ -3609,32 +3636,32 @@ gbString write_expr_to_string(gbString str, AstNode *node) { 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 = ce->arg_list; arg != NULL; arg = arg->next) { + + gb_for_array(i, ce->args) { + AstNode *arg = ce->args[i]; if (i > 0) { str = gb_string_appendc(str, ", "); } str = write_expr_to_string(str, arg); - i++; } str = gb_string_appendc(str, ")"); case_end; case_ast_node(pt, ProcType, node); str = gb_string_appendc(str, "proc("); - str = write_field_list_to_string(str, pt->param_list, ", "); + str = write_fields_to_string(str, pt->params, ", "); str = gb_string_appendc(str, ")"); case_end; case_ast_node(st, StructType, node); str = gb_string_appendc(str, "struct{"); - // str = write_field_list_to_string(str, st->decl_list, ", "); + // str = write_fields_to_string(str, st->decl_list, ", "); str = gb_string_appendc(str, "}"); case_end; case_ast_node(st, RawUnionType, node); str = gb_string_appendc(str, "raw_union{"); - // str = write_field_list_to_string(str, st->decl_list, ", "); + // str = write_fields_to_string(str, st->decl_list, ", "); str = gb_string_appendc(str, "}"); case_end; diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 75c6ad11d..636ccdb34 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -9,17 +9,17 @@ enum StmtFlag : u32 { void check_stmt(Checker *c, AstNode *node, u32 flags); -void check_stmt_list(Checker *c, AstNode *list, isize list_count, u32 flags) { +void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) { b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0; u32 f = flags & (~Stmt_FallthroughAllowed); - isize i = 0; - for (AstNode *n = list; n != NULL; n = n->next, i++) { + gb_for_array(i, stmts) { + AstNode *n = stmts[i]; if (n->kind == AstNode_EmptyStmt) { continue; } u32 new_flags = f; - if (ft_ok && i+1 == list_count) { + if (ft_ok && i+1 == gb_array_count(stmts)) { new_flags |= Stmt_FallthroughAllowed; } check_stmt(c, n, new_flags); @@ -29,24 +29,22 @@ void check_stmt_list(Checker *c, AstNode *list, isize list_count, u32 flags) { b32 check_is_terminating(AstNode *node); b32 check_has_break(AstNode *stmt, b32 implicit); -b32 check_is_terminating_list(AstNode *list) { - // Get to end of list - for (; list != NULL; list = list->next) { - if (list->next == NULL) - break; - } +b32 check_is_terminating_list(AstNodeArray stmts) { // Iterate backwards - for (AstNode *n = list; n != NULL; n = n->prev) { - if (n->kind != AstNode_EmptyStmt) - return check_is_terminating(n); + for (isize n = gb_array_count(stmts)-1; n >= 0; n--) { + AstNode *stmt = stmts[n]; + if (stmt->kind != AstNode_EmptyStmt) { + return check_is_terminating(stmt); + } } return false; } -b32 check_has_break_list(AstNode *list, b32 implicit) { - for (AstNode *stmt = list; stmt != NULL; stmt = stmt->next) { +b32 check_has_break_list(AstNodeArray stmts, b32 implicit) { + gb_for_array(i, stmts) { + AstNode *stmt = stmts[i]; if (check_has_break(stmt, implicit)) { return true; } @@ -63,7 +61,7 @@ b32 check_has_break(AstNode *stmt, b32 implicit) { } break; case AstNode_BlockStmt: - return check_has_break_list(stmt->BlockStmt.list, implicit); + return check_has_break_list(stmt->BlockStmt.stmts, implicit); case AstNode_IfStmt: if (check_has_break(stmt->IfStmt.body, implicit) || @@ -91,7 +89,7 @@ b32 check_is_terminating(AstNode *node) { case_end; case_ast_node(bs, BlockStmt, node); - return check_is_terminating_list(bs->list); + return check_is_terminating_list(bs->stmts); case_end; case_ast_node(es, ExprStmt, node); @@ -115,7 +113,8 @@ b32 check_is_terminating(AstNode *node) { case_ast_node(ms, MatchStmt, node); b32 has_default = false; - for (AstNode *clause = ms->body->BlockStmt.list; clause != NULL; clause = clause->next) { + gb_for_array(i, ms->body->BlockStmt.stmts) { + AstNode *clause = ms->body->BlockStmt.stmts[i]; ast_node(cc, CaseClause, clause); if (cc->list == NULL) { has_default = true; @@ -130,7 +129,8 @@ b32 check_is_terminating(AstNode *node) { case_ast_node(ms, TypeMatchStmt, node); b32 has_default = false; - for (AstNode *clause = ms->body->BlockStmt.list; clause != NULL; clause = clause->next) { + gb_for_array(i, ms->body->BlockStmt.stmts) { + AstNode *clause = ms->body->BlockStmt.stmts[i]; ast_node(cc, CaseClause, clause); if (cc->list == NULL) { has_default = true; @@ -259,8 +259,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex return e->type; } -void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNode *init_list, isize init_count, String context_name) { - if ((lhs == NULL || lhs_count == 0) && init_count == 0) +void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) { + if ((lhs == NULL || lhs_count == 0) && gb_array_count(inits) == 0) return; // TODO(bill): Do not use heap allocation here if I can help it @@ -268,7 +268,8 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNode *in gb_array_init(operands, gb_heap_allocator()); defer (gb_array_free(operands)); - for (AstNode *rhs = init_list; rhs != NULL; rhs = rhs->next) { + gb_for_array(i, inits) { + AstNode *rhs = inits[i]; Operand o = {}; check_multi_expr(c, &o, rhs); if (o.type->kind != Type_Tuple) { @@ -422,7 +423,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod push_procedure(c, type); ast_node(bs, BlockStmt, body); // TODO(bill): Check declarations first (except mutable variable declarations) - check_stmt_list(c, bs->list, bs->list_count, 0); + check_stmt_list(c, bs->stmts, 0); if (type->Proc.result_count > 0) { if (!check_is_terminating(body)) { error(&c->error_collector, bs->close, "Missing return statement at the end of the procedure"); @@ -548,7 +549,10 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count entities[i]->type = e->type; } - check_init_variables(c, entities, entity_count, init_expr, 1, make_string("variable declaration")); + AstNodeArray inits; + gb_array_init(inits, c->allocator); + gb_array_append(inits, init_expr); + check_init_variables(c, entities, entity_count, inits, make_string("variable declaration")); } @@ -587,7 +591,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc void check_var_decl_node(Checker *c, AstNode *node) { ast_node(vd, VarDecl, node); - isize entity_count = vd->name_count; + isize entity_count = gb_array_count(vd->names); isize entity_index = 0; Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count); switch (vd->kind) { @@ -595,7 +599,8 @@ void check_var_decl_node(Checker *c, AstNode *node) { Entity **new_entities = gb_alloc_array(c->allocator, Entity *, entity_count); isize new_entity_count = 0; - for (AstNode *name = vd->name_list; name != NULL; name = name->next) { + gb_for_array(i, vd->names) { + AstNode *name = vd->names[i]; Entity *entity = NULL; Token token = name->Ident; if (name->kind == AstNode_Ident) { @@ -648,23 +653,22 @@ void check_var_decl_node(Checker *c, AstNode *node) { e->type = init_type; } - check_init_variables(c, entities, entity_count, vd->value_list, vd->value_count, make_string("variable declaration")); + check_init_variables(c, entities, entity_count, vd->values, make_string("variable declaration")); - AstNode *name = vd->name_list; - for (isize i = 0; i < new_entity_count; i++, name = name->next) { - add_entity(c, c->context.scope, name, new_entities[i]); + gb_for_array(i, vd->names) { + add_entity(c, c->context.scope, vd->names[i], new_entities[i]); } } break; case Declaration_Immutable: { - for (AstNode *name = vd->name_list, *value = vd->value_list; - name != NULL && value != NULL; - name = name->next, value = value->next) { + gb_for_array(i, vd->values) { + AstNode *name = vd->names[i]; + AstNode *value = vd->values[i]; + GB_ASSERT(name->kind == AstNode_Ident); ExactValue v = {ExactValue_Invalid}; - ast_node(i, Ident, name); - String str = i->string; + String str = name->Ident.string; Entity *found = current_scope_lookup_entity(c->context.scope, str); if (found == NULL) { Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v); @@ -675,8 +679,8 @@ void check_var_decl_node(Checker *c, AstNode *node) { } } - isize lhs_count = vd->name_count; - isize rhs_count = vd->value_count; + isize lhs_count = gb_array_count(vd->names); + isize rhs_count = gb_array_count(vd->values); // TODO(bill): Better error messages or is this good enough? if (rhs_count == 0 && vd->type == NULL) { @@ -685,9 +689,8 @@ void check_var_decl_node(Checker *c, AstNode *node) { error(&c->error_collector, ast_node_token(node), "Extra initial expression"); } - AstNode *name = vd->name_list; - for (isize i = 0; i < entity_count; i++, name = name->next) { - add_entity(c, c->context.scope, name, entities[i]); + gb_for_array(i, vd->names) { + add_entity(c, c->context.scope, vd->names[i], entities[i]); } } break; @@ -769,7 +772,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { switch (as->op.kind) { case Token_Eq: { // a, b, c = 1, 2, 3; // Multisided - if (as->lhs_count == 0) { + if (gb_array_count(as->lhs) == 0) { error(&c->error_collector, as->op, "Missing lhs in assignment statement"); return; } @@ -779,7 +782,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { gb_array_init(operands, gb_heap_allocator()); defer (gb_array_free(operands)); - for (AstNode *rhs = as->rhs_list; rhs != NULL; rhs = rhs->next) { + gb_for_array(i, as->rhs) { + AstNode *rhs = as->rhs[i]; Operand o = {}; check_multi_expr(c, &o, rhs); if (o.type->kind != Type_Tuple) { @@ -793,25 +797,23 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { } } - isize lhs_count = as->lhs_count; + isize lhs_count = gb_array_count(as->lhs); isize rhs_count = gb_array_count(operands); isize operand_index = 0; - for (AstNode *lhs = as->lhs_list; - lhs != NULL; - lhs = lhs->next, operand_index++) { - check_assignment_variable(c, &operands[operand_index], lhs); - + gb_for_array(i, as->lhs) { + AstNode *lhs = as->lhs[i]; + check_assignment_variable(c, &operands[i], lhs); } if (lhs_count != rhs_count) { - error(&c->error_collector, ast_node_token(as->lhs_list), "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count); + error(&c->error_collector, ast_node_token(as->lhs[0]), "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count); } } break; default: { // a += 1; // Single-sided Token op = as->op; - if (as->lhs_count != 1 || as->rhs_count != 1) { + if (gb_array_count(as->lhs) != 1 || gb_array_count(as->rhs) != 1) { error(&c->error_collector, op, "Assignment operation `%.*s` requires single-valued expressions", LIT(op.string)); return; } @@ -825,21 +827,21 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { ast_node(be, BinaryExpr, &binary_expr); be->op = op; // NOTE(bill): Only use the first one will be used - be->left = as->lhs_list; - be->right = as->rhs_list; + be->left = as->lhs[0]; + be->right = as->rhs[0]; 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, as->lhs_list); + check_assignment_variable(c, &operand, as->lhs[0]); } break; } case_end; case_ast_node(bs, BlockStmt, node); check_open_scope(c, node); - check_stmt_list(c, bs->list, bs->list_count, mod_flags); + check_stmt_list(c, bs->stmts, mod_flags); check_close_scope(c); case_end; @@ -887,15 +889,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { isize result_count = 0; if (proc_type->Proc.results) result_count = proc_type->Proc.results->Tuple.variable_count; - if (result_count != rs->result_count) { + if (result_count != gb_array_count(rs->results)) { error(&c->error_collector, rs->token, "Expected %td return %s, got %td", result_count, (result_count != 1 ? "values" : "value"), - rs->result_count); + gb_array_count(rs->results)); } else if (result_count > 0) { auto *tuple = &proc_type->Proc.results->Tuple; check_init_variables(c, tuple->variables, tuple->variable_count, - rs->result_list, rs->result_count, make_string("return statement")); + rs->results, make_string("return statement")); } case_end; @@ -947,11 +949,12 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { // NOTE(bill): Check for multiple defaults AstNode *first_default = NULL; ast_node(bs, BlockStmt, ms->body); - for (AstNode *stmt = bs->list; stmt != NULL; stmt = stmt->next) { + gb_for_array(i, bs->stmts) { + AstNode *stmt = bs->stmts[i]; AstNode *default_stmt = NULL; if (stmt->kind == AstNode_CaseClause) { ast_node(c, CaseClause, stmt); - if (c->list_count == 0) { + if (gb_array_count(c->list) == 0) { default_stmt = stmt; } } else { @@ -979,8 +982,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { Map seen = {}; // Multimap map_init(&seen, gb_heap_allocator()); defer (map_destroy(&seen)); - isize i = 0; - for (AstNode *stmt = bs->list; stmt != NULL; stmt = stmt->next) { + gb_for_array(i, bs->stmts) { + AstNode *stmt = bs->stmts[i]; if (stmt->kind != AstNode_CaseClause) { // NOTE(bill): error handled by above multiple default checker continue; @@ -988,7 +991,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { ast_node(cc, CaseClause, stmt); - for (AstNode *expr = cc->list; expr != NULL; expr = expr->next) { + gb_for_array(j, cc->list) { + AstNode *expr = cc->list[j]; Operand y = {}; Operand z = {}; Token eq = {Token_CmpEq}; @@ -1051,12 +1055,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { check_open_scope(c, stmt); u32 ft_flags = mod_flags; - if (i+1 < bs->list_count) { + if (i+1 < gb_array_count(bs->stmts)) { ft_flags |= Stmt_FallthroughAllowed; } - check_stmt_list(c, cc->stmts, cc->stmt_count, ft_flags); + check_stmt_list(c, cc->stmts, ft_flags); check_close_scope(c); - i++; } case_end; @@ -1083,11 +1086,12 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { // NOTE(bill): Check for multiple defaults AstNode *first_default = NULL; ast_node(bs, BlockStmt, ms->body); - for (AstNode *stmt = bs->list; stmt != NULL; stmt = stmt->next) { + gb_for_array(i, bs->stmts) { + AstNode *stmt = bs->stmts[i]; AstNode *default_stmt = NULL; if (stmt->kind == AstNode_CaseClause) { ast_node(c, CaseClause, stmt); - if (c->list_count == 0) { + if (gb_array_count(c->list) == 0) { default_stmt = stmt; } } else { @@ -1116,15 +1120,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { defer (map_destroy(&seen)); - - for (AstNode *stmt = bs->list; stmt != NULL; stmt = stmt->next) { + gb_for_array(i, bs->stmts) { + AstNode *stmt = bs->stmts[i]; if (stmt->kind != AstNode_CaseClause) { // NOTE(bill): error handled by above multiple default checker continue; } ast_node(cc, CaseClause, stmt); - AstNode *type_expr = cc->list; + AstNode *type_expr = cc->list[0]; Type *tag_type = NULL; if (type_expr != NULL) { // Otherwise it's a default expression Operand y = {}; @@ -1171,7 +1175,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, ms->var->Ident, tag_ptr_type); add_entity(c, c->context.scope, ms->var, tag_var); } - check_stmt_list(c, cc->stmts, cc->stmt_count, mod_flags); + check_stmt_list(c, cc->stmts, mod_flags); check_close_scope(c); } case_end; @@ -1311,12 +1315,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { case_end; case_ast_node(vd, VarDecl, us->node); - if (vd->name_count > 1 && vd->type != NULL) { + if (gb_array_count(vd->names) > 1 && vd->type != NULL) { error(&c->error_collector, us->token, "`using` can only be applied to one variable of the same type"); } check_var_decl_node(c, us->node); - for (AstNode *item = vd->name_list; item != NULL; item = item->next) { + gb_for_array(name_index, vd->names) { + AstNode *item = vd->names[name_index]; ast_node(i, Ident, item); String name = i->string; Entity *e = scope_lookup_entity(c, c->context.scope, name); diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index fc55600ab..8a9e00e6d 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -1792,9 +1792,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case Type_Vector: { isize index = 0; ssaValue *result = ssa_emit_load(proc, v); - for (AstNode *elem = cl->elem_list; - elem != NULL; - elem = elem->next, index++) { + for (; index < gb_array_count(cl->elems); index++) { + AstNode *elem = cl->elems[index]; ssaValue *field_elem = ssa_build_expr(proc, elem); Type *t = ssa_type(field_elem); GB_ASSERT(t->kind != Type_Tuple); @@ -1819,13 +1818,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case Type_Record: { GB_ASSERT(is_type_struct(base_type)); auto *st = &base_type->Record; - if (cl->elem_list != NULL) { - isize index = 0; - AstNode *elem = cl->elem_list; - for (; - elem != NULL; - elem = elem->next, index++) { - isize field_index = index; + if (cl->elems != NULL && gb_array_count(cl->elems) > 0) { + gb_for_array(field_index, cl->elems) { + AstNode *elem = cl->elems[field_index]; ssaValue *field_expr = NULL; Entity *field = NULL; @@ -1850,32 +1845,29 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } } break; case Type_Array: { - isize index = 0; - for (AstNode *elem = cl->elem_list; - elem != NULL; - elem = elem->next, index++) { + gb_for_array(i, cl->elems) { + AstNode *elem = cl->elems[i]; ssaValue *field_expr = ssa_build_expr(proc, elem); Type *t = ssa_type(field_expr); GB_ASSERT(t->kind != Type_Tuple); ssaValue *ev = ssa_emit_conv(proc, field_expr, et); - ssaValue *gep = ssa_emit_struct_gep(proc, v, index, et); + ssaValue *gep = ssa_emit_struct_gep(proc, v, i, et); ssa_emit_store(proc, gep, ev); } } break; case Type_Slice: { - i64 count = cl->elem_count; + i64 count = gb_array_count(cl->elems); Type *elem_type = base_type->Slice.elem; Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type); ssaValue *array = ssa_add_local_generated(proc, make_type_array(proc->module->allocator, elem_type, count)); - isize index = 0; - for (AstNode *elem = cl->elem_list; - elem != NULL; - elem = elem->next, index++) { + + gb_for_array(i, cl->elems) { + AstNode *elem = cl->elems[i]; ssaValue *field_expr = ssa_build_expr(proc, elem); Type *t = ssa_type(field_expr); GB_ASSERT(t->kind != Type_Tuple); ssaValue *ev = ssa_emit_conv(proc, field_expr, elem_type); - ssaValue *gep = ssa_emit_struct_gep(proc, array, index, elem_ptr_type); + ssaValue *gep = ssa_emit_struct_gep(proc, array, i, elem_ptr_type); ssa_emit_store(proc, gep, ev); } @@ -1906,7 +1898,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // new :: proc(Type) -> ^Type gbAllocator allocator = proc->module->allocator; - Type *type = type_of_expr(proc->module->info, ce->arg_list); + Type *type = type_of_expr(proc->module->info, ce->args[0]); Type *ptr_type = make_type_pointer(allocator, type); i64 s = type_size_of(proc->module->sizes, allocator, type); @@ -1925,7 +1917,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // new_slice :: proc(Type, len: int[, cap: int]) -> ^Type gbAllocator allocator = proc->module->allocator; - Type *type = type_of_expr(proc->module->info, ce->arg_list); + Type *type = type_of_expr(proc->module->info, ce->args[0]); Type *ptr_type = make_type_pointer(allocator, type); Type *slice_type = make_type_slice(allocator, type); @@ -1935,13 +1927,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue *elem_size = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(s)); ssaValue *elem_align = ssa_make_value_constant(allocator, t_int, make_exact_value_integer(a)); - AstNode *len_node = ce->arg_list->next; - AstNode *cap_node = len_node->next; - - ssaValue *len = ssa_build_expr(proc, len_node); + ssaValue *len = ssa_build_expr(proc, ce->args[1]); ssaValue *cap = len; - if (cap_node != NULL) { - cap = ssa_build_expr(proc, cap_node); + if (gb_array_count(ce->args) == 3) { + cap = ssa_build_expr(proc, ce->args[2]); } Token mul = {Token_Mul}; @@ -1966,7 +1955,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue // delete :: proc(slice: []Type) gbAllocator allocator = proc->module->allocator; - ssaValue *value = ssa_build_expr(proc, ce->arg_list); + ssaValue *value = ssa_build_expr(proc, ce->args[0]); if (is_type_slice(ssa_type(value))) { Type *etp = get_base_type(ssa_type(value)); @@ -1982,7 +1971,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_assert: { ssa_emit_comment(proc, make_string("assert")); - ssaValue *cond = ssa_build_expr(proc, ce->arg_list); + ssaValue *cond = ssa_build_expr(proc, ce->args[0]); GB_ASSERT(is_type_boolean(ssa_type(cond))); Token eq = {Token_CmpEq}; @@ -1993,9 +1982,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssa_emit_if(proc, cond, err, done); proc->curr_block = err; - Token token = ast_node_token(ce->arg_list); + Token token = ast_node_token(ce->args[0]); TokenPos pos = token.pos; - gbString expr = expr_to_string(ce->arg_list); + gbString expr = expr_to_string(ce->args[0]); defer (gb_string_free(expr)); isize err_len = pos.file.len + 1 + 10 + 1 + 10 + 1; @@ -2029,7 +2018,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssa_emit_comment(proc, make_string("len")); // len :: proc(v: Type) -> int // NOTE(bill): len of an array is a constant expression - ssaValue *v = ssa_build_expr(proc, ce->arg_list); + ssaValue *v = ssa_build_expr(proc, ce->args[0]); Type *t = get_base_type(ssa_type(v)); if (t == t_string) return ssa_string_len(proc, v); @@ -2040,15 +2029,15 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssa_emit_comment(proc, make_string("cap")); // cap :: proc(v: Type) -> int // NOTE(bill): cap of an array is a constant expression - ssaValue *v = ssa_build_expr(proc, ce->arg_list); + ssaValue *v = ssa_build_expr(proc, ce->args[0]); Type *t = get_base_type(ssa_type(v)); return ssa_slice_cap(proc, v); } break; case BuiltinProc_copy: { ssa_emit_comment(proc, make_string("copy")); // copy :: proc(dst, src: []Type) -> int - AstNode *dst_node = ce->arg_list; - AstNode *src_node = ce->arg_list->next; + AstNode *dst_node = ce->args[0]; + AstNode *src_node = ce->args[1]; ssaValue *dst_slice = ssa_build_expr(proc, dst_node); ssaValue *src_slice = ssa_build_expr(proc, src_node); Type *slice_type = get_base_type(ssa_type(dst_slice)); @@ -2083,8 +2072,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_append: { ssa_emit_comment(proc, make_string("append")); // append :: proc(s: ^[]Type, item: Type) -> bool - AstNode *sptr_node = ce->arg_list; - AstNode *item_node = ce->arg_list->next; + AstNode *sptr_node = ce->args[0]; + AstNode *item_node = ce->args[1]; ssaValue *slice_ptr = ssa_build_expr(proc, sptr_node); ssaValue *slice = ssa_emit_load(proc, slice_ptr); @@ -2143,16 +2132,17 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_swizzle: { ssa_emit_comment(proc, make_string("swizzle")); - ssaValue *vector = ssa_build_expr(proc, ce->arg_list); - isize index_count = ce->arg_list_count-1; + ssaValue *vector = ssa_build_expr(proc, ce->args[0]); + isize index_count = gb_array_count(ce->args)-1; if (index_count == 0) { return vector; } i32 *indices = gb_alloc_array(proc->module->allocator, i32, index_count); isize index = 0; - for (AstNode *arg = ce->arg_list->next; arg != NULL; arg = arg->next) { - TypeAndValue *tv = type_and_value_of_expression(proc->module->info, arg); + gb_for_array(i, ce->args) { + if (i == 0) continue; + TypeAndValue *tv = type_and_value_of_expression(proc->module->info, ce->args[i]); GB_ASSERT(is_type_integer(tv->type)); GB_ASSERT(tv->value.kind == ExactValue_Integer); indices[index++] = cast(i32)tv->value.value_integer; @@ -2164,15 +2154,15 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_ptr_offset: { ssa_emit_comment(proc, make_string("ptr_offset")); - ssaValue *ptr = ssa_build_expr(proc, ce->arg_list); - ssaValue *offset = ssa_build_expr(proc, ce->arg_list->next); + ssaValue *ptr = ssa_build_expr(proc, ce->args[0]); + ssaValue *offset = ssa_build_expr(proc, ce->args[1]); return ssa_emit_ptr_offset(proc, ptr, offset); } break; case BuiltinProc_ptr_sub: { ssa_emit_comment(proc, make_string("ptr_sub")); - ssaValue *ptr_a = ssa_build_expr(proc, ce->arg_list); - ssaValue *ptr_b = ssa_build_expr(proc, ce->arg_list->next); + ssaValue *ptr_a = ssa_build_expr(proc, ce->args[0]); + ssaValue *ptr_b = ssa_build_expr(proc, ce->args[1]); Type *ptr_type = get_base_type(ssa_type(ptr_a)); GB_ASSERT(ptr_type->kind == Type_Pointer); isize elem_size = type_size_of(proc->module->sizes, proc->module->allocator, ptr_type->Pointer.elem); @@ -2190,14 +2180,14 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_slice_ptr: { ssa_emit_comment(proc, make_string("slice_ptr")); - ssaValue *ptr = ssa_build_expr(proc, ce->arg_list); - ssaValue *len = ssa_build_expr(proc, ce->arg_list->next); + ssaValue *ptr = ssa_build_expr(proc, ce->args[0]); + ssaValue *len = ssa_build_expr(proc, ce->args[1]); ssaValue *cap = len; len = ssa_emit_conv(proc, len, t_int, true); - if (ce->arg_list->next->next != NULL) { - cap = ssa_build_expr(proc, ce->arg_list->next->next); + if (gb_array_count(ce->args) == 3) { + cap = ssa_build_expr(proc, ce->args[2]); cap = ssa_emit_conv(proc, cap, t_int, true); } @@ -2212,8 +2202,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_min: { ssa_emit_comment(proc, make_string("min")); - ssaValue *x = ssa_build_expr(proc, ce->arg_list); - ssaValue *y = ssa_build_expr(proc, ce->arg_list->next); + ssaValue *x = ssa_build_expr(proc, ce->args[0]); + ssaValue *y = ssa_build_expr(proc, ce->args[1]); Type *t = get_base_type(ssa_type(x)); Token lt = {Token_Lt}; ssaValue *cond = ssa_emit_comp(proc, lt, x, y); @@ -2222,8 +2212,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_max: { ssa_emit_comment(proc, make_string("max")); - ssaValue *x = ssa_build_expr(proc, ce->arg_list); - ssaValue *y = ssa_build_expr(proc, ce->arg_list->next); + ssaValue *x = ssa_build_expr(proc, ce->args[0]); + ssaValue *y = ssa_build_expr(proc, ce->args[1]); Type *t = get_base_type(ssa_type(x)); Token gt = {Token_Gt}; ssaValue *cond = ssa_emit_comp(proc, gt, x, y); @@ -2235,7 +2225,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue Token lt = {Token_Lt}; Token sub = {Token_Sub}; - ssaValue *x = ssa_build_expr(proc, ce->arg_list); + ssaValue *x = ssa_build_expr(proc, ce->args[0]); Type *t = ssa_type(x); ssaValue *neg_x = ssa_emit_arith(proc, sub, v_zero, x, t); @@ -2248,8 +2238,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue **found = map_get(&proc->module->members, hash_string(make_string("__type_info_data"))); GB_ASSERT(found != NULL); ssaValue *type_info_data = *found; - ssaValue *x = ssa_build_expr(proc, ce->arg_list); - Type *t = default_type(type_of_expr(proc->module->info, ce->arg_list)); + ssaValue *x = ssa_build_expr(proc, ce->args[0]); + Type *t = default_type(type_of_expr(proc->module->info, ce->args[0])); MapFindResult fr = map__find(&proc->module->info->type_info_types, hash_pointer(t)); GB_ASSERT(fr.entry_index >= 0); // Zero is null and void @@ -2272,7 +2262,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue isize arg_index = 0; isize arg_count = 0; - for (AstNode *a = ce->arg_list; a != NULL; a = a->next) { + gb_for_array(i, ce->args) { + AstNode *a = ce->args[i]; Type *at = get_base_type(type_of_expr(proc->module->info, a)); if (at->kind == Type_Tuple) { arg_count += at->Tuple.variable_count; @@ -2283,11 +2274,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, arg_count); b32 variadic = proc_type_->Proc.variadic; - AstNode *arg = ce->arg_list; - for (; - arg != NULL; - arg = arg->next) { - ssaValue *a = ssa_build_expr(proc, arg); + gb_for_array(i, ce->args) { + ssaValue *a = ssa_build_expr(proc, ce->args[i]); Type *at = ssa_type(a); if (at->kind == Type_Tuple) { for (isize i = 0; i < at->Tuple.variable_count; i++) { @@ -2732,9 +2720,10 @@ void ssa_gen_global_type_name(ssaModule *m, Entity *e, String name) { -void ssa_build_stmt_list(ssaProcedure *proc, AstNode *list) { - for (AstNode *stmt = list ; stmt != NULL; stmt = stmt->next) - ssa_build_stmt(proc, stmt); +void ssa_build_stmt_list(ssaProcedure *proc, AstNodeArray stmts) { + gb_for_array(i, stmts) { + ssa_build_stmt(proc, stmts[i]); + } } void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { @@ -2751,15 +2740,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(vd, VarDecl, node); if (vd->kind == Declaration_Mutable) { - if (vd->name_count == vd->value_count) { // 1:1 assigment + if (gb_array_count(vd->names) == gb_array_count(vd->values)) { // 1:1 assigment gbArray(ssaAddr) lvals; gbArray(ssaValue *) inits; - gb_array_init_reserve(lvals, gb_heap_allocator(), vd->name_count); - gb_array_init_reserve(inits, gb_heap_allocator(), vd->name_count); + gb_array_init_reserve(lvals, gb_heap_allocator(), gb_array_count(vd->names)); + gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(vd->names)); defer (gb_array_free(lvals)); defer (gb_array_free(inits)); - for (AstNode *name = vd->name_list; name != NULL; name = name->next) { + gb_for_array(i, vd->names) { + AstNode *name = vd->names[i]; ssaAddr lval = ssa_make_addr(NULL, NULL); if (!ssa_is_blank_ident(name)) { ssa_add_local_for_identifier(proc, name, false); @@ -2769,9 +2759,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_append(lvals, lval); } - - for (AstNode *value = vd->value_list; value != NULL; value = value->next) { - ssaValue *init = ssa_build_expr(proc, value); + gb_for_array(i, vd->values) { + ssaValue *init = ssa_build_expr(proc, vd->values[i]); gb_array_append(inits, init); } @@ -2781,8 +2770,9 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssa_lvalue_store(proc, lvals[i], v); } - } else if (vd->value_count == 0) { // declared and zero-initialized - for (AstNode *name = vd->name_list; name != NULL; name = name->next) { + } else if (gb_array_count(vd->values) == 0) { // declared and zero-initialized + gb_for_array(i, vd->names) { + AstNode *name = vd->names[i]; if (!ssa_is_blank_ident(name)) { ssa_add_local_for_identifier(proc, name, true); } @@ -2790,12 +2780,13 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { } else { // Tuple(s) gbArray(ssaAddr) lvals; gbArray(ssaValue *) inits; - gb_array_init_reserve(lvals, gb_heap_allocator(), vd->name_count); - gb_array_init_reserve(inits, gb_heap_allocator(), vd->name_count); + gb_array_init_reserve(lvals, gb_heap_allocator(), gb_array_count(vd->names)); + gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(vd->names)); defer (gb_array_free(lvals)); defer (gb_array_free(inits)); - for (AstNode *name = vd->name_list; name != NULL; name = name->next) { + gb_for_array(i, vd->names) { + AstNode *name = vd->names[i]; ssaAddr lval = ssa_make_addr(NULL, NULL); if (!ssa_is_blank_ident(name)) { ssa_add_local_for_identifier(proc, name, false); @@ -2805,8 +2796,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_append(lvals, lval); } - for (AstNode *value = vd->value_list; value != NULL; value = value->next) { - ssaValue *init = ssa_build_expr(proc, value); + gb_for_array(i, vd->values) { + ssaValue *init = ssa_build_expr(proc, vd->values[i]); Type *t = ssa_type(init); if (t->kind == Type_Tuple) { for (isize i = 0; i < t->Tuple.variable_count; i++) { @@ -2923,9 +2914,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_init(lvals, gb_heap_allocator()); defer (gb_array_free(lvals)); - for (AstNode *lhs = as->lhs_list; - lhs != NULL; - lhs = lhs->next) { + gb_for_array(i, as->lhs) { + AstNode *lhs = as->lhs[i]; ssaAddr lval = {}; if (!ssa_is_blank_ident(lhs)) { lval = ssa_build_addr(proc, lhs); @@ -2933,9 +2923,9 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_append(lvals, lval); } - if (as->lhs_count == as->rhs_count) { - if (as->lhs_count == 1) { - AstNode *rhs = as->rhs_list; + if (gb_array_count(as->lhs) == gb_array_count(as->rhs)) { + if (gb_array_count(as->lhs) == 1) { + AstNode *rhs = as->rhs[0]; ssaValue *init = ssa_build_expr(proc, rhs); ssa_lvalue_store(proc, lvals[0], init); } else { @@ -2943,8 +2933,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals)); defer (gb_array_free(inits)); - for (AstNode *rhs = as->rhs_list; rhs != NULL; rhs = rhs->next) { - ssaValue *init = ssa_build_expr(proc, rhs); + gb_for_array(i, as->rhs) { + ssaValue *init = ssa_build_expr(proc, as->rhs[i]); gb_array_append(inits, init); } @@ -2957,8 +2947,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals)); defer (gb_array_free(inits)); - for (AstNode *rhs = as->rhs_list; rhs != NULL; rhs = rhs->next) { - ssaValue *init = ssa_build_expr(proc, rhs); + gb_for_array(i, as->rhs) { + ssaValue *init = ssa_build_expr(proc, as->rhs[i]); Type *t = ssa_type(init); // TODO(bill): refactor for code reuse as this is repeated a bit if (t->kind == Type_Tuple) { @@ -2986,8 +2976,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { i32 kind = op.kind; kind += Token_Add - Token_AddEq; // Convert += to + op.kind = cast(TokenKind)kind; - ssaAddr lhs = ssa_build_addr(proc, as->lhs_list); - ssaValue *value = ssa_build_expr(proc, as->rhs_list); + ssaAddr lhs = ssa_build_addr(proc, as->lhs[0]); + ssaValue *value = ssa_build_expr(proc, as->rhs[0]); ssa_build_assign_op(proc, lhs, value, op); } break; } @@ -3000,7 +2990,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(bs, BlockStmt, node); proc->scope_index++; - ssa_build_stmt_list(proc, bs->list); + ssa_build_stmt_list(proc, bs->stmts); ssa_emit_defer_stmts(proc, ssaDefer_Default, NULL); proc->scope_index--; case_end; @@ -3019,24 +3009,20 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssaValue *v = NULL; auto *return_type_tuple = &proc->type->Proc.results->Tuple; isize return_count = proc->type->Proc.result_count; - if (rs->result_count == 1 && return_count > 1) { + if (gb_array_count(rs->results) == 1 && return_count > 1) { GB_PANIC("ReturnStmt tuple return statement"); } else if (return_count == 1) { Entity *e = return_type_tuple->variables[0]; - v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->result_list), e->type); + v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[0]), e->type); } else if (return_count == 0) { // No return values } else { // 1:1 multiple return values Type *ret_type = proc->type->Proc.results; v = ssa_add_local_generated(proc, ret_type); - isize i = 0; - AstNode *r = rs->result_list; - for (; - i < return_count && r != NULL; - i++, r = r->next) { + gb_for_array(i, rs->results) { Entity *e = return_type_tuple->variables[i]; - ssaValue *res = ssa_emit_conv(proc, ssa_build_expr(proc, r), e->type); + ssaValue *res = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[i]), e->type); ssaValue *field = ssa_emit_struct_gep(proc, v, i, e->type); ssa_emit_store(proc, field, res); } @@ -3150,18 +3136,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ast_node(body, BlockStmt, ms->body); - AstNode *default_stmts = NULL; + AstNodeArray default_stmts = NULL; ssaBlock *default_fall = NULL; ssaBlock *default_block = NULL; ssaBlock *fall = NULL; b32 append_fall = false; - isize case_count = body->list_count; - isize i = 0; - for (AstNode *clause = body->list; - clause != NULL; - clause = clause->next, i++) { + isize case_count = gb_array_count(body->stmts); + gb_for_array(i, body->stmts) { + AstNode *clause = body->stmts[i]; ssaBlock *body = fall; b32 append_body = false; @@ -3170,7 +3154,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { if (body == NULL) { append_body = true; - if (cc->list == NULL) { + if (gb_array_count(cc->list)) { body = ssa__make_block(proc, clause, make_string("match.dflt.body")); } else { body = ssa__make_block(proc, clause, make_string("match.case.body")); @@ -3187,7 +3171,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { fall = ssa__make_block(proc, clause, make_string("match.fall.body")); } - if (cc->list == NULL) { + if (gb_array_count(cc->list)) { // default case default_stmts = cc->stmts; default_fall = fall; @@ -3197,7 +3181,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssaBlock *next_cond = NULL; Token eq = {Token_CmpEq}; - for (AstNode *expr = cc->list; expr != NULL; expr = expr->next) { + gb_for_array(j, cc->list) { + AstNode *expr = cc->list[j]; next_cond = ssa__make_block(proc, clause, make_string("match.case.next")); ssaValue *cond = ssa_emit_comp(proc, eq, tag, ssa_build_expr(proc, expr)); @@ -3256,16 +3241,17 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { String tag_var_name = ms->var->Ident.string; - AstNode *default_stmts = NULL; + AstNodeArray default_stmts = NULL; ssaBlock *default_block = NULL; - isize case_count = body->list_count; - for (AstNode *clause = body->list; clause != NULL; clause = clause->next) { + isize case_count = gb_array_count(body->stmts); + gb_for_array(i, body->stmts) { + AstNode *clause = body->stmts[i]; ast_node(cc, CaseClause, clause); - if (cc->list == NULL) { + if (gb_array_count(cc->list) == 0) { // default case - default_stmts = cc->stmts; + default_stmts = cc->stmts; default_block = ssa__make_block(proc, clause, make_string("type-match.dflt.body")); continue; } @@ -3276,7 +3262,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { Scope *scope = *map_get(&proc->module->info->scopes, hash_pointer(clause)); Entity *tag_var_entity = current_scope_lookup_entity(scope, tag_var_name); - GB_ASSERT(tag_var_entity != NULL); + GB_ASSERT_MSG(tag_var_entity != NULL, "%.*s", LIT(tag_var_name)); ssaValue *tag_var = ssa_add_local(proc, tag_var_entity); ssaValue *data_ptr = ssa_emit_conv(proc, data, tag_var_entity->type); ssa_emit_store(proc, tag_var, data_ptr); diff --git a/src/main.cpp b/src/main.cpp index 6099e10f7..06cfc73f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,7 +41,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) { } -#if 0 +#if 1 #define INIT_TIMER() u64 start_time, end_time = 0, total_time = 0; start_time = gb_utc_time_now() #define PRINT_TIMER(section) do { \ u64 diff; \ @@ -92,6 +92,7 @@ int main(int argc, char **argv) { // print_ast(parser.files[0].decls, 0); +#if 1 Checker checker = {}; init_checker(&checker, &parser); @@ -101,7 +102,7 @@ int main(int argc, char **argv) { PRINT_TIMER("Semantic Checker"); - +#endif #if 1 ssaGen ssa = {}; if (!ssa_gen_init(&ssa, &checker)) diff --git a/src/parser.cpp b/src/parser.cpp index 3dd92d096..e0902d795 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -13,6 +13,7 @@ enum ParseFileError { ParseFile_Count, }; +typedef gbArray(AstNode *) AstNodeArray; struct AstFile { gbArena arena; @@ -25,8 +26,7 @@ struct AstFile { // NOTE(bill): Used to prevent type literals in control clauses isize expr_level; - AstNode *decls; - isize decl_count; + AstNodeArray decls; AstNode *curr_proc; isize scope_level; @@ -74,6 +74,13 @@ enum CallExprKind { CallExpr_Infix, // a ''call b }; +AstNodeArray make_ast_node_array(AstFile *f) { + AstNodeArray a; + gb_array_init(a, gb_arena_allocator(&f->arena)); + return a; +} + + #define AST_NODE_KINDS \ AST_NODE_KIND(Invalid, "invalid node", struct{}) \ AST_NODE_KIND(BasicLit, "basic literal", Token) \ @@ -89,8 +96,7 @@ enum CallExprKind { }) \ AST_NODE_KIND(CompoundLit, "compound literal", struct { \ AstNode *type; \ - AstNode *elem_list; \ - isize elem_count; \ + AstNodeArray elems; \ Token open, close; \ }) \ AST_NODE_KIND(_ExprBegin, "", struct{}) \ @@ -103,8 +109,8 @@ AST_NODE_KIND(_ExprBegin, "", struct{}) \ AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \ AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \ AST_NODE_KIND(CallExpr, "call expression", struct { \ - AstNode *proc, *arg_list; \ - isize arg_list_count; \ + AstNode *proc; \ + gbArray(AstNode *) args; \ Token open, close; \ Token ellipsis; \ CallExprKind kind; \ @@ -129,13 +135,11 @@ AST_NODE_KIND(_StmtBegin, "", struct{}) \ }) \ AST_NODE_KIND(AssignStmt, "assign statement", struct { \ Token op; \ - AstNode *lhs_list, *rhs_list; \ - isize lhs_count, rhs_count; \ + AstNodeArray lhs, rhs; \ }) \ AST_NODE_KIND(_ComplexStmtBegin, "", struct{}) \ AST_NODE_KIND(BlockStmt, "block statement", struct { \ - AstNode *list; \ - isize list_count; \ + AstNodeArray stmts; \ Token open, close; \ }) \ AST_NODE_KIND(IfStmt, "if statement", struct { \ @@ -147,8 +151,7 @@ AST_NODE_KIND(_ComplexStmtBegin, "", struct{}) \ }) \ AST_NODE_KIND(ReturnStmt, "return statement", struct { \ Token token; \ - AstNode *result_list; \ - isize result_count; \ + AstNodeArray results; \ }) \ AST_NODE_KIND(ForStmt, "for statement", struct { \ Token token; \ @@ -157,9 +160,7 @@ AST_NODE_KIND(_ComplexStmtBegin, "", struct{}) \ }) \ AST_NODE_KIND(CaseClause, "case clause", struct { \ Token token; \ - AstNode *list; \ - AstNode *stmts; \ - isize list_count, stmt_count; \ + AstNodeArray list, stmts; \ }) \ AST_NODE_KIND(MatchStmt, "match statement", struct { \ Token token; \ @@ -197,10 +198,9 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \ DeclKind kind; \ u32 tags; \ b32 is_using; \ - AstNode *name_list; \ + AstNodeArray names; \ AstNode *type; \ - AstNode *value_list; \ - isize name_count, value_count; \ + AstNodeArray values; \ }) \ AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \ AstNode *name; \ @@ -215,17 +215,14 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \ AST_NODE_KIND(_DeclEnd, "", struct{}) \ AST_NODE_KIND(_TypeBegin, "", struct{}) \ AST_NODE_KIND(Field, "field", struct { \ - AstNode *name_list; \ - isize name_count; \ + AstNodeArray names; \ AstNode *type; \ b32 is_using; \ }) \ AST_NODE_KIND(ProcType, "procedure type", struct { \ Token token; \ - AstNode *param_list; \ - AstNode *result_list; \ - isize param_count; \ - isize result_count; \ + AstNodeArray params; \ + AstNodeArray results; \ }) \ AST_NODE_KIND(PointerType, "pointer type", struct { \ Token token; \ @@ -243,25 +240,24 @@ AST_NODE_KIND(_TypeBegin, "", struct{}) \ }) \ AST_NODE_KIND(StructType, "struct type", struct { \ Token token; \ - AstNode *decl_list; \ + AstNodeArray decls; \ isize decl_count; \ b32 is_packed; \ }) \ AST_NODE_KIND(UnionType, "union type", struct { \ Token token; \ - AstNode *decl_list; \ + AstNodeArray decls; \ isize decl_count; \ }) \ AST_NODE_KIND(RawUnionType, "raw union type", struct { \ Token token; \ - AstNode *decl_list; \ + AstNodeArray decls; \ isize decl_count; \ }) \ AST_NODE_KIND(EnumType, "enum type", struct { \ Token token; \ AstNode *base_type; \ - AstNode *field_list; \ - isize field_count; \ + AstNodeArray fields; \ }) \ AST_NODE_KIND(_TypeEnd, "", struct{}) \ AST_NODE_KIND(Count, "", struct{}) @@ -280,7 +276,7 @@ String const ast_node_strings[] = { struct AstNode { AstNodeKind kind; - AstNode *prev, *next; // NOTE(bill): allow for Linked list + // AstNode *prev, *next; // NOTE(bill): allow for Linked list union { #define AST_NODE_KIND(_kind_name_, name, ...) __VA_ARGS__ _kind_name_; AST_NODE_KINDS @@ -382,7 +378,7 @@ Token ast_node_token(AstNode *node) { case AstNode_BadDecl: return node->BadDecl.begin; case AstNode_VarDecl: - return ast_node_token(node->VarDecl.name_list); + return ast_node_token(node->VarDecl.names[0]); case AstNode_ProcDecl: return node->ProcDecl.name->Ident; case AstNode_TypeDecl: @@ -392,8 +388,8 @@ Token ast_node_token(AstNode *node) { case AstNode_ForeignSystemLibrary: return node->ForeignSystemLibrary.token; case AstNode_Field: { - if (node->Field.name_list) - return ast_node_token(node->Field.name_list); + if (node->Field.names) + return ast_node_token(node->Field.names[0]); else return ast_node_token(node->Field.type); } @@ -512,11 +508,10 @@ gb_inline AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token return result; } -gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNode *arg_list, isize arg_list_count, Token open, Token close, Token ellipsis) { +gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, gbArray(AstNode *)args, Token open, Token close, Token ellipsis) { AstNode *result = make_node(f, AstNode_CallExpr); result->CallExpr.proc = proc; - result->CallExpr.arg_list = arg_list; - result->CallExpr.arg_list_count = arg_list_count; + result->CallExpr.args = args; result->CallExpr.open = open; result->CallExpr.close = close; result->CallExpr.ellipsis = ellipsis; @@ -596,12 +591,10 @@ gb_inline AstNode *make_field_value(AstFile *f, AstNode *field, AstNode *value, return result; } -gb_inline AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNode *elem_list, isize elem_count, - Token open, Token close) { +gb_inline AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token open, Token close) { AstNode *result = make_node(f, AstNode_CompoundLit); result->CompoundLit.type = type; - result->CompoundLit.elem_list = elem_list; - result->CompoundLit.elem_count = elem_count; + result->CompoundLit.elems = elems; result->CompoundLit.open = open; result->CompoundLit.close = close; return result; @@ -633,20 +626,17 @@ gb_inline AstNode *make_inc_dec_stmt(AstFile *f, Token op, AstNode *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) { +gb_inline AstNode *make_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rhs) { AstNode *result = make_node(f, AstNode_AssignStmt); 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; + result->AssignStmt.lhs = lhs; + result->AssignStmt.rhs = rhs; return result; } -gb_inline AstNode *make_block_stmt(AstFile *f, AstNode *list, isize list_count, Token open, Token close) { +gb_inline AstNode *make_block_stmt(AstFile *f, AstNodeArray stmts, Token open, Token close) { AstNode *result = make_node(f, AstNode_BlockStmt); - result->BlockStmt.list = list; - result->BlockStmt.list_count = list_count; + result->BlockStmt.stmts = stmts; result->BlockStmt.open = open; result->BlockStmt.close = close; return result; @@ -662,11 +652,10 @@ gb_inline AstNode *make_if_stmt(AstFile *f, Token token, AstNode *init, AstNode return result; } -gb_inline AstNode *make_return_stmt(AstFile *f, Token token, AstNode *result_list, isize result_count) { +gb_inline AstNode *make_return_stmt(AstFile *f, Token token, AstNodeArray results) { AstNode *result = make_node(f, AstNode_ReturnStmt); result->ReturnStmt.token = token; - result->ReturnStmt.result_list = result_list; - result->ReturnStmt.result_count = result_count; + result->ReturnStmt.results = results; return result; } @@ -700,13 +689,11 @@ gb_inline AstNode *make_type_match_stmt(AstFile *f, Token token, AstNode *tag, A return result; } -gb_inline AstNode *make_case_clause(AstFile *f, Token token, AstNode *list, isize list_count, AstNode *stmts, isize stmt_count) { +gb_inline AstNode *make_case_clause(AstFile *f, Token token, AstNodeArray list, AstNodeArray stmts) { AstNode *result = make_node(f, AstNode_CaseClause); result->CaseClause.token = token; result->CaseClause.list = list; - result->CaseClause.list_count = list_count; result->CaseClause.stmts = stmts; - result->CaseClause.stmt_count = stmt_count; return result; } @@ -768,33 +755,28 @@ gb_inline AstNode *make_bad_decl(AstFile *f, Token begin, Token end) { return result; } -gb_inline AstNode *make_var_decl(AstFile *f, DeclKind kind, AstNode *name_list, isize name_count, AstNode *type, AstNode *value_list, isize value_count) { +gb_inline AstNode *make_var_decl(AstFile *f, DeclKind kind, AstNodeArray names, AstNode *type, AstNodeArray values) { AstNode *result = make_node(f, AstNode_VarDecl); result->VarDecl.kind = kind; - result->VarDecl.name_list = name_list; - result->VarDecl.name_count = name_count; + result->VarDecl.names = names; result->VarDecl.type = type; - result->VarDecl.value_list = value_list; - result->VarDecl.value_count = value_count; + result->VarDecl.values = values; return result; } -gb_inline AstNode *make_field(AstFile *f, AstNode *name_list, isize name_count, AstNode *type, b32 is_using) { +gb_inline AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) { AstNode *result = make_node(f, AstNode_Field); - result->Field.name_list = name_list; - result->Field.name_count = name_count; + result->Field.names = names; result->Field.type = type; result->Field.is_using = is_using; return result; } -gb_inline AstNode *make_proc_type(AstFile *f, Token token, AstNode *param_list, isize param_count, AstNode *result_list, isize result_count) { +gb_inline AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results) { AstNode *result = make_node(f, AstNode_ProcType); 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; + result->ProcType.params = params; + result->ProcType.results = results; return result; } @@ -831,39 +813,38 @@ gb_inline AstNode *make_vector_type(AstFile *f, Token token, AstNode *count, Ast return result; } -gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNode *decl_list, isize decl_count, b32 is_packed) { +gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count, b32 is_packed) { AstNode *result = make_node(f, AstNode_StructType); result->StructType.token = token; - result->StructType.decl_list = decl_list; + result->StructType.decls = decls; result->StructType.decl_count = decl_count; result->StructType.is_packed = is_packed; return result; } -gb_inline AstNode *make_union_type(AstFile *f, Token token, AstNode *decl_list, isize decl_count) { +gb_inline AstNode *make_union_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count) { AstNode *result = make_node(f, AstNode_UnionType); result->UnionType.token = token; - result->UnionType.decl_list = decl_list; + result->UnionType.decls = decls; result->UnionType.decl_count = decl_count; return result; } -gb_inline AstNode *make_raw_union_type(AstFile *f, Token token, AstNode *decl_list, isize decl_count) { +gb_inline AstNode *make_raw_union_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count) { AstNode *result = make_node(f, AstNode_RawUnionType); result->RawUnionType.token = token; - result->RawUnionType.decl_list = decl_list; + result->RawUnionType.decls = decls; result->RawUnionType.decl_count = decl_count; return result; } -gb_inline AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, AstNode *field_list, isize field_count) { +gb_inline AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, AstNodeArray fields) { AstNode *result = make_node(f, AstNode_EnumType); result->EnumType.token = token; result->EnumType.base_type = base_type; - result->EnumType.field_list = field_list; - result->EnumType.field_count = field_count; + result->EnumType.fields = fields; return result; } @@ -1014,11 +995,11 @@ b32 expect_semicolon_after_stmt(AstFile *f, AstNode *s) { } -AstNode *parse_expr(AstFile *f, b32 lhs); -AstNode *parse_proc_type(AstFile *f); -AstNode *parse_stmt_list(AstFile *f, isize *list_count_); -AstNode *parse_stmt(AstFile *f); -AstNode *parse_body(AstFile *f); +AstNode * parse_expr(AstFile *f, b32 lhs); +AstNode * parse_proc_type(AstFile *f); +AstNodeArray parse_stmt_list(AstFile *f); +AstNode * parse_stmt(AstFile *f); +AstNode * parse_body(AstFile *f); AstNode *parse_identifier(AstFile *f) { Token token = f->cursor[0]; @@ -1053,10 +1034,8 @@ AstNode *unparen_expr(AstNode *node) { AstNode *parse_value(AstFile *f); -AstNode *parse_element_list(AstFile *f, isize *element_count_) { - AstNode *root = NULL; - AstNode *curr = NULL; - isize element_count = 0; +AstNodeArray parse_element_list(AstFile *f) { + AstNodeArray elems = make_ast_node_array(f); while (f->cursor[0].kind != Token_CloseBrace && f->cursor[0].kind != Token_EOF) { @@ -1066,28 +1045,29 @@ AstNode *parse_element_list(AstFile *f, isize *element_count_) { AstNode *value = parse_value(f); elem = make_field_value(f, elem, value, eq); } - DLIST_APPEND(root, curr, elem); - element_count++; - if (f->cursor[0].kind != Token_Comma) + + gb_array_append(elems, elem); + + if (f->cursor[0].kind != Token_Comma) { break; + } next_token(f); } - if (element_count_) *element_count_ = element_count; - return root; + return elems; } AstNode *parse_literal_value(AstFile *f, AstNode *type) { - AstNode *element_list = NULL; - isize element_count = 0; + AstNodeArray elems = NULL; Token open = expect_token(f, Token_OpenBrace); f->expr_level++; - if (f->cursor[0].kind != Token_CloseBrace) - element_list = parse_element_list(f, &element_count); + if (f->cursor[0].kind != Token_CloseBrace) { + elems = parse_element_list(f); + } f->expr_level--; Token close = expect_token(f, Token_CloseBrace); - return make_compound_lit(f, type, element_list, element_count, open, close); + return make_compound_lit(f, type, elems, open, close); } AstNode *parse_value(AstFile *f) { @@ -1294,9 +1274,7 @@ b32 is_literal_type(AstNode *node) { } AstNode *parse_call_expr(AstFile *f, AstNode *operand) { - AstNode *arg_list = NULL; - AstNode *arg_list_curr = NULL; - isize arg_list_count = 0; + AstNodeArray args = make_ast_node_array(f); Token open_paren, close_paren; Token ellipsis = {}; @@ -1314,8 +1292,7 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) { next_token(f); } - DLIST_APPEND(arg_list, arg_list_curr, parse_expr(f, false)); - arg_list_count++; + gb_array_append(args, parse_expr(f, false)); if (f->cursor[0].kind != Token_Comma) { if (f->cursor[0].kind == Token_CloseParen) @@ -1328,7 +1305,7 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) { f->expr_level--; close_paren = expect_token(f, Token_CloseParen); - return make_call_expr(f, operand, arg_list, arg_list_count, open_paren, close_paren, ellipsis); + return make_call_expr(f, operand, args, open_paren, close_paren, ellipsis); } AstNode *parse_atom_expr(AstFile *f, b32 lhs) { @@ -1344,7 +1321,10 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) { // TODO(bill): Handle this } AstNode *proc = parse_identifier(f); - operand = make_call_expr(f, proc, operand, 1, ast_node_token(operand), op, empty_token); + gbArray(AstNode *) args; + gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 1); + gb_array_append(args, operand); + operand = make_call_expr(f, proc, args, ast_node_token(operand), op, empty_token); } break; case Token_OpenParen: { @@ -1478,13 +1458,17 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) { } switch (op.kind) { - case Token_DoublePrime: { - AstNode *proc = parse_identifier(f); - AstNode *right = parse_binary_expr(f, false, prec+1); - expression->next = right; - expression = make_call_expr(f, proc, expression, 2, op, ast_node_token(right), empty_token); - continue; - } break; + // case Token_DoublePrime: { + // AstNode *proc = parse_identifier(f); + // AstNode *right = parse_binary_expr(f, false, prec+1); + // expression->next = right; + // gbArray(AstNode *) args; + // gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2); + // gb_array_append(args, expression); + // gb_array_append(args, right); + // expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token); + // continue; + // } break; case Token_as: case Token_transmute: @@ -1510,39 +1494,34 @@ AstNode *parse_expr(AstFile *f, b32 lhs) { } -AstNode *parse_expr_list(AstFile *f, b32 lhs, isize *list_count_) { - AstNode *list_root = NULL; - AstNode *list_curr = NULL; - isize list_count = 0; - +AstNodeArray parse_expr_list(AstFile *f, b32 lhs) { + AstNodeArray list = make_ast_node_array(f); do { AstNode *e = parse_expr(f, lhs); - DLIST_APPEND(list_root, list_curr, e); - list_count++; + gb_array_append(list, e); if (f->cursor[0].kind != Token_Comma || - f->cursor[0].kind == Token_EOF) + f->cursor[0].kind == Token_EOF) { break; + } next_token(f); } while (true); - if (list_count_) *list_count_ = list_count; - - return list_root; + return list; } -AstNode *parse_lhs_expr_list(AstFile *f, isize *list_count) { - return parse_expr_list(f, true, list_count); +AstNodeArray parse_lhs_expr_list(AstFile *f) { + return parse_expr_list(f, true); } -AstNode *parse_rhs_expr_list(AstFile *f, isize *list_count) { - return parse_expr_list(f, false, list_count); +AstNodeArray parse_rhs_expr_list(AstFile *f) { + return parse_expr_list(f, false); } -AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count); +AstNode *parse_decl(AstFile *f, AstNodeArray names); AstNode *parse_simple_stmt(AstFile *f) { isize lhs_count = 0, rhs_count = 0; - AstNode *lhs_expr_list = parse_lhs_expr_list(f, &lhs_count); + AstNodeArray lhs = parse_lhs_expr_list(f); AstNode *statement = NULL; @@ -1568,18 +1547,16 @@ AstNode *parse_simple_stmt(AstFile *f) { return make_bad_stmt(f, f->cursor[0], f->cursor[0]); } next_token(f); - AstNode *rhs_expr_list = parse_rhs_expr_list(f, &rhs_count); - if (rhs_expr_list == NULL) { + AstNodeArray rhs = parse_rhs_expr_list(f); + if (gb_array_count(rhs) == 0) { ast_file_err(f, token, "No right-hand side in assignment statement."); return make_bad_stmt(f, token, f->cursor[0]); } - return make_assign_stmt(f, token, - lhs_expr_list, lhs_count, - rhs_expr_list, rhs_count); + return make_assign_stmt(f, token, lhs, rhs); } break; case Token_Colon: // Declare - return parse_decl(f, lhs_expr_list, lhs_count); + return parse_decl(f, lhs); } if (lhs_count > 1) { @@ -1595,12 +1572,12 @@ AstNode *parse_simple_stmt(AstFile *f) { ast_file_err(f, f->cursor[0], "You cannot use a simple statement in the file scope"); return make_bad_stmt(f, f->cursor[0], f->cursor[0]); } - statement = make_inc_dec_stmt(f, token, lhs_expr_list); + statement = make_inc_dec_stmt(f, token, lhs[0]); next_token(f); return statement; } - return make_expr_stmt(f, lhs_expr_list); + return make_expr_stmt(f, lhs[0]); } @@ -1625,23 +1602,19 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { return make_bad_expr(f, f->cursor[0], f->cursor[1]); } -AstNode *parse_identfier_list(AstFile *f, isize *list_count_) { - AstNode *list_root = NULL; - AstNode *list_curr = NULL; - isize list_count = 0; +AstNodeArray parse_identfier_list(AstFile *f) { + AstNodeArray list = make_ast_node_array(f); do { - DLIST_APPEND(list_root, list_curr, parse_identifier(f)); - list_count++; + gb_array_append(list, parse_identifier(f)); if (f->cursor[0].kind != Token_Comma || - f->cursor[0].kind == Token_EOF) + f->cursor[0].kind == Token_EOF) { break; + } next_token(f); } while (true); - if (list_count_) *list_count_ = list_count; - - return list_root; + return list; } @@ -1667,34 +1640,29 @@ AstNode *parse_type(AstFile *f) { Token parse_procedure_signature(AstFile *f, - AstNode **param_list, isize *param_count, - AstNode **result_list, isize *result_count); + AstNodeArray *params, AstNodeArray *results); AstNode *parse_proc_type(AstFile *f) { - AstNode *params = NULL; - AstNode *results = NULL; - isize param_count = 0; - isize result_count = 0; + AstNodeArray params = NULL; + AstNodeArray results = NULL; - Token proc_token = parse_procedure_signature(f, ¶ms, ¶m_count, &results, &result_count); + Token proc_token = parse_procedure_signature(f, ¶ms, &results); - return make_proc_type(f, proc_token, params, param_count, results, result_count); + return make_proc_type(f, proc_token, params, results); } AstNode *parse_field_decl(AstFile *f) { - AstNode *name_list = NULL; - isize name_count = 0; b32 is_using = false; if (allow_token(f, Token_using)) { is_using = true; } - name_list = parse_lhs_expr_list(f, &name_count); - if (name_count == 0) { + AstNodeArray names = parse_lhs_expr_list(f); + if (gb_array_count(names) == 0) { ast_file_err(f, f->cursor[0], "Empty field declaration"); } - if (name_count > 1 && is_using) { + if (gb_array_count(names) > 1 && is_using) { ast_file_err(f, f->cursor[0], "Cannot apply `using` to more than one of the same type"); is_using = false; } @@ -1711,7 +1679,7 @@ AstNode *parse_field_decl(AstFile *f) { ast_file_err(f, f->cursor[0], "variadic parameter is missing a type after `..`"); type = make_bad_expr(f, ellipsis, f->cursor[0]); } else { - if (name_count > 1) { + if (gb_array_count(names) > 1) { ast_file_err(f, f->cursor[0], "mutliple variadic parameters, only `..`"); } else { type = make_ellipsis(f, ellipsis, type); @@ -1725,32 +1693,28 @@ AstNode *parse_field_decl(AstFile *f) { ast_file_err(f, f->cursor[0], "Expected a type for this field declaration"); } - AstNode *field = make_field(f, name_list, name_count, type, is_using); + AstNode *field = make_field(f, names, type, is_using); return field; } -AstNode *parse_parameter_list(AstFile *f, isize *param_count_) { - AstNode *param_list = NULL; - AstNode *param_list_curr = NULL; - isize param_count = 0; +AstNodeArray parse_parameter_list(AstFile *f) { + AstNodeArray params = make_ast_node_array(f); while (f->cursor[0].kind == Token_Identifier || f->cursor[0].kind == Token_using) { AstNode *field = parse_field_decl(f); - DLIST_APPEND(param_list, param_list_curr, field); - param_count += field->Field.name_count; - if (f->cursor[0].kind != Token_Comma) + gb_array_append(params, field); + if (f->cursor[0].kind != Token_Comma) { break; + } next_token(f); } - if (param_count_) *param_count_ = param_count; - return param_list; + return params; } -AstNode *parse_struct_params(AstFile *f, isize *decl_count_, b32 using_allowed) { - AstNode *decls = NULL; - AstNode *decls_curr = NULL; +AstNodeArray parse_struct_params(AstFile *f, isize *decl_count_, b32 using_allowed) { + AstNodeArray decls = make_ast_node_array(f); isize decl_count = 0; while (f->cursor[0].kind == Token_Identifier || @@ -1759,9 +1723,8 @@ AstNode *parse_struct_params(AstFile *f, isize *decl_count_, b32 using_allowed) if (allow_token(f, Token_using)) { is_using = true; } - isize name_count = 0; - AstNode *name_list = parse_lhs_expr_list(f, &name_count); - if (name_count == 0) { + AstNodeArray names = parse_lhs_expr_list(f); + if (gb_array_count(names) == 0) { ast_file_err(f, f->cursor[0], "Empty field declaration"); } @@ -1769,34 +1732,33 @@ AstNode *parse_struct_params(AstFile *f, isize *decl_count_, b32 using_allowed) ast_file_err(f, f->cursor[0], "Cannot apply `using` to members of a union"); is_using = false; } - if (name_count > 1 && is_using) { + if (gb_array_count(names) > 1 && is_using) { ast_file_err(f, f->cursor[0], "Cannot apply `using` to more than one of the same type"); } AstNode *decl = NULL; if (f->cursor[0].kind == Token_Colon) { - decl = parse_decl(f, name_list, name_count); + decl = parse_decl(f, names); if (decl->kind == AstNode_ProcDecl) { ast_file_err(f, f->cursor[0], "Procedure declarations are not allowed within a structure"); - decl = make_bad_decl(f, ast_node_token(name_list), f->cursor[0]); + decl = make_bad_decl(f, ast_node_token(names[0]), f->cursor[0]); } } else { ast_file_err(f, f->cursor[0], "Illegal structure field"); - decl = make_bad_decl(f, ast_node_token(name_list), f->cursor[0]); + decl = make_bad_decl(f, ast_node_token(names[0]), f->cursor[0]); } expect_semicolon_after_stmt(f, decl); if (decl != NULL && is_ast_node_decl(decl)) { - DLIST_APPEND(decls, decls_curr, decl); + gb_array_append(decls, decl); if (decl->kind == AstNode_VarDecl) { - decl_count += decl->VarDecl.name_count; decl->VarDecl.is_using = is_using && using_allowed; if (decl->VarDecl.kind == Declaration_Mutable) { - if (decl->VarDecl.value_count > 0) { + if (gb_array_count(decl->VarDecl.values) > 0) { ast_file_err(f, f->cursor[0], "Default variable assignments within a structure will be ignored (at the moment)"); } } @@ -1808,6 +1770,7 @@ AstNode *parse_struct_params(AstFile *f, isize *decl_count_, b32 using_allowed) } if (decl_count_) *decl_count_ = decl_count; + return decls; } @@ -1870,7 +1833,7 @@ AstNode *parse_identifier_or_type(AstFile *f) { Token open = expect_token(f, Token_OpenBrace); isize decl_count = 0; - AstNode *decls = parse_struct_params(f, &decl_count, true); + AstNodeArray decls = parse_struct_params(f, &decl_count, true); Token close = expect_token(f, Token_CloseBrace); return make_struct_type(f, token, decls, decl_count, is_packed); @@ -1880,7 +1843,7 @@ AstNode *parse_identifier_or_type(AstFile *f) { Token token = expect_token(f, Token_union); Token open = expect_token(f, Token_OpenBrace); isize decl_count = 0; - AstNode *decls = parse_struct_params(f, &decl_count, false); + AstNodeArray decls = parse_struct_params(f, &decl_count, false); Token close = expect_token(f, Token_CloseBrace); return make_union_type(f, token, decls, decl_count); @@ -1890,7 +1853,7 @@ AstNode *parse_identifier_or_type(AstFile *f) { Token token = expect_token(f, Token_raw_union); Token open = expect_token(f, Token_OpenBrace); isize decl_count = 0; - AstNode *decls = parse_struct_params(f, &decl_count, true); + AstNodeArray decls = parse_struct_params(f, &decl_count, true); Token close = expect_token(f, Token_CloseBrace); return make_raw_union_type(f, token, decls, decl_count); @@ -1905,9 +1868,7 @@ AstNode *parse_identifier_or_type(AstFile *f) { base_type = parse_type(f); } - AstNode *root = NULL; - AstNode *curr = NULL; - isize field_count = 0; + AstNodeArray fields = make_ast_node_array(f); open = expect_token(f, Token_OpenBrace); @@ -1921,16 +1882,16 @@ AstNode *parse_identifier_or_type(AstFile *f) { value = parse_value(f); } AstNode *field = make_field_value(f, name, value, eq); - DLIST_APPEND(root, curr, field); - field_count++; - if (f->cursor[0].kind != Token_Comma) + gb_array_append(fields, field); + if (f->cursor[0].kind != Token_Comma) { break; + } next_token(f); } close = expect_token(f, Token_CloseBrace); - return make_enum_type(f, token, base_type, root, field_count); + return make_enum_type(f, token, base_type, fields); } case Token_proc: { @@ -1970,67 +1931,59 @@ AstNode *parse_identifier_or_type(AstFile *f) { } -AstNode *parse_results(AstFile *f, isize *result_count) { +AstNodeArray parse_results(AstFile *f) { + AstNodeArray results = make_ast_node_array(f); if (allow_token(f, Token_ArrowRight)) { if (f->cursor[0].kind == Token_OpenParen) { expect_token(f, Token_OpenParen); - AstNode *list = NULL; - AstNode *list_curr = NULL; - isize count = 0; while (f->cursor[0].kind != Token_CloseParen && f->cursor[0].kind != Token_EOF) { - DLIST_APPEND(list, list_curr, parse_type(f)); - count++; - if (f->cursor[0].kind != Token_Comma) + gb_array_append(results, parse_type(f)); + if (f->cursor[0].kind != Token_Comma) { break; + } next_token(f); } expect_token(f, Token_CloseParen); - if (result_count) *result_count = count; - return list; + return results; } - AstNode *result = parse_type(f); - if (result_count) *result_count = 1; - return result; + gb_array_append(results, parse_type(f)); + return results; } - if (result_count) *result_count = 0; - return NULL; + return results; } Token parse_procedure_signature(AstFile *f, - AstNode **param_list, isize *param_count, - AstNode **result_list, isize *result_count) { + AstNodeArray *params, + AstNodeArray *results) { Token proc_token = expect_token(f, Token_proc); expect_token(f, Token_OpenParen); - *param_list = parse_parameter_list(f, param_count); + *params = parse_parameter_list(f); expect_token(f, Token_CloseParen); - *result_list = parse_results(f, result_count); + *results = parse_results(f); return proc_token; } AstNode *parse_body(AstFile *f) { - AstNode *statement_list = NULL; - isize statement_list_count = 0; + AstNodeArray stmts = NULL; Token open, close; open = expect_token(f, Token_OpenBrace); - statement_list = parse_stmt_list(f, &statement_list_count); + stmts = parse_stmt_list(f); close = expect_token(f, Token_CloseBrace); - return make_block_stmt(f, statement_list, statement_list_count, open, close); + return make_block_stmt(f, stmts, open, close); } AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { - AstNode *param_list = NULL; - AstNode *result_list = NULL; - isize param_count = 0; - isize result_count = 0; + AstNodeArray params = NULL; + AstNodeArray results = NULL; - parse_procedure_signature(f, ¶m_list, ¶m_count, &result_list, &result_count); - AstNode *proc_type = make_proc_type(f, proc_token, param_list, param_count, result_list, result_count); + parse_procedure_signature(f, ¶ms, &results); + AstNode *proc_type = make_proc_type(f, proc_token, params, results); AstNode *body = NULL; u64 tags = 0; @@ -2052,10 +2005,10 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { return make_proc_decl(f, name, proc_type, body, tags, foreign_name); } -AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) { - AstNode *value_list = NULL; +AstNode *parse_decl(AstFile *f, AstNodeArray names) { + AstNodeArray values = NULL; AstNode *type = NULL; - isize value_count = 0; + if (allow_token(f, Token_Colon)) { if (!allow_token(f, Token_type)) { type = parse_identifier_or_type(f); @@ -2081,9 +2034,9 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) { if (token.kind == Token_type) { next_token(f); } - if (name_count != 1) { - ast_file_err(f, ast_node_token(name_list), "You can only declare one type at a time"); - return make_bad_decl(f, name_list->Ident, token); + if (gb_array_count(names) != 1) { + ast_file_err(f, ast_node_token(names[0]), "You can only declare one type at a time"); + return make_bad_decl(f, names[0]->Ident, token); } if (type != NULL) { @@ -2092,13 +2045,13 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) { } AstNode *type = parse_type(f); - return make_type_decl(f, token, name_list, type); + return make_type_decl(f, token, names[0], type); } else if (f->cursor[0].kind == Token_proc && declaration_kind == Declaration_Immutable) { // NOTE(bill): Procedure declarations Token proc_token = f->cursor[0]; - AstNode *name = name_list; - if (name_count != 1) { + AstNode *name = names[0]; + if (gb_array_count(names) != 1) { ast_file_err(f, proc_token, "You can only declare one procedure at a time"); return make_bad_decl(f, name->Ident, proc_token); } @@ -2107,25 +2060,25 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) { return proc_decl; } else { - value_list = parse_rhs_expr_list(f, &value_count); - if (value_count > name_count) { + values = parse_rhs_expr_list(f); + if (gb_array_count(values) > gb_array_count(names)) { ast_file_err(f, f->cursor[0], "Too many values on the right hand side of the declaration"); - } else if (value_count < name_count && + } else if (gb_array_count(values) < gb_array_count(names) && declaration_kind == Declaration_Immutable) { ast_file_err(f, f->cursor[0], "All constant declarations must be defined"); - } else if (value_list == NULL) { + } else if (gb_array_count(values) == 0) { ast_file_err(f, f->cursor[0], "Expected an expression for this declaration"); } } } if (declaration_kind == Declaration_Mutable) { - if (type == NULL && value_list == NULL) { + if (type == NULL && gb_array_count(values) == 0) { ast_file_err(f, f->cursor[0], "Missing variable type or initialization"); return make_bad_decl(f, f->cursor[0], f->cursor[0]); } } else if (declaration_kind == Declaration_Immutable) { - if (type == NULL && value_list == NULL && name_count > 0) { + if (type == NULL && gb_array_count(values) == 0 && gb_array_count(names) > 0) { ast_file_err(f, f->cursor[0], "Missing constant value"); return make_bad_decl(f, f->cursor[0], f->cursor[0]); } @@ -2136,8 +2089,11 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) { return make_bad_decl(f, begin, f->cursor[0]); } - AstNode *var_decl = make_var_decl(f, declaration_kind, name_list, name_count, type, value_list, value_count); - return var_decl; + if (values == NULL) { + values = make_ast_node_array(f); + } + + return make_var_decl(f, declaration_kind, names, type, values); } @@ -2202,18 +2158,17 @@ AstNode *parse_return_stmt(AstFile *f) { } Token token = expect_token(f, Token_return); - AstNode *result = NULL; - isize result_count = 0; + AstNodeArray results = make_ast_node_array(f); if (f->cursor[0].kind != Token_Semicolon && f->cursor[0].kind != Token_CloseBrace && f->cursor[0].pos.line == token.pos.line) { - result = parse_rhs_expr_list(f, &result_count); + results = parse_rhs_expr_list(f); } if (f->cursor[0].kind != Token_CloseBrace) { - expect_semicolon_after_stmt(f, result); + expect_semicolon_after_stmt(f, results ? results[0] : NULL); } - return make_return_stmt(f, token, result, result_count); + return make_return_stmt(f, token, results); } AstNode *parse_for_stmt(AstFile *f) { @@ -2262,34 +2217,31 @@ AstNode *parse_for_stmt(AstFile *f) { AstNode *parse_case_clause(AstFile *f) { Token token = f->cursor[0]; - AstNode *list = NULL; - isize list_count = 0; + AstNodeArray list = NULL; if (allow_token(f, Token_case)) { - list = parse_rhs_expr_list(f, &list_count); + list = parse_rhs_expr_list(f); } else { expect_token(f, Token_default); } expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax? - isize stmt_count = 0; - AstNode *stmts = parse_stmt_list(f, &stmt_count); + AstNodeArray stmts = parse_stmt_list(f); - return make_case_clause(f, token, list, list_count, stmts, stmt_count); + return make_case_clause(f, token, list, stmts); } AstNode *parse_type_case_clause(AstFile *f) { Token token = f->cursor[0]; - AstNode *clause = NULL; + AstNodeArray clause = make_ast_node_array(f); if (allow_token(f, Token_case)) { - clause = parse_expr(f, false); + gb_array_append(clause, parse_expr(f, false)); } else { expect_token(f, Token_default); } expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax? - isize stmt_count = 0; - AstNode *stmts = parse_stmt_list(f, &stmt_count); + AstNodeArray stmts = parse_stmt_list(f); - return make_case_clause(f, token, clause, 1, stmts, stmt_count); + return make_case_clause(f, token, clause, stmts); } @@ -2311,18 +2263,15 @@ AstNode *parse_match_stmt(AstFile *f) { AstNode *var = parse_identifier(f); open = expect_token(f, Token_OpenBrace); - AstNode *list = NULL; - AstNode *list_curr = NULL; - isize list_count = 0; + AstNodeArray list = make_ast_node_array(f); while (f->cursor[0].kind == Token_case || f->cursor[0].kind == Token_default) { - DLIST_APPEND(list, list_curr, parse_type_case_clause(f)); - list_count++; + gb_array_append(list, parse_type_case_clause(f)); } close = expect_token(f, Token_CloseBrace); - body = make_block_stmt(f, list, list_count, open, close); + body = make_block_stmt(f, list, open, close); return make_type_match_stmt(f, token, tag, var, body); } else { @@ -2344,19 +2293,16 @@ AstNode *parse_match_stmt(AstFile *f) { } open = expect_token(f, Token_OpenBrace); - AstNode *list = NULL; - AstNode *list_curr = NULL; - isize list_count = 0; + AstNodeArray list = make_ast_node_array(f); while (f->cursor[0].kind == Token_case || f->cursor[0].kind == Token_default) { - DLIST_APPEND(list, list_curr, parse_case_clause(f)); - list_count++; + gb_array_append(list, parse_case_clause(f)); } close = expect_token(f, Token_CloseBrace); - body = make_block_stmt(f, list, list_count, open, close); + body = make_block_stmt(f, list, open, close); tag = convert_stmt_to_expr(f, tag, make_string("match expression")); return make_match_stmt(f, token, init, tag, body); @@ -2542,10 +2488,8 @@ AstNode *parse_stmt(AstFile *f) { return make_bad_stmt(f, token, f->cursor[0]); } -AstNode *parse_stmt_list(AstFile *f, isize *list_count_) { - AstNode *list_root = NULL; - AstNode *list_curr = NULL; - isize list_count = 0; +AstNodeArray parse_stmt_list(AstFile *f) { + AstNodeArray list = make_ast_node_array(f); while (f->cursor[0].kind != Token_case && f->cursor[0].kind != Token_default && @@ -2553,14 +2497,11 @@ AstNode *parse_stmt_list(AstFile *f, isize *list_count_) { f->cursor[0].kind != Token_EOF) { AstNode *stmt = parse_stmt(f); if (stmt && stmt->kind != AstNode_EmptyStmt) { - DLIST_APPEND(list_root, list_curr, stmt); - list_count++; + gb_array_append(list, stmt); } } - if (list_count_) *list_count_ = list_count; - - return list_root; + return list; } @@ -2712,9 +2653,10 @@ void parse_file(Parser *p, AstFile *f) { base_dir.len--; } - f->decls = parse_stmt_list(f, &f->decl_count); + f->decls = parse_stmt_list(f); - for (AstNode *node = f->decls; node != NULL; node = node->next) { + gb_for_array(i, f->decls) { + AstNode *node = f->decls[i]; if (!is_ast_node_decl(node) && node->kind != AstNode_BadStmt && node->kind != AstNode_EmptyStmt) { diff --git a/src/printer.cpp b/src/printer.cpp index 63127acd4..f53e69364 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -29,7 +29,9 @@ void print_ast(AstNode *node, isize indent) { print_indent(indent); gb_printf("(compound lit)\n"); print_ast(node->CompoundLit.type, indent+1); - print_ast(node->CompoundLit.elem_list, indent+1); + gb_for_array(i, node->CompoundLit.elems) { + print_ast(node->CompoundLit.elems[i], indent+1); + } break; @@ -56,7 +58,9 @@ void print_ast(AstNode *node, isize indent) { print_indent(indent); gb_printf("(call)\n"); print_ast(node->CallExpr.proc, indent+1); - print_ast(node->CallExpr.arg_list, indent+1); + gb_for_array(i, node->CallExpr.args) { + print_ast(node->CallExpr.args[i], indent+1); + } break; case AstNode_SelectorExpr: print_indent(indent); @@ -88,13 +92,19 @@ void print_ast(AstNode *node, isize indent) { case AstNode_AssignStmt: print_indent(indent); print_token(node->AssignStmt.op); - print_ast(node->AssignStmt.lhs_list, indent+1); - print_ast(node->AssignStmt.rhs_list, indent+1); + gb_for_array(i, node->AssignStmt.lhs) { + print_ast(node->AssignStmt.lhs[i], indent+1); + } + gb_for_array(i, node->AssignStmt.rhs) { + print_ast(node->AssignStmt.rhs[i], indent+1); + } break; case AstNode_BlockStmt: print_indent(indent); gb_printf("(block)\n"); - print_ast(node->BlockStmt.list, indent+1); + gb_for_array(i, node->BlockStmt.stmts) { + print_ast(node->BlockStmt.stmts[i], indent+1); + } break; case AstNode_IfStmt: @@ -111,7 +121,9 @@ void print_ast(AstNode *node, isize indent) { case AstNode_ReturnStmt: print_indent(indent); gb_printf("(return)\n"); - print_ast(node->ReturnStmt.result_list, indent+1); + gb_for_array(i, node->ReturnStmt.results) { + print_ast(node->ReturnStmt.results[i], indent+1); + } break; case AstNode_ForStmt: print_indent(indent); @@ -130,13 +142,18 @@ void print_ast(AstNode *node, isize indent) { case AstNode_VarDecl: print_indent(indent); - if (node->VarDecl.kind == Declaration_Mutable) + if (node->VarDecl.kind == Declaration_Mutable) { gb_printf("(decl:var,mutable)\n"); - else if (node->VarDecl.kind == Declaration_Immutable) + } else if (node->VarDecl.kind == Declaration_Immutable) { gb_printf("(decl:var,immutable)\n"); - print_ast(node->VarDecl.name_list, indent+1); + } + gb_for_array(i, node->VarDecl.names) { + print_ast(node->VarDecl.names[i], indent+1); + } print_ast(node->VarDecl.type, indent+1); - print_ast(node->VarDecl.value_list, indent+1); + gb_for_array(i, node->VarDecl.values) { + print_ast(node->VarDecl.values[i], indent+1); + } break; case AstNode_ProcDecl: print_indent(indent); @@ -154,16 +171,22 @@ void print_ast(AstNode *node, isize indent) { case AstNode_ProcType: print_indent(indent); - 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) { + gb_printf("(type:proc)(%td -> %td)\n", gb_array_count(node->ProcType.params), gb_array_count(node->ProcType.results)); + gb_for_array(i, node->ProcType.params) { + print_ast(node->ProcType.params[i], indent+1); + } + if (gb_array_count(node->ProcType.results) > 0) { print_indent(indent+1); gb_printf("->\n"); - print_ast(node->ProcType.result_list, indent+1); + gb_for_array(i, node->ProcType.results) { + print_ast(node->ProcType.results[i], indent+1); + } } break; case AstNode_Field: - print_ast(node->Field.name_list, indent); + gb_for_array(i, node->Field.names) { + print_ast(node->Field.names[i], indent+1); + } print_ast(node->Field.type, indent); break; case AstNode_PointerType: @@ -180,10 +203,12 @@ void print_ast(AstNode *node, isize indent) { case AstNode_StructType: print_indent(indent); gb_printf("(struct)\n"); - print_ast(node->StructType.decl_list, indent+1); + gb_for_array(i, node->StructType.decls) { + print_ast(node->StructType.decls[i], indent+1); + } break; } - if (node->next) - print_ast(node->next, indent); + // if (node->next) + // print_ast(node->next, indent); }