fixed a couple of very annoying bugs
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 15 Nov 2021 15:28:48 +0000 (09:28 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 15 Nov 2021 15:28:48 +0000 (09:28 -0600)
core/container/iter.onyx
include/astnodes.h
src/checker.c
src/clone.c
src/polymorph.c
src/symres.c
src/wasm_emit.c
tests/lazy_iterators
tests/lazy_iterators.onyx

index fc508515a76653d9c9520c785784fac386e2739b..cb9b372a3ed3eb3f01d6368650096764d243de2e 100644 (file)
@@ -22,7 +22,7 @@ filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
     filter_iterator.iterator = it;
     filter_iterator.predicate = predicate;
 
-    next :: ($T: type_expr, fi: ^FilterIterator(T)) -> (T, bool) {
+    next :: (fi: ^FilterIterator($T)) -> (T, bool) {
         value, cont := fi.iterator.next(fi.iterator.data);
         if cont {
             while !fi.predicate(value) {
@@ -36,7 +36,7 @@ filter :: (it: Iterator($T), predicate: (T) -> bool) -> Iterator(T) {
         }
     }
 
-    close :: ($T: type_expr, fi: ^FilterIterator(T)) {
+    close :: (fi: ^FilterIterator($T)) {
         if fi.iterator.close != null_proc do fi.iterator.close(fi.iterator.data);
         cfree(fi);
     }
@@ -58,14 +58,14 @@ map :: (it: Iterator($T), transform: (T) -> $R) -> Iterator(R) {
     map_iterator.iterator = it;
     map_iterator.transform = transform;
 
-    next :: ($T: type_expr, $R: type_expr, mi: ^MapIterator(T, R)) -> (R, bool) {
+    next :: (mi: ^MapIterator($T, $R)) -> (R, bool) {
         value, cont := mi.iterator.next(mi.iterator.data);
         if !cont do return __zero_value(R), false;
 
         return mi.transform(value), true;
     }
 
-    close :: ($T: type_expr, $R: type_expr, mi: ^MapIterator(T, R)) {
+    close :: (mi: ^MapIterator($T, $R)) {
         if mi.iterator.close != null_proc do mi.iterator.close(mi.iterator.data);
         cfree(mi);
     }
index 277a01866b7f20217398355953cf855cd4a93a85..64a620dd8ec0f7d0946019815cb7de49d935a5d9 100644 (file)
@@ -951,7 +951,6 @@ struct AstFunction {
 
     char* name;
 
-
     // NOTE: This is NULL, unless this function was generated from a polymorphic
     // procedure call. Then it is set to the token of the call node.
     OnyxToken* generated_from;
index bb586666f7b93a457c7b9df2456b7b3bc46f465a..e03fe86e53c75637735d2df3fa19809ee46c17d2 100644 (file)
@@ -1926,7 +1926,7 @@ CheckStatus check_function(AstFunction* func) {
     if (func->flags & Ast_Flag_Has_Been_Checked) return Check_Success;
     if (func->entity_header && func->entity_header->state < Entity_State_Code_Gen)
         YIELD(func->token->pos, "Waiting for procedure header to pass type-checking");
-    
+
     expected_return_type = &func->type->Function.return_type;
     if (func->body) {
         CheckStatus status = check_block(func->body);
index 753a23e4a3305494a404681a16e3d0d939793222..b1411deb27fa29f75a81d830696c5c7cb6639210 100644 (file)
@@ -162,6 +162,7 @@ AstNode* ast_clone(bh_allocator a, void* n) {
             break;
 
         case Ast_Kind_Call:
+            C(AstCall, callee);
             arguments_deep_clone(a, &((AstCall *) nn)->args, &((AstCall *) node)->args);
             break;
 
@@ -404,6 +405,7 @@ AstNode* ast_clone(bh_allocator a, void* n) {
             AstFunction* sf = (AstFunction *) node;
 
             if (sf->is_foreign) return node;
+            assert(df->scope == NULL);
 
             df->return_type = (AstType *) ast_clone(a, sf->return_type);
             df->body = (AstBlock *) ast_clone(a, sf->body);
@@ -524,6 +526,7 @@ AstFunction* clone_function_header(bh_allocator a, AstFunction* func) {
 
     AstFunction* new_func = onyx_ast_node_new(a, sizeof(AstFunction), func->kind);
     memmove(new_func, func, sizeof(AstFunction));
+    assert(new_func->scope == NULL);
 
     new_func->return_type = (AstType *) ast_clone(a, func->return_type);
 
index 51f6da592f0f7b87195d133a2ab208503e649513..dd3c6dff70f8674724f4bd28cbc2e98d457ba525 100644 (file)
@@ -20,11 +20,8 @@ static b32 doing_nested_polymorph_lookup = 0;
 AstTyped node_that_signals_a_yield = { Ast_Kind_Function, 0 };
 
 static void ensure_polyproc_cache_is_created(AstPolyProc* pp) {
-    if (pp->concrete_funcs == NULL) {
-        bh_table_init(global_heap_allocator, pp->concrete_funcs, 16);
-
-        bh_imap_init(&pp->active_queries, global_heap_allocator, 31);
-    }
+    if (pp->concrete_funcs == NULL)        bh_table_init(global_heap_allocator, pp->concrete_funcs, 16);
+    if (pp->active_queries.hashes == NULL) bh_imap_init(&pp->active_queries, global_heap_allocator, 31);
 }
 
 void insert_poly_sln_into_scope(Scope* scope, AstPolySolution *sln) {
@@ -102,32 +99,32 @@ static char* build_poly_slns_unique_key(bh_arr(AstPolySolution) slns) {
 // NOTE: This function adds a solidified function to the entity heap for it to be processed
 // later. It optionally can start the function header entity at the code generation state if
 // the header has already been processed.
-static b32 add_solidified_function_entities(AstSolidifiedFunction solidified_func) {
-    solidified_func.func->flags |= Ast_Flag_Function_Used;
-    solidified_func.func->flags |= Ast_Flag_From_Polymorphism;
+static b32 add_solidified_function_entities(AstSolidifiedFunction *solidified_func) {
+    solidified_func->func->flags |= Ast_Flag_Function_Used;
+    solidified_func->func->flags |= Ast_Flag_From_Polymorphism;
 
     Entity func_header_entity = {
         .state = Entity_State_Resolve_Symbols,
         .type = Entity_Type_Function_Header,
-        .function = solidified_func.func,
+        .function = solidified_func->func,
         .package = NULL,
-        .scope = solidified_func.func->poly_scope,
+        .scope = solidified_func->func->poly_scope,
     };
 
     Entity func_entity = {
         .state = Entity_State_Resolve_Symbols,
         .type = Entity_Type_Function,
-        .function = solidified_func.func,
+        .function = solidified_func->func,
         .package = NULL,
-        .scope = solidified_func.func->poly_scope,
+        .scope = solidified_func->func->poly_scope,
     };
 
     Entity* entity_header = entity_heap_insert(&context.entities, func_header_entity);
     Entity* entity_body   = entity_heap_insert(&context.entities, func_entity);
 
-    solidified_func.func_header_entity  = entity_header;
-    solidified_func.func->entity_header = entity_header;
-    solidified_func.func->entity_body   = entity_body;
+    solidified_func->func_header_entity  = entity_header;
+    solidified_func->func->entity_header = entity_header;
+    solidified_func->func->entity_body   = entity_body;
 
     return 1;
 }
@@ -179,9 +176,9 @@ static AstSolidifiedFunction generate_solidified_function(
     return solidified_func;
 }
 
-static void ensure_solidified_function_has_body(AstPolyProc* pp, AstSolidifiedFunction solidified_func) {
-    if (solidified_func.func->flags & Ast_Flag_Incomplete_Body) {
-        clone_function_body(context.ast_alloc, solidified_func.func, pp->base_func);
+static void ensure_solidified_function_has_body(AstPolyProc* pp, AstSolidifiedFunction *solidified_func) {
+    if (solidified_func->func->flags & Ast_Flag_Incomplete_Body) {
+        clone_function_body(context.ast_alloc, solidified_func->func, pp->base_func);
 
         // HACK: I'm asserting that this function should return without an error, because
         // the only case where it can return an error is if there was a problem with the
@@ -190,7 +187,7 @@ static void ensure_solidified_function_has_body(AstPolyProc* pp, AstSolidifiedFu
         // procedure.
         assert(add_solidified_function_entities(solidified_func));
 
-        solidified_func.func->flags &= ~Ast_Flag_Incomplete_Body;
+        solidified_func->func->flags &= ~Ast_Flag_Incomplete_Body;
     }
 }
 
@@ -633,6 +630,7 @@ TypeMatch find_polymorphic_sln(AstPolySolution *out, AstPolyParam *param, AstFun
 // solving for the polymorphic variables, in order to return an array of the solutions for all
 // of the polymorphic variables.
 static bh_arr(AstPolySolution) find_polymorphic_slns(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual, OnyxToken *tkn, b32 necessary) {
+    ensure_polyproc_cache_is_created(pp);
     if (bh_imap_has(&pp->active_queries, (u64) actual)) {
         AstPolyQuery *query = (AstPolyQuery *) bh_imap_get(&pp->active_queries, (u64) actual);
         assert(query->kind == Ast_Kind_Polymorph_Query);
@@ -662,6 +660,7 @@ static bh_arr(AstPolySolution) find_polymorphic_slns(AstPolyProc* pp, PolyProcLo
     query->slns = slns;
     query->function_header = clone_function_header(context.ast_alloc, pp->base_func);
     query->function_header->flags |= Ast_Flag_Header_Check_No_Error;
+    query->function_header->scope = NULL;
     query->error_on_fail = necessary;
     query->successful_symres = 1;
 
@@ -703,7 +702,7 @@ AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
         // NOTE: If this solution was originally created from a "build_only_header" call, then the body
         // will not have been or type checked, or anything. This ensures that the body is copied, the
         // entities are created and entered into the pipeline.
-        ensure_solidified_function_has_body(pp, solidified_func);
+        ensure_solidified_function_has_body(pp, &solidified_func);
 
         // NOTE: Again, if this came from a "build_only_header" call, then there was no known token and
         // the "generated_from" member will be null. It is best to set it here so errors reported in that
@@ -715,12 +714,11 @@ AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
     }
 
     AstSolidifiedFunction solidified_func = generate_solidified_function(pp, slns, tkn, 0);
+    add_solidified_function_entities(&solidified_func);
 
     // NOTE: Cache the function for later use, reducing duplicate functions.
     bh_table_put(AstSolidifiedFunction, pp->concrete_funcs, unique_key, solidified_func);
 
-    add_solidified_function_entities(solidified_func);
-
     return (AstFunction *) &node_that_signals_a_yield;
 }
 
@@ -757,7 +755,7 @@ AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
         // made it through the symbol resolution phase.
         //                                                    - brendanfh 2020/12/25
         AstPolyProc* new_pp = onyx_ast_node_new(context.ast_alloc, sizeof(AstPolyProc), Ast_Kind_Polymorphic_Proc);
-        new_pp->token = pp->token;                            // TODO: Change this to be the solidify->token
+        new_pp->token = tkn;
         new_pp->base_func = pp->base_func;
         new_pp->flags = pp->flags;
         new_pp->poly_params = pp->poly_params;
index 85690d2e829ac7479f9c3a64ac2b3cecd323be38..12ad701cf8cee185d14bb660d33c18e75ef7b1e3 100644 (file)
@@ -917,7 +917,7 @@ SymresStatus symres_function_header(AstFunction* func) {
 
     bh_arr_each(AstParam, param, func->params) {
         symbol_introduce(curr_scope, param->local->token, (AstNode *) param->local);
-        
+
         if (param->local->type_node != NULL) {
             SYMRES(type, &param->local->type_node);
         }
@@ -943,9 +943,8 @@ SymresStatus symres_function_header(AstFunction* func) {
 }
 
 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;
+    assert(func->scope);
 
     scope_enter(func->scope);
 
@@ -1319,11 +1318,7 @@ static SymresStatus symres_polyquery(AstPolyQuery *query) {
 }
 
 void symres_entity(Entity* ent) {
-    Scope* old_scope = NULL;
-    if (ent->scope) {
-        old_scope = curr_scope;
-        scope_enter(ent->scope);
-    }
+    if (ent->scope) scope_enter(ent->scope);
 
     report_unresolved_symbols = context.cycle_detected;
                                 //(context.entities.type_count[Entity_Type_Static_If] == 0 &&
@@ -1380,5 +1375,5 @@ void symres_entity(Entity* ent) {
         ent->state = next_state;
     }
 
-    if (ent->scope) curr_scope = old_scope;
+    curr_scope = NULL;
 }
index 5589cb7edf5e4331997db34c97eb8f4527ab76a7..850050f08e44e8284e5f9a6b0c305afc02edd0c7 100644 (file)
@@ -2545,12 +2545,14 @@ EMIT_FUNC(expression, AstTyped* expr) {
                         fori (idx, 0, mem_count) WIL(WI_LOCAL_GET, localidx + idx);
 
                     } else {
+                        assert(localidx & LOCAL_IS_WASM);
                         WIL(WI_LOCAL_GET, localidx);
                     }
                     break;
                 }
 
                 case Param_Pass_By_Implicit_Pointer: {
+                    assert(localidx & LOCAL_IS_WASM);
                     WIL(WI_LOCAL_GET, localidx);
                     emit_load_instruction(mod, &code, expr->type, 0);
                     break;
@@ -2682,6 +2684,7 @@ EMIT_FUNC(expression, AstTyped* expr) {
             if (field->expr->kind == Ast_Kind_Param) {
                 if (type_get_param_pass(field->expr->type) == Param_Pass_By_Value && !type_is_pointer(field->expr->type)) {
                     u64 localidx = bh_imap_get(&mod->local_map, (u64) field->expr) + field->idx;
+                    assert(localidx & LOCAL_IS_WASM);
                     WIL(WI_LOCAL_GET, localidx);
                     break;
                 }
index 2c7ab48d001adb3abcb124139d15df6892071d52..24126473185884cf6f97f88cd4c6473fa0ec5dc4 100644 (file)
@@ -1,9 +1,9 @@
 Closing the count iterator...
-54
-56
-58
-60
-62
+54.0000
+56.0000
+58.0000
+60.0000
+62.0000
 Starting the iteration...
 54
 56
index 700bf1b5a9e84a571edb6153f558bce876add716..7eb274a6829a828bc9ea16fa002b833c5c87a50f 100644 (file)
@@ -2,9 +2,8 @@
 
 use package core
 
-count_iterator :: (lo: i32, hi: i32, step := 1) -> Iterator(i32) {
-    next :: (data: rawptr) -> (i32, bool) {
-        ci := cast(^CountIterator) data;
+count_iterator :: (lo: $T, hi: T, step: T = 1) -> Iterator(T) {
+    next :: (ci: ^CountIterator($T)) -> (T, bool) {
         if ci.current > ci.high do return 0, false;
 
         defer ci.current += ci.step;
@@ -16,36 +15,39 @@ count_iterator :: (lo: i32, hi: i32, step := 1) -> Iterator(i32) {
         cfree(data);
     }
 
-    CountIterator :: struct {
-        low, high, step: i32;
-        current: i32;
+    CountIterator :: struct (T:type_expr) {
+        low, high, step: T;
+        current: T;
     }
 
-    count_iterator := new(CountIterator);
+    count_iterator := new(CountIterator(T));
     count_iterator.low = lo;
     count_iterator.high = hi;
     count_iterator.step = step;
     count_iterator.current = lo;
 
     return .{
-        data = count_iterator,
-        next = next,
+        data  = count_iterator,
+        next  = #solidify next {T=T},
         close = close,
     };
 }
 
 main :: (args: [] cstr) {
     // Hopefully soon, the following will be possible.
-    quick_iterator :=
-                count_iterator(1, 10)
-                |> iter.map((x) => x * 2)
-                |> iter.filter((x) => x > 10)
-                |> iter.map((x) => x + 42)
-                |> iter.take(5)
-                |> iter.to_array();
-
-    for v: quick_iterator {
-        println(v);
+
+    {
+        quick_iterator :=
+                    count_iterator(1.0f, 10.0f)
+                    |> iter.map((x) => x * 2)
+                    |> iter.filter((x) => x > 10)
+                    |> iter.map((x) => x + 42)
+                    |> iter.take(5)
+                    |> iter.to_array();
+
+        for v: quick_iterator {
+            println(v);
+        }
     }
 
     iterator := count_iterator(1, 10)