diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-07 21:59:03 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-07 21:59:03 +0100 |
| commit | 50aeea1c2e11ed1413ca29bf5993b80dff38fa62 (patch) | |
| tree | de70baca88806155386dd82299ebbdb469508d04 /src/checker | |
| parent | 7ba13a18a33d8f852eb41b58da662ddb4649d04f (diff) | |
Remove AstNode linked lists and replace with arrays
Diffstat (limited to 'src/checker')
| -rw-r--r-- | src/checker/checker.cpp | 30 | ||||
| -rw-r--r-- | src/checker/expr.cpp | 293 | ||||
| -rw-r--r-- | src/checker/stmt.cpp | 151 |
3 files changed, 254 insertions, 220 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<Entity *> 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<TypeAndToken> 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); |