mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Save before Demo 001
This commit is contained in:
+11
-10
@@ -3,18 +3,18 @@
|
|||||||
#load "game.odin"
|
#load "game.odin"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
// _ = hellope();
|
_ = hellope();
|
||||||
// procedures();
|
procedures();
|
||||||
// variables();
|
variables();
|
||||||
// constants();
|
constants();
|
||||||
// types();
|
types();
|
||||||
// data_control();
|
data_control();
|
||||||
// using_fields();
|
using_fields();
|
||||||
|
|
||||||
|
// run_game();
|
||||||
run_game();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
hellope :: proc() -> int {
|
hellope :: proc() -> int {
|
||||||
print_string("Hellope, 世界\n");
|
print_string("Hellope, 世界\n");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -35,7 +35,7 @@ hellope :: proc() -> int {
|
|||||||
|
|
||||||
apple, banana, carrot: bool;
|
apple, banana, carrot: bool;
|
||||||
box, carboard: bool = true, false;
|
box, carboard: bool = true, false;
|
||||||
hellope_value: int = hellope(); // The procedure is ran just before `main`
|
// hellope_value: int = hellope(); // The procedure is ran just before `main`
|
||||||
|
|
||||||
variables :: proc() {
|
variables :: proc() {
|
||||||
i: int; // initialized with zero value
|
i: int; // initialized with zero value
|
||||||
@@ -711,3 +711,4 @@ using_fields :: proc() {
|
|||||||
print_f32(t.pos._xy.x); print_nl();
|
print_f32(t.pos._xy.x); print_nl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -190,6 +190,21 @@ struct Checker {
|
|||||||
|
|
||||||
gb_global Scope *universal_scope = NULL;
|
gb_global Scope *universal_scope = NULL;
|
||||||
|
|
||||||
|
struct CycleChecker {
|
||||||
|
gbArray(Entity *) path; // Entity_TypeName
|
||||||
|
};
|
||||||
|
|
||||||
|
CycleChecker *cycle_checker_add(CycleChecker *cc, Entity *e) {
|
||||||
|
GB_ASSERT(cc != NULL);
|
||||||
|
if (cc->path == NULL) {
|
||||||
|
gb_array_init(cc->path, gb_heap_allocator());
|
||||||
|
}
|
||||||
|
GB_ASSERT(e != NULL && e->kind == Entity_TypeName);
|
||||||
|
gb_array_append(cc->path, e);
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Scope *make_scope(Scope *parent, gbAllocator allocator) {
|
Scope *make_scope(Scope *parent, gbAllocator allocator) {
|
||||||
Scope *s = gb_alloc_item(allocator, Scope);
|
Scope *s = gb_alloc_item(allocator, Scope);
|
||||||
@@ -561,6 +576,30 @@ void add_curr_ast_file(Checker *c, AstFile *file) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct CycleCheck {
|
||||||
|
gbArray(Entity *) path; // HACK(bill): Memory Leak
|
||||||
|
};
|
||||||
|
|
||||||
|
void cycle_check_add(CycleCheck *cc, Entity *entity) {
|
||||||
|
if (cc == NULL)
|
||||||
|
return;
|
||||||
|
if (cc->path == NULL) {
|
||||||
|
gb_array_init(cc->path, gb_heap_allocator());
|
||||||
|
}
|
||||||
|
GB_ASSERT(entity->kind == Entity_TypeName);
|
||||||
|
gb_array_append(cc->path, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_type_name_cycles(Checker *c, CycleCheck *cc, Entity *e) {
|
||||||
|
GB_ASSERT(e->kind == Entity_TypeName);
|
||||||
|
Type *t = e->type;
|
||||||
|
// if (t->kind == Type_Named) {
|
||||||
|
// if (t->Named.type_name == e) {
|
||||||
|
// gb_printf("Illegal cycle %.*s!!!\n", LIT(e->token.string));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_parsed_files(Checker *c) {
|
void check_parsed_files(Checker *c) {
|
||||||
// Collect Entities
|
// Collect Entities
|
||||||
|
|||||||
+49
-119
@@ -4,12 +4,12 @@ void check_expr (Checker *c, Operand *operand, AstNode *e
|
|||||||
void check_multi_expr (Checker *c, Operand *operand, AstNode *expression);
|
void check_multi_expr (Checker *c, Operand *operand, AstNode *expression);
|
||||||
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression);
|
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression);
|
||||||
ExpressionKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint = NULL);
|
ExpressionKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint = NULL);
|
||||||
Type * check_type (Checker *c, AstNode *expression, Type *named_type = NULL);
|
Type * check_type (Checker *c, AstNode *expression, Type *named_type = NULL, CycleChecker *cycle_checker = NULL);
|
||||||
void check_selector (Checker *c, Operand *operand, AstNode *node);
|
void check_selector (Checker *c, Operand *operand, AstNode *node);
|
||||||
void check_not_tuple (Checker *c, Operand *operand);
|
void check_not_tuple (Checker *c, Operand *operand);
|
||||||
void convert_to_typed (Checker *c, Operand *operand, Type *target_type);
|
void convert_to_typed (Checker *c, Operand *operand, Type *target_type);
|
||||||
gbString expr_to_string (AstNode *expression);
|
gbString expr_to_string (AstNode *expression);
|
||||||
void check_entity_decl (Checker *c, Entity *e, DeclInfo *decl, Type *named_type);
|
void check_entity_decl (Checker *c, Entity *e, DeclInfo *decl, Type *named_type, CycleChecker *cycle_checker = NULL);
|
||||||
void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
|
void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
|
||||||
void update_expr_type (Checker *c, AstNode *e, Type *type, b32 final);
|
void update_expr_type (Checker *c, AstNode *e, Type *type, b32 final);
|
||||||
|
|
||||||
@@ -45,7 +45,9 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map<Entity *>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_fields(Checker *c, AstNode *node, AstNode *field_list, Entity **fields, isize field_count, String context) {
|
void check_fields(Checker *c, AstNode *node,
|
||||||
|
AstNode *field_list, Entity **fields, isize field_count,
|
||||||
|
CycleChecker *cycle_checker, String context) {
|
||||||
Map<Entity *> entity_map = {};
|
Map<Entity *> entity_map = {};
|
||||||
map_init(&entity_map, gb_heap_allocator());
|
map_init(&entity_map, gb_heap_allocator());
|
||||||
defer (map_destroy(&entity_map));
|
defer (map_destroy(&entity_map));
|
||||||
@@ -53,7 +55,7 @@ void check_fields(Checker *c, AstNode *node, AstNode *field_list, Entity **field
|
|||||||
isize field_index = 0;
|
isize field_index = 0;
|
||||||
for (AstNode *field = field_list; field != NULL; field = field->next) {
|
for (AstNode *field = field_list; field != NULL; field = field->next) {
|
||||||
ast_node(f, Field, field);
|
ast_node(f, Field, field);
|
||||||
Type *type = check_type(c, f->type);
|
Type *type = check_type(c, f->type, NULL, cycle_checker);
|
||||||
|
|
||||||
if (f->is_using) {
|
if (f->is_using) {
|
||||||
if (f->name_count > 1) {
|
if (f->name_count > 1) {
|
||||||
@@ -93,7 +95,7 @@ void check_fields(Checker *c, AstNode *node, AstNode *field_list, Entity **field
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecker *cycle_checker) {
|
||||||
GB_ASSERT(node->kind == AstNode_StructType);
|
GB_ASSERT(node->kind == AstNode_StructType);
|
||||||
GB_ASSERT(struct_type->kind == Type_Struct);
|
GB_ASSERT(struct_type->kind == Type_Struct);
|
||||||
ast_node(st, StructType, node);
|
ast_node(st, StructType, node);
|
||||||
@@ -107,13 +109,13 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, st->field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, st->field_count);
|
||||||
check_fields(c, node, st->field_list, fields, field_count, make_string("structure"));
|
check_fields(c, node, st->field_list, fields, field_count, cycle_checker, make_string("structure"));
|
||||||
struct_type->Struct.fields = fields;
|
struct_type->Struct.fields = fields;
|
||||||
struct_type->Struct.field_count = field_count;
|
struct_type->Struct.field_count = field_count;
|
||||||
struct_type->Struct.is_packed = st->is_packed;
|
struct_type->Struct.is_packed = st->is_packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) {
|
||||||
GB_ASSERT(node->kind == AstNode_UnionType);
|
GB_ASSERT(node->kind == AstNode_UnionType);
|
||||||
GB_ASSERT(union_type->kind == Type_Union);
|
GB_ASSERT(union_type->kind == Type_Union);
|
||||||
ast_node(ut, UnionType, node);
|
ast_node(ut, UnionType, node);
|
||||||
@@ -127,7 +129,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, ut->field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, ut->field_count);
|
||||||
check_fields(c, node, ut->field_list, fields, field_count, make_string("union"));
|
check_fields(c, node, ut->field_list, fields, field_count, cycle_checker, make_string("union"));
|
||||||
union_type->Union.fields = fields;
|
union_type->Union.fields = fields;
|
||||||
union_type->Union.field_count = field_count;
|
union_type->Union.field_count = field_count;
|
||||||
}
|
}
|
||||||
@@ -273,7 +275,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, CycleChecker *cycle_checker = NULL) {
|
||||||
GB_ASSERT(n->kind == AstNode_Ident);
|
GB_ASSERT(n->kind == AstNode_Ident);
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
o->expr = n;
|
o->expr = n;
|
||||||
@@ -286,10 +288,18 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
|||||||
}
|
}
|
||||||
add_entity_use(&c->info, n, e);
|
add_entity_use(&c->info, n, e);
|
||||||
|
|
||||||
|
CycleChecker local_cycle_checker = {};
|
||||||
|
if (cycle_checker == NULL) {
|
||||||
|
cycle_checker = &local_cycle_checker;
|
||||||
|
}
|
||||||
|
defer (if (local_cycle_checker.path != NULL) {
|
||||||
|
gb_array_free(local_cycle_checker.path);
|
||||||
|
});
|
||||||
|
|
||||||
if (e->type == NULL) {
|
if (e->type == NULL) {
|
||||||
auto *found = map_get(&c->info.entities, hash_pointer(e));
|
auto *found = map_get(&c->info.entities, hash_pointer(e));
|
||||||
if (found != NULL) {
|
if (found != NULL) {
|
||||||
check_entity_decl(c, e, *found, named_type);
|
check_entity_decl(c, e, *found, named_type, cycle_checker);
|
||||||
} else {
|
} else {
|
||||||
GB_PANIC("Internal Compiler Error: DeclInfo not found!");
|
GB_PANIC("Internal Compiler Error: DeclInfo not found!");
|
||||||
}
|
}
|
||||||
@@ -300,10 +310,12 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type *type = e->type;
|
||||||
|
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case Entity_Constant:
|
case Entity_Constant:
|
||||||
add_declaration_dependency(c, e);
|
add_declaration_dependency(c, e);
|
||||||
if (e->type == t_invalid)
|
if (type == t_invalid)
|
||||||
return;
|
return;
|
||||||
o->value = e->Constant.value;
|
o->value = e->Constant.value;
|
||||||
GB_ASSERT(o->value.kind != ExactValue_Invalid);
|
GB_ASSERT(o->value.kind != ExactValue_Invalid);
|
||||||
@@ -313,14 +325,30 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
|||||||
case Entity_Variable:
|
case Entity_Variable:
|
||||||
add_declaration_dependency(c, e);
|
add_declaration_dependency(c, e);
|
||||||
e->Variable.used = true;
|
e->Variable.used = true;
|
||||||
if (e->type == t_invalid)
|
if (type == t_invalid)
|
||||||
return;
|
return;
|
||||||
o->mode = Addressing_Variable;
|
o->mode = Addressing_Variable;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Entity_TypeName:
|
case Entity_TypeName: {
|
||||||
o->mode = Addressing_Type;
|
o->mode = Addressing_Type;
|
||||||
break;
|
#if 0
|
||||||
|
// TODO(bill): Fix cyclical dependancy checker
|
||||||
|
gb_for_array(i, cycle_checker->path) {
|
||||||
|
Entity *prev = cycle_checker->path[i];
|
||||||
|
if (prev == e) {
|
||||||
|
error(&c->error_collector, e->token, "Illegal declaration cycle for %.*s", LIT(e->token.string));
|
||||||
|
for (isize j = i; j < gb_array_count(cycle_checker->path); j++) {
|
||||||
|
Entity *ref = cycle_checker->path[j];
|
||||||
|
error(&c->error_collector, ref->token, "\t%.*s refers to", LIT(ref->token.string));
|
||||||
|
}
|
||||||
|
error(&c->error_collector, e->token, "\t%.*s", LIT(e->token.string));
|
||||||
|
type = t_invalid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
|
|
||||||
case Entity_Procedure:
|
case Entity_Procedure:
|
||||||
add_declaration_dependency(c, e);
|
add_declaration_dependency(c, e);
|
||||||
@@ -337,7 +365,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
o->type = e->type;
|
o->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 check_array_count(Checker *c, AstNode *e) {
|
i64 check_array_count(Checker *c, AstNode *e) {
|
||||||
@@ -365,105 +393,7 @@ i64 check_array_count(Checker *c, AstNode *e) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *check_type_expr_extra(Checker *c, AstNode *e, Type *named_type) {
|
Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_checker) {
|
||||||
gbString err_str = NULL;
|
|
||||||
defer (gb_string_free(err_str));
|
|
||||||
|
|
||||||
switch (e->kind) {
|
|
||||||
case_ast_node(i, Ident, e);
|
|
||||||
Operand o = {};
|
|
||||||
check_identifier(c, &o, e, named_type);
|
|
||||||
switch (o.mode) {
|
|
||||||
case Addressing_Type: {
|
|
||||||
Type *t = o.type;
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
return t;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case Addressing_Invalid:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Addressing_NoValue:
|
|
||||||
err_str = expr_to_string(e);
|
|
||||||
error(&c->error_collector, ast_node_token(e), "`%s` used as a type", err_str);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err_str = expr_to_string(e);
|
|
||||||
error(&c->error_collector, ast_node_token(e), "`%s` used as a type when not a type", err_str);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(pe, ParenExpr, e);
|
|
||||||
return check_type(c, pe->expr, named_type);
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
|
|
||||||
case_ast_node(at, ArrayType, e);
|
|
||||||
if (at->count != NULL) {
|
|
||||||
Type *t = make_type_array(c->allocator,
|
|
||||||
check_type(c, at->elem),
|
|
||||||
check_array_count(c, at->count));
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
return t;
|
|
||||||
} else {
|
|
||||||
Type *t = make_type_slice(c->allocator, check_type(c, at->elem));
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(vt, VectorType, e);
|
|
||||||
Type *elem = check_type(c, vt->elem);
|
|
||||||
Type *be = get_base_type(elem);
|
|
||||||
if (!is_type_vector(be) &&
|
|
||||||
!(is_type_boolean(be) || is_type_numeric(be))) {
|
|
||||||
err_str = type_to_string(elem);
|
|
||||||
error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be a boolean, numerical, or vector. Got `%s`", err_str);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
i64 count = check_array_count(c, vt->count);
|
|
||||||
Type *t = make_type_vector(c->allocator, elem, count);
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(st, StructType, e);
|
|
||||||
Type *t = make_type_struct(c->allocator);
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
check_struct_type(c, t, e);
|
|
||||||
return t;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(pt, PointerType, e);
|
|
||||||
Type *t = make_type_pointer(c->allocator, check_type(c, pt->type));
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
return t;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(pt, ProcType, e);
|
|
||||||
Type *t = alloc_type(c->allocator, Type_Proc);
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
check_open_scope(c, e);
|
|
||||||
check_procedure_type(c, t, e);
|
|
||||||
check_close_scope(c);
|
|
||||||
return t;
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
default:
|
|
||||||
err_str = expr_to_string(e);
|
|
||||||
error(&c->error_collector, ast_node_token(e), "`%s` is not a type", err_str);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *t = t_invalid;
|
|
||||||
set_base_type(named_type, t);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Type *check_type(Checker *c, AstNode *e, Type *named_type) {
|
|
||||||
ExactValue null_value = {ExactValue_Invalid};
|
ExactValue null_value = {ExactValue_Invalid};
|
||||||
Type *type = NULL;
|
Type *type = NULL;
|
||||||
gbString err_str = NULL;
|
gbString err_str = NULL;
|
||||||
@@ -472,7 +402,7 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) {
|
|||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case_ast_node(i, Ident, e);
|
case_ast_node(i, Ident, e);
|
||||||
Operand operand = {};
|
Operand operand = {};
|
||||||
check_identifier(c, &operand, e, named_type);
|
check_identifier(c, &operand, e, named_type, cycle_checker);
|
||||||
switch (operand.mode) {
|
switch (operand.mode) {
|
||||||
case Addressing_Type: {
|
case Addressing_Type: {
|
||||||
type = operand.type;
|
type = operand.type;
|
||||||
@@ -505,13 +435,13 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pe, ParenExpr, e);
|
case_ast_node(pe, ParenExpr, e);
|
||||||
return check_type(c, pe->expr, named_type);
|
return check_type(c, pe->expr, named_type, cycle_checker);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(at, ArrayType, e);
|
case_ast_node(at, ArrayType, e);
|
||||||
if (at->count != NULL) {
|
if (at->count != NULL) {
|
||||||
type = make_type_array(c->allocator,
|
type = make_type_array(c->allocator,
|
||||||
check_type(c, at->elem),
|
check_type(c, at->elem, NULL, cycle_checker),
|
||||||
check_array_count(c, at->count));
|
check_array_count(c, at->count));
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
} else {
|
} else {
|
||||||
@@ -538,14 +468,14 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) {
|
|||||||
case_ast_node(st, StructType, e);
|
case_ast_node(st, StructType, e);
|
||||||
type = make_type_struct(c->allocator);
|
type = make_type_struct(c->allocator);
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
check_struct_type(c, type, e);
|
check_struct_type(c, type, e, cycle_checker);
|
||||||
goto end;
|
goto end;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(st, UnionType, e);
|
case_ast_node(st, UnionType, e);
|
||||||
type = make_type_union(c->allocator);
|
type = make_type_union(c->allocator);
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
check_union_type(c, type, e);
|
check_union_type(c, type, e, cycle_checker);
|
||||||
goto end;
|
goto end;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+31
-9
@@ -359,16 +359,30 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e
|
|||||||
check_init_constant(c, e, &operand);
|
check_init_constant(c, e, &operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *named_type) {
|
void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, CycleChecker *cycle_checker) {
|
||||||
GB_ASSERT(e->type == NULL);
|
GB_ASSERT(e->type == NULL);
|
||||||
Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
|
Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
|
||||||
named->Named.type_name = e;
|
named->Named.type_name = e;
|
||||||
set_base_type(named_type, named);
|
if (def != NULL && def->kind == Type_Named) {
|
||||||
|
def->Named.base = named;
|
||||||
|
}
|
||||||
e->type = named;
|
e->type = named;
|
||||||
|
|
||||||
check_type(c, type_expr, named);
|
CycleChecker local_cycle_checker = {};
|
||||||
|
if (cycle_checker == NULL) {
|
||||||
|
cycle_checker = &local_cycle_checker;
|
||||||
|
}
|
||||||
|
defer (if (local_cycle_checker.path != NULL) {
|
||||||
|
gb_array_free(local_cycle_checker.path);
|
||||||
|
});
|
||||||
|
|
||||||
set_base_type(named, get_base_type(get_base_type(named)));
|
check_type(c, type_expr, named, cycle_checker_add(cycle_checker, e));
|
||||||
|
|
||||||
|
|
||||||
|
named->Named.base = get_base_type(named->Named.base);
|
||||||
|
if (named->Named.base == t_invalid) {
|
||||||
|
gb_printf("%s\n", type_to_string(named));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
||||||
@@ -486,7 +500,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, CycleChecker *cycle_checker) {
|
||||||
if (e->type != NULL)
|
if (e->type != NULL)
|
||||||
return;
|
return;
|
||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
@@ -498,9 +512,17 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
|||||||
c->context.decl = d;
|
c->context.decl = d;
|
||||||
check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr);
|
check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr);
|
||||||
break;
|
break;
|
||||||
case Entity_TypeName:
|
case Entity_TypeName: {
|
||||||
check_type_decl(c, e, d->type_expr, named_type);
|
CycleChecker local_cycle_checker = {};
|
||||||
break;
|
if (cycle_checker == NULL) {
|
||||||
|
cycle_checker = &local_cycle_checker;
|
||||||
|
}
|
||||||
|
check_type_decl(c, e, d->type_expr, named_type, cycle_checker);
|
||||||
|
|
||||||
|
if (local_cycle_checker.path != NULL) {
|
||||||
|
gb_array_free(local_cycle_checker.path);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case Entity_Procedure:
|
case Entity_Procedure:
|
||||||
check_proc_decl(c, e, d, true);
|
check_proc_decl(c, e, d, true);
|
||||||
break;
|
break;
|
||||||
@@ -875,7 +897,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
ast_node(name, Ident, td->name);
|
ast_node(name, Ident, td->name);
|
||||||
Entity *e = make_entity_type_name(c->allocator, c->context.scope, name->token, NULL);
|
Entity *e = make_entity_type_name(c->allocator, c->context.scope, name->token, NULL);
|
||||||
add_entity(c, c->context.scope, td->name, e);
|
add_entity(c, c->context.scope, td->name, e);
|
||||||
check_type_decl(c, e, td->type, NULL);
|
check_type_decl(c, e, td->type, NULL, NULL);
|
||||||
case_end;
|
case_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,7 +143,10 @@ struct Type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Type *get_base_type(Type *t) {
|
Type *get_base_type(Type *t) {
|
||||||
while (t->kind == Type_Named) {
|
for (;;) {
|
||||||
|
if (t == NULL || t->kind != Type_Named) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
t = t->Named.base;
|
t = t->Named.base;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
@@ -583,6 +586,8 @@ gb_global i64 basic_type_sizes[] = {
|
|||||||
8, // Basic_f64
|
8, // Basic_f64
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
|
i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
|
||||||
i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
|
i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
|
||||||
i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
|
i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
|
||||||
@@ -668,6 +673,7 @@ b32 type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
|
|
||||||
i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||||
t = get_base_type(t);
|
t = get_base_type(t);
|
||||||
|
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Basic: {
|
case Type_Basic: {
|
||||||
GB_ASSERT(is_type_typed(t));
|
GB_ASSERT(is_type_typed(t));
|
||||||
|
|||||||
+2
-2
@@ -1057,7 +1057,7 @@ b32 is_foreign_name_valid(String name) {
|
|||||||
case '_':
|
case '_':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!rune_is_letter(rune))
|
if (!gb_char_is_alpha(cast(char)rune))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1069,7 @@ b32 is_foreign_name_valid(String name) {
|
|||||||
case '_':
|
case '_':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!rune_is_letter(rune) && !rune_is_digit(rune)) {
|
if (!gb_char_is_alphanumeric(cast(char)rune)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
-1
@@ -157,7 +157,7 @@ gb_no_inline void error(ErrorCollector *ec, Token token, char *fmt, ...) {
|
|||||||
|
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, fmt);
|
va_start(va, fmt);
|
||||||
gb_printf_err("%.*s(%td:%td) Error: %s\n",
|
gb_printf_err("%.*s(%td:%td) %s\n",
|
||||||
LIT(token.pos.file), token.pos.line, token.pos.column,
|
LIT(token.pos.file), token.pos.line, token.pos.column,
|
||||||
gb_bprintf_va(fmt, va));
|
gb_bprintf_va(fmt, va));
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|||||||
Reference in New Issue
Block a user