Unreleased
Additions:
+* Tagged unions (`union` type)
* String literals can have unicode code points.
- '\uXXXX' for small code points (less than U+FFFF)
- '\UXXXXXX' for large code points
Removals:
Changes:
+* `Optional` is now a tagged-union
+* `Result` is now a tagged-union
* `iter.single` can take a `dispose` function, which is called on close of the
iterator, with the single value yielded.
* `io.write_escaped_str` supports escaping "\\" now.
if (!type_is_integer(switchnode->expr->type) && switchnode->expr->type->kind != Type_Kind_Enum) {
switchnode->switch_kind = Switch_Kind_Use_Equals;
}
- if (switchnode->expr->type->kind == Type_Kind_Union) {
+ if (switchnode->expr->type->kind == Type_Kind_Union
+ || (switchnode->expr->type->kind == Type_Kind_Pointer && switchnode->expr->type->Pointer.elem->kind == Type_Kind_Union)) {
switchnode->switch_kind = Switch_Kind_Union;
}
}
if (sc->capture && switchnode->switch_kind != Switch_Kind_Union) {
- ERROR(sc->capture->token->pos, "Captures in switch cases are only allowed when switching over a union type.");
+ ERROR_(sc->capture->token->pos, "Captures in switch cases are only allowed when switching over a union type. Switching over '%s' here.",
+ type_get_name(switchnode->expr->type));
}
if (sc->flags & Ast_Flag_Has_Been_Checked) goto check_switch_case_block;
}
if (switchnode->switch_kind == Switch_Kind_Union) {
- TYPE_CHECK(value, resolved_expr_type->Union.tag_type) {
+ Type *union_expr_type = resolved_expr_type;
+ if (union_expr_type->kind == Type_Kind_Pointer) {
+ union_expr_type = union_expr_type->Pointer.elem;
+ }
+
+ TYPE_CHECK(value, union_expr_type->Union.tag_type) {
OnyxToken* tkn = sc->block->token;
if ((*value)->token) tkn = (*value)->token;
ERROR_(tkn->pos, "'%b' is not a variant of '%s'.",
- (*value)->token->text, (*value)->token->length, type_get_name(resolved_expr_type));
+ (*value)->token->text, (*value)->token->length, type_get_name(union_expr_type));
}
// nocheckin Explain the -1
- UnionVariant *union_variant = resolved_expr_type->Union.variants_ordered[get_expression_integer_value(*value, NULL) - 1];
+ UnionVariant *union_variant = union_expr_type->Union.variants_ordered[get_expression_integer_value(*value, NULL) - 1];
if (sc->capture) {
if (sc->capture_is_by_pointer) {
sc->capture->type = type_make_pointer(context.ast_alloc, union_variant->type);
emit_expression(mod, &code, switch_node->expr);
if (switch_node->switch_kind == Switch_Kind_Union) {
- assert(switch_node->expr->type->kind == Type_Kind_Union);
+ Type *union_expr_type = switch_node->expr->type;
+ if (union_expr_type->kind == Type_Kind_Pointer) {
+ union_expr_type = union_expr_type->Pointer.elem;
+ }
+ assert(union_expr_type->kind == Type_Kind_Union);
+
union_capture_idx = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
WIL(NULL, WI_LOCAL_TEE, union_capture_idx);
- emit_load_instruction(mod, &code, switch_node->expr->type->Union.tag_type, 0);
+ emit_load_instruction(mod, &code, union_expr_type->Union.tag_type, 0);
}
if (switch_node->min_case != 0) {
if (sc->capture) {
assert(union_capture_idx != 0);
+ Type *union_expr_type = switch_node->expr->type;
+ if (union_expr_type->kind == Type_Kind_Pointer) {
+ union_expr_type = union_expr_type->Pointer.elem;
+ }
+
if (sc->capture_is_by_pointer) {
u64 capture_pointer_local = emit_local_allocation(mod, &code, (AstTyped *) sc->capture);
WIL(NULL, WI_LOCAL_GET, union_capture_idx);
- WIL(NULL, WI_PTR_CONST, switch_node->expr->type->Union.alignment);
+ WIL(NULL, WI_PTR_CONST, union_expr_type->Union.alignment);
WI(NULL, WI_PTR_ADD);
WIL(NULL, WI_LOCAL_SET, capture_pointer_local);
emit_location(mod, &code, (AstTyped *) sc->capture);
WIL(NULL, WI_LOCAL_GET, union_capture_idx);
- WIL(NULL, WI_PTR_CONST, switch_node->expr->type->Union.alignment);
+ WIL(NULL, WI_PTR_CONST, union_expr_type->Union.alignment);
WI(NULL, WI_PTR_ADD);
WIL(NULL, WI_I32_CONST, type_size_of(sc->capture->type));
If not, an assertion is thrown and the context's assert handler must
take care of it.
"""
- unwrap_ptr :: (o: ?$T) -> &T {
+ unwrap_ptr :: (o: & ?$T) -> &T {
switch o {
case .Some => &v do return v;
case #default {