static inline i32 entity_phase(Entity* e1) {
if (e1->state <= Entity_State_Parse) return 1;
- if (e1->state <= Entity_State_Comptime_Check_Types) return 2;
+ if (e1->state < Entity_State_Code_Gen) return 2;
return 3;
}
i32 phase1 = entity_phase(e1);
i32 phase2 = entity_phase(e2);
- if (phase1 != phase2 || phase1 != 2) {
- if (e1->state != e2->state)
- return (i32) e1->state - (i32) e2->state;
- else if (e1->type != e2->type)
- return (i32) e1->type - (i32) e2->type;
- else
- return (i32) (e1->micro_attempts - e2->micro_attempts);
-
- } else {
+ if (phase1 != phase2)
+ return phase1 - phase2;
+ else if (e1->macro_attempts != e2->macro_attempts)
return (i32) e1->macro_attempts - (i32) e2->macro_attempts;
- }
+ else if (e1->state != e2->state)
+ return (i32) e1->state - (i32) e2->state;
+ else if (e1->type != e2->type)
+ return (i32) e1->type - (i32) e2->type;
+ else
+ return (i32) (e1->micro_attempts - e2->micro_attempts);
+
}
#define eh_parent(index) (((index) - 1) / 2)
case Ast_Kind_Use: {
if (((AstUse *) node)->expr->kind == Ast_Kind_Package) {
- ent.state = Entity_State_Comptime_Resolve_Symbols;
+ ent.state = Entity_State_Resolve_Symbols;
ent.type = Entity_Type_Use_Package;
} else {
ent.type = Entity_Type_Use;
}
case Ast_Kind_Static_If: {
- ent.state = Entity_State_Comptime_Resolve_Symbols;
+ ent.state = Entity_State_Resolve_Symbols;
ent.type = Entity_Type_Static_If;
ent.static_if = (AstIf *) node;
ENTITY_INSERT(ent);
}
if (ifnode->kind == Ast_Kind_Static_If) {
+ if ((ifnode->flags & Ast_Flag_Static_If_Resolved) == 0) {
+ return Symres_Yield_Macro;
+ }
+
if (static_if_resolution(ifnode)) {
if (ifnode->true_stmt != NULL) SYMRES(statement, (AstNode **) &ifnode->true_stmt, NULL);
scope_enter(func->scope);
- bh_arr_each(AstParam, param, func->params) {
- symbol_introduce(curr_scope, param->local->token, (AstNode *) param->local);
-
- // CLEANUP: Currently, in order to 'use' parameters, the type must be completely
- // resolved and built. This is excessive because all that should need to be known
- // is the names of the members, since all that happens is implicit field accesses
- // are placed in the scope. So instead, there should be a way to just query all the
- // member names in the structure, without needing to know their type. This would be
- // easy if it were not for 'use' statements in structs. It is made even more complicated
- // by this situtation:
- //
- // Foo :: struct (T: type_expr) {
- // use t : T;
- //
- // something_else := 5 + 6 * 8;
- // }
- //
- // The 'use t : T' member requires completely knowing the type of T, to know which
- // members should be brought in. At the moment, that requires completely building the
- // type of Foo($T).
- if (param->local->flags & Ast_Flag_Param_Use) {
- if (param->local->type_node != NULL && param->local->type == NULL) {
- param->local->type = type_build_from_ast(context.ast_alloc, param->local->type_node);
- }
-
- if (type_is_struct(param->local->type)) {
- Type* st;
- if (param->local->type->kind == Type_Kind_Struct) {
- st = param->local->type;
- } else {
- st = param->local->type->Pointer.elem;
+ if ((func->flags & Ast_Flag_Has_Been_Symres) == 0) {
+ func->flags |= Ast_Flag_Has_Been_Symres;
+
+ bh_arr_each(AstParam, param, func->params) {
+ symbol_introduce(curr_scope, param->local->token, (AstNode *) param->local);
+
+ // CLEANUP: Currently, in order to 'use' parameters, the type must be completely
+ // resolved and built. This is excessive because all that should need to be known
+ // is the names of the members, since all that happens is implicit field accesses
+ // are placed in the scope. So instead, there should be a way to just query all the
+ // member names in the structure, without needing to know their type. This would be
+ // easy if it were not for 'use' statements in structs. It is made even more complicated
+ // by this situtation:
+ //
+ // Foo :: struct (T: type_expr) {
+ // use t : T;
+ //
+ // something_else := 5 + 6 * 8;
+ // }
+ //
+ // The 'use t : T' member requires completely knowing the type of T, to know which
+ // members should be brought in. At the moment, that requires completely building the
+ // type of Foo($T).
+ if (param->local->flags & Ast_Flag_Param_Use) {
+ if (param->local->type_node != NULL && param->local->type == NULL) {
+ param->local->type = type_build_from_ast(context.ast_alloc, param->local->type_node);
}
- bh_table_each_start(StructMember, st->Struct.members);
- AstFieldAccess* fa = make_field_access(context.ast_alloc, (AstTyped *) param->local, value.name);
- symbol_raw_introduce(curr_scope, value.name, param->local->token->pos, (AstNode *) fa);
- bh_table_each_end;
+ if (type_is_struct(param->local->type)) {
+ Type* st;
+ if (param->local->type->kind == Type_Kind_Struct) {
+ st = param->local->type;
+ } else {
+ st = param->local->type->Pointer.elem;
+ }
- } else if (param->local->type != NULL) {
- onyx_report_error(param->local->token->pos, "Can only 'use' structures or pointers to structures.");
+ bh_table_each_start(StructMember, st->Struct.members);
+ AstFieldAccess* fa = make_field_access(context.ast_alloc, (AstTyped *) param->local, value.name);
+ symbol_raw_introduce(curr_scope, value.name, param->local->token->pos, (AstNode *) fa);
+ bh_table_each_end;
- } else {
- // :ExplicitTyping
- onyx_report_error(param->local->token->pos, "Cannot deduce type of parameter '%b'; Try adding it explicitly.",
- param->local->token->text,
- param->local->token->length);
+ } else if (param->local->type != NULL) {
+ onyx_report_error(param->local->token->pos, "Can only 'use' structures or pointers to structures.");
+
+ } else {
+ // :ExplicitTyping
+ onyx_report_error(param->local->token->pos, "Cannot deduce type of parameter '%b'; Try adding it explicitly.",
+ param->local->token->text,
+ param->local->token->length);
+ }
}
}
}
break;
}
- case Entity_Type_Static_If: {
- ss = symres_static_if(ent->static_if);
- next_state = Entity_State_Comptime_Check_Types;
- break;
- }
+ case Entity_Type_Static_If: ss = symres_static_if(ent->static_if); break;
case Entity_Type_Foreign_Function_Header:
case Entity_Type_Function_Header: ss = symres_function_header(ent->function); break;
default: break;
}
- if (ss == Symres_Success) ent->state = next_state;
if (ss == Symres_Yield_Macro) ent->macro_attempts++;
if (ss == Symres_Yield_Micro) ent->micro_attempts++;
+ if (ss == Symres_Success) {
+ ent->macro_attempts = 0;
+ ent->micro_attempts = 0;
+ ent->state = next_state;
+ }
if (ent->scope) curr_scope = old_scope;
}