mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Remove: string overloads; defer
This commit is contained in:
+46
-43
@@ -508,10 +508,10 @@ void init_universal_scope(void) {
|
||||
}
|
||||
|
||||
// Constants
|
||||
add_global_constant(a, make_string("true"), t_untyped_bool, make_exact_value_bool(true));
|
||||
add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false));
|
||||
add_global_constant(a, str_lit("true"), t_untyped_bool, make_exact_value_bool(true));
|
||||
add_global_constant(a, str_lit("false"), t_untyped_bool, make_exact_value_bool(false));
|
||||
|
||||
add_global_entity(make_entity_nil(a, make_string("nil"), t_untyped_nil));
|
||||
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
|
||||
|
||||
// Builtin Procedures
|
||||
for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
|
||||
@@ -671,7 +671,7 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity)
|
||||
}
|
||||
|
||||
b32 add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
|
||||
if (entity->token.string != make_string("_")) {
|
||||
if (str_ne(entity->token.string, str_lit("_"))) {
|
||||
Entity *insert_entity = scope_insert_entity(scope, entity);
|
||||
if (insert_entity) {
|
||||
Entity *up = insert_entity->using_parent;
|
||||
@@ -714,7 +714,7 @@ void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) {
|
||||
|
||||
|
||||
void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(identifier->Ident.string == e->token.string);
|
||||
GB_ASSERT(str_eq(identifier->Ident.string, e->token.string));
|
||||
add_entity(c, e->scope, identifier, e);
|
||||
map_set(&c->info.entities, hash_pointer(e), d);
|
||||
}
|
||||
@@ -925,7 +925,7 @@ void init_preload_types(Checker *c) {
|
||||
|
||||
|
||||
if (t_type_info == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Type_Info"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Type_Info`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
@@ -961,7 +961,7 @@ void init_preload_types(Checker *c) {
|
||||
}
|
||||
|
||||
if (t_allocator == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Allocator"));
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Allocator"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Allocator`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
@@ -971,7 +971,7 @@ void init_preload_types(Checker *c) {
|
||||
}
|
||||
|
||||
if (t_context == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Context"));
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Context"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Context`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
@@ -992,14 +992,42 @@ void add_implicit_value(Checker *c, ImplicitValueId id, String name, String back
|
||||
c->info.implicit_values[id] = value;
|
||||
}
|
||||
|
||||
|
||||
void check_global_entity(Checker *c, EntityKind kind) {
|
||||
PROF_SCOPED("check_global_entity");
|
||||
for_array(i, c->info.entities.entries) {
|
||||
auto *entry = &c->info.entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
if (e->kind == kind) {
|
||||
DeclInfo *d = entry->value;
|
||||
|
||||
add_curr_ast_file(c, d->scope->file);
|
||||
|
||||
if (d->scope == e->scope) {
|
||||
if (kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) {
|
||||
if (e->scope->is_init) {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
} else if (e->scope->is_global && str_eq(e->token.string, str_lit("main"))) {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
|
||||
Scope *prev_scope = c->context.scope;
|
||||
c->context.scope = d->scope;
|
||||
check_entity_decl(c, e, d, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_parsed_files(Checker *c) {
|
||||
Array<AstNode *> import_decls;
|
||||
array_init(&import_decls, heap_allocator());
|
||||
defer (array_free(&import_decls));
|
||||
|
||||
Map<Scope *> file_scopes; // Key: String (fullpath)
|
||||
map_init(&file_scopes, heap_allocator());
|
||||
defer (map_destroy(&file_scopes));
|
||||
|
||||
// Map full filepaths to Scopes
|
||||
for_array(i, c->parser->files) {
|
||||
@@ -1176,7 +1204,7 @@ void check_parsed_files(Checker *c) {
|
||||
warning(id->token, "Multiple #import of the same file within this scope");
|
||||
}
|
||||
|
||||
if (id->import_name.string == ".") {
|
||||
if (str_eq(id->import_name.string, str_lit("."))) {
|
||||
// NOTE(bill): Add imported entities to this file's scope
|
||||
for_array(elem_index, scope->elements.entries) {
|
||||
Entity *e = scope->elements.entries[elem_index].value;
|
||||
@@ -1241,39 +1269,10 @@ void check_parsed_files(Checker *c) {
|
||||
}
|
||||
}
|
||||
|
||||
auto check_global_entity = [](Checker *c, EntityKind kind) {
|
||||
PROF_SCOPED("check_global_entity");
|
||||
for_array(i, c->info.entities.entries) {
|
||||
auto *entry = &c->info.entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
if (e->kind == kind) {
|
||||
DeclInfo *d = entry->value;
|
||||
|
||||
add_curr_ast_file(c, d->scope->file);
|
||||
|
||||
if (d->scope == e->scope) {
|
||||
if (kind != Entity_Procedure && e->token.string == "main") {
|
||||
if (e->scope->is_init) {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
} else if (e->scope->is_global && e->token.string == "main") {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
|
||||
Scope *prev_scope = c->context.scope;
|
||||
c->context.scope = d->scope;
|
||||
check_entity_decl(c, e, d, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
check_global_entity(c, Entity_TypeName);
|
||||
|
||||
init_preload_types(c);
|
||||
add_implicit_value(c, ImplicitValue_context, make_string("context"), make_string("__context"), t_context);
|
||||
add_implicit_value(c, ImplicitValue_context, str_lit("context"), str_lit("__context"), t_context);
|
||||
|
||||
check_global_entity(c, Entity_Constant);
|
||||
check_global_entity(c, Entity_Procedure);
|
||||
@@ -1299,8 +1298,8 @@ void check_parsed_files(Checker *c) {
|
||||
b32 bounds_check = (pi->tags & ProcTag_bounds_check) != 0;
|
||||
b32 no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
|
||||
|
||||
auto prev_context = c->context;
|
||||
defer (c->context = prev_context);
|
||||
CheckerContext prev_context = c->context;
|
||||
|
||||
if (bounds_check) {
|
||||
c->context.stmt_state_flags |= StmtStateFlag_bounds_check;
|
||||
c->context.stmt_state_flags &= ~StmtStateFlag_no_bounds_check;
|
||||
@@ -1310,6 +1309,8 @@ void check_parsed_files(Checker *c) {
|
||||
}
|
||||
|
||||
check_proc_body(c, pi->token, pi->decl, pi->type, pi->body);
|
||||
|
||||
c->context = prev_context;
|
||||
}
|
||||
|
||||
// Add untyped expression values
|
||||
@@ -1365,6 +1366,8 @@ void check_parsed_files(Checker *c) {
|
||||
// gb_printf("%td - %s\n", e->value, type_to_string(prev_type));
|
||||
// }
|
||||
|
||||
map_destroy(&file_scopes);
|
||||
array_free(&import_decls);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+21
-16
@@ -16,7 +16,6 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
||||
|
||||
if (operand->mode == Addressing_Builtin) {
|
||||
gbString expr_str = expr_to_string(operand->expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
|
||||
// TODO(bill): is this a good enough error message?
|
||||
error(ast_node_token(operand->expr),
|
||||
@@ -25,6 +24,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
||||
LIT(context_name));
|
||||
|
||||
operand->mode = Addressing_Invalid;
|
||||
|
||||
gb_string_free(expr_str);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +65,6 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||
// an extra allocation
|
||||
@@ -102,6 +102,8 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
||||
if (rhs_count > 0 && lhs_count != rhs_count) {
|
||||
error(lhs[0]->token, "Assignment count mismatch `%td` := `%td`", lhs_count, rhs_count);
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,10 +131,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
check_proc_decl(c, e, d);
|
||||
return;
|
||||
}
|
||||
auto prev = c->context;
|
||||
CheckerContext prev = c->context;
|
||||
c->context.scope = d->scope;
|
||||
c->context.decl = d;
|
||||
defer (c->context = prev);
|
||||
|
||||
switch (e->kind) {
|
||||
case Entity_Constant:
|
||||
@@ -145,6 +146,8 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
check_type_decl(c, e, d->type_expr, named_type, cycle_checker);
|
||||
break;
|
||||
}
|
||||
|
||||
c->context = prev;
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +168,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
|
||||
String str = token.string;
|
||||
Entity *found = NULL;
|
||||
// NOTE(bill): Ignore assignments to `_`
|
||||
if (str != make_string("_")) {
|
||||
if (str_ne(str, str_lit("_"))) {
|
||||
found = current_scope_lookup_entity(c->context.scope, str);
|
||||
}
|
||||
if (found == NULL) {
|
||||
@@ -208,7 +211,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
|
||||
e->type = init_type;
|
||||
}
|
||||
|
||||
check_init_variables(c, entities, entity_count, vd->values, make_string("variable declaration"));
|
||||
check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
|
||||
|
||||
for_array(i, vd->names) {
|
||||
if (entities[i] != NULL) {
|
||||
@@ -256,7 +259,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
||||
e->type = operand->type;
|
||||
}
|
||||
|
||||
check_assignment(c, operand, e->type, make_string("constant declaration"));
|
||||
check_assignment(c, operand, e->type, str_lit("constant declaration"));
|
||||
if (operand->mode == Addressing_Invalid) {
|
||||
return;
|
||||
}
|
||||
@@ -311,7 +314,6 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
|
||||
if (cycle_checker == NULL) {
|
||||
cycle_checker = &local_cycle_checker;
|
||||
}
|
||||
defer (cycle_checker_destroy(&local_cycle_checker));
|
||||
|
||||
Type *bt = check_type(c, type_expr, named, cycle_checker_add(cycle_checker, e));
|
||||
named->Named.base = bt;
|
||||
@@ -319,6 +321,8 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
|
||||
if (named->Named.base == t_invalid) {
|
||||
gb_printf("check_type_decl: %s\n", type_to_string(named));
|
||||
}
|
||||
|
||||
cycle_checker_destroy(&local_cycle_checker);
|
||||
}
|
||||
|
||||
|
||||
@@ -368,8 +372,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
|
||||
e->type = proc_type;
|
||||
ast_node(pd, ProcDecl, d->proc_decl);
|
||||
|
||||
check_open_scope(c, pd->type);
|
||||
defer (check_close_scope(c));
|
||||
check_procedure_type(c, proc_type, pd->type);
|
||||
|
||||
b32 is_foreign = (pd->tags & ProcTag_foreign) != 0;
|
||||
@@ -378,16 +382,15 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
b32 is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
|
||||
|
||||
if ((d->scope->is_file || d->scope->is_global) &&
|
||||
e->token.string == "main") {
|
||||
str_eq(e->token.string, str_lit("main"))) {
|
||||
if (proc_type != NULL) {
|
||||
auto *pt = &proc_type->Proc;
|
||||
if (pt->param_count != 0 ||
|
||||
pt->result_count) {
|
||||
gbString str = type_to_string(proc_type);
|
||||
defer (gb_string_free(str));
|
||||
|
||||
error(e->token,
|
||||
"Procedure type of `main` was expected to be `proc()`, got %s", str);
|
||||
gb_string_free(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,6 +458,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
map_set(fp, key, e);
|
||||
}
|
||||
}
|
||||
|
||||
check_close_scope(c);
|
||||
}
|
||||
|
||||
void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr) {
|
||||
@@ -482,7 +487,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
||||
GB_ASSERT(entities == NULL || entities[0] == e);
|
||||
Operand operand = {};
|
||||
check_expr(c, &operand, init_expr);
|
||||
check_init_variable(c, e, &operand, make_string("variable declaration"));
|
||||
check_init_variable(c, e, &operand, str_lit("variable declaration"));
|
||||
}
|
||||
|
||||
if (type_expr != NULL) {
|
||||
@@ -493,7 +498,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
||||
AstNodeArray inits;
|
||||
array_init(&inits, c->allocator, 1);
|
||||
array_add(&inits, init_expr);
|
||||
check_init_variables(c, entities, entity_count, inits, make_string("variable declaration"));
|
||||
check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
|
||||
}
|
||||
|
||||
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
||||
@@ -502,8 +507,6 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
|
||||
CheckerContext old_context = c->context;
|
||||
c->context.scope = decl->scope;
|
||||
c->context.decl = decl;
|
||||
defer (c->context = old_context);
|
||||
|
||||
|
||||
GB_ASSERT(type->kind == Type_Proc);
|
||||
if (type->Proc.param_count > 0) {
|
||||
@@ -552,6 +555,8 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
|
||||
|
||||
|
||||
check_scope_usage(c, c->context.scope);
|
||||
|
||||
c->context = old_context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ Entity *make_entity_implicit_value(gbAllocator a, String name, Type *type, Impli
|
||||
|
||||
|
||||
Entity *make_entity_dummy_variable(gbAllocator a, Scope *file_scope, Token token) {
|
||||
token.string = make_string("_");
|
||||
token.string = str_lit("_");
|
||||
return make_entity_variable(a, file_scope, token, NULL);
|
||||
}
|
||||
|
||||
|
||||
+193
-182
File diff suppressed because it is too large
Load Diff
+61
-42
@@ -18,12 +18,11 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
struct Delay {
|
||||
typedef struct {
|
||||
Entity *e;
|
||||
DeclInfo *d;
|
||||
};
|
||||
} Delay;
|
||||
Array<Delay> delayed_const; array_init(&delayed_const, c->tmp_allocator, stmts.count);
|
||||
Array<Delay> delayed_type; array_init(&delayed_type, c->tmp_allocator, stmts.count);
|
||||
|
||||
@@ -95,6 +94,8 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
||||
}
|
||||
check_stmt(c, n, new_flags);
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
b32 check_is_terminating_list(AstNodeArray stmts) {
|
||||
@@ -238,9 +239,9 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
|
||||
// NOTE(bill): Ignore assignments to `_`
|
||||
if (node->kind == AstNode_Ident &&
|
||||
node->Ident.string == "_") {
|
||||
str_eq(node->Ident.string, str_lit("_"))) {
|
||||
add_entity_definition(&c->info, node, NULL);
|
||||
check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier"));
|
||||
check_assignment(c, op_a, NULL, str_lit("assignment to `_` identifier"));
|
||||
if (op_a->mode == Addressing_Invalid)
|
||||
return NULL;
|
||||
return op_a->type;
|
||||
@@ -282,7 +283,6 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
}
|
||||
|
||||
gbString str = expr_to_string(op_b.expr);
|
||||
defer (gb_string_free(str));
|
||||
switch (op_b.mode) {
|
||||
case Addressing_Value:
|
||||
error(ast_node_token(op_b.expr), "Cannot assign to `%s`", str);
|
||||
@@ -291,13 +291,14 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
error(ast_node_token(op_b.expr), "Cannot assign to `%s`", str);
|
||||
break;
|
||||
}
|
||||
|
||||
gb_string_free(str);
|
||||
} break;
|
||||
}
|
||||
|
||||
check_assignment(c, op_a, op_b.type, make_string("assignment"));
|
||||
if (op_a->mode == Addressing_Invalid)
|
||||
check_assignment(c, op_a, op_b.type, str_lit("assignment"));
|
||||
if (op_a->mode == Addressing_Invalid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return op_a->type;
|
||||
}
|
||||
@@ -314,15 +315,13 @@ b32 check_valid_type_match_type(Type *type, b32 *is_union_ptr, b32 *is_any) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void check_stmt_internal(Checker *c, AstNode *node, u32 flags);
|
||||
void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
u32 prev_stmt_state_flags = c->context.stmt_state_flags;
|
||||
defer (c->context.stmt_state_flags = prev_stmt_state_flags);
|
||||
|
||||
if (node->stmt_state_flags != 0) {
|
||||
u32 in = node->stmt_state_flags;
|
||||
u32 out = c->context.stmt_state_flags;
|
||||
defer (c->context.stmt_state_flags = out);
|
||||
|
||||
if (in & StmtStateFlag_bounds_check) {
|
||||
out |= StmtStateFlag_bounds_check;
|
||||
@@ -331,9 +330,16 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
out |= StmtStateFlag_no_bounds_check;
|
||||
out &= ~StmtStateFlag_bounds_check;
|
||||
}
|
||||
|
||||
c->context.stmt_state_flags = out;
|
||||
}
|
||||
|
||||
check_stmt_internal(c, node, flags);
|
||||
|
||||
c->context.stmt_state_flags = prev_stmt_state_flags;
|
||||
}
|
||||
|
||||
void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
u32 mod_flags = flags & (~Stmt_FallthroughAllowed);
|
||||
switch (node->kind) {
|
||||
case_ast_node(_, EmptyStmt, node); case_end;
|
||||
@@ -352,16 +358,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
case Addressing_NoValue:
|
||||
return;
|
||||
default: {
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
if (kind == Expr_Stmt) {
|
||||
return;
|
||||
}
|
||||
if (operand.expr->kind == AstNode_CallExpr) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
error(ast_node_token(node), "Expression is not used: `%s`", expr_str);
|
||||
gb_string_free(expr_str);
|
||||
} break;
|
||||
}
|
||||
case_end;
|
||||
@@ -403,7 +408,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
ast_node(bl, BasicLit, &basic_lit);
|
||||
*bl = ids->op;
|
||||
bl->kind = Token_Integer;
|
||||
bl->string = make_string("1");
|
||||
bl->string = str_lit("1");
|
||||
|
||||
AstNode binary_expr = {AstNode_BinaryExpr};
|
||||
ast_node(be, BinaryExpr, &binary_expr);
|
||||
@@ -425,7 +430,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||
// an extra allocation
|
||||
@@ -458,6 +462,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
if (lhs_count != rhs_count) {
|
||||
error(ast_node_token(as->lhs[0]), "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
@@ -501,10 +507,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
PROF_SCOPED("check_stmt - IfStmt");
|
||||
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
if (is->init != NULL)
|
||||
if (is->init != NULL) {
|
||||
check_stmt(c, is->init, 0);
|
||||
}
|
||||
|
||||
Operand operand = {Addressing_Invalid};
|
||||
check_expr(c, &operand, is->cond);
|
||||
@@ -528,6 +534,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, ReturnStmt, node);
|
||||
@@ -558,7 +566,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
error(ast_node_token(node), "Expected %td return values, got 0", result_count);
|
||||
} else {
|
||||
check_init_variables(c, variables, result_count,
|
||||
rs->results, make_string("return statement"));
|
||||
rs->results, str_lit("return statement"));
|
||||
}
|
||||
} else if (rs->results.count > 0) {
|
||||
error(ast_node_token(rs->results[0]), "No return values expected");
|
||||
@@ -570,10 +578,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
if (fs->init != NULL)
|
||||
if (fs->init != NULL) {
|
||||
check_stmt(c, fs->init, 0);
|
||||
}
|
||||
if (fs->cond) {
|
||||
Operand operand = {Addressing_Invalid};
|
||||
check_expr(c, &operand, fs->cond);
|
||||
@@ -583,9 +591,12 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
"Non-boolean condition in `for` statement");
|
||||
}
|
||||
}
|
||||
if (fs->post != NULL)
|
||||
if (fs->post != NULL) {
|
||||
check_stmt(c, fs->post, 0);
|
||||
}
|
||||
check_stmt(c, fs->body, new_flags);
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, MatchStmt, node);
|
||||
@@ -595,14 +606,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
mod_flags |= Stmt_BreakAllowed;
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
if (ms->init != NULL) {
|
||||
check_stmt(c, ms->init, 0);
|
||||
}
|
||||
if (ms->tag != NULL) {
|
||||
check_expr(c, &x, ms->tag);
|
||||
check_assignment(c, &x, NULL, make_string("match expression"));
|
||||
check_assignment(c, &x, NULL, str_lit("match expression"));
|
||||
} else {
|
||||
x.mode = Addressing_Constant;
|
||||
x.type = t_bool;
|
||||
@@ -610,7 +620,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
Token token = {};
|
||||
token.pos = ast_node_token(ms->body).pos;
|
||||
token.string = make_string("true");
|
||||
token.string = str_lit("true");
|
||||
x.expr = make_ident(c->curr_ast_file, token);
|
||||
}
|
||||
|
||||
@@ -649,7 +659,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
|
||||
map_init(&seen, heap_allocator());
|
||||
defer (map_destroy(&seen));
|
||||
|
||||
for_array(i, bs->stmts) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
if (stmt->kind != AstNode_CaseClause) {
|
||||
@@ -689,8 +699,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
auto *found = map_get(&seen, key);
|
||||
if (found != NULL) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
isize count = multi_map_count(&seen, key);
|
||||
TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
|
||||
|
||||
@@ -713,6 +721,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
|
||||
if (continue_outer) {
|
||||
continue;
|
||||
}
|
||||
@@ -730,6 +740,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
check_stmt_list(c, cc->stmts, ft_flags);
|
||||
check_close_scope(c);
|
||||
}
|
||||
|
||||
map_destroy(&seen);
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, TypeMatchStmt, node);
|
||||
@@ -739,18 +753,17 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
mod_flags |= Stmt_BreakAllowed;
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
b32 is_union_ptr = false;
|
||||
b32 is_any = false;
|
||||
|
||||
check_expr(c, &x, ms->tag);
|
||||
check_assignment(c, &x, NULL, make_string("type match expression"));
|
||||
check_assignment(c, &x, NULL, str_lit("type match expression"));
|
||||
if (!check_valid_type_match_type(x.type, &is_union_ptr, &is_any)) {
|
||||
gbString str = type_to_string(x.type);
|
||||
defer (gb_string_free(str));
|
||||
error(ast_node_token(x.expr),
|
||||
"Invalid type for this type match expression, got `%s`", str);
|
||||
gb_string_free(str);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -789,8 +802,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
Map<b32> seen = {};
|
||||
map_init(&seen, heap_allocator());
|
||||
defer (map_destroy(&seen));
|
||||
|
||||
|
||||
for_array(i, bs->stmts) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
@@ -822,9 +833,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
if (!tag_type_found) {
|
||||
gbString type_str = type_to_string(y.type);
|
||||
defer (gb_string_free(type_str));
|
||||
error(ast_node_token(y.expr),
|
||||
"Unknown tag type, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
continue;
|
||||
}
|
||||
case_type = y.type;
|
||||
@@ -868,6 +879,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
check_stmt_list(c, cc->stmts, mod_flags);
|
||||
check_close_scope(c);
|
||||
}
|
||||
map_destroy(&seen);
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
|
||||
@@ -930,9 +944,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
|
||||
switch (e->kind) {
|
||||
case Entity_TypeName: {
|
||||
Type *t = base_type(e->type);
|
||||
@@ -941,7 +952,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *f = t->Record.other_fields[i];
|
||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
f->using_parent = e;
|
||||
@@ -951,7 +964,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *f = t->Record.fields[i];
|
||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
f->using_parent = e;
|
||||
@@ -960,7 +975,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *f = t->Record.other_fields[i];
|
||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
f->using_parent = e;
|
||||
@@ -974,6 +991,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *decl = scope->elements.entries[i].value;
|
||||
Entity *found = scope_insert_entity(c->context.scope, decl);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token,
|
||||
"Namespace collision while `using` `%s` of: %.*s\n"
|
||||
"\tat %.*s(%td:%td)\n"
|
||||
@@ -982,6 +1000,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
LIT(found->token.pos.file), found->token.pos.line, found->token.pos.column,
|
||||
LIT(decl->token.pos.file), decl->token.pos.line, decl->token.pos.column
|
||||
);
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1001,7 +1020,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
Entity *prev = scope_insert_entity(c->context.scope, uvar);
|
||||
if (prev != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(prev->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1085,7 +1106,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
case_ast_node(pa, PushAllocator, node);
|
||||
Operand op = {};
|
||||
check_expr(c, &op, pa->expr);
|
||||
check_assignment(c, &op, t_allocator, make_string("argument to push_allocator"));
|
||||
check_assignment(c, &op, t_allocator, str_lit("argument to push_allocator"));
|
||||
check_stmt(c, pa->body, mod_flags);
|
||||
case_end;
|
||||
|
||||
@@ -1093,7 +1114,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
case_ast_node(pa, PushContext, node);
|
||||
Operand op = {};
|
||||
check_expr(c, &op, pa->expr);
|
||||
check_assignment(c, &op, t_context, make_string("argument to push_context"));
|
||||
check_assignment(c, &op, t_context, str_lit("argument to push_context"));
|
||||
check_stmt(c, pa->body, mod_flags);
|
||||
case_end;
|
||||
|
||||
@@ -1128,7 +1149,5 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
add_entity_and_decl_info(c, pd->name, e, d);
|
||||
check_entity_decl(c, e, d, NULL);
|
||||
case_end;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+28
-28
@@ -719,7 +719,7 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
if (!are_types_identical(x->Record.fields[i]->type, y->Record.fields[i]->type)) {
|
||||
return false;
|
||||
}
|
||||
if (x->Record.fields[i]->token.string != y->Record.fields[i]->token.string) {
|
||||
if (str_ne(x->Record.fields[i]->token.string, y->Record.fields[i]->token.string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -836,7 +836,7 @@ gb_global Entity *entity__slice_capacity = NULL;
|
||||
Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_type, Selection sel = empty_selection) {
|
||||
GB_ASSERT(type_ != NULL);
|
||||
|
||||
if (field_name == "_") {
|
||||
if (str_eq(field_name, str_lit("_"))) {
|
||||
return empty_selection;
|
||||
}
|
||||
|
||||
@@ -849,8 +849,8 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
if (type->kind == Type_Basic) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_any: {
|
||||
String type_info_str = make_string("type_info");
|
||||
String data_str = make_string("data");
|
||||
String type_info_str = str_lit("type_info");
|
||||
String data_str = str_lit("data");
|
||||
if (entity__any_type_info == NULL) {
|
||||
entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 0);
|
||||
}
|
||||
@@ -858,19 +858,19 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
entity__any_data = make_entity_field(a, NULL, make_token_ident(data_str), t_rawptr, false, 1);
|
||||
}
|
||||
|
||||
if (field_name == type_info_str) {
|
||||
if (str_eq(field_name, type_info_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
sel.entity = entity__any_type_info;
|
||||
return sel;
|
||||
} else if (field_name == data_str) {
|
||||
} else if (str_eq(field_name, data_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
sel.entity = entity__any_data;
|
||||
return sel;
|
||||
}
|
||||
} break;
|
||||
case Basic_string: {
|
||||
String data_str = make_string("data");
|
||||
String count_str = make_string("count");
|
||||
String data_str = str_lit("data");
|
||||
String count_str = str_lit("count");
|
||||
if (entity__string_data == NULL) {
|
||||
entity__string_data = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, t_u8), false, 0);
|
||||
}
|
||||
@@ -879,11 +879,11 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
entity__string_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
|
||||
}
|
||||
|
||||
if (field_name == data_str) {
|
||||
if (str_eq(field_name, data_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
sel.entity = entity__string_data;
|
||||
return sel;
|
||||
} else if (field_name == count_str) {
|
||||
} else if (str_eq(field_name, count_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
sel.entity = entity__string_count;
|
||||
return sel;
|
||||
@@ -893,17 +893,17 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
|
||||
return sel;
|
||||
} else if (type->kind == Type_Array) {
|
||||
String count_str = make_string("count");
|
||||
String count_str = str_lit("count");
|
||||
// NOTE(bill): Underlying memory address cannot be changed
|
||||
if (field_name == count_str) {
|
||||
if (str_eq(field_name, count_str)) {
|
||||
// HACK(bill): Memory leak
|
||||
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Array.count));
|
||||
return sel;
|
||||
}
|
||||
} else if (type->kind == Type_Vector) {
|
||||
String count_str = make_string("count");
|
||||
String count_str = str_lit("count");
|
||||
// NOTE(bill): Vectors are not addressable
|
||||
if (field_name == count_str) {
|
||||
if (str_eq(field_name, count_str)) {
|
||||
// HACK(bill): Memory leak
|
||||
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Vector.count));
|
||||
return sel;
|
||||
@@ -914,9 +914,9 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
switch (type->Vector.count) {
|
||||
#define _VECTOR_FIELD_CASE(_length, _name) \
|
||||
case (_length): \
|
||||
if (field_name == _name) { \
|
||||
if (str_eq(field_name, str_lit(_name))) { \
|
||||
selection_add_index(&sel, (_length)-1); \
|
||||
sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(make_string(_name)), type->Vector.elem, (_length)-1); \
|
||||
sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(str_lit(_name)), type->Vector.elem, (_length)-1); \
|
||||
return sel; \
|
||||
} \
|
||||
/*fallthrough*/
|
||||
@@ -932,16 +932,16 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
}
|
||||
|
||||
} else if (type->kind == Type_Slice) {
|
||||
String data_str = make_string("data");
|
||||
String count_str = make_string("count");
|
||||
String capacity_str = make_string("capacity");
|
||||
String data_str = str_lit("data");
|
||||
String count_str = str_lit("count");
|
||||
String capacity_str = str_lit("capacity");
|
||||
|
||||
if (field_name == data_str) {
|
||||
if (str_eq(field_name, data_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
// HACK(bill): Memory leak
|
||||
sel.entity = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, type->Slice.elem), false, 0);
|
||||
return sel;
|
||||
} else if (field_name == count_str) {
|
||||
} else if (str_eq(field_name, count_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
if (entity__slice_count == NULL) {
|
||||
entity__slice_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
|
||||
@@ -949,7 +949,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
|
||||
sel.entity = entity__slice_count;
|
||||
return sel;
|
||||
} else if (field_name == capacity_str) {
|
||||
} else if (str_eq(field_name, capacity_str)) {
|
||||
selection_add_index(&sel, 2);
|
||||
if (entity__slice_capacity == NULL) {
|
||||
entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2);
|
||||
@@ -972,7 +972,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
GB_ASSERT(f->kind == Entity_TypeName);
|
||||
String str = f->token.string;
|
||||
|
||||
if (field_name == str) {
|
||||
if (str_eq(field_name, str)) {
|
||||
sel.entity = f;
|
||||
selection_add_index(&sel, i);
|
||||
return sel;
|
||||
@@ -985,7 +985,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
GB_ASSERT(f->kind != Entity_Variable);
|
||||
String str = f->token.string;
|
||||
|
||||
if (field_name == str) {
|
||||
if (str_eq(field_name, str)) {
|
||||
sel.entity = f;
|
||||
selection_add_index(&sel, i);
|
||||
return sel;
|
||||
@@ -993,13 +993,13 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
}
|
||||
|
||||
if (is_type_enum(type)) {
|
||||
if (field_name == "count") {
|
||||
if (str_eq(field_name, str_lit("count"))) {
|
||||
sel.entity = type->Record.enum_count;
|
||||
return sel;
|
||||
} else if (field_name == "min_value") {
|
||||
} else if (str_eq(field_name, str_lit("min_value"))) {
|
||||
sel.entity = type->Record.min_value;
|
||||
return sel;
|
||||
} else if (field_name == "max_value") {
|
||||
} else if (str_eq(field_name, str_lit("max_value"))) {
|
||||
sel.entity = type->Record.max_value;
|
||||
return sel;
|
||||
}
|
||||
@@ -1010,7 +1010,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
Entity *f = type->Record.fields[i];
|
||||
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
|
||||
String str = f->token.string;
|
||||
if (field_name == str) {
|
||||
if (str_eq(field_name, str)) {
|
||||
selection_add_index(&sel, i); // HACK(bill): Leaky memory
|
||||
sel.entity = f;
|
||||
return sel;
|
||||
|
||||
Reference in New Issue
Block a user