Type* type_make_slice(bh_allocator alloc, Type* of);
Type* type_make_dynarray(bh_allocator alloc, Type* of);
Type* type_make_varargs(bh_allocator alloc, Type* of);
+Type* type_make_optional(bh_allocator alloc, Type* of);
void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u32 offset);
b32 type_struct_member_apply_use(bh_allocator alloc, Type *s_type, StructMember *smem);
Type* type_struct_is_just_one_basic_value(Type *type);
u32 type_union_get_variant_count(Type *type);
UnionVariant* type_lookup_union_variant_by_idx(Type* type, i32 idx);
+UnionVariant* type_lookup_union_variant_by_name(Type* type, char *name);
#endif // #ifndef ONYX_TYPES
}
}
+ if (type_union_get_variant_count(field->expr->type) > 0) {
+ UnionVariant *uv = type_lookup_union_variant_by_name(field->expr->type, field->field);
+ if (uv) {
+ field->is_union_variant_access = 1;
+ field->idx = uv->tag_value;
+
+ // HACK make a function for this.
+ if (!field->type_node) {
+ AstPolyCallType* pctype = onyx_ast_node_new(context.ast_alloc, sizeof(AstPolyCallType), Ast_Kind_Poly_Call_Type);
+ pctype->token = field->token;
+ pctype->callee = builtin_optional_type;
+ bh_arr_new(context.ast_alloc, pctype->params, 1);
+ bh_arr_push(pctype->params, (AstNode *) uv->type->ast_type);
+
+ field->type_node = (AstType *) pctype;
+ }
+
+ field->type = type_build_from_ast(context.ast_alloc, field->type_node);
+ if (!field->type) YIELD(field->token->pos, "Waiting for field access type to be constructed.");
+
+ field->flags |= Ast_Flag_Has_Been_Checked;
+ return Check_Success;
+ }
+ }
+
goto try_resolve_from_type;
}
return la->curr_stack - size;
}
+static void local_free_type_in_memory(LocalAllocator* la, Type* type) {
+ u32 size = type_size_of(type);
+ u32 alignment = type_alignment_of(type);
+ bh_align(size, alignment);
+
+ la->curr_stack -= size;
+}
+
static u64 local_allocate(LocalAllocator* la, AstTyped* local) {
if (local_is_wasm_local(local)) {
WasmType wt = onyx_type_to_wasm_type(local->type);
local_raw_free(la, wt);
} else {
- u32 size = type_size_of(local->type);
- u32 alignment = type_alignment_of(local->type);
- bh_align(size, alignment);
-
- la->curr_stack -= size;
+ local_free_type_in_memory(la, local->type);
}
}
WIL(NULL, WI_LOCAL_GET, localidx);
}
+ else if (field->is_union_variant_access) {
+ u64 intermediate_local = emit_local_allocation(mod, &code, (AstTyped *) field);
+ assert((intermediate_local & LOCAL_IS_WASM) == 0);
+
+ emit_expression(mod, &code, field->expr);
+ u64 source_base_ptr = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+ WIL(NULL, WI_LOCAL_TEE, source_base_ptr);
+ emit_load_instruction(mod, &code, &basic_types[Basic_Kind_U32], 0);
+ WIL(NULL, WI_I32_CONST, field->idx);
+ WI(NULL, WI_I32_EQ);
+ emit_enter_structured_block(mod, &code, SBT_Basic_If, field->token);
+ emit_stack_address(mod, &code, intermediate_local, field->token);
+ WIL(NULL, WI_I32_CONST, 2); // 2 is Some
+ emit_store_instruction(mod, &code, &basic_types[Basic_Kind_I32], 0);
+
+ emit_stack_address(mod, &code, intermediate_local + type_alignment_of(field->type), field->token);
+ WIL(NULL, WI_LOCAL_GET, source_base_ptr);
+ WIL(NULL, WI_I32_CONST, type_alignment_of(field->expr->type));
+ WI(NULL, WI_I32_ADD);
+ WIL(NULL, WI_I32_CONST, type_size_of(field->type->Union.variants_ordered[1]->type));
+ emit_wasm_copy(mod, &code, NULL);
+
+ WI(NULL, WI_ELSE);
+ emit_stack_address(mod, &code, intermediate_local, field->token);
+ WIL(NULL, WI_I32_CONST, 1); // 1 is None
+ emit_store_instruction(mod, &code, &basic_types[Basic_Kind_I32], 0);
+ emit_leave_structured_block(mod, &code);
+
+ local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
+ emit_stack_address(mod, &code, intermediate_local, field->token);
+ }
+
else if (is_lval((AstNode *) field->expr) || type_is_pointer(field->expr->type)) {
u64 offset = 0;
emit_field_access_location(mod, &code, field, &offset);
}
}
- or_return :: macro (o: ?$T) -> T {
- switch value := o; value {
- case .Some => v do return v;
- case #default {
- return return .{};
+ or_return :: #match {
+ macro (o: ?$T) -> T {
+ switch value := o; value {
+ case .Some => v do return v;
+ case #default {
+ return return .{};
+ }
}
- }
+ },
+ macro (o: ?$T, return_value: $R) -> T {
+ switch value := o; value {
+ case .Some => v do return v;
+ case #default {
+ return return return_value;
+ }
+ }
+ },
}
catch :: macro (o: ?$T, body: Code) -> T {
switch value := o; value {
case .Some => v do return v;
+ case .None {
+ #unquote body;
+ }
}
-
- #unquote body;
}
#doc """