mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
alias and unified parameters lists for procedures and structures.
This commit is contained in:
+14
-6
@@ -297,12 +297,12 @@ void init_universal_scope(void) {
|
||||
for (isize i = 0; i < gb_count_of(basic_types); i++) {
|
||||
Token token = {Token_Identifier};
|
||||
token.string = basic_types[i].basic.name;
|
||||
add_global_entity(alloc_entity(a, Entity_TypeName, NULL, token, &basic_types[i]));
|
||||
add_global_entity(make_entity_type_name(a, NULL, token, &basic_types[i]));
|
||||
}
|
||||
for (isize i = 0; i < gb_count_of(basic_type_aliases); i++) {
|
||||
Token token = {Token_Identifier};
|
||||
token.string = basic_type_aliases[i].basic.name;
|
||||
add_global_entity(alloc_entity(a, Entity_TypeName, NULL, token, &basic_type_aliases[i]));
|
||||
add_global_entity(make_entity_type_name(a, NULL, token, &basic_type_aliases[i]));
|
||||
}
|
||||
|
||||
// Constants
|
||||
@@ -555,8 +555,8 @@ void check_parsed_files(Checker *c) {
|
||||
add_file_entity(c, name, e, di);
|
||||
}
|
||||
|
||||
isize lhs_count = vd->name_list_count;
|
||||
isize rhs_count = vd->value_list_count;
|
||||
isize lhs_count = vd->name_count;
|
||||
isize rhs_count = vd->value_count;
|
||||
|
||||
if (rhs_count == 0 && vd->type_expression == NULL) {
|
||||
error(&c->error_collector, ast_node_token(decl), "Missing type or initial expression");
|
||||
@@ -566,11 +566,11 @@ void check_parsed_files(Checker *c) {
|
||||
} break;
|
||||
|
||||
case Declaration_Mutable: {
|
||||
isize entity_count = vd->name_list_count;
|
||||
isize entity_count = vd->name_count;
|
||||
isize entity_index = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
|
||||
DeclarationInfo *di = NULL;
|
||||
if (vd->value_list_count == 1) {
|
||||
if (vd->value_count == 1) {
|
||||
di = make_declaration_info(gb_heap_allocator(), c->global_scope);
|
||||
di->entities = entities;
|
||||
di->entity_count = entity_count;
|
||||
@@ -610,6 +610,14 @@ void check_parsed_files(Checker *c) {
|
||||
add_file_entity(c, identifier, e, d);
|
||||
} break;
|
||||
|
||||
case AstNode_AliasDeclaration: {
|
||||
AstNode *identifier = decl->alias_declaration.name;
|
||||
Entity *e = make_entity_alias_name(c->allocator, c->global_scope, identifier->identifier.token, NULL);
|
||||
DeclarationInfo *d = make_declaration_info(c->allocator, e->parent);
|
||||
d->type_expr = decl->alias_declaration.type_expression;
|
||||
add_file_entity(c, identifier, e, d);
|
||||
} break;
|
||||
|
||||
case AstNode_ProcedureDeclaration: {
|
||||
AstNode *identifier = decl->procedure_declaration.name;
|
||||
Token token = identifier->identifier.token;
|
||||
|
||||
@@ -8,6 +8,7 @@ enum EntityKind {
|
||||
Entity_Constant,
|
||||
Entity_Variable,
|
||||
Entity_TypeName,
|
||||
Entity_AliasName,
|
||||
Entity_Procedure,
|
||||
Entity_Builtin,
|
||||
|
||||
@@ -33,6 +34,7 @@ struct Entity {
|
||||
b8 used;
|
||||
} variable;
|
||||
struct {} type_name;
|
||||
struct {} alias_name;
|
||||
struct {} procedure;
|
||||
struct { BuiltinProcedureId id; } builtin;
|
||||
};
|
||||
@@ -70,14 +72,19 @@ Entity *make_entity_type_name(gbAllocator a, Scope *parent, Token token, Type *t
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *make_entity_alias_name(gbAllocator a, Scope *parent, Token token, Type *type) {
|
||||
Entity *entity = alloc_entity(a, Entity_AliasName, parent, token, type);
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *make_entity_param(gbAllocator a, Scope *parent, Token token, Type *type) {
|
||||
Entity *entity = alloc_entity(a, Entity_Variable, parent, token, type);
|
||||
Entity *entity = make_entity_variable(a, parent, token, type);
|
||||
entity->variable.used = true;
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *make_entity_field(gbAllocator a, Scope *parent, Token token, Type *type) {
|
||||
Entity *entity = alloc_entity(a, Entity_Variable, parent, token, type);
|
||||
Entity *entity = make_entity_variable(a, parent, token, type);
|
||||
entity->variable.is_field = true;
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -123,13 +123,13 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
||||
// gb_printf("%td -> %td\n", param_count, result_count);
|
||||
|
||||
Type *params = check_get_params(c, c->context.scope, proc_type_node->procedure_type.param_list, param_count);
|
||||
Type *results = check_get_results(c, c->context.scope, proc_type_node->procedure_type.results_list, result_count);
|
||||
Type *results = check_get_results(c, c->context.scope, proc_type_node->procedure_type.result_list, result_count);
|
||||
|
||||
type->procedure.scope = c->context.scope;
|
||||
type->procedure.params = params;
|
||||
type->procedure.params_count = proc_type_node->procedure_type.param_count;
|
||||
type->procedure.results = results;
|
||||
type->procedure.results_count = proc_type_node->procedure_type.result_count;
|
||||
type->procedure.scope = c->context.scope;
|
||||
type->procedure.params = params;
|
||||
type->procedure.param_count = proc_type_node->procedure_type.param_count;
|
||||
type->procedure.results = results;
|
||||
type->procedure.result_count = proc_type_node->procedure_type.result_count;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
||||
break;
|
||||
|
||||
case Entity_TypeName:
|
||||
case Entity_AliasName:
|
||||
o->mode = Addressing_Type;
|
||||
break;
|
||||
|
||||
@@ -1416,9 +1417,9 @@ ExpressionKind check_call_expression(Checker *c, Operand *operand, AstNode *call
|
||||
check_call_arguments(c, operand, proc_type, call);
|
||||
|
||||
auto *proc = &proc_type->procedure;
|
||||
if (proc->results_count == 0) {
|
||||
if (proc->result_count == 0) {
|
||||
operand->mode = Addressing_NoValue;
|
||||
} else if (proc->results_count == 1) {
|
||||
} else if (proc->result_count == 1) {
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = proc->results->tuple.variables[0]->type;
|
||||
} else {
|
||||
@@ -1524,7 +1525,6 @@ void check_expression_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ExpressionKind check__expression_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) {
|
||||
ExpressionKind kind = Expression_Statement;
|
||||
|
||||
|
||||
@@ -360,6 +360,17 @@ void check_type_declaration(Checker *c, Entity *e, AstNode *type_expr, Type *nam
|
||||
set_base_type(named, get_base_type(get_base_type(named)));
|
||||
}
|
||||
|
||||
void check_alias_declaration(Checker *c, Entity *e, AstNode *type_expr, Type *alias_type) {
|
||||
GB_ASSERT(e->type == NULL);
|
||||
Type *named = make_type_alias(c->allocator, e->token.string, NULL, e);
|
||||
named->alias.alias_name = e;
|
||||
set_base_type(alias_type, named);
|
||||
e->type = named;
|
||||
|
||||
check_type(c, type_expr, named);
|
||||
|
||||
set_base_type(named, get_base_type(get_base_type(named)));
|
||||
}
|
||||
|
||||
void check_procedure_body(Checker *c, Token token, DeclarationInfo *decl, Type *type, AstNode *body) {
|
||||
GB_ASSERT(body->kind == AstNode_BlockStatement);
|
||||
@@ -370,7 +381,7 @@ void check_procedure_body(Checker *c, Token token, DeclarationInfo *decl, Type *
|
||||
|
||||
push_procedure(c, type);
|
||||
check_statement_list(c, body->block_statement.list, 0);
|
||||
if (type->procedure.results_count > 0) {
|
||||
if (type->procedure.result_count > 0) {
|
||||
if (!check_is_terminating(c, body)) {
|
||||
error(&c->error_collector, body->block_statement.close, "Missing return statement at the end of the procedure");
|
||||
}
|
||||
@@ -498,6 +509,9 @@ void check_entity_declaration(Checker *c, Entity *e, Type *named_type) {
|
||||
case Entity_TypeName:
|
||||
check_type_declaration(c, e, d->type_expr, named_type);
|
||||
break;
|
||||
case Entity_AliasName:
|
||||
check_alias_declaration(c, e, d->type_expr, named_type);
|
||||
break;
|
||||
case Entity_Procedure:
|
||||
check_procedure_declaration(c, e, d, true);
|
||||
break;
|
||||
@@ -763,7 +777,7 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
|
||||
// Declarations
|
||||
case AstNode_VariableDeclaration: {
|
||||
auto *vd = &node->variable_declaration;
|
||||
isize entity_count = vd->name_list_count;
|
||||
isize entity_count = vd->name_count;
|
||||
isize entity_index = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
|
||||
switch (vd->kind) {
|
||||
@@ -820,7 +834,7 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
|
||||
|
||||
check_init_variables(c, entities, entity_count, vd->value_list, vd->value_list_count, make_string("variable declaration"));
|
||||
check_init_variables(c, entities, entity_count, vd->value_list, vd->value_count, make_string("variable declaration"));
|
||||
|
||||
AstNode *name = vd->name_list;
|
||||
for (isize i = 0; i < new_entity_count; i++, name = name->next) {
|
||||
@@ -840,8 +854,8 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
|
||||
check_constant_declaration(c, e, vd->type_expression, value);
|
||||
}
|
||||
|
||||
isize lhs_count = vd->name_list_count;
|
||||
isize rhs_count = vd->value_list_count;
|
||||
isize lhs_count = vd->name_count;
|
||||
isize rhs_count = vd->value_count;
|
||||
|
||||
// TODO(bill): Better error messages or is this good enough?
|
||||
if (rhs_count == 0 && vd->type_expression == NULL) {
|
||||
@@ -881,5 +895,13 @@ void check_statement(Checker *c, AstNode *node, u32 flags) {
|
||||
add_entity(c, c->context.scope, name, e);
|
||||
check_type_declaration(c, e, td->type_expression, NULL);
|
||||
} break;
|
||||
|
||||
case AstNode_AliasDeclaration: {
|
||||
auto *ad = &node->alias_declaration;
|
||||
AstNode *name = ad->name;
|
||||
Entity *e = make_entity_alias_name(c->allocator, c->context.scope, name->identifier.token, NULL);
|
||||
add_entity(c, c->context.scope, name, e);
|
||||
check_alias_declaration(c, e, ad->type_expression, NULL);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
+42
-10
@@ -60,6 +60,7 @@ enum TypeKind {
|
||||
Type_Structure,
|
||||
Type_Pointer,
|
||||
Type_Named,
|
||||
Type_Alias,
|
||||
Type_Tuple,
|
||||
Type_Procedure,
|
||||
|
||||
@@ -81,7 +82,7 @@ struct Type {
|
||||
Entity **fields; // Entity_Variable
|
||||
isize field_count; // == offset_count
|
||||
i64 * offsets;
|
||||
b32 offsets_set;
|
||||
b32 are_offsets_set;
|
||||
} structure;
|
||||
struct { Type *element; } pointer;
|
||||
struct {
|
||||
@@ -89,6 +90,11 @@ struct Type {
|
||||
Type * base;
|
||||
Entity *type_name; // Entity_TypeName
|
||||
} named;
|
||||
struct {
|
||||
String name;
|
||||
Type * base;
|
||||
Entity *alias_name; // Entity_AliasName
|
||||
} alias;
|
||||
struct {
|
||||
Entity **variables; // Entity_Variable
|
||||
isize variable_count;
|
||||
@@ -97,15 +103,18 @@ struct Type {
|
||||
Scope *scope;
|
||||
Type * params; // Type_Tuple
|
||||
Type * results; // Type_Tuple
|
||||
isize params_count;
|
||||
isize results_count;
|
||||
isize param_count;
|
||||
isize result_count;
|
||||
} procedure;
|
||||
};
|
||||
};
|
||||
|
||||
Type *get_base_type(Type *t) {
|
||||
while (t->kind == Type_Named) {
|
||||
t = t->named.base;
|
||||
while (t->kind == Type_Named || t->kind == Type_Alias) {
|
||||
if (t->kind == Type_Named)
|
||||
t = t->named.base;
|
||||
else
|
||||
t = t->alias.base;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
@@ -113,6 +122,8 @@ Type *get_base_type(Type *t) {
|
||||
void set_base_type(Type *t, Type *base) {
|
||||
if (t && t->kind == Type_Named) {
|
||||
t->named.base = base;
|
||||
} else if (t && t->kind == Type_Alias) {
|
||||
t->alias.base = base;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,18 +173,26 @@ Type *make_type_named(gbAllocator a, String name, Type *base, Entity *type_name)
|
||||
return t;
|
||||
}
|
||||
|
||||
Type *make_type_alias(gbAllocator a, String name, Type *base, Entity *alias_name) {
|
||||
Type *t = alloc_type(a, Type_Alias);
|
||||
t->alias.name = name;
|
||||
t->alias.base = base;
|
||||
t->alias.alias_name = alias_name;
|
||||
return t;
|
||||
}
|
||||
|
||||
Type *make_type_tuple(gbAllocator a) {
|
||||
Type *t = alloc_type(a, Type_Tuple);
|
||||
return t;
|
||||
}
|
||||
|
||||
Type *make_type_procedure(gbAllocator a, Scope *scope, Type *params, isize params_count, Type *results, isize results_count) {
|
||||
Type *make_type_procedure(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count) {
|
||||
Type *t = alloc_type(a, Type_Procedure);
|
||||
t->procedure.scope = scope;
|
||||
t->procedure.params = params;
|
||||
t->procedure.params_count = params_count;
|
||||
t->procedure.param_count = param_count;
|
||||
t->procedure.results = results;
|
||||
t->procedure.results_count = results_count;
|
||||
t->procedure.result_count = result_count;
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -343,6 +362,10 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
return are_types_identical(x->pointer.element, y->pointer.element);
|
||||
break;
|
||||
|
||||
|
||||
case Type_Alias:
|
||||
return are_types_identical(get_base_type(x), y);
|
||||
|
||||
case Type_Named:
|
||||
if (y->kind == Type_Named)
|
||||
return x->named.base == y->named.base;
|
||||
@@ -463,9 +486,9 @@ i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields
|
||||
|
||||
b32 type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
GB_ASSERT(t->kind == Type_Structure);
|
||||
if (!t->structure.offsets_set) {
|
||||
if (!t->structure.are_offsets_set) {
|
||||
t->structure.offsets = type_set_offsets_of(s, allocator, t->structure.fields, t->structure.field_count);
|
||||
t->structure.offsets_set = true;
|
||||
t->structure.are_offsets_set = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -571,6 +594,15 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Alias:
|
||||
if (type->alias.alias_name != NULL) {
|
||||
str = gb_string_append_length(str, type->alias.name.text, type->alias.name.len);
|
||||
} else {
|
||||
// NOTE(bill): Just in case
|
||||
str = gb_string_appendc(str, "<alias type>");
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Tuple:
|
||||
if (type->tuple.variable_count > 0) {
|
||||
for (isize i = 0; i < type->tuple.variable_count; i++) {
|
||||
|
||||
Reference in New Issue
Block a user