polymorphic procedures are allowed in overloaded functions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 11 Jan 2021 05:39:30 +0000 (23:39 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 11 Jan 2021 05:39:30 +0000 (23:39 -0600)
14 files changed:
bin/onyx
core/alloc.onyx
core/memory.onyx
include/onyxastnodes.h
include/onyxerrors.h
onyx.exe
src/onyx.c
src/onyxchecker.c
src/onyxclone.c
src/onyxerrors.c
src/onyxsymres.c
src/onyxutils.c
src/onyxwasm.c
tests/aoc-2020/day23.onyx

index 23dd19cdf4c5e69a038d7aded1025d5ee3c6a5c3..42c02224c1b6319f5943955013b0a329dca35dd6 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index d6c47662b349b2b5658e85bf57fea9d5d226079b..792e497c41c81b09c151b43a27000ca69cb13d55 100644 (file)
@@ -15,12 +15,6 @@ heap_allocator : Allocator;
 temp_state     : ring.RingState;
 temp_allocator : Allocator;
 
-
-alloc_slice :: proc (sl: ^[] $T, count: i32) {
-    sl.data  = calloc(sizeof T * count);
-    sl.count = count;
-}
-
 init :: proc () {
     heap.init();
 
index da952cbe3cb9522c97c493c54b82670c0e7719f5..fd7f0805233f3f1d8ba09a9908920e855b519984 100644 (file)
@@ -10,3 +10,8 @@ set :: proc (start: rawptr, length: u32, value: u8) {
     s := cast(^u8) start;
     for i: 0 .. length do s[i] = value;
 }
+
+alloc_slice :: proc (sl: ^[] $T, count: i32) {
+    sl.data  = calloc(sizeof T * count);
+    sl.count = count;
+}
\ No newline at end of file
index 113f92327eeb3049e5853f63d8f44fa036ddae40..a2ff911595206f959b075635af5d042bc2eca5c8 100644 (file)
@@ -201,6 +201,8 @@ typedef enum AstFlags {
 
     // HACK: NullProcHack
     Ast_Flag_Proc_Is_Null          = BH_BIT(22),
+
+    Ast_Flag_From_Polymorphism     = BH_BIT(23),
 } AstFlags;
 
 typedef enum UnaryOp {
@@ -954,10 +956,14 @@ void initialize_builtins(bh_allocator a, ProgramInfo* prog);
 // NOTE: Useful not inlined functions
 AstTyped* ast_reduce(bh_allocator a, AstTyped* node);
 AstNode* ast_clone(bh_allocator a, void* n);
+AstFunction* clone_function_header(bh_allocator a, AstFunction* func);
+
 void promote_numlit_to_larger(AstNumLit* num);
 b32 convert_numlit_to_type(AstNumLit* num, Type* type);
+
 b32 type_check_or_auto_cast(AstTyped** pnode, Type* type);
 Type* resolve_expression_type(AstTyped* node);
+
 b32 cast_is_legal(Type* from_, Type* to_, char** err_msg);
 char* get_function_name(AstFunction* func);
 
@@ -970,10 +976,12 @@ AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field);
 typedef enum PolyProcLookupMethod {
     PPLM_By_Call,
     PPLM_By_Function_Type,
+    PPLM_By_Value_Array,
 } PolyProcLookupMethod;
 AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual, OnyxFilePos pos);
 AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) slns, OnyxFilePos pos);
 AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution) slns, OnyxFilePos pos);
+AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual);
 
 
 AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos);
index dcc2fbfad4dd03bb2085a082290904c154508bdc..7b544619a1ab7749d38db5130321ebdb41feaa31 100644 (file)
@@ -30,5 +30,6 @@ void onyx_errors_init(bh_table(bh_file_contents)* files);
 void onyx_report_error(OnyxFilePos pos, char * format, ...);
 void onyx_errors_print();
 b32  onyx_has_errors();
+void onyx_clear_errors();
 
 #endif
index d9206455fd119e4ad0aae6de39ff40cbf1f2c618..117b2fcae117a119dfb7a1c4c275b7eeb06ad25e 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index 852129e768a1e09b904938921f92d69308897d9b..67164bac677558fce37865d5f6da7855c629bf21 100644 (file)
@@ -345,13 +345,14 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res
                 break;
             }
 
-            case Ast_Kind_Struct_Type:
-            case Ast_Kind_Poly_Struct_Type: {
+            case Ast_Kind_Struct_Type: {
                 ent.type = Entity_Type_Struct_Member_Default;
                 ent.type_alias = (AstType *) node;
                 entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 // fallthrough
             }
+
+            case Ast_Kind_Poly_Struct_Type:
             case Ast_Kind_Type_Alias: {
                 ent.type = Entity_Type_Type_Alias;
                 ent.type_alias = (AstType *) node;
index 90d7b607dca6da27bd712cb06dc96b23f0e363f3..70f29ac417eef4a4fa857d149141a5831a0358e1 100644 (file)
@@ -45,6 +45,7 @@ CheckStatus check_struct(AstStructType* s_node);
 CheckStatus check_function_header(AstFunction* func);
 CheckStatus check_memres_type(AstMemRes* memres);
 CheckStatus check_memres(AstMemRes* memres);
+CheckStatus check_type_alias(AstTypeAlias* type_alias);
 
 static inline void fill_in_type(AstTyped* node);
 
@@ -295,12 +296,19 @@ CheckStatus check_switch(AstSwitch* switchnode) {
 }
 static AstTyped* match_overloaded_function(bh_arr(AstTyped *) arg_arr, bh_arr(AstTyped *) overloads) {
     bh_arr_each(AstTyped *, node, overloads) {
-        AstFunction* overload = (AstFunction *) *node;
+        AstFunction* overload = NULL;
+        if ((*node)->kind == Ast_Kind_Function) {
+            overload = (AstFunction *) *node;
+        }
+        else if ((*node)->kind == Ast_Kind_Polymorphic_Proc) {
+            overload = polymorphic_proc_build_only_header((AstPolyProc *) *node, PPLM_By_Value_Array, arg_arr);
+        }
+
+        if (overload == NULL) continue;
 
         fill_in_type((AstTyped *) overload);
 
         TypeFunction* ol_type = &overload->type->Function;
-
         if (bh_arr_length(arg_arr) < (i32) ol_type->needed_param_count) continue;
 
         Type** param_type = ol_type->params;
@@ -320,7 +328,7 @@ static AstTyped* match_overloaded_function(bh_arr(AstTyped *) arg_arr, bh_arr(As
             param_type++;
         }
 
-        return (AstTyped *) overload;
+        return (AstTyped *) *node;
 
 no_match:
         continue;
@@ -356,6 +364,7 @@ CheckStatus check_call(AstCall* call) {
     // NOTE: Check arguments
     bh_arr_each (AstArgument *, actual, arg_arr) {
         CHECK(expression, (AstTyped **) actual);
+        (*actual)->type = (*actual)->value->type;
 
         if ((*actual)->value->kind == Ast_Kind_Overloaded_Function) {
             onyx_report_error((*actual)->token->pos,
@@ -1467,8 +1476,8 @@ CheckStatus check_overloaded_function(AstOverloadedFunction* func) {
             return Check_Error;
         }
 
-        if ((*node)->kind != Ast_Kind_Function) {
-            onyx_report_error((*node)->token->pos, "Overload option not function. Got '%s'",
+        if ((*node)->kind != Ast_Kind_Function && (*node)->kind != Ast_Kind_Polymorphic_Proc) {
+            onyx_report_error((*node)->token->pos, "Overload option not procedure. Got '%s'",
                 onyx_ast_node_kind_string((*node)->kind));
 
             return Check_Error;
@@ -1621,6 +1630,22 @@ CheckStatus check_memres(AstMemRes* memres) {
     return Check_Success;
 }
 
+CheckStatus check_type_alias(AstTypeAlias* type_alias) {
+    AstType* to = type_alias->to;
+
+    if (to->kind == Ast_Kind_Poly_Call_Type) {
+        AstPolyCallType* pc_node = (AstPolyCallType *) to;
+        bh_arr_each(AstNode *, param, pc_node->params) {
+            if (!node_is_type(*param)) {
+                CHECK(expression, (AstTyped **) param);
+                resolve_expression_type((AstTyped *) *param);
+            }
+        }
+    }
+
+    return Check_Success;
+}
+
 CheckStatus check_node(AstNode* node) {
     switch (node->kind) {
         case Ast_Kind_Function:             return check_function((AstFunction *) node);
@@ -1668,6 +1693,8 @@ void check_entity(Entity* ent) {
         case Entity_Type_Type_Alias:
             if (ent->type_alias->kind == Ast_Kind_Struct_Type)
                 cs = check_struct((AstStructType *) ent->type_alias);
+            else if (ent->type_alias->kind == Ast_Kind_Type_Alias)
+                check_type_alias((AstTypeAlias *) ent->type_alias);
             break;
 
         case Entity_Type_Memory_Reservation_Type:
index 9d04ebe611626547c83314bd6bb255e359e6e5ce..dcb73be119a527217856b75dcd1b07a1f7816535 100644 (file)
@@ -411,3 +411,26 @@ AstNode* ast_clone(bh_allocator a, void* n) {
 
        return nn;
 }
+
+AstFunction* clone_function_header(bh_allocator a, AstFunction* func) {
+    if (func->kind != Ast_Kind_Function) return NULL;
+
+    if (func->flags & Ast_Flag_Foreign) return func;
+
+    AstFunction* new_func = onyx_ast_node_new(a, sizeof(AstFunction), func->kind);
+    memmove(new_func, func, sizeof(AstFunction));
+
+    new_func->return_type = (AstType *) ast_clone(a, func->return_type);
+
+    new_func->params = NULL;
+    bh_arr_new(global_heap_allocator, new_func->params, bh_arr_length(func->params));
+    bh_arr_each(AstParam, param, func->params) {
+        AstParam new_param;
+        new_param.local = (AstLocal *) ast_clone(a, param->local);
+        new_param.default_value = (AstTyped *) ast_clone(a, param->default_value);
+        new_param.vararg_kind = param->vararg_kind;
+        bh_arr_push(new_func->params, new_param);
+    }
+
+    return new_func;
+}
\ No newline at end of file
index ed8bc702fdf7dd0f857d90f29f4bf92bec21fe75..682f37c909c1b3b7d791d476c6ea3b429958d9c3 100644 (file)
@@ -71,3 +71,8 @@ void onyx_errors_print() {
 b32 onyx_has_errors() {
     return bh_arr_length(errors.errors) > 0;
 }
+
+void onyx_clear_errors() {
+    bh_printf("ERRORS WERE CLEARED!!!\n");
+    bh_arr_set_length(errors.errors, 0);
+}
\ No newline at end of file
index 77edbbebd77aa740cfe89e2eb5187fcf8cc7b57f..9fbf29c689cc538542abc2186e557c0ebdec583a 100644 (file)
@@ -643,7 +643,7 @@ void symres_function_header(AstFunction* func) {
         }
     }
 
-    if (func->operator_overload != (BinaryOp) -1) {
+    if ((func->flags & Ast_Flag_From_Polymorphism) == 0 && func->operator_overload != (BinaryOp) -1) {
         if (bh_arr_length(func->params) != 2) {
             onyx_report_error(func->token->pos, "Expected 2 exactly arguments for binary operator overload.");
         }
@@ -831,6 +831,18 @@ static void symres_struct_defaults(AstType* t) {
 
 static void symres_polyproc(AstPolyProc* pp) {
     pp->poly_scope = semstate.curr_scope;
+
+    if (pp->base_func->operator_overload != (BinaryOp) -1) {
+        if (bh_arr_length(pp->base_func->params) != 2) {
+            onyx_report_error(pp->base_func->token->pos, "Expected 2 exactly arguments for binary operator overload.");
+        }
+
+        if (binop_is_assignment(pp->base_func->operator_overload)) {
+            onyx_report_error(pp->base_func->token->pos, "'%s' is not currently overloadable.", binaryop_string[pp->base_func->operator_overload]);
+        }
+
+        bh_arr_push(operator_overloads[pp->base_func->operator_overload], (AstTyped *) pp);
+    }
 }
 
 void symres_entity(Entity* ent) {
index f6eab9bb729ce3714532783643ab4439be7001d7..efd2a486ef8d77b8d86757f375c3e5a27ca08cfa 100644 (file)
@@ -329,11 +329,7 @@ static PolySolveResult solve_poly_type(AstNode* target, AstType* type_expr, Type
     return result;
 }
 
-AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual, OnyxFilePos pos) {
-    if (pp->concrete_funcs == NULL) {
-        bh_table_init(global_heap_allocator, pp->concrete_funcs, 8);
-    }
-
+static bh_arr(AstPolySolution) find_polymorphic_slns(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual, char** err_msg) {
     bh_arr(AstPolySolution) slns = NULL;
     bh_arr_new(global_heap_allocator, slns, bh_arr_length(pp->poly_params));
 
@@ -353,39 +349,50 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
 
         if (pp_lookup == PPLM_By_Call) {
             if (param->idx >= ((AstCall *) actual)->arg_count) {
-                onyx_report_error(pos, "Not enough arguments to polymorphic procedure.");
-                return NULL;
+                if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure.";
+                goto sln_not_found;
             }
 
             bh_arr(AstArgument *) arg_arr = ((AstCall *) actual)->arg_arr;
             actual_type = resolve_expression_type(arg_arr[param->idx]->value);
         }
 
+        else if (pp_lookup == PPLM_By_Value_Array) {
+            bh_arr(AstTyped *) arg_arr = (bh_arr(AstTyped *)) actual;
+
+            if ((i32) param->idx >= bh_arr_length(arg_arr)) {
+                if (err_msg) *err_msg = "Not enough arguments to polymorphic procedure.";
+                goto sln_not_found;
+            }
+
+            actual_type = resolve_expression_type(arg_arr[param->idx]);
+        }
+
         else if (pp_lookup == PPLM_By_Function_Type) {
             Type* ft = (Type*) actual;
             if (param->idx >= ft->Function.param_count) {
-                onyx_report_error(pos, "Incompatible polymorphic argument to function paramter.");
-                return NULL;
+                if (err_msg) *err_msg = "Incompatible polymorphic argument to function paramter.";
+                goto sln_not_found;
             }
 
             actual_type = ft->Function.params[param->idx];
         }
 
         else {
-            onyx_report_error(pos, "Cannot resolve polymorphic function type.");
-            return NULL;
+            if (err_msg) *err_msg = "Cannot resolve polymorphic function type.";
+            goto sln_not_found;
         }
 
         PolySolveResult resolved = solve_poly_type(param->poly_sym, param->type_expr, actual_type);
 
         switch (resolved.kind) {
             case PSK_Undefined:
-                onyx_report_error(pos,
+                if (err_msg) *err_msg = bh_aprintf(global_heap_allocator,
                     "Unable to solve for polymoprhic variable '%b', using the type '%s'.",
                     param->poly_sym->token->text,
                     param->poly_sym->token->length,
                     type_get_name(actual_type));
-                return NULL;
+                goto sln_not_found;
 
             case PSK_Type:
                 bh_arr_push(slns, ((AstPolySolution) {
@@ -405,6 +412,25 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
         }
     }
 
+    return slns;
+
+sln_not_found:
+    bh_arr_free(slns);
+    return NULL;
+}
+
+AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual, OnyxFilePos pos) {
+    if (pp->concrete_funcs == NULL) {
+        bh_table_init(global_heap_allocator, pp->concrete_funcs, 8);
+    }
+
+    char *err_msg = NULL;
+    bh_arr(AstPolySolution) slns = find_polymorphic_slns(pp, pp_lookup, actual, &err_msg);
+    if (slns == NULL) {
+        if (err_msg != NULL) onyx_report_error(pos, err_msg);
+        else                 onyx_report_error(pos, "Some kind of error occured when generating a polymorphic procedure. You hopefully will not see this");
+    }
+
     AstFunction* result = polymorphic_proc_solidify(pp, slns, pos);
     
     bh_arr_free(slns);
@@ -476,6 +502,7 @@ AstFunction* polymorphic_proc_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
     bh_table_put(AstFunction *, pp->concrete_funcs, unique_key, func);
 
     func->flags |= Ast_Flag_Function_Used;
+    func->flags |= Ast_Flag_From_Polymorphism;
 
     Entity func_header_entity = {
         .state = Entity_State_Resolve_Symbols,
@@ -559,6 +586,36 @@ AstNode* polymorphic_proc_try_solidify(AstPolyProc* pp, bh_arr(AstPolySolution)
     }
 }
 
+AstFunction* polymorphic_proc_build_only_header(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual) {
+    bh_arr(AstPolySolution) slns = find_polymorphic_slns(pp, pp_lookup, actual, NULL);
+    if (slns == NULL) return NULL;
+
+    Scope* poly_scope = scope_create(semstate.node_allocator, pp->poly_scope, (OnyxFilePos) { 0 });
+    insert_poly_slns_into_scope(poly_scope, slns);
+
+    // 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
+    AstFunction* new_func = clone_function_header(semstate.node_allocator, pp->base_func);
+    new_func->flags |= Ast_Flag_From_Polymorphism;
+
+    Entity func_header_entity = {
+        .state = Entity_State_Resolve_Symbols,
+        .type = Entity_Type_Function_Header,
+        .function = new_func,
+        .package = NULL,
+        .scope = poly_scope,
+    };
+
+    entity_bring_to_state(&func_header_entity, Entity_State_Code_Gen);
+    if (onyx_has_errors()) {
+        onyx_clear_errors();
+        return NULL;
+    }
+
+    return new_func;
+}
+
 char* build_poly_struct_name(AstPolyStructType* ps_type, Type* cs_type) {
     char name_buf[256];
     fori (i, 0, 256) name_buf[i] = 0;
index e1837dd736758aa055239e415136296cf6ee5f0c..57bf4e87fe5d8b8e25ca30b7882a8b6df1105d56 100644 (file)
@@ -209,6 +209,7 @@ EMIT_FUNC(struct_load,                   Type* type, u64 offset);
 EMIT_FUNC(struct_lval,                   AstTyped* lval);
 EMIT_FUNC(struct_store,                  Type* type, u64 offset);
 EMIT_FUNC(struct_literal,                AstStructLiteral* sl);
+EMIT_FUNC(array_store,                   Type* type, u32 offset);
 EMIT_FUNC(array_literal,                 AstArrayLiteral* al);
 EMIT_FUNC(range_literal,                 AstRangeLiteral* range);
 EMIT_FUNC(expression,                    AstTyped* expr);
@@ -394,15 +395,15 @@ EMIT_FUNC(assignment_of_array, AstBinaryOp* assign) {
     Type* rtype = assign->right->type;
     assert(rtype->kind == Type_Kind_Array);
 
-    Type* elem_type = rtype;
-    u32 elem_count = 1;
-    while (elem_type->kind == Type_Kind_Array) {
-        elem_count *= elem_type->Array.count;
-        elem_type = elem_type->Array.elem;
-    }
-    u32 elem_size = type_size_of(elem_type);
-
     if (assign->right->kind == Ast_Kind_Array_Literal) {
+        Type* elem_type = rtype;
+        u32 elem_count = 1;
+        while (elem_type->kind == Type_Kind_Array) {
+            elem_count *= elem_type->Array.count;
+            elem_type = elem_type->Array.elem;
+        }
+        u32 elem_size = type_size_of(elem_type);
+
         u64 lptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
 
         emit_location(mod, &code, assign->left);
@@ -426,39 +427,9 @@ EMIT_FUNC(assignment_of_array, AstBinaryOp* assign) {
         local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
 
     } else {
-        u64 lptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
-        u64 rptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
-
         emit_location(mod, &code, assign->left);
-        WIL(WI_LOCAL_SET, lptr_local);
-
         emit_expression(mod, &code, assign->right);
-        WIL(WI_LOCAL_SET, rptr_local);
-
-        // NOTE: Currently, we inline the copying of the array; But if the array has
-        // many elements, this could result in a LOT of instructions. Maybe for lengths
-        // greater than like 16 we output a loop that copies them?
-        //                                               - brendanfh 2020/12/16
-        fori (i, 0, elem_count) {
-            if (!type_is_structlike(elem_type))
-                WIL(WI_LOCAL_GET, lptr_local);
-
-            if (bh_arr_last(code).type == WI_LOCAL_SET && (u64) bh_arr_last(code).data.l == rptr_local)
-                bh_arr_last(code).type = WI_LOCAL_TEE;
-            else
-                WIL(WI_LOCAL_GET, rptr_local);
-            emit_load_instruction(mod, &code, elem_type, i * elem_size);
-
-            if (!type_is_structlike(elem_type)) {
-                emit_store_instruction(mod, &code, elem_type, i * elem_size);
-            } else {
-                WIL(WI_LOCAL_GET, lptr_local);
-                emit_store_instruction(mod, &code, elem_type, i * elem_size);
-            }
-        }
-
-        local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
-        local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+        emit_array_store(mod, &code, rtype, 0);
     }
 
     *pcode = code;
@@ -473,6 +444,11 @@ EMIT_FUNC(store_instruction, Type* type, u32 offset) {
         return;
     }
 
+    if (type->kind == Type_Kind_Array) {
+        emit_array_store(mod, pcode, type, offset);
+        return;
+    }
+
     if (type->kind == Type_Kind_Enum) {
         type = type->Enum.backing;
     }
@@ -1953,6 +1929,52 @@ EMIT_FUNC(struct_literal, AstStructLiteral* sl) {
     *pcode = code;
 }
 
+EMIT_FUNC(array_store, Type* type, u32 offset) {
+    assert(type->kind == Type_Kind_Array);
+    bh_arr(WasmInstruction) code = *pcode;
+
+    Type* elem_type = type;
+    u32 elem_count = 1;
+    while (elem_type->kind == Type_Kind_Array) {
+        elem_count *= elem_type->Array.count;
+        elem_type = elem_type->Array.elem;
+    }
+    u32 elem_size = type_size_of(elem_type);
+
+    u64 lptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+    u64 rptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+    WIL(WI_LOCAL_SET, rptr_local);
+    WIL(WI_LOCAL_SET, lptr_local);
+
+    // NOTE: Currently, we inline the copying of the array; But if the array has
+    // many elements, this could result in a LOT of instructions. Maybe for lengths
+    // greater than like 16 we output a loop that copies them?
+    //                                               - brendanfh 2020/12/16
+    fori (i, 0, elem_count) {
+        if (!type_is_structlike(elem_type))
+            WIL(WI_LOCAL_GET, lptr_local);
+
+        if (bh_arr_last(code).type == WI_LOCAL_SET && (u64) bh_arr_last(code).data.l == rptr_local)
+            bh_arr_last(code).type = WI_LOCAL_TEE;
+        else
+            WIL(WI_LOCAL_GET, rptr_local);
+        emit_load_instruction(mod, &code, elem_type, i * elem_size);
+
+        if (!type_is_structlike(elem_type)) {
+            emit_store_instruction(mod, &code, elem_type, i * elem_size + offset);
+        } else {
+            WIL(WI_LOCAL_GET, lptr_local);
+            emit_store_instruction(mod, &code, elem_type, i * elem_size + offset);
+        }
+    }
+
+    local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+    local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+
+    *pcode = code;
+    return;
+}
+
 EMIT_FUNC(array_literal, AstArrayLiteral* al) {
     bh_arr(WasmInstruction) code = *pcode;
 
@@ -2442,12 +2464,19 @@ EMIT_FUNC(stack_enter, u64 stacksize) {
     u64 stack_top_idx = bh_imap_get(&mod->index_map, (u64) &builtin_stack_top);
 
     // HACK: slightly... There will be space for 5 instructions
-    code[0] = (WasmInstruction) { WI_GLOBAL_GET, { .l = stack_top_idx } };
-    code[1] = (WasmInstruction) { WI_LOCAL_TEE,  { .l = mod->stack_base_idx} };
-    code[2] = (WasmInstruction) { WI_I32_CONST,  { .l = stacksize } };
-    code[3] = (WasmInstruction) { WI_I32_ADD,    0 };
-    code[4] = (WasmInstruction) { WI_GLOBAL_SET, { .l = stack_top_idx } };
-
+    if (stacksize == 0) {
+        code[0] = (WasmInstruction) { WI_GLOBAL_GET, { .l = stack_top_idx } };
+        code[1] = (WasmInstruction) { WI_LOCAL_SET,  { .l = mod->stack_base_idx} };
+        code[2] = (WasmInstruction) { WI_NOP,        0 };
+        code[3] = (WasmInstruction) { WI_NOP,        0 };
+        code[4] = (WasmInstruction) { WI_NOP,        0 };
+    } else {
+        code[0] = (WasmInstruction) { WI_GLOBAL_GET, { .l = stack_top_idx } };
+        code[1] = (WasmInstruction) { WI_LOCAL_TEE,  { .l = mod->stack_base_idx} };
+        code[2] = (WasmInstruction) { WI_I32_CONST,  { .l = stacksize } };
+        code[3] = (WasmInstruction) { WI_I32_ADD,    0 };
+        code[4] = (WasmInstruction) { WI_GLOBAL_SET, { .l = stack_top_idx } };
+    }
     *pcode = code;
 }
 
@@ -3528,6 +3557,8 @@ static void output_instruction(WasmFunc* func, WasmInstruction* instr, bh_buffer
     i32 leb_len;
     u8* leb;
 
+    if (instr->type == WI_NOP) return;
+
     if (instr->type & SIMD_INSTR_MASK) {
         bh_buffer_write_byte(buff, 0xFD);
         leb = uint_to_uleb128((u64) (instr->type &~ SIMD_INSTR_MASK), &leb_len);
index 886d91612b68ce0ddea81c49cbe8aeda6d1caf3c..4d28fcbfd3ec50c9fdd0210cead37b79c851c604 100644 (file)
@@ -26,7 +26,7 @@ range_by :: proc (lo: i32, hi: i32) -> range {
 
 simulate :: proc (cups: [] i32, moves := 100) {
     cw : [] i32;
-    alloc.alloc_slice(^cw, cups.count);
+    memory.alloc_slice(^cw, cups.count);
     defer cfree(cw.data);
 
     for i: 0 .. cups.count do cw[cups[i]] = cups[w(i + 1)];