macros working! needs a lot of cleanup however
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 12 Aug 2021 19:30:40 +0000 (14:30 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 12 Aug 2021 19:30:40 +0000 (14:30 -0500)
bin/onyx
core/container/bucket_array.onyx
include/onyxastnodes.h
modules/immediate_mode/immediate_renderer.onyx
src/onyxchecker.c
src/onyxsymres.c
src/onyxutils.c

index aa21c0e3226919004132157e66201ee23689a301..5d1db354bbb530e15b69912db51f024ff3d0d445 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 367e3f4f1a13c959232cb34b92d49ee613f3f058..10a22d161f0062ab90ba1e420682ec53b9fe6ddc 100644 (file)
@@ -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 };
 }
index f412e13740e3d8a7127435632ce95043a3be70fb..aa4985321457f6a62625f9223f1207d4186b25db 100644 (file)
@@ -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);
 
index c0bdcf282f23e4a7333b119c2e7c1ad28ab97ac1..81756646fc66f00fd80e68b5c840770e06944c12 100644 (file)
@@ -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();
index dfe018022de73af1c672295e6cf544d5c4430c3a..8642554676081f3a011d8255a628de3baa298171 100644 (file)
@@ -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);
 
index 89b6d4883b7943177551e89dbcace7d3ec9521ef..0372ee89532cd19adf8d0d79c5563dbb03d4b97f 100644 (file)
@@ -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;
 }
index cebbc890d99e0745a595d6898146f98df24e8324..3ab680a5d28088d9e8dbd8af5f3e727b56a8400e 100644 (file)
@@ -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
 //