From 054dd0137c8b1ae6628be75a16a7535f913a203c Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 28 Nov 2023 12:16:42 -0600 Subject: [PATCH] added: shorthand syntax for `void` typed union variants --- compiler/include/astnodes.h | 1 + compiler/src/astnodes.c | 45 ++++++++++++++++++++++ core/alloc/memdebug.onyx | 4 +- core/container/optional.onyx | 8 ++-- core/encoding/kdl/kql.onyx | 4 +- core/encoding/kdl/parser.onyx | 8 ++-- core/encoding/kdl/utils.onyx | 2 +- core/runtime/platform/wasi/wasix_misc.onyx | 2 +- 8 files changed, 60 insertions(+), 14 deletions(-) diff --git a/compiler/include/astnodes.h b/compiler/include/astnodes.h index e92f9707..0c294da8 100644 --- a/compiler/include/astnodes.h +++ b/compiler/include/astnodes.h @@ -2037,6 +2037,7 @@ AstNode* make_symbol(bh_allocator a, OnyxToken* sym); AstUnaryOp* make_cast(bh_allocator a, AstTyped* expr, Type* to); AstZeroValue* make_zero_value(bh_allocator a, OnyxToken *token, Type* type); AstStructLiteral* make_optional_literal_some(bh_allocator a, AstTyped *expr, Type* opt_type); +AstStructLiteral* make_union_variant_of_void(bh_allocator a, Type* union_type, OnyxToken* token, UnionVariant* variant); void arguments_initialize(Arguments* args); b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg, b32 insert_zero_values); diff --git a/compiler/src/astnodes.c b/compiler/src/astnodes.c index 0f96e128..a8f12e1d 100644 --- a/compiler/src/astnodes.c +++ b/compiler/src/astnodes.c @@ -644,6 +644,34 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) { } if (node->kind == Ast_Kind_Unary_Field_Access) { + if (type->kind == Type_Kind_Union) { + token_toggle_end(node->token); + int index = 0; + if ((index = shgeti(type->Union.variants, node->token->text)) != -1) { + UnionVariant *uv = type->Union.variants[index].value; + if (uv->type != &basic_types[Basic_Kind_Void]) { + if (permanent) { + onyx_report_error(node->token->pos, Error_Critical, + "Shorthand union literal syntax '.%s' is not all for this variant, because its type is not void; it is '%s'. Use the longer syntax, '.{ %s = value }'", + node->token->text, + type_get_name(uv->type), + node->token->text); + } + token_toggle_end(node->token); + return TYPE_MATCH_FAILED; + } + + if (permanent) { + AstStructLiteral *sl = make_union_variant_of_void(context.ast_alloc, type, node->token, uv); + *pnode = (AstTyped *) sl; + } + + token_toggle_end(node->token); + return TYPE_MATCH_SUCCESS; + } + token_toggle_end(node->token); + } + AstType* ast_type = type->ast_type; AstNode* resolved = try_symbol_resolve_from_node((AstNode *) ast_type, node->token); if (resolved == NULL) { @@ -1655,6 +1683,23 @@ AstStructLiteral* make_optional_literal_some(bh_allocator a, AstTyped *expr, Typ return opt_lit; } +AstStructLiteral* make_union_variant_of_void(bh_allocator a, Type* union_type, OnyxToken* token, UnionVariant* variant) { + AstStructLiteral *lit = onyx_ast_node_new(a, sizeof(AstStructLiteral), Ast_Kind_Struct_Literal); + lit->token = token; + + assert(variant->type == &basic_types[Basic_Kind_Void]); + + arguments_initialize(&lit->args); + arguments_ensure_length(&lit->args, 2); + lit->args.values[0] = (AstTyped *) make_int_literal(a, variant->tag_value); + lit->args.values[1] = (AstTyped *) make_zero_value(a, token, variant->type); + + lit->type = union_type; + lit->args.values[0]->type = union_type->Union.tag_type; + + lit->flags |= Ast_Flag_Has_Been_Checked; + return lit; +} void arguments_initialize(Arguments* args) { diff --git a/core/alloc/memdebug.onyx b/core/alloc/memdebug.onyx index 9df3a61e..4a5b7969 100644 --- a/core/alloc/memdebug.onyx +++ b/core/alloc/memdebug.onyx @@ -58,8 +58,8 @@ make :: (a: Allocator, listen_addr: &net.SocketAddress) -> MemDebugState { return .{ a, *listen_addr, - .{ None = .{} }, - .{ None = .{} } + .None, + .None }; } diff --git a/core/container/optional.onyx b/core/container/optional.onyx index 56a2045a..67041dc7 100644 --- a/core/container/optional.onyx +++ b/core/container/optional.onyx @@ -39,7 +39,7 @@ use core from_ptr :: macro (p: &$T) -> ?T { p_ := p; if p_ do return *p_; - return .{ None = .{} }; + return .None; } #doc """ @@ -53,7 +53,7 @@ use core #doc "Clears the value in the Optional, zeroing the memory of the value." reset :: (o: &?$T) { - *o = .{ None = .{} }; + *o = .None; } #doc "Sets the value in the Optional." @@ -65,7 +65,7 @@ use core and_then :: (o: ?$T, transform: (T) -> ?$R) -> ?R { return switch o { case v: .Some => transform(v); - case #default => .{ None = .{} }; + case #default => .None; }; } @@ -73,7 +73,7 @@ use core transform :: (o: ?$T, transform: (T) -> $R) -> ?R { switch o { case v: .Some do return .{ Some = transform(v) }; - case #default do return .{ None = .{} }; + case #default do return .None; } } diff --git a/core/encoding/kdl/kql.onyx b/core/encoding/kdl/kql.onyx index 4854454a..1df3af36 100644 --- a/core/encoding/kdl/kql.onyx +++ b/core/encoding/kdl/kql.onyx @@ -414,7 +414,7 @@ parse_matcher :: (p: &QueryParser) -> ? &Matcher { m.details << .{ accessor = .{ Scope = .{} }, op = .Equal, - value = .{ None = .{} }, + value = .None, }; } else { @@ -437,7 +437,7 @@ parse_matcher :: (p: &QueryParser) -> ? &Matcher { m.details << .{ accessor = .{ Node = .{} }, op = .Equal, - value = .{ None = .{} }, + value = .None, }; continue; } diff --git a/core/encoding/kdl/parser.onyx b/core/encoding/kdl/parser.onyx index 46f452aa..303f0050 100644 --- a/core/encoding/kdl/parser.onyx +++ b/core/encoding/kdl/parser.onyx @@ -60,7 +60,7 @@ Token :: union { peek_char :: (self: &#Self) -> ? u32 { codepoint_length := utf8.rune_length_from_first_byte(self.doc[self.cursor]); - if self.cursor + codepoint_length >= self.doc.length do return .{ None = .{} }; + if self.cursor + codepoint_length >= self.doc.length do return .None; value := utf8.decode_rune(string.advance(self.doc, self.cursor)); return value; @@ -68,7 +68,7 @@ Token :: union { eat_char :: (self: &#Self) -> ? u32 { codepoint_length := utf8.rune_length_from_first_byte(self.doc[self.cursor]); - if self.cursor + codepoint_length >= self.doc.length do return .{ None = .{} }; + if self.cursor + codepoint_length >= self.doc.length do return .None; value := utf8.decode_rune(string.advance(self.doc, self.cursor)); self.cursor += codepoint_length; @@ -478,7 +478,7 @@ Parse_Error :: union { } }); - return .{ Ok = .{ None = .{} } }; + return .{ Ok = .None }; } parse_identifier :: (self: &#Self) -> Result(? str, Parse_Error) { @@ -491,7 +491,7 @@ Parse_Error :: union { } case .EOF { - return .{ Ok = .{ None = .{} } }; + return .{ Ok = .None }; } case #default { diff --git a/core/encoding/kdl/utils.onyx b/core/encoding/kdl/utils.onyx index fdbf7a13..8c6421a8 100644 --- a/core/encoding/kdl/utils.onyx +++ b/core/encoding/kdl/utils.onyx @@ -25,7 +25,7 @@ use core {string} create_node :: (d: &Document, name: str) -> &Node { return d.allocator->move(Node.{ node = name, - type_annotation = .{ None = .{} }, + type_annotation = .None, values = make([..] Value, d.allocator), props = make(Map(str, Value), d.allocator), children = make([..] &Node, d.allocator) diff --git a/core/runtime/platform/wasi/wasix_misc.onyx b/core/runtime/platform/wasi/wasix_misc.onyx index 98f16bcb..bf1c9bd4 100644 --- a/core/runtime/platform/wasi/wasix_misc.onyx +++ b/core/runtime/platform/wasi/wasix_misc.onyx @@ -6,7 +6,7 @@ use core.os __futex_wait :: (addr: rawptr, expected: i32, timeout: i32) -> i32 { tm: wasi.OptionTimestamp; if timeout < 0 { - tm = .{ None = .{} }; + tm = .None; } else { tm = .{ Some = ~~timeout }; } -- 2.25.1