if thread_count != 0 {
dist := distributor(iter);
- t_data := Thread_Data(T, Ctx).{
+ t_data := Thread_Data(iter.Iter_Type, Ctx).{
iter = ^dist,
data = thread_data,
};
array.init(^entries, allocator=allocator);
}
-free :: (use map: ^Map($K, $V)) {
+free :: (use map: ^Map) {
memory.free_slice(^hashes, allocator=allocator);
array.free(^entries);
}
}
}
-clear :: (use map: ^Map($K, $V)) {
+clear :: (use map: ^Map) {
for i: 0 .. hashes.count do hashes.data[i] = -1;
entries.count = 0;
}
-empty :: (use map: ^Map($K, $V)) -> bool {
+empty :: (use map: ^Map) -> bool {
return entries.count == 0;
}
return lr;
}
- full :: (use map: ^Map($K, $V)) => entries.count >= ~~(0.75f * ~~hashes.count);
+ full :: (use map: ^Map) => entries.count >= ~~(0.75f * ~~hashes.count);
- grow :: (use map: ^Map($K, $V)) {
+ grow :: (use map: ^Map) {
new_size := math.max(hashes.count << 1, 8);
rehash(map, new_size);
}
- rehash :: (use map: ^Map($K, $V), new_size: i32) {
+ rehash :: (use map: ^Map, new_size: i32) {
memory.free_slice(^hashes, allocator);
memory.alloc_slice(^hashes, new_size, allocator);
memory.fill_slice(hashes, -1);
Entity* entity_heap_top(EntityHeap* entities);
void entity_heap_change_top(EntityHeap* entities, Entity* new_top);
void entity_heap_remove_top(EntityHeap* entities);
+void entity_change_type(EntityHeap* entities, Entity *ent, EntityType new_type);
// If target_arr is null, the entities will be placed directly in the heap.
void add_entities_for_node(bh_arr(Entity *)* target_arr, AstNode* node, Scope* scope, Package* package);
AstNode* polymorphic_proc_try_solidify(AstFunction* pp, bh_arr(AstPolySolution) slns, OnyxToken* tkn);
AstFunction* polymorphic_proc_build_only_header(AstFunction* pp, PolyProcLookupMethod pp_lookup, ptr actual);
AstFunction* polymorphic_proc_build_only_header_with_slns(AstFunction* pp, bh_arr(AstPolySolution) slns, b32 error_if_failed);
+b32 potentially_convert_function_to_polyproc(AstFunction *func);
void add_overload_option(bh_arr(OverloadOption)* poverloads, u64 precedence, AstTyped* overload);
AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, Arguments* args);
return NULL;
}
+static inline void convert_polyproc_to_function(AstFunction *func) {
+ if (func->kind != Ast_Kind_Polymorphic_Proc) return;
+
+ func->kind = Ast_Kind_Function;
+ func->parent_scope_of_poly_proc = NULL;
+ func->poly_params = NULL;
+ func->known_slns = NULL;
+ func->concrete_funcs = NULL;
+ func->active_queries.hashes = NULL;
+ func->active_queries.entries = NULL;
+ func->poly_scope = NULL;
+ func->entity = NULL;
+}
+
+static inline void convert_function_to_polyproc(AstFunction *func) {
+ if (func->kind != Ast_Kind_Function) return;
+
+ func->kind = Ast_Kind_Polymorphic_Proc;
+ func->parent_scope_of_poly_proc = func->scope->parent;
+ func->scope = NULL;
+ if (func->entity) entity_change_type(&context.entities, func->entity, Entity_Type_Polymorphic_Proc);
+}
+
#endif // #ifndef ONYXASTNODES_H
case Ast_Kind_Param:
if (expr->type == NULL) {
- onyx_report_error(expr->token->pos, Error_Critical, "Parameter with bad type.");
- retval = Check_Error;
+ YIELD(expr->token->pos, "Waiting on parameter type.");
}
break;
case Ast_Kind_Memres:
case Ast_Kind_StrLit:
case Ast_Kind_Package:
- case Ast_Kind_Enum_Type:
- case Ast_Kind_Enum_Value:
case Ast_Kind_Overloaded_Function:
case Ast_Kind_Alias:
case Ast_Kind_Code_Block:
case Ast_Kind_Macro:
case Ast_Kind_File_Contents:
case Ast_Kind_Symbol:
+ case Ast_Kind_Poly_Struct_Type:
+ case Ast_Kind_Basic_Type:
+ case Ast_Kind_Enum_Type:
+ case Ast_Kind_Enum_Value:
return 0;
default: return 1;
AstFunction* df = (AstFunction *) nn;
AstFunction* sf = (AstFunction *) node;
- if (node->kind == Ast_Kind_Polymorphic_Proc) {
- df->kind = Ast_Kind_Function;
- df->parent_scope_of_poly_proc = NULL;
- df->poly_params = NULL;
- df->known_slns = NULL;
- df->concrete_funcs = NULL;
- df->active_queries.hashes = NULL;
- df->active_queries.entries = NULL;
- df->poly_scope = NULL;
- df->entity = NULL;
- }
+ convert_polyproc_to_function(df);
if (sf->is_foreign) return node;
assert(df->scope == NULL);
memmove(new_func, func, sizeof(AstFunction));
assert(new_func->scope == NULL);
- if (func->kind == Ast_Kind_Polymorphic_Proc) {
- new_func->kind = Ast_Kind_Function;
- new_func->parent_scope_of_poly_proc = NULL;
- new_func->poly_params = NULL;
- new_func->known_slns = NULL;
- new_func->concrete_funcs = NULL;
- new_func->active_queries.hashes = NULL;
- new_func->active_queries.entries = NULL;
- new_func->poly_scope = NULL;
- new_func->entity = NULL;
- }
+ convert_polyproc_to_function(new_func);
- // new_func->body = NULL;
new_func->return_type = (AstType *) ast_clone(a, func->return_type);
new_func->params = NULL;
eh_shift_down(entities, 0);
}
+void entity_change_type(EntityHeap* entities, Entity *ent, EntityType new_type) {
+ entities->type_count[ent->type]--;
+ entities->type_count[new_type]++;
+ ent->type = new_type;
+}
+
// 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) \
return (AstFunction *) &node_that_signals_a_yield;
}
+typedef struct AutoPolymorphVariable {
+ u32 idx;
+ u32 variable_count;
+ AstType *base_type;
+ AstType **replace;
+} AutoPolymorphVariable;
+
+// This should be called after all the parameter types have been symresed, but before anything
+// happens to the body.
+b32 potentially_convert_function_to_polyproc(AstFunction *func) {
+ bh_arr(AutoPolymorphVariable) auto_vars = NULL;
+ bh_arr_new(global_heap_allocator, auto_vars, 2);
+
+ u32 param_idx = 0;
+ bh_arr_each(AstParam, param, func->params) {
+ AstType **to_replace = ¶m->local->type_node;
+ AstType *param_type = param->local->type_node;
+
+ b32 done = 0;
+ while (!done && param_type) {
+ switch (param_type->kind) {
+ case Ast_Kind_Pointer_Type: to_replace = &((AstPointerType *) *to_replace)->elem; param_type = ((AstPointerType *) param_type)->elem; break;
+ case Ast_Kind_Array_Type: to_replace = &((AstArrayType *) *to_replace)->elem; param_type = ((AstArrayType *) param_type)->elem; break;
+ case Ast_Kind_Slice_Type: to_replace = &((AstSliceType *) *to_replace)->elem; param_type = ((AstSliceType *) param_type)->elem; break;
+ case Ast_Kind_DynArr_Type: to_replace = &((AstDynArrType *) *to_replace)->elem; param_type = ((AstDynArrType *) param_type)->elem; break;
+ case Ast_Kind_Alias: param_type = ((AstAlias *) param_type)->alias; break;
+ case Ast_Kind_Type_Alias: param_type = ((AstTypeAlias *) param_type)->to; break;
+ case Ast_Kind_Poly_Struct_Type: {
+ AutoPolymorphVariable apv;
+ apv.idx = param_idx;
+ apv.base_type = param->local->type_node;
+ apv.variable_count = bh_arr_length(((AstPolyStructType *) param_type)->poly_params);
+ apv.replace = to_replace;
+
+ bh_arr_push(auto_vars, apv);
+ done = 1;
+ break;
+ }
+
+ default: done = 1; break;
+ }
+ }
+
+ param_idx++;
+ }
+
+ if (bh_arr_length(auto_vars) == 0) return 0;
+
+ param_idx = 0;
+ bh_arr_each(AutoPolymorphVariable, apv, auto_vars) {
+ AstPolyParam pp;
+ pp.idx = apv->idx;
+ pp.kind = PPK_Poly_Type;
+
+ AstPolyCallType* pcall = onyx_ast_node_new(context.ast_alloc, sizeof(AstPolyCallType), Ast_Kind_Poly_Call_Type);
+ pcall->callee = *apv->replace;
+ pcall->token = pcall->callee->token;
+ bh_arr_new(global_heap_allocator, pcall->params, apv->variable_count);
+
+ if (apv->base_type->kind == Ast_Kind_Poly_Struct_Type) {
+ pp.type_expr = (AstType *) pcall;
+ } else {
+ pp.type_expr = apv->base_type;
+ }
+ *apv->replace = (AstType *) pcall;
+
+ fori (i, 0, apv->variable_count) {
+ OnyxToken* name_token = bh_alloc_item(context.ast_alloc, OnyxToken);
+ name_token->text = bh_aprintf(context.ast_alloc, "__autopoly_var_%d\0", param_idx);
+ name_token->length = strlen(name_token->text);
+ name_token->type = Token_Type_Symbol;
+ name_token->pos = pcall->token->pos;
+
+ pp.poly_sym = make_symbol(context.ast_alloc, name_token);
+ bh_arr_push(pcall->params, pp.poly_sym);
+ bh_arr_push(func->poly_params, pp);
+ param_idx ++;
+ }
+ }
+
+ convert_function_to_polyproc(func);
+ return 1;
+}
+
//
// Polymorphic Structures
//
case Ast_Kind_Alias: {
AstAlias* alias = (AstAlias *) *type;
alias->flags |= Ast_Flag_Symbol_Invisible;
- SYMRES(type, (AstType **) &alias->alias);
+ SymresStatus ss = symres_type((AstType **) &alias->alias);
alias->flags &= ~Ast_Flag_Symbol_Invisible;
+ if (ss > Symres_Errors_Start) return ss;
+
break;
}
case Ast_Kind_Align_Of: SYMRES(align_of, (AstAlignOf *)*expr); break;
case Ast_Kind_Alias: {
(*expr)->flags |= Ast_Flag_Symbol_Invisible;
- SYMRES(expression, &((AstAlias *) *expr)->alias);
+ SymresStatus ss = symres_expression((AstTyped **) &((AstAlias *) *expr)->alias);
(*expr)->flags &= ~Ast_Flag_Symbol_Invisible;
+ if (ss > Symres_Errors_Start) return ss;
break;
}
}
}
- SYMRES(type, &func->return_type);
- if (!node_is_type((AstNode *) func->return_type)) {
- AstType* return_type = (AstType *) strip_aliases((AstNode *) func->return_type);
- if (return_type->kind == Ast_Kind_Symbol) return Symres_Yield_Macro;
-
- onyx_report_error(func->token->pos, Error_Critical, "Return type is not a type.");
+ if (potentially_convert_function_to_polyproc(func)) {
+ return Symres_Complete;
}
+ SYMRES(type, &func->return_type);
+
if (func->constraints.constraints != NULL) {
bh_arr_each(AstConstraint *, constraint, func->constraints.constraints) {
SYMRES(constraint, *constraint);
SymresStatus symres_function(AstFunction* func) {
if (func->entity_header && func->entity_header->state < Entity_State_Check_Types) return Symres_Yield_Macro;
+ if (func->kind == Ast_Kind_Polymorphic_Proc) return Symres_Complete;
assert(func->scope);
scope_enter(func->scope);