return 0;
}
-
+ if (from->kind == Type_Kind_Union && to->kind == Type_Kind_Enum) {
+ if (from->Union.tag_type->id == to->id) {
+ return 1;
+ }
+ }
if (from->kind == Type_Kind_Enum) from = from->Enum.backing;
if (to->kind == Type_Kind_Enum) to = to->Enum.backing;
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_Union_Type)
+ cs = check_union((AstUnionType *) ent->type_alias);
else
cs = check_type(&ent->type_alias);
break;
while (parser->curr->type == '#') {
if (parser->hit_unexpected_token) return NULL;
- if (parse_possible_directive(parser, "union")) s_node->is_union = 1;
+ if (next_tokens_are(parser, 2, '#', Token_Type_Keyword_Union)) {
+ consume_tokens(parser, 2);
+ s_node->is_union = 1;
+ }
else if (parse_possible_directive(parser, "pack")) s_node->is_packed = 1;
if (expr->kind == Ast_Kind_Struct_Type ||
expr->kind == Ast_Kind_Poly_Struct_Type ||
expr->kind == Ast_Kind_Enum_Type ||
- expr->kind == Ast_Kind_Type_Raw_Alias) {
+ expr->kind == Ast_Kind_Type_Raw_Alias ||
+ expr->kind == Ast_Kind_Union_Type) {
force_a_lookup = 1;
}
u_type = union_->pending_type;
}
+ union_->pending_type_is_valid = 1;
+
//
// All variants need to have type know.
bh_arr_each(AstUnionVariant *, pvariant, union_->variants) {
return result;
}
+ case Ast_Kind_Union_Type: {
+ AstUnionType* utype = (AstUnionType *) node;
+ if (utype->utcache != NULL) {
+ //
+ // nocheckin Should this be hard coded?
+ if (!strcmp(symbol, "tag_enum")) {
+ return (AstNode *) utype->utcache->Union.tag_type->ast_type;
+ }
+ }
+ break;
+ }
+
case Ast_Kind_Poly_Struct_Type: {
AstPolyStructType* stype = ((AstPolyStructType *) node);
return symbol_raw_resolve(stype->scope, symbol);
i32 store_size = type_size_of(type);
i32 is_basic = type->kind == Type_Kind_Basic || type->kind == Type_Kind_Pointer || type->kind == Type_Kind_MultiPointer;
- if (is_basic && (type->Basic.flags & Basic_Flag_Pointer)) {
+ if (!is_basic) {
+ onyx_report_error((OnyxFilePos) { 0 }, Error_Critical,
+ "Failed to generate store instruction for type '%s'. (compiler bug)",
+ type_get_name(type));
+ }
+
+ if (type->Basic.flags & Basic_Flag_Pointer) {
WID(NULL, WI_I32_STORE, ((WasmInstructionData) { 2, offset }));
- } else if (is_basic && ((type->Basic.flags & Basic_Flag_Integer)
- || (type->Basic.flags & Basic_Flag_Boolean)
- || (type->Basic.flags & Basic_Flag_Type_Index))) {
+ } else if ((type->Basic.flags & Basic_Flag_Integer)
+ || (type->Basic.flags & Basic_Flag_Boolean)
+ || (type->Basic.flags & Basic_Flag_Type_Index)) {
if (store_size == 1) WID(NULL, WI_I32_STORE_8, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 2) WID(NULL, WI_I32_STORE_16, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 4) WID(NULL, WI_I32_STORE, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 8) WID(NULL, WI_I64_STORE, ((WasmInstructionData) { alignment, offset }));
- } else if (is_basic && (type->Basic.flags & Basic_Flag_Float)) {
+ } else if (type->Basic.flags & Basic_Flag_Float) {
if (store_size == 4) WID(NULL, WI_F32_STORE, ((WasmInstructionData) { alignment, offset }));
else if (store_size == 8) WID(NULL, WI_F64_STORE, ((WasmInstructionData) { alignment, offset }));
- } else if (is_basic && (type->Basic.flags & Basic_Flag_SIMD)) {
+ } else if (type->Basic.flags & Basic_Flag_SIMD) {
WID(NULL, WI_V128_STORE, ((WasmInstructionData) { alignment, offset }));
- } else {
- onyx_report_error((OnyxFilePos) { 0 }, Error_Critical,
- "Failed to generate store instruction for type '%s'.",
- type_get_name(type));
+ } else if (type->Basic.kind == Basic_Kind_Void) {
+ // Do nothing, but drop the destination pointer.
+ WI(NULL, WI_DROP);
}
*pcode = code;
return;
}
+ if (from->kind == Type_Kind_Union) {
+ // This should be check in the checker that are only casting
+ // to the union's tag_type.
+ emit_load_instruction(mod, &code, from->Union.tag_type, 0);
+ *pcode = code;
+ return;
+ }
+
if (to->kind == Type_Kind_Basic && from->kind == Type_Kind_Function) {
WI(NULL, WI_DROP);
WI(NULL, WI_DROP);
SimpleUnion :: union {
a: i32;
b: struct {
- c, d: str;
+ c: str;
};
+
+ empty: void;
+ large: i64;
+}
+
+call_test :: (u_: SimpleUnion) {
+ u := u_;
+ __byte_dump(&u, sizeof typeof u);
+
+ switch cast(SimpleUnion.tag_enum) u {
+ case .a do println("It was a!");
+ case .b do println("It was B!");
+ case .empty do println("It was EMPTY!");
+ case .large do println("It was a large number!");
+ }
}
simple_test :: () {
- u := SimpleUnion.{ a = 123 };
+ u := SimpleUnion.{ b = .{ "asdf" } };
+ u = .{ a = 123 };
+ u = .{ empty = .{} };
+ u = .{ large = 0x0123456789abcdef };
- println(sizeof str);
- println(sizeof str * 2 + sizeof i32);
+ println(cast(SimpleUnion.tag_enum) u);
- __byte_dump(&u, sizeof typeof u);
- println(u.a);
+ call_test(u);
}
-main :: () {simple_test();}
+main :: () {simple_test();} //link_test();}
+Link :: union {
+ End: void;
+ Next: struct {
+ data: i32;
+ next: &Link;
+ }
+}
+
+/*
+print_links :: (l: Link) {
+ walker := l;
+ while true {
+ switch walker {
+ case Link.End do break;
+ case Link.Next => &next {
+ printf("{} ", next.data);
+ walker = next.next;
+ }
+ }
+ }
+}
+
+link_test :: () {
+ l := Link.{
+ Next = .{
+ data = 123,
+ next = &Link.{
+ End = .{}
+ }
+ }
+ };
+
+ print_links(l);
+}
+*/
-// Link :: union {
-// End: void;
-// Next: struct {
-// data: i32;
-// next: &Link;
-// }
-// }
-//
-// print_links :: (l: Link) {
-// walker := l;
-// while true {
-// switch walker {
-// case .End do break;
-// case .Next {
-// next: struct {data: i32; next: rawptr};
-// printf("{} ", next.data);
-// walker = next.next;
-// }
-// }
-// }
-// }
-//
-// link_test :: () {
-// l := Link.{
-// Next = .{
-// data = 123,
-// next = &Link.{
-// End = .{}
-// }
-// }
-// };
-//
-// print_links(l);
-// }
-//
// main :: () { link_test(); }
// Optional :: union (T: type_expr) {