AstTyped_base;
bh_arr(AstTyped *) meta_tags;
};
+struct AstPolyUnionType {
+ AstType_base;
+ char *name;
+
+ Scope *scope;
+ bh_arr(AstPolyStructParam) poly_params;
+ Table(AstUnionType *) concrete_unions;
+
+ AstUnionType* base_union;
+};
struct AstEnumType {
AstType_base;
char *name;
AstFunction* macro_resolve_header(AstMacro* macro, Arguments* args, OnyxToken* callsite, b32 error_if_failed);
Type* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos, b32 error_if_failed);
+Type* polymorphic_union_lookup(AstPolyUnionType* pu_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos, b32 error_if_failed);
b32 resolve_intrinsic_interface_constraint(AstConstraint *constraint);
bh_arr(struct AstPolySolution) poly_sln; \
struct AstType *constructed_from; \
bh_arr(struct AstTyped *) meta_tags; \
- })
+ }) \
+ TYPE_KIND(PolyUnion, struct { \
+ char* name; \
+ bh_arr(struct AstTyped *) meta_tags; \
+ }) \
if (call->kind == Ast_Kind_Call) {
AstNode* callee = strip_aliases((AstNode *) call->callee);
- if (callee->kind == Ast_Kind_Poly_Struct_Type) {
+ if (callee->kind == Ast_Kind_Poly_Struct_Type ||
+ callee->kind == Ast_Kind_Poly_Union_Type) {
*pcall = (AstCall *) convert_call_to_polycall(call);
CHECK(expression, (AstTyped **) pcall);
return Check_Success;
expr = *pexpr;
// Don't try to construct a polystruct ahead of time because you can't.
- if (expr->kind != Ast_Kind_Poly_Struct_Type) {
+ if (expr->kind != Ast_Kind_Poly_Struct_Type &&
+ expr->kind != Ast_Kind_Poly_Union_Type) {
if (type_build_from_ast(context.ast_alloc, (AstType*) expr) == NULL) {
YIELD(expr->token->pos, "Trying to construct type.");
}
if (ofunc->expected_return_node) {
AstType *expected_return_node = (AstType *) strip_aliases((AstNode *) ofunc->expected_return_node);
- if (expected_return_node->kind == Ast_Kind_Poly_Struct_Type) {
+ if (expected_return_node->kind == Ast_Kind_Poly_Struct_Type ||
+ expected_return_node->kind == Ast_Kind_Poly_Union_Type) {
//
// When you declare the expected return type of a #match'ed procedure to
// be a polymorphic structure type, a special case has to happen. By trying
}
CheckStatus check_union(AstUnionType *u_node) {
+ if (u_node->polymorphic_argument_types) {
+ assert(u_node->polymorphic_arguments);
+
+ fori (i, 0, (i64) bh_arr_length(u_node->polymorphic_argument_types)) {
+ Type *arg_type = type_build_from_ast(context.ast_alloc, u_node->polymorphic_argument_types[i]);
+ if (arg_type == NULL) YIELD(u_node->polymorphic_argument_types[i]->token->pos, "Waiting to build type for polymorph argument.");
+
+ //
+ // This check should always be false, but it handles
+ // the case where somewhere a type was expected, but
+ // not enough values were provided. This is checked
+ // elsewhere when instantiating a polymorphic sturucture.
+ if (i >= bh_arr_length(u_node->polymorphic_arguments)
+ || !u_node->polymorphic_arguments[i].value) continue;
+
+
+ TYPE_CHECK(&u_node->polymorphic_arguments[i].value, arg_type) {
+ ERROR_(u_node->polymorphic_arguments[i].value->token->pos, "Expected value of type %s, got %s.",
+ type_get_name(arg_type),
+ type_get_name(u_node->polymorphic_arguments[i].value->type));
+ }
+ }
+ }
+
if (u_node->constraints.constraints) {
u_node->constraints.produce_errors = (u_node->flags & Ast_Flag_Header_Check_No_Error) == 0;
case Ast_Kind_Import: return sizeof(AstImport);
case Ast_Kind_Capture_Block: return sizeof(AstCaptureBlock);
case Ast_Kind_Capture_Local: return sizeof(AstCaptureLocal);
+ case Ast_Kind_Union_Type: return sizeof(AstUnionType);
+ case Ast_Kind_Union_Variant: return sizeof(AstUnionVariant);
case Ast_Kind_Count: return 0;
}
break;
}
+ case Ast_Kind_Union_Type: {
+ AstUnionType* du = (AstUnionType *) nn;
+ AstUnionType* su = (AstUnionType *) node;
+
+ du->variants = NULL;
+ bh_arr_new(global_heap_allocator, du->variants, bh_arr_length(su->variants));
+
+ bh_arr_each(AstUnionVariant *, uv, su->variants) {
+ bh_arr_push(du->variants, (AstUnionVariant *) ast_clone(a, *uv));
+ }
+
+ du->meta_tags = NULL;
+ bh_arr_new(global_heap_allocator, du->meta_tags, bh_arr_length(su->meta_tags));
+ bh_arr_each(AstTyped *, tag, su->meta_tags) {
+ bh_arr_push(du->meta_tags, (AstTyped *) ast_clone(a, *tag));
+ }
+
+ if (su->constraints.constraints) {
+ memset(&du->constraints, 0, sizeof(ConstraintContext));
+ bh_arr_new(global_heap_allocator, du->constraints.constraints, bh_arr_length(su->constraints.constraints));
+
+ bh_arr_each(AstConstraint *, constraint, su->constraints.constraints) {
+ bh_arr_push(du->constraints.constraints, (AstConstraint *) ast_clone(a, (AstNode *) *constraint));
+ }
+ }
+
+ du->utcache = NULL;
+ break;
+ }
+
+ case Ast_Kind_Union_Variant: {
+ C(AstUnionVariant, type_node);
+
+ AstUnionVariant *du = (AstUnionVariant *) nn;
+ AstUnionVariant *su = (AstUnionVariant *) node;
+
+ du->meta_tags = NULL;
+ bh_arr_new(global_heap_allocator, du->meta_tags, bh_arr_length(su->meta_tags));
+ bh_arr_each(AstTyped *, tag, su->meta_tags) {
+ bh_arr_push(du->meta_tags, (AstTyped *) ast_clone(a, *tag));
+ }
+
+ break;
+ }
+
case Ast_Kind_Poly_Call_Type: {
AstPolyCallType* pcd = (AstPolyCallType *) nn;
AstPolyCallType* pcs = (AstPolyCallType *) node;
}
case Ast_Kind_Union_Type:
+ case Ast_Kind_Poly_Union_Type:
case Ast_Kind_Poly_Struct_Type:
case Ast_Kind_Type_Alias: {
ent.type = Entity_Type_Type_Alias;
OnyxToken* union_token = expect_token(parser, Token_Type_Keyword_Union);
AstUnionType* u_node;
+ AstPolyUnionType* poly_union = NULL;
+
u_node = make_node(AstUnionType, Ast_Kind_Union_Type);
u_node->token = union_token;
Scope *scope_to_restore_parser_to = parser->current_scope;
Scope *scope_symbols_in_unions_should_be_bound_to = u_node->scope;
+ if (consume_token_if_next(parser, '(')) {
+ bh_arr(AstPolyStructParam) poly_params = NULL;
+ bh_arr_new(global_heap_allocator, poly_params, 1);
+
+ while (!consume_token_if_next(parser, ')')) {
+ if (parser->hit_unexpected_token) return NULL;
+
+ OnyxToken* sym_token = expect_token(parser, Token_Type_Symbol);
+ expect_token(parser, ':');
+
+ AstType* param_type = parse_type(parser);
+
+ bh_arr_push(poly_params, ((AstPolyStructParam) {
+ .token = sym_token,
+ .type_node = param_type,
+ .type = NULL,
+ }));
+
+ if (parser->curr->type != ')')
+ expect_token(parser, ',');
+ }
+
+ poly_union = make_node(AstPolyUnionType, Ast_Kind_Poly_Union_Type);
+ poly_union->token = union_token;
+ poly_union->poly_params = poly_params;
+ poly_union->base_union = u_node;
+ poly_union->scope = u_node->scope;
+ u_node->scope = NULL;
+ }
+
// Parse constraints clause
if (parser->curr->type == Token_Type_Keyword_Where) {
parse_constraints(parser, &u_node->constraints);
parser->current_scope = scope_to_restore_parser_to;
- ENTITY_SUBMIT(u_node);
- return u_node;
+ if (poly_union != NULL) {
+ // NOTE: Not a UnionType
+ return (AstUnionType *) poly_union;
- //if (poly_struct != NULL) {
- // // NOTE: Not a StructType
- // return (AstStructType *) poly_struct;
-
- //} else {
- // ENTITY_SUBMIT(s_node);
- // return s_node;
- //}
+ } else {
+ ENTITY_SUBMIT(u_node);
+ return u_node;
+ }
}
static AstInterface* parse_interface(OnyxParser* parser) {
case Ast_Kind_Enum_Type:
case Ast_Kind_Distinct_Type:
case Ast_Kind_Union_Type:
+ case Ast_Kind_Poly_Union_Type:
((AstStructType *) node)->name = generate_name_within_scope(parser, symbol);
goto default_case;
}
case Ast_Kind_Poly_Call_Type: {
- if (elem.actual->kind != Type_Kind_Struct) break;
- if (bh_arr_length(elem.actual->Struct.poly_sln) != bh_arr_length(((AstPolyCallType *) elem.type_expr)->params)) break;
+ if (elem.actual->kind != Type_Kind_Struct && elem.actual->kind != Type_Kind_Union) break;
+
+ bh_arr(AstPolySolution) slns;
+ if (elem.actual->kind == Type_Kind_Struct) slns = elem.actual->Struct.poly_sln;
+ if (elem.actual->kind == Type_Kind_Union) slns = elem.actual->Union.poly_sln;
+
+ if (bh_arr_length(slns) != bh_arr_length(((AstPolyCallType *) elem.type_expr)->params)) break;
AstPolyCallType* pt = (AstPolyCallType *) elem.type_expr;
fori (i, 0, bh_arr_length(pt->params)) {
- PolySolutionKind kind = elem.actual->Struct.poly_sln[i].kind;
+ PolySolutionKind kind = slns[i].kind;
if (kind == PSK_Type) {
bh_arr_push(elem_queue, ((PolySolveElem) {
.kind = kind,
.type_expr = (AstType *) pt->params[i],
- .actual = elem.actual->Struct.poly_sln[i].type,
+ .actual = slns[i].type,
}));
} else {
bh_arr_push(elem_queue, ((PolySolveElem) {
.kind = kind,
.type_expr = (AstType *) pt->params[i],
- .value = elem.actual->Struct.poly_sln[i].value,
+ .value = slns[i].value,
}));
}
}
// The above documentation is very incorrect but I don't want to fix it right now. Basically, polymorphic
// structures now have a delay instantiation phase and are not forced to be completed immediately.
-char* build_poly_struct_name(AstPolyStructType* ps_type, Type* cs_type) {
+char* build_poly_struct_name(char *name, Type* type) {
char name_buf[256];
fori (i, 0, 256) name_buf[i] = 0;
// Special case for `? T`
- if (cs_type->Struct.constructed_from == builtin_optional_type) {
+ if (type->kind == Type_Kind_Struct
+ && type->Struct.constructed_from == builtin_optional_type) {
strncat(name_buf, "? ", 255);
- strncat(name_buf, type_get_name(cs_type->Struct.poly_sln[0].type), 255);
+ strncat(name_buf, type_get_name(type->Struct.poly_sln[0].type), 255);
return bh_aprintf(global_heap_allocator, "%s", name_buf);
}
+ bh_arr(AstPolySolution) slns = NULL;
+ if (type->kind == Type_Kind_Struct) slns = type->Struct.poly_sln;
+ if (type->kind == Type_Kind_Union) slns = type->Union.poly_sln;
+
- strncat(name_buf, ps_type->name, 255);
+ strncat(name_buf, name, 255);
strncat(name_buf, "(", 255);
- bh_arr_each(AstPolySolution, ptype, cs_type->Struct.poly_sln) {
- if (ptype != cs_type->Struct.poly_sln)
+ bh_arr_each(AstPolySolution, ptype, slns) {
+ if (ptype != slns)
strncat(name_buf, ", ", 255);
// This logic will have to be other places as well.
cs_type->Struct.constructed_from = (AstType *) ps_type;
if (cs_type->Struct.poly_sln == NULL) cs_type->Struct.poly_sln = bh_arr_copy(global_heap_allocator, slns);
- if (cs_type->Struct.name == NULL) cs_type->Struct.name = build_poly_struct_name(ps_type, cs_type);
+ if (cs_type->Struct.name == NULL) cs_type->Struct.name = build_poly_struct_name(ps_type->name, cs_type);
return cs_type;
}
add_entities_for_node(NULL, (AstNode *) concrete_struct, sln_scope, NULL);
return NULL;
}
+
+Type* polymorphic_union_lookup(AstPolyUnionType* pu_type, bh_arr(AstPolySolution) slns, OnyxFilePos pos, b32 error_if_failed) {
+ if (pu_type->scope == NULL) {
+ return NULL;
+ }
+
+ assert(!pu_type->base_union->scope);
+
+ if (pu_type->concrete_unions == NULL) {
+ sh_new_arena(pu_type->concrete_unions);
+ }
+
+ if (bh_arr_length(slns) != bh_arr_length(pu_type->poly_params)) {
+ onyx_report_error(pos, Error_Critical, "Wrong number of arguments for '%s'. Expected %d, got %d.",
+ pu_type->name,
+ bh_arr_length(pu_type->poly_params),
+ bh_arr_length(slns));
+
+ return NULL;
+ }
+
+ i32 i = 0;
+ bh_arr_each(AstPolySolution, sln, slns) {
+ sln->poly_sym = (AstNode *) &pu_type->poly_params[i];
+ i++;
+ }
+
+ char* unique_key = build_poly_slns_unique_key(slns);
+ i32 index = shgeti(pu_type->concrete_unions, unique_key);
+ if (index != -1) {
+ AstUnionType* concrete_union = pu_type->concrete_unions[index].value;
+
+ if (concrete_union->entity->state < Entity_State_Check_Types) {
+ return NULL;
+ }
+
+ if (concrete_union->entity->state == Entity_State_Failed) {
+ return (Type *) &node_that_signals_failure;
+ }
+
+ Type* cu_type = type_build_from_ast(context.ast_alloc, (AstType *) concrete_union);
+ if (!cu_type) return NULL;
+
+ cu_type->Union.constructed_from = (AstType *) pu_type;
+
+ if (cu_type->Union.poly_sln == NULL) cu_type->Union.poly_sln = bh_arr_copy(global_heap_allocator, slns);
+ cu_type->Union.name = build_poly_struct_name(pu_type->name, cu_type);
+
+ return cu_type;
+ }
+
+ Scope* sln_scope = scope_create(context.ast_alloc, pu_type->scope, pu_type->token->pos);
+ insert_poly_slns_into_scope(sln_scope, slns);
+
+ AstUnionType* concrete_union = (AstUnionType *) ast_clone(context.ast_alloc, pu_type->base_union);
+ concrete_union->scope = scope_create(context.ast_alloc, sln_scope, pu_type->token->pos);
+ concrete_union->polymorphic_error_loc = pos;
+ BH_MASK_SET(concrete_union->flags, !error_if_failed, Ast_Flag_Header_Check_No_Error);
+
+ i64 arg_count = bh_arr_length(pu_type->poly_params);
+ bh_arr_new(global_heap_allocator, concrete_union->polymorphic_argument_types, arg_count);
+ bh_arr_set_length(concrete_union->polymorphic_argument_types, arg_count);
+ concrete_union->polymorphic_arguments = bh_arr_copy(global_heap_allocator, slns);
+ concrete_union->name = pu_type->name;
+
+ fori (i, 0, (i64) bh_arr_length(pu_type->poly_params)) {
+ concrete_union->polymorphic_argument_types[i] = (AstType *) ast_clone(context.ast_alloc, pu_type->poly_params[i].type_node);
+ }
+
+ shput(pu_type->concrete_unions, unique_key, concrete_union);
+ add_entities_for_node(NULL, (AstNode *) concrete_union, sln_scope, NULL);
+ return NULL;
+}
assert(u_node->scope);
scope_enter(u_node->scope);
- // if (u_node->polymorphic_argument_types) {
- // assert(u_node->polymorphic_arguments);
+ if (u_node->polymorphic_argument_types) {
+ assert(u_node->polymorphic_arguments);
- // SymresStatus ss = Symres_Success, result;
- // fori (i, 0, (i64) bh_arr_length(u_node->polymorphic_argument_types)) {
- // result = symres_type(&u_node->polymorphic_argument_types[i]);
- // if (result > ss) ss = result;
+ SymresStatus ss = Symres_Success, result;
+ fori (i, 0, (i64) bh_arr_length(u_node->polymorphic_argument_types)) {
+ result = symres_type(&u_node->polymorphic_argument_types[i]);
+ if (result > ss) ss = result;
- // if (u_node->polymorphic_arguments[i].value) {
- // result = symres_expression(&u_node->polymorphic_arguments[i].value);
- // if (result > ss) ss = result;
- // }
- // }
- // }
+ if (u_node->polymorphic_arguments[i].value) {
+ result = symres_expression(&u_node->polymorphic_arguments[i].value);
+ if (result > ss) ss = result;
+ }
+ }
+ }
if (u_node->constraints.constraints) {
bh_arr_each(AstConstraint *, constraint, u_node->constraints.constraints) {
break;
}
+ case Ast_Kind_Poly_Union_Type: {
+ AstPolyUnionType* put_node = (AstPolyUnionType *) *type;
+ assert(put_node->scope);
+ break;
+ }
+
case Ast_Kind_Poly_Call_Type: {
AstPolyCallType* pc_node = (AstPolyCallType *) *type;
SYMRES(arguments, &call->args);
AstNode* callee = strip_aliases((AstNode *) call->callee);
- if (callee->kind == Ast_Kind_Poly_Struct_Type) {
+ if (callee->kind == Ast_Kind_Poly_Struct_Type ||
+ callee->kind == Ast_Kind_Poly_Union_Type) {
*pcall = (AstCall *) convert_call_to_polycall(call);
SYMRES(type, (AstType **) pcall);
return Symres_Success;
expr->kind == Ast_Kind_Poly_Struct_Type ||
expr->kind == Ast_Kind_Enum_Type ||
expr->kind == Ast_Kind_Type_Raw_Alias ||
- expr->kind == Ast_Kind_Union_Type) {
+ expr->kind == Ast_Kind_Union_Type ||
+ expr->kind == Ast_Kind_Poly_Union_Type) {
force_a_lookup = 1;
}
return NULL;
}
+ case Ast_Kind_Poly_Union_Type: {
+ if (type_node->type_id != 0) return NULL;
+
+ Type* p_type = type_create(Type_Kind_PolyUnion, alloc, 0);
+ p_type->ast_type = type_node;
+ p_type->PolyUnion.name = ((AstPolyUnionType *) type_node)->name;
+ p_type->PolyUnion.meta_tags = ((AstPolyUnionType *) type_node)->base_union->meta_tags;
+
+ type_register(p_type);
+ return NULL;
+ }
+
case Ast_Kind_Poly_Call_Type: {
AstPolyCallType* pc_type = (AstPolyCallType *) type_node;
pc_type->callee = (AstType *) strip_aliases((AstNode *) pc_type->callee);
- if (!(pc_type->callee && pc_type->callee->kind == Ast_Kind_Poly_Struct_Type)) {
+ if (!(pc_type->callee && (
+ pc_type->callee->kind == Ast_Kind_Poly_Struct_Type ||
+ pc_type->callee->kind == Ast_Kind_Poly_Union_Type
+ ))) {
+
// If it is an unresolved field access or symbol, just return because an error will be printed elsewhere.
if (pc_type->callee->kind == Ast_Kind_Field_Access || pc_type->callee->kind == Ast_Kind_Symbol) return NULL;
return NULL;
}
- AstPolyStructType* ps_type = (AstPolyStructType *) pc_type->callee;
-
bh_arr(AstPolySolution) slns = NULL;
bh_arr_new(global_heap_allocator, slns, bh_arr_length(pc_type->params));
bh_arr_each(AstNode *, given, pc_type->params) {
}
}
- Type* concrete = polymorphic_struct_lookup(ps_type, slns, pc_type->token->pos, (pc_type->flags & Ast_Flag_Header_Check_No_Error) == 0);
+ Type* concrete = NULL;
+ if (pc_type->callee->kind == Ast_Kind_Poly_Struct_Type) {
+ AstPolyStructType* ps_type = (AstPolyStructType *) pc_type->callee;
+ concrete = polymorphic_struct_lookup(ps_type, slns, pc_type->token->pos, (pc_type->flags & Ast_Flag_Header_Check_No_Error) == 0);
+ }
+ else if (pc_type->callee->kind == Ast_Kind_Poly_Union_Type) {
+ AstPolyUnionType* pu_type = (AstPolyUnionType *) pc_type->callee;
+ concrete = polymorphic_union_lookup(pu_type, slns, pc_type->token->pos, (pc_type->flags & Ast_Flag_Header_Check_No_Error) == 0);
+ }
// This should be copied in the previous function.
// CLEANUP: Maybe don't copy it and just use this one since it is allocated on the heap?
if (!concrete) return NULL;
if (concrete == (Type *) &node_that_signals_failure) return concrete;
- concrete->Struct.constructed_from = (AstType *) ps_type;
pc_type->resolved_type = concrete;
return concrete;
}
case Type_Kind_PolyStruct:
return type->PolyStruct.name;
+ case Type_Kind_PolyUnion:
+ return type->PolyUnion.name;
+
case Type_Kind_Struct:
if (type->Struct.name)
return type->Struct.name;
bh_arr_free(method_data);
break;
}
+
+ case Type_Kind_PolyUnion: {
+ u32* tag_locations = bh_alloc_array(global_scratch_allocator, u32, bh_arr_length(type->PolyUnion.meta_tags));
+ memset(tag_locations, 0, sizeof(u32) * bh_arr_length(type->PolyUnion.meta_tags));
+
+ u32 name_base = table_buffer.length;
+ u32 name_length = strlen(type->PolyUnion.name);
+ bh_buffer_append(&table_buffer, type->PolyUnion.name, name_length);
+
+ u32 tags_count = bh_arr_length(type->PolyUnion.meta_tags);
+ i32 i = 0;
+ bh_arr_each(AstTyped *, tag, type->PolyUnion.meta_tags) {
+ AstTyped* value = *tag;
+
+ tag_locations[i] = build_constexpr(value, &table_buffer, &constexpr_ctx);
+ if (tag_locations[i] == 0) {
+ // Polymorphic structs are weird in this case, because the tag might not be constructed generically for
+ // the polymorphic structure so it should only be constructed for actual solidified structures.
+ // See core/containers/map.onyx with Custom_Format for an example.
+ tags_count--;
+ } else {
+ i++;
+ }
+ }
+
+ bh_buffer_align(&table_buffer, 8);
+ u32 tags_base = table_buffer.length;
+
+ fori (i, 0, tags_count) {
+ WRITE_SLICE(tag_locations[i], type->PolyUnion.meta_tags[i]->type->id);
+ }
+
+ bh_buffer_align(&table_buffer, 8);
+ table_info[type_idx] = table_buffer.length;
+ bh_buffer_write_u32(&table_buffer, type->kind);
+ bh_buffer_write_u32(&table_buffer, 0);
+ bh_buffer_write_u32(&table_buffer, 0);
+ WRITE_SLICE(name_base, name_length);
+ WRITE_SLICE(tags_base, tags_count);
+
+ break;
+ }
}
}
else do io.write_str(writer, "<anonymous union>");
}
+ case .Polymorphic_Union {
+ u := cast(&Type_Info_Polymorphic_Union) info;
+ if u.name.count > 0 do io.write_str(writer, u.name);
+ else do io.write_str(writer, "<anonymous polymorphic union>");
+ }
+
case .Compound {
comp := cast(&Type_Info_Compound) info;
io.write_str(writer, "(");
Enum :: 0x0C;
Distinct :: 0x0D;
Union :: 0x0E;
+ Polymorphic_Union :: 0x0F;
}
kind := Kind.Invalid;
methods: [] Method;
}
+Type_Info_Polymorphic_Union :: struct {
+ use base : Type_Info;
+
+ name: str;
+ tags: [] any;
+}
+
get_type_info :: (t: type_expr) -> &Type_Info {
// Grossness to get around the fact that type_exprs are not technically comparable, because in most
// cases you should not compare them as the number assigned to them is arbitrary.
use core {*}
+NewOptional :: union (T: type_expr) {
+ None: void;
+ Some: T;
+}
+
+unwrap_optional :: (o: NewOptional($T)) -> T {
+ switch o {
+ case .Some => v do return v;
+ case .None do return .{};
+ }
+}
+
+new_optional_test :: () {
+ v := NewOptional(i32).{ Some = 123 };
+ v2 := NewOptional(str).{ None = .{} };
+ println(v);
+ println(v2);
+
+ v = .{ None = .{} };
+ println(unwrap_optional(v));
+}
+
union_is :: macro (u: $U, $variant: U.tag_enum) -> bool {
return cast(U.tag_enum, u) == variant;
}
println(u);
}
-main :: () {simple_test(); link_test();}
+main :: () {simple_test(); link_test(); new_optional_test();}
Link :: union {
End: void;