aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-09-07 21:59:03 +0100
committerGinger Bill <bill@gingerbill.org>2016-09-07 21:59:03 +0100
commit50aeea1c2e11ed1413ca29bf5993b80dff38fa62 (patch)
treede70baca88806155386dd82299ebbdb469508d04 /src
parent7ba13a18a33d8f852eb41b58da662ddb4649d04f (diff)
Remove AstNode linked lists and replace with arrays
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.cpp30
-rw-r--r--src/checker/expr.cpp293
-rw-r--r--src/checker/stmt.cpp151
-rw-r--r--src/codegen/ssa.cpp220
-rw-r--r--src/main.cpp5
-rw-r--r--src/parser.cpp492
-rw-r--r--src/printer.cpp61
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<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);
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, &params, &param_count, &results, &result_count);
+ Token proc_token = parse_procedure_signature(f, &params, &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, &param_list, &param_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, &params, &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);
}