SOA :: struct {
a : [..] i32;
b : [..] i64;
+ c : [..] V2;
}
soa_init :: proc (s: ^SOA) {
array_init(^s.a);
array_init(^s.b);
+ array_init(^s.c);
}
soa_deinit :: proc (s: ^SOA) {
array_free(^s.a);
array_free(^s.b);
+ array_free(^s.c);
}
get_range :: proc (arr: ^[..] $T) -> range {
return range.{ low = r.low, high = r.high, step = s };
}
+V2 :: struct { x: i32; y: i32; }
+print_v2 :: proc (v: V2) #add_overload print {
+ print("V2(");
+ print(v.x);
+ print(", ");
+ print(v.y);
+ print(")");
+}
+
main :: proc (args: [] cstring) {
res := compose(5, proc (x: i32) -> i32 do return x * 3;,
proc (x: i32) -> i32 do return x + 5;);
for i: 0 .. 100 {
array_push(^s.a, (5 * i) % 21);
array_push(^s.b, 3l * cast(i64) i);
+ array_push(^s.c, V2.{ i, i * i });
}
r := ^s.a |> get_range() |> by(3);
print(r);
print_array(^s.a);
+ for vec: s.c {
+ print(vec);
+ print(" ");
+ }
+ print("\n");
+
+
array_sort(^s.a, cmp_dec);
array_sort(^s.b, cmp_dec);
WIL(WI_LOCAL_SET, step_local);
WIL(WI_LOCAL_SET, high_local);
- WIL(WI_LOCAL_SET, low_local);
if (it_is_local) {
- WIL(WI_LOCAL_GET, low_local);
+ WIL(WI_LOCAL_TEE, low_local);
WIL(WI_LOCAL_SET, iter_local);
+
} else {
+ WIL(WI_LOCAL_SET, low_local);
emit_local_location(mod, &code, var, &offset);
WIL(WI_LOCAL_GET, low_local);
emit_store_instruction(mod, &code, var->type, offset);
*pcode = code;
}
+EMIT_FUNC(for_slice, AstFor* for_node, u64 iter_local) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ // NOTE: This implementation is only for loops by value, not by pointer.
+
+ // At this point the stack will look like:
+ // data
+ // count
+ //
+ // The locals we need to have:
+ // end_ptr
+ // start_ptr
+ //
+
+ u64 end_ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+ u64 ptr_local = local_raw_allocate(mod->local_alloc, WASM_TYPE_INT32);
+
+ AstLocal* var = for_node->var;
+ u64 elem_size = type_size_of(var->type);
+ b32 it_is_local = (b32) ((iter_local & LOCAL_IS_WASM) != 0);
+ u64 offset = 0;
+
+ WIL(WI_LOCAL_SET, end_ptr_local);
+ WIL(WI_LOCAL_TEE, ptr_local);
+ WIL(WI_LOCAL_GET, end_ptr_local);
+ if (elem_size != 1) {
+ WID(WI_I32_CONST, elem_size);
+ WI(WI_I32_MUL);
+ }
+ WI(WI_I32_ADD);
+ WIL(WI_LOCAL_SET, end_ptr_local);
+
+ WID(WI_BLOCK_START, 0x40);
+ WID(WI_LOOP_START, 0x40);
+ WID(WI_BLOCK_START, 0x40);
+
+ bh_arr_push(mod->structured_jump_target, 1);
+ bh_arr_push(mod->structured_jump_target, 0);
+ bh_arr_push(mod->structured_jump_target, 2);
+
+ WIL(WI_LOCAL_GET, ptr_local);
+ WIL(WI_LOCAL_GET, end_ptr_local);
+ WI(WI_I32_GE_S);
+ WID(WI_COND_JUMP, 0x02);
+
+ // NOTE: Storing structs requires that the location to store it is,
+ // the top most thing on the stack. Everything requires it to be
+ // 'under' the other element being stored. -brendanfh 2020/09/04
+ if (!it_is_local && var->type->kind != Type_Kind_Struct) {
+ emit_local_location(mod, &code, var, &offset);
+ }
+
+ WIL(WI_LOCAL_GET, ptr_local);
+ emit_load_instruction(mod, &code, var->type, 0);
+ if (it_is_local) {
+ WIL(WI_LOCAL_SET, iter_local);
+ } else {
+ if (var->type->kind != Type_Kind_Struct) {
+ emit_store_instruction(mod, &code, var->type, offset);
+ } else {
+ emit_local_location(mod, &code, var, &offset);
+ emit_store_instruction(mod, &code, var->type, offset);
+ }
+ }
+
+ emit_block(mod, &code, for_node->stmt, 0);
+
+ bh_arr_pop(mod->structured_jump_target);
+ WI(WI_BLOCK_END);
+
+ WIL(WI_LOCAL_GET, ptr_local);
+ WIL(WI_I32_CONST, elem_size);
+ WI(WI_I32_ADD);
+ WIL(WI_LOCAL_SET, ptr_local);
+
+ bh_arr_pop(mod->structured_jump_target);
+ bh_arr_pop(mod->structured_jump_target);
+
+ if (bh_arr_last(code).type != WI_JUMP)
+ WID(WI_JUMP, 0x00);
+
+ WI(WI_LOOP_END);
+ WI(WI_BLOCK_END);
+
+ local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+ local_raw_free(mod->local_alloc, WASM_TYPE_INT32);
+
+ *pcode = code;
+}
+
EMIT_FUNC(for, AstFor* for_node) {
bh_arr(WasmInstruction) code = *pcode;
if (for_node->loop_type == For_Loop_Range) {
emit_for_range(mod, &code, for_node, iter_local);
+ } else if (for_node->loop_type == For_Loop_Slice) {
+ emit_for_slice(mod, &code, for_node, iter_local);
+ } else if (for_node->loop_type == For_Loop_DynArr) {
+ // NOTE: A dynamic array is just a slice with an extra capacity field on the end.
+ // Just dropping the capacity field will mean we can just use the slice implementation.
+ // - brendanfh 2020/09/04
+ WI(WI_DROP);
+ emit_for_slice(mod, &code, for_node, iter_local);
} else {
onyx_report_error(for_node->token->pos, "Invalid for loop type. You should probably not be seeing this...");
}