Ast_Flag_Has_Been_Symres = BH_BIT(26),
- Ast_Flag_Static_If_Resolved = BH_BIT(27),
+ Ast_Flag_Has_Been_Checked = BH_BIT(27),
+
+ Ast_Flag_Static_If_Resolved = BH_BIT(28),
} AstFlags;
typedef enum UnaryOp {
OnyxToken* foreign_name;
};
};
+
+ struct Entity* entity_header;
+ struct Entity* entity_body;
};
struct AstOverloadedFunction {
void entity_heap_init(EntityHeap* entities);
void entity_heap_insert_existing(EntityHeap* entities, Entity* e);
-void entity_heap_insert(EntityHeap* entities, Entity e);
+Entity* entity_heap_insert(EntityHeap* entities, Entity e);
Entity* entity_heap_top(EntityHeap* entities);
void entity_heap_change_top(EntityHeap* entities, Entity* new_top);
void entity_heap_remove_top(EntityHeap* entities);
if (bh_arr_length(eh->entities) == 0) return;
static const char* state_colors[] = {
- "\e[91m", "\e[93m", "\e[94m", "\e[93m", "\e[97m",
- "\e[95m", "\e[97m", "\e[95m", "\e[96m", "\e[92m",
+ "\e[91m", "\e[93m", "\e[94m", "\e[93m",
+ "\e[97m", "\e[95m", "\e[96m", "\e[92m",
};
printf("\e[2;1H");
CHECK(expression, &ifnode->cond);
if (!type_is_bool(ifnode->cond->type)) {
- onyx_report_error(ifnode->cond->token->pos, "expected boolean type for condition");
+ onyx_report_error(ifnode->cond->token->pos, "Expected expression of type 'bool' for condition, got '%s'", type_get_name(ifnode->cond->type));
return Check_Error;
}
CHECK(expression, &whilenode->cond);
if (!type_is_bool(whilenode->cond->type)) {
- onyx_report_error(whilenode->cond->token->pos, "expected boolean type for condition");
+ onyx_report_error(whilenode->cond->token->pos, "Expected expression of type 'bool' for condition, got '%s'", type_get_name(whilenode->cond->type));
return Check_Error;
}
// SPEED CLEANUP: Keeping an original copy for basically no reason except that sometimes you
// need to know the baked argument values in code generation.
+ // This should only be done once, but right now it is being done everytime this is checked,
+ // which can be multiple if we have to yield on a callee's type.
arguments_clone(&call->original_args, &call->args);
if (call->callee->kind == Ast_Kind_Overloaded_Function) {
// NOTE: Build callee's type
fill_in_type((AstTyped *) callee);
- if (callee->type == NULL) {
- onyx_report_error(call->token->pos, "There was an error with looking up the type of this function.");
- return Check_Error;
- }
+ if (callee->type == NULL) return Check_Yield_Macro;
if (callee->type->kind != Type_Kind_Function) {
onyx_report_error(call->token->pos,
CheckStatus check_function(AstFunction* func) {
if (func->flags & Ast_Flag_Already_Checked) return Check_Success;
+ if (func->entity_header && func->entity_header->state < Entity_State_Code_Gen) return Check_Yield_Macro;
expected_return_type = func->type->Function.return_type;
if (func->body) {
CheckStatus check_static_if(AstIf* static_if) {
expression_types_must_be_known = 1;
CheckStatus result = check_expression(&static_if->cond);
+ if (result == Check_Yield_Macro) return Check_Yield_Macro;
expression_types_must_be_known = 0;
if (result > Check_Errors_Start || !(static_if->cond->flags & Ast_Flag_Comptime)) {
switch (ent->type) {
case Entity_Type_Foreign_Function_Header:
- case Entity_Type_Function_Header:
- cs = check_function_header(ent->function);
- break;
-
- case Entity_Type_Function:
- cs = check_function(ent->function);
- break;
-
- case Entity_Type_Overloaded_Function:
- cs = check_overloaded_function(ent->overloaded_function);
- break;
-
- case Entity_Type_Global:
- cs = check_global(ent->global);
- break;
+ case Entity_Type_Function_Header: cs = check_function_header(ent->function); break;
+ case Entity_Type_Function: cs = check_function(ent->function); break;
+ case Entity_Type_Overloaded_Function: cs = check_overloaded_function(ent->overloaded_function); break;
+ case Entity_Type_Global: cs = check_global(ent->global); break;
+ case Entity_Type_Struct_Member_Default: cs = check_struct_defaults((AstStructType *) ent->type_alias); break;
+ case Entity_Type_Memory_Reservation_Type: cs = check_memres_type(ent->mem_res); break;
+ case Entity_Type_Memory_Reservation: cs = check_memres(ent->mem_res); break;
+ case Entity_Type_Static_If: cs = check_static_if(ent->static_if); break;
case Entity_Type_Expression:
cs = check_expression(&ent->expr);
cs = check_type(ent->type_alias);
break;
- case Entity_Type_Struct_Member_Default:
- cs = check_struct_defaults((AstStructType *) ent->type_alias);
- break;
-
- case Entity_Type_Memory_Reservation_Type:
- cs = check_memres_type(ent->mem_res);
- break;
-
- case Entity_Type_Memory_Reservation:
- cs = check_memres(ent->mem_res);
- break;
-
- case Entity_Type_Static_If:
- cs = check_static_if(ent->static_if);
- break;
-
default: break;
}
- if (cs == Check_Success) ent->state = Entity_State_Code_Gen;
- if (cs == Check_Complete) ent->state = Entity_State_Finalized;
- else if (cs == Check_Yield_Macro) {
- ent->macro_attempts++;
- }
+ if (cs == Check_Success) ent->state = Entity_State_Code_Gen;
+ if (cs == Check_Complete) ent->state = Entity_State_Finalized;
+ if (cs == Check_Yield_Macro) ent->macro_attempts++;
}
static inline i32 entity_phase(Entity* e1) {
if (e1->state <= Entity_State_Parse) return 1;
- if (e1->state < Entity_State_Code_Gen) return 2;
- return 3;
+ if (e1->state < Entity_State_Code_Gen) return 3;
+ return 4;
}
// NOTE: Returns >0 if e1 should be processed after e2.
entities->all_count[e->state][e->type]++;
}
-// nocheckin
-// Temporary wrapper
-void entity_heap_insert(EntityHeap* entities, Entity e) {
+Entity* entity_heap_insert(EntityHeap* entities, Entity e) {
Entity* entity = entity_heap_register(entities, e);
entity_heap_insert_existing(entities, entity);
+ return entity;
}
Entity* entity_heap_top(EntityHeap* entities) {
// NOTE(Brendan Hansen): Uses the entity heap in the context structure
void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* scope, Package* package) {
-#define ENTITY_INSERT(_ent) { \
- Entity* entity = entity_heap_register(entities, _ent); \
+#define ENTITY_INSERT(_ent) \
+ entity = entity_heap_register(entities, _ent); \
if (target_arr) { \
bh_arr(Entity *) __tmp_arr = *target_arr; \
bh_arr_push(__tmp_arr, entity); \
} else { \
entity_heap_insert_existing(entities, entity); \
} \
- }
+
EntityHeap* entities = &context.entities;
+ Entity* entity;
Entity ent;
ent.state = Entity_State_Resolve_Symbols;
ent.type = Entity_Type_Function_Header;
ent.function = (AstFunction *) node;
ENTITY_INSERT(ent);
+ ((AstFunction *) node)->entity_header = entity;
ent.type = Entity_Type_Function;
ent.function = (AstFunction *) node;
ENTITY_INSERT(ent);
+ ((AstFunction *) node)->entity_body = entity;
}
break;
}
SymresStatus symres_function(AstFunction* func) {
if (func->scope == NULL)
func->scope = scope_create(context.ast_alloc, curr_scope, func->token->pos);
+ if (func->entity_header && func->entity_header->state < Entity_State_Check_Types) return Symres_Yield_Macro;
scope_enter(func->scope);
.scope = solidified_func.poly_scope,
};
- entity_heap_insert(&context.entities, func_header_entity);
- entity_heap_insert(&context.entities, func_entity);
+ Entity* entity_header = entity_heap_insert(&context.entities, func_header_entity);
+ Entity* entity_body = entity_heap_insert(&context.entities, func_entity);
+
+ solidified_func.func->entity_header = entity_header;
+ solidified_func.func->entity_body = entity_body;
return 1;
}
}
void entity_bring_to_state(Entity* ent, EntityState state) {
+ EntityState last_state = ent->state;
+
while (ent->state != state) {
switch (ent->state) {
case Entity_State_Resolve_Symbols: symres_entity(ent); break;
default: return;
}
+ if (ent->state == last_state) break;
+ last_state = ent->state;
+
if (onyx_has_errors()) return;
}
}