}
}
-make :: ($T: type_expr, elements_per_bucket: i32,
+make :: ($T: type_expr, elements: i32,
array_allocator := context.allocator, bucket_allocator := context.allocator) -> Bucket_Array(T) {
buckets : Bucket_Array(T);
- init(^buckets);
+ init(^buckets, elements);
return buckets;
}
-init :: (use b: ^Bucket_Array($T), elements_per_bucket: i32,
+init :: (use b: ^Bucket_Array($T), elements: i32,
array_allocator := context.allocator, bucket_allocator := context.allocator) {
allocator = bucket_allocator;
- buckets = array.make(#type Bucket(T), allocator=array_allocator);
+ b.elements_per_bucket = elements;
+ buckets = array.make(#type Bucket_Array.Bucket(T), allocator=array_allocator);
initial_bucket := alloc_bucket(b);
array.push(^buckets, initial_bucket);
last_bucket.count -= 1;
}
+// Give you a pointer to the bucket data via 'it'.
+for_each :: macro (b: Bucket_Array($T), $body: Code) {
+ for ^bucket: b.buckets {
+ for bucket_index: bucket.count {
+ it := ^bucket.data[bucket_index];
+
+ #insert body;
+ }
+ }
+}
#private
-alloc_bucket :: (use b: ^Bucket_Array($T)) -> Bucket(T) {
+alloc_bucket :: (use b: ^Bucket_Array($T)) -> Bucket_Array.Bucket(T) {
data := raw_alloc(allocator, sizeof T * elements_per_bucket);
return .{ 0, data };
}
calling_a_macro = 1;
call->callee = callee;
- callee = ((AstMacro *) callee)->body;
- if (callee->kind == Ast_Kind_Polymorphic_Proc) {
- onyx_report_error(call->token->pos, "Cannot call polymorphic macros... yet.");
- return Check_Error;
- }
+ AstTyped* new_callee = (AstTyped *) macro_resolve_header((AstMacro *) callee, &call->args, call->token);
+ if (new_callee == (AstTyped *) &node_that_signals_a_yield) return Check_Yield_Macro;
+ if (new_callee == NULL) return Check_Error;
+
+ arguments_remove_baked(&call->args);
+ callee = new_callee;
} else if (callee->kind == Ast_Kind_Polymorphic_Proc) {
AstTyped* new_callee = (AstTyped *) polymorphic_proc_lookup((AstPolyProc *) callee, PPLM_By_Arguments, &call->args, call->token);
callee->flags |= Ast_Flag_Function_Used;
if (call->kind == Ast_Kind_Call && call->callee->kind == Ast_Kind_Macro) {
- expand_macro(pcall);
+ expand_macro(pcall, callee);
return Check_Return_To_Symres;
}
if (insert->flags & Ast_Flag_Has_Been_Checked) return Check_Success;
CHECK(expression, &insert->code_expr);
- if (insert->code_expr->type == NULL) return Check_Yield_Macro;
+ if (insert->code_expr->type == NULL) {
+ if (insert->code_expr->entity && insert->code_expr->entity->state >= Entity_State_Code_Gen) {
+ onyx_report_error(insert->token->pos, "Expected expression of type 'Code'.");
+ return Check_Error;
+ }
+
+ return Check_Yield_Macro;
+ }
Type* code_type = type_build_from_ast(context.ast_alloc, builtin_code_type);
if (param->type == NULL)
param->type = type_build_from_ast(context.ast_alloc, param->type_expr);
+ assert(param->type);
if (!type_check_or_auto_cast(&value, param->type)) {
if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator,
- "The procedure '%s' expects a value of type '%s' for %d%s parameter, got '%s'.",
+ "The procedure '%s' expects a value of type '%s' for baked %d%s parameter, got '%s'.",
get_function_name(pp->base_func),
type_get_name(param->type),
param->idx + 1,
default: if (err_msg) *err_msg = "Invalid polymorphic parameter kind. This is a compiler bug.";
}
- if (flag_to_yield) {
- bh_arr_free(slns);
- return NULL;
- }
+ if (flag_to_yield) goto sln_not_found;
switch (resolved.kind) {
case PSK_Undefined:
b32 successful = entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
if (onyx_has_errors()) {
+ onyx_errors_print();
onyx_clear_errors();
return NULL;
}
//
//
// TODO: Write this documentation
-void expand_macro(AstCall** pcall) {
+void expand_macro(AstCall** pcall, AstFunction* template) {
AstCall* call = *pcall;
AstMacro* macro = (AstMacro *) call->callee;
assert(macro->kind == Ast_Kind_Macro);
- AstFunction* template = (AstFunction *) macro->body;
assert(template->kind == Ast_Kind_Function);
assert(template->type != NULL);
(AstNode *) ((AstArgument *) call->args.values[i])->value);
}
+ if (template->flags & Ast_Flag_From_Polymorphism) {
+ // SLOW DUMB HACKY WAY TO DO THIS!!!!! FIX IT!!!!!
+
+ AstPolyProc* pp = (AstPolyProc *) macro->body;
+ bh_table_each_start(AstSolidifiedFunction, pp->concrete_funcs);
+
+ if (value.func == template)
+ scope_include(argument_scope, value.poly_scope, call->token->pos);
+
+ bh_table_each_end;
+ }
+
*(AstBlock **) pcall = expansion;
return;
}
+AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* callsite) {
+ switch (macro->body->kind) {
+ case Ast_Kind_Function: return (AstFunction *) macro->body;
+
+ case Ast_Kind_Polymorphic_Proc: {
+ AstPolyProc* pp = (AstPolyProc *) macro->body;
+ ensure_polyproc_cache_is_created(pp);
+
+ char* err_msg=NULL;
+ bh_arr(AstPolySolution) slns = find_polymorphic_slns(pp, PPLM_By_Arguments, args, &err_msg);
+
+ if (slns == NULL) {
+ if (flag_to_yield) {
+ flag_to_yield = 0;
+ return (AstFunction *) &node_that_signals_a_yield;
+ }
+
+ onyx_report_error(callsite->pos, err_msg);
+ return NULL;
+ }
+
+ // CLEANUP Copy'n'pasted from polymorphic_proc_build_only_header
+ AstSolidifiedFunction solidified_func;
+
+ char* unique_key = build_poly_slns_unique_key(slns);
+ if (bh_table_has(AstSolidifiedFunction, pp->concrete_funcs, unique_key)) {
+ solidified_func = bh_table_get(AstSolidifiedFunction, pp->concrete_funcs, unique_key);
+
+ } else {
+ // NOTE: This function is only going to have the header of it correctly created.
+ // Nothing should happen to this function's body or else the original will be corrupted.
+ // - brendanfh 2021/01/10
+ solidified_func = generate_solidified_function(pp, slns, callsite, 1);
+ }
+
+ if (solidified_func.header_complete) return solidified_func.func;
+
+ Entity func_header_entity = {
+ .state = Entity_State_Resolve_Symbols,
+ .type = Entity_Type_Function_Header,
+ .function = solidified_func.func,
+ .package = NULL,
+ .scope = solidified_func.poly_scope,
+ };
+
+ b32 successful = entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
+ if (onyx_has_errors()) return NULL;
+
+ solidified_func.header_complete = successful;
+
+ bh_table_put(AstSolidifiedFunction, pp->concrete_funcs, unique_key, solidified_func);
+ if (!successful) return (AstFunction *) &node_that_signals_a_yield;
+
+ return solidified_func.func;
+ }
+
+ default: assert(("Bad macro body type.", 0));
+ }
+}
+
//
// Polymorphic Structures
//