From: Brendan Hansen Date: Thu, 12 Aug 2021 19:30:40 +0000 (-0500) Subject: macros working! needs a lot of cleanup however X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=60324d9f14bc7d3a66fed4dbee5e884e02405556;p=onyx.git macros working! needs a lot of cleanup however --- diff --git a/bin/onyx b/bin/onyx index aa21c0e3..5d1db354 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/container/bucket_array.onyx b/core/container/bucket_array.onyx index 367e3f4f..10a22d16 100644 --- a/core/container/bucket_array.onyx +++ b/core/container/bucket_array.onyx @@ -16,19 +16,20 @@ Bucket_Array :: struct (T: type_expr) { } } -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); @@ -77,9 +78,19 @@ pop :: (use b: ^Bucket_Array($T)) { 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 }; } diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index f412e137..aa498532 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -1354,7 +1354,8 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads, AstTyped* find_matching_overload_by_type(bh_arr(OverloadOption) overloads, Type* type); void report_unable_to_match_overload(AstCall* call); -void expand_macro(AstCall** pcall); +void expand_macro(AstCall** pcall, AstFunction* template); +AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* callsite); AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos); diff --git a/modules/immediate_mode/immediate_renderer.onyx b/modules/immediate_mode/immediate_renderer.onyx index c0bdcf28..81756646 100644 --- a/modules/immediate_mode/immediate_renderer.onyx +++ b/modules/immediate_mode/immediate_renderer.onyx @@ -520,7 +520,7 @@ apply_transform :: (transform: Transform) do global_renderer->apply_transform(tr -save_matrix :: #code { +save_matrix :: macro () { I :: package immediate_mode I.push_matrix(); defer I.pop_matrix(); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index dfe01802..86425546 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -444,12 +444,13 @@ static CheckStatus check_resolve_callee(AstCall* call, AstTyped** effective_call 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); @@ -702,7 +703,7 @@ type_checking_done: 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; } @@ -1764,7 +1765,14 @@ CheckStatus check_insert_directive(AstDirectiveInsert** pinsert) { 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); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 89b6d488..0372ee89 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -1158,6 +1158,9 @@ static SymresStatus symres_macro(AstMacro* macro) { if (macro->body->kind == Ast_Kind_Function) { SYMRES(function_header, (AstFunction *) macro->body); } + else if (macro->body->kind == Ast_Kind_Polymorphic_Proc) { + SYMRES(polyproc, (AstPolyProc *) macro->body); + } return Symres_Success; } diff --git a/src/onyxutils.c b/src/onyxutils.c index cebbc890..3ab680a5 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -729,10 +729,11 @@ static void solve_for_polymorphic_param_value(PolySolveResult* resolved, AstPoly 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, @@ -783,10 +784,7 @@ static bh_arr(AstPolySolution) find_polymorphic_slns(AstPolyProc* pp, PolyProcLo 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: @@ -968,6 +966,7 @@ AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupM 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; } @@ -1205,12 +1204,11 @@ void report_unable_to_match_overload(AstCall* call) { // // // 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); @@ -1232,10 +1230,82 @@ void expand_macro(AstCall** pcall) { (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 //