__zero_value(T) -> T.{}
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 24 May 2022 01:13:34 +0000 (20:13 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 24 May 2022 01:13:34 +0000 (20:13 -0500)
24 files changed:
core/alloc/auto_heap.onyx
core/container/array.onyx
core/container/bucket_array.onyx
core/container/iter.onyx
core/container/list.onyx
core/container/map.onyx
core/container/set.onyx
core/intrinsics/onyx.onyx
core/net/tcp.onyx
core/os/os.onyx
examples/22_interfaces.onyx
include/astnodes.h
misc/vscode/onyx-0.0.3.vsix
misc/vscode/syntaxes/onyx.tmLanguage
misc/vscode/textmate-configuration.json
modules/ui/components/workspace.onyx
modules/vecmath/vector2.onyx
modules/wasm_utils/instructions.onyx
scripts/onyx-pkg.onyx
src/astnodes.c
src/builtins.c
src/checker.c
src/utils.c
src/wasm_emit.c

index 05349be238b6588b9812df2a11fea7bbf493183a..bd8cbe0b12caf03344a13a87fe219583ad6babc6 100644 (file)
@@ -1,10 +1,8 @@
 package core.alloc.heap
 
-#local _Z :: (package core.intrinsics.onyx).__zero_value
-
 AutoHeapState :: struct {
     backing_allocator: Allocator;
-    set := _Z(Set(rawptr));
+    set := Set(rawptr).{};
 }
 
 #local auto_heap_alloc_proc :: (data: ^AutoHeapState, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr {
index a643a4b7c0845aedd42e784d186d99228a5f4fe8..7a5bc4fccbc60b9e2bf2d67d5d5f6babb5fdcaa9 100644 (file)
@@ -1,7 +1,5 @@
 package core.array
 
-use package core.intrinsics.onyx { __zero_value }
-
 // [..] T == Array(T)
 //   where
 // Array :: struct (T: type_expr) {
@@ -152,7 +150,7 @@ remove :: (arr: ^[..] $T, elem: T) {
 }
 
 delete :: (arr: ^[..] $T, idx: u32) -> T {
-    if idx >= arr.count do return __zero_value(T);
+    if idx >= arr.count do return .{};
 
     to_return := arr.data[idx];
     for i: idx .. arr.count - 1 {
@@ -164,7 +162,7 @@ delete :: (arr: ^[..] $T, idx: u32) -> T {
 }
 
 fast_delete :: (arr: ^[..] $T, idx: u32) -> T {
-    if idx >= arr.count do return __zero_value(T);
+    if idx >= arr.count do return .{};
 
     to_return := arr.data[idx];
     if idx != arr.count - 1 do arr.data[idx] = arr.data[arr.count - 1];
@@ -174,7 +172,7 @@ fast_delete :: (arr: ^[..] $T, idx: u32) -> T {
 }
 
 pop :: (arr: ^[..] $T) -> T {
-    if arr.count == 0 do return __zero_value(T);
+    if arr.count == 0 do return .{};
 
     arr.count -= 1;
     return arr.data[arr.count];
@@ -265,7 +263,7 @@ transplant :: (arr: [] $T, old_index: i32, new_index: i32) -> bool {
 }
 
 get :: (arr: [] $T, idx: i32) -> T {
-    if arr.count == 0 do return __zero_value(T);
+    if arr.count == 0 do return .{};
 
     while idx < 0          do idx += arr.count;
     while idx >= arr.count do idx -= arr.count;
index f28e89f22d53ba6b9217a8f5c09e5a67e55954d4..14cc2847ca0d7a7e0e0fd951bf9876fd1d3a2ec0 100644 (file)
@@ -121,7 +121,7 @@ iterator :: (b: ^Bucket_Array($T)) -> Iterator(T) {
         bucket := ^ba.buckets[bucket_idx];
         while elem_idx == bucket.count {
             bucket_idx += 1;
-            if bucket_idx == ba.buckets.count do return __zero_value(T), false;
+            if bucket_idx == ba.buckets.count do return .{}, false;
 
             bucket = ^ba.buckets[bucket_idx];
             elem_idx = 0;
index a2c6813da128d0b65fbcb82b204c6e5d0477081f..2ca0b67e11c336d6222228afcba43a2e9770c6b5 100644 (file)
@@ -1,6 +1,5 @@
 package core.iter
 
-use package core.intrinsics.onyx { __zero_value }
 #local memory :: package core.memory
 #local alloc  :: package core.alloc
 
@@ -132,7 +131,7 @@ map :: #match {}
 
     next :: (mi: ^MapIterator($T, $R)) -> (R, bool) {
         value, cont := mi.iterator.next(mi.iterator.data);
-        if !cont do return __zero_value(R), false;
+        if !cont do return .{}, false;
 
         return mi.transform(value), true;
     }
@@ -165,7 +164,7 @@ map :: #match {}
 
     next :: (mi: ^MapIterator($T, $R, $Ctx)) -> (R, bool) {
         value, cont := mi.iterator.next(mi.iterator.data);
-        if !cont do return __zero_value(R), false;
+        if !cont do return .{}, false;
 
         return mi.transform(value, mi.ctx), true;
     }
@@ -219,7 +218,7 @@ take :: (it: Iterator($T), count: u32, allocator := iter_allocator) -> Iterator(
     take_iterator.allocator = allocator;
 
     next :: ($T: type_expr, ti: ^TakeIterator(T)) -> (T, bool) {
-        if ti.remaining == 0 do return __zero_value(T), false;
+        if ti.remaining == 0 do return .{}, false;
 
         ti.remaining -= 1;
         return ti.iterator.next(ti.iterator.data);
@@ -356,7 +355,7 @@ concat :: (iters: ..Iterator($T)) -> Iterator(T) {
 
     next :: (use c: ^Context($T)) -> (T, bool) {
         while true {
-            if idx >= iters.count do return __zero_value(T), false;        
+            if idx >= iters.count do return .{}, false;        
 
             curr_iter := ^iters[idx];
             value, valid := curr_iter.next(curr_iter.data);
@@ -426,7 +425,7 @@ enumerate :: #match {}
     next :: (use data: ^Enumeration_Context($T)) -> (Enumeration_Value(T), bool) {
         value, cont := iterator.next(iterator.data);
 
-        if !cont do return .{ current_index, __zero_value(T) }, false;
+        if !cont do return .{ current_index, .{} }, false;
 
         defer current_index += 1;
         return .{ current_index, value }, true;
@@ -489,7 +488,7 @@ from_array :: (arr: [] $T) -> Iterator(^T) {
             return arr.data[current], true;
 
         } else {
-            return __zero_value(T), false;
+            return .{}, false;
         }
     }
 
@@ -659,7 +658,7 @@ to_array :: (it: Iterator($T), allocator := context.allocator) -> [..] T {
         }
 
         next :: (use c: ^Context($T)) -> (T, bool) {
-            if ended do return __zero_value(T), false;
+            if ended do return .{}, false;
             sync.scoped_mutex(^mutex);
 
             if v, success := take_one(iterator); !success {
index 56e2f240318211face61953e4eebec718974f25b..ec6022ec3fcffbb25f58c18e90983dd1070202c3 100644 (file)
@@ -1,7 +1,5 @@
 package core.list
 
-use package core.intrinsics.onyx { __zero_value }
-
 ListElem :: struct (T: type_expr) {
     next: ^ListElem(T) = null;
     prev: ^ListElem(T) = null;
@@ -63,7 +61,7 @@ push_begin :: (list: ^List, x: list.Elem_Type) {
     if list.last == null do list.last = new_elem;
 }
 
-pop_end :: (list: ^List($T), default: T = __zero_value(T)) -> T {
+pop_end :: (list: ^List($T), default: T = .{}) -> T {
     if list.last == null do return default;
 
     end := list.last;
@@ -74,7 +72,7 @@ pop_end :: (list: ^List($T), default: T = __zero_value(T)) -> T {
     return end.data;
 }
 
-pop_begin :: (list: ^List($T), default: T = __zero_value(T)) -> T {
+pop_begin :: (list: ^List($T), default: T = .{}) -> T {
     if list.last == null do return default;
 
     begin := list.first;
@@ -151,8 +149,7 @@ map :: #match {}
 #match iter.as_iterator get_iterator
 get_iterator :: (list: ^List($T)) -> Iterator(T) {
     iterator_next :: (list_iter: ^ListIterator($T)) -> (T, bool) {
-        use package core.intrinsics.onyx { __zero_value }
-        if list_iter.current == null do return __zero_value(T), false;
+        if list_iter.current == null do return .{}, false;
 
         defer list_iter.current = list_iter.current.next;
         return list_iter.current.data, true;
index b8db2fb8d2f03cb0ad9e577eca50968277e7bc10..5f62d2ef99f0b8f88e93c237955441aebfba5a73 100644 (file)
@@ -7,7 +7,7 @@ package core.map
     math   :: package core.math
     conv   :: package core.conv
 
-    use package core.intrinsics.onyx { __zero_value, __initialize }
+    use package core.intrinsics.onyx { __initialize }
 }
 
 #local {
@@ -55,7 +55,7 @@ Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Ty
     empty   :: (package core.map).empty
 }
 
-make :: ($Key: type_expr, $Value: type_expr, default := __zero_value(Value)) -> Map(Key, Value) {
+make :: ($Key: type_expr, $Value: type_expr, default := Value.{}) -> Map(Key, Value) {
     map : Map(Key, Value);
     init(^map, default = default);
     return map;
@@ -63,7 +63,7 @@ make :: ($Key: type_expr, $Value: type_expr, default := __zero_value(Value)) ->
 
 #match (package builtin).__make_overload macro (x: ^Map($K, $V), allocator := context.allocator) => (package core.map).make(K, V);
 
-init :: (use map: ^Map($K, $V), default := __zero_value(V)) {
+init :: (use map: ^Map($K, $V), default := V.{}) {
     __initialize(map);
 
     allocator = context.allocator;
index 2738e2924ed10729967f45d5eebd8932c8765787..c758f0adab19460c933026c171d76574d4dbb717 100644 (file)
@@ -6,7 +6,6 @@ package core.set
     memory :: package core.memory
     math :: package core.math
 }
-use package core.intrinsics.onyx { __zero_value }
 
 #local SetValue :: interface (t: $T) {
     { hash.to_u32(t) } -> u32;
@@ -39,7 +38,7 @@ Set :: struct (Elem_Type: type_expr) where SetValue(Elem_Type) {
     iterator :: iterator
 }
 
-make :: ($T: type_expr, default := __zero_value(T), allocator := context.allocator) -> Set(T) {
+make :: ($T: type_expr, default := T.{}, allocator := context.allocator) -> Set(T) {
     set : Set(T);
     init(^set, default=default, allocator=allocator);
     return set;
@@ -47,7 +46,7 @@ make :: ($T: type_expr, default := __zero_value(T), allocator := context.allocat
 
 #match (package builtin).__make_overload macro (x: ^Set, allocator: Allocator) => (package core.set).make(x.Elem_Type, allocator = allocator);
 
-init :: (set: ^Set($T), default := __zero_value(T), allocator := context.allocator) {
+init :: (set: ^Set($T), default := T.{}, allocator := context.allocator) {
     set.allocator = allocator;
     set.default_value = default;
 
@@ -85,7 +84,7 @@ has :: (use set: ^Set, value: set.Elem_Type) -> bool {
 
 get :: (use set: ^Set, value: set.Elem_Type) -> set.Elem_Type {
     lr := lookup(set, value);
-    return entries[lr.entry_index].value if lr.entry_index >= 0 else __zero_value(set.Elem_Type);
+    return entries[lr.entry_index].value if lr.entry_index >= 0 else set.Elem_Type.{};
 }
 
 get_ptr :: (use set: ^Set, value: set.Elem_Type) -> ^set.Elem_Type {
@@ -137,7 +136,7 @@ iterator :: (set: ^Set($T)) -> Iterator(T) {
             return set.entries[position].value, true;
 
         } else {
-            return __zero_value(T), false;
+            return .{}, false;
         }
     }
 
index ad7064681ee814ac3de758bc8a429ee47dea9de7..ff06000579f4ab5d1b12197ee098f4bf793b0a78 100644 (file)
@@ -1,7 +1,6 @@
 package core.intrinsics.onyx
 
 __initialize :: (val: ^$T)      -> void #intrinsic ---
-__zero_value :: ($T: type_expr) -> T    #intrinsic ---
 
 init :: macro ($T: type_expr) -> T {
     __initialize :: __initialize
index e845ea18e03faf52d98a0b465f0ffbadfd68dd57..7c1c917e4727109b2859275e18080e000b8df075 100644 (file)
@@ -8,8 +8,6 @@ package core.net
     memory  :: package core.memory
     alloc   :: package core.alloc
     os      :: package core.os
-
-    use package core.intrinsics.onyx { __zero_value }
 }
 
 #if !runtime.Multi_Threading_Enabled {
@@ -62,7 +60,7 @@ TCP_Event :: struct {
 
 tcp_get_events :: (use conn: ^TCP_Connection) -> Iterator(TCP_Event) {
     next :: (use conn: ^TCP_Connection) -> (TCP_Event, bool) {
-        if event_cursor == events.count do return __zero_value(TCP_Event), false;
+        if event_cursor == events.count do return .{}, false;
 
         defer event_cursor += 1;
         return events[event_cursor], true;
index 6eb4c57a245327098e05d6b3e44dd15d3b98eb59..dc16daca7c2785fd6cbaeb0ef59c281a314b8bc6 100644 (file)
@@ -17,12 +17,11 @@ list_directory :: (path: str) -> Iterator(DirectoryEntry) {
     }
 
     next :: (use c: ^Context) -> (DirectoryEntry, bool) {
-        use package core.intrinsics.onyx {__zero_value}
-        if !opened do return __zero_value(DirectoryEntry), false;
+        if !opened do return .{}, false;
 
         entry: DirectoryEntry;
         if !dir_read(dir, ^entry) {
-            return __zero_value(DirectoryEntry), false;
+            return .{}, false;
         }
 
         return entry, true;
index d2dcbd9e7bf1b2b59ed5ae565a3ab10a4a3198d2..1bf958afecce30f727eeca6e1fabe167690d7296 100644 (file)
@@ -72,8 +72,8 @@ NumberLike :: interface (t: $T) {
 // Here, Vector2 has the type constraint of NumberLike for T. This constraint
 // is checked when Vector2 is constructed with any parameters.
 Vector2 :: struct (T: type_expr) where NumberLike(T) {
-    x := __zero_value(T);
-    y := __zero_value(T);
+    x := T.{};
+    y := T.{};
 }
 
 #operator + (x, y: Vector2($T)) => Vector2(T).{ x.x + y.x, x.y + y.y };
index b337faa49e518d58e8038efa298a0cb641db156c..89b0f0827e90e31a45c76d55f59ccb5b04d9522d 100644 (file)
                                \
     NODE(ForeignBlock)         \
                                \
-    NODE(Package)          
+    NODE(Package)              \
+                               \
+    NODE(ZeroValue)
 
 #define NODE(name) typedef struct Ast ## name Ast ## name;
 AST_NODES
@@ -222,6 +224,8 @@ typedef enum AstKind {
 
     Ast_Kind_Foreign_Block,
 
+    Ast_Kind_Zero_Value,
+
     Ast_Kind_Note,
 
     Ast_Kind_Count
@@ -342,7 +346,7 @@ typedef enum OnyxIntrinsic {
     ONYX_INTRINSIC_MEMORY_SIZE, ONYX_INTRINSIC_MEMORY_GROW,
     ONYX_INTRINSIC_MEMORY_COPY, ONYX_INTRINSIC_MEMORY_FILL,
 
-    ONYX_INTRINSIC_INITIALIZE, ONYX_INTRINSIC_ZERO_VALUE,
+    ONYX_INTRINSIC_INITIALIZE,
 
     ONYX_INTRINSIC_I32_CLZ,   ONYX_INTRINSIC_I32_CTZ, ONYX_INTRINSIC_I32_POPCNT,
     ONYX_INTRINSIC_I32_AND,   ONYX_INTRINSIC_I32_OR,  ONYX_INTRINSIC_I32_XOR,
@@ -718,6 +722,9 @@ struct AstDoBlock {
 
     AstBlock* block;
 };
+struct AstZeroValue {
+    AstTyped_base;
+};
 
 struct AstDirectiveSolidify {
     AstTyped_base;
@@ -1656,9 +1663,10 @@ AstAddressOf*    make_address_of(bh_allocator a, AstTyped* node);
 AstLocal*        make_local(bh_allocator a, OnyxToken* token, AstType* type_node);
 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);
 
 void arguments_initialize(Arguments* args);
-b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg);
+b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg, b32 insert_zero_values);
 void arguments_ensure_length(Arguments* args, u32 count);
 void arguments_copy(Arguments* dest, Arguments* src);
 void arguments_clone(Arguments* dest, Arguments* src);
index cbf41e65aaa3d4b541b70e21a9a709251c2665e7..6768cd37cd54653daa1aedc129809523e40fc0e8 100644 (file)
Binary files a/misc/vscode/onyx-0.0.3.vsix and b/misc/vscode/onyx-0.0.3.vsix differ
index df335efda14674a0a242baeb79acf251fe22f5cb..b35555aa9ca61588e7be725b9997d6b6a80edcf9 100644 (file)
                                                </dict>
                                        </dict>
                                </dict>
+                               <dict>
+                                       <key>match</key>
+                                       <string>\b([#]\s*foreign)</string>
+                                       <key>captures</key>
+                                       <dict>
+                                               <key>1</key>
+                                               <dict>
+                                                       <key>name</key>
+                                                       <string>keyword.tag.onyx entity.name.block.onyx</string>
+                                               </dict>
+                                       </dict>
+                               </dict>
                                <dict>
                                        <key>match</key>
                                        <string>\b(\b[[:alpha:]_]+[[:alnum:]_\.]*\b)\s*[\(]</string>
                                        <string>string.quoted.double.onyx</string>
                                        <key>patterns</key>
                                        <array>
-                                               <dict>
-                                                       <key>include</key>
-                                                       <string>#string_placeholder</string>
-                                               </dict>
                                                <dict>
                                                        <key>include</key>
                                                        <string>#string_escaped_char</string>
index d61a8ec964f0943b6c0990abc84acea51e3ab263..23901782624b7865233ac1b58689c0bc6b48b07f 100644 (file)
@@ -21,7 +21,8 @@
     },
     "declarations": [
         "entity.name.function.onyx",
-        "entity.name.type.onyx"
+        "entity.name.type.onyx",
+        "entity.name.block.onyx"
     ],
     "indentation": {
       "punctuation.block.begin.onyx": 1,
index 853c28b06c28e8a0db35a58926bcc4b618cd709a..8dfadd7b752014e59668309ce19c8645e394d3bc 100644 (file)
@@ -1,7 +1,7 @@
 package ui
 
 use package core
-use package core.intrinsics.onyx { __zero_value, __initialize }
+use package core.intrinsics.onyx { __initialize }
 
 Workspace_State :: struct {
     transform: gfx.Transform = .{
index cd1864805c126f4f342d6fe7c2d64e96b191ec0f..1daf4b9f373d21ccd1bbd6df3c9ca7e023e2c6dc 100644 (file)
@@ -1,14 +1,13 @@
 package vecmath
 
 #local io :: package core.io
-use package core.intrinsics.onyx { __zero_value }
 
 Vector2i :: #type Vector2(i32);
 Vector2f :: #type Vector2(f32);
 
 Vector2 :: struct (T: type_expr) {
-    x := __zero_value(T);
-    y := __zero_value(T);
+    x := T.{};
+    y := T.{};
 }
 
 #operator + vector2_add
index 72380e3c9f20b3b57fea7637db82621f9fa5e5b3..e5bb6cf8be1021bd26d4ec75cf96d7d42c019f37 100644 (file)
@@ -1,7 +1,5 @@
 package wasm_utils
 
-Z :: (package core.intrinsics.onyx).__zero_value
-
 WasmInstructionCode :: enum {
     unreachable   :: 0x00;
     nop           :: 0x01;
@@ -252,7 +250,7 @@ instruction_iterator :: (binary: ^WasmBinary, code: ^WasmCode, allocator := cont
     data.reader = io.reader_make(^data.stream);
 
     next :: (use c: ^CodeContext) -> (WasmInstruction, bool) {
-        if current_block_depth == 0 do return Z(WasmInstruction), false;
+        if current_block_depth == 0 do return .{}, false;
 
         return parse_instruction(^reader, binary, code.code_offset, ^current_block_depth), true;
     }
index 8c7183e26f369b3beb68bf1d592e5fb7976efc7e..ad021424a33aeba8eccbe04e1bffa18e81d60b8e 100644 (file)
@@ -4,7 +4,7 @@
 Version :: SemVer.{0, 1, 1}
 
 use core
-use core.intrinsics.onyx {__initialize, __zero_value}
+use core.intrinsics.onyx {__initialize}
 
 global_arguments: struct {
     #tag "--config-file"
index 2d276316296ff75ca1c54c3960da296905f7b45d..a2068921a64a05957c7f579eb48522c4b0edfa0e 100644 (file)
@@ -105,6 +105,7 @@ static const char* ast_node_names[] = {
     "DO BLOCK",
 
     "FOREIGN BLOCK",
+    "ZERO VALUE",
 
     "NOTE",
 
@@ -567,7 +568,18 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
     if (node->kind == Ast_Kind_Struct_Literal && (node->type_node == NULL && node->type == NULL)) {
         if (node->entity != NULL) return TYPE_MATCH_SUCCESS;
         if (type->kind == Type_Kind_VarArgs) type = type->VarArgs.elem;
-        if (!type_is_sl_constructable(type)) return TYPE_MATCH_FAILED;
+
+        //
+        // If the structure literal has arguments, and the type is not constructable
+        // using a struct literal, then they cannot be unified. However, if no arguments
+        // are given, e.g. .{}, then any type should be matched, as that is the universal
+        // zero-value.
+        if (!type_is_sl_constructable(type)) {
+            AstStructLiteral *sl = (AstStructLiteral *) node;
+            if (bh_arr_length(sl->args.values) != 0 || bh_arr_length(sl->args.named_values) != 0) {
+                return TYPE_MATCH_FAILED;
+            }
+        }
 
         // If this shouldn't make permanent changes and submit entities,
         // just assume that it works and don't submit the entities.
@@ -781,6 +793,13 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
         }
     }
 
+    else if (node->kind == Ast_Kind_Zero_Value) {
+        if (node_type == NULL) {
+            node->type = type;
+            return TYPE_MATCH_SUCCESS;
+        }
+    }
+
     return TYPE_MATCH_FAILED;
 }
 
@@ -1195,6 +1214,14 @@ AstUnaryOp* make_cast(bh_allocator a, AstTyped* expr, Type* to) {
     return cast;
 }
 
+AstZeroValue* make_zero_value(bh_allocator a, OnyxToken* token, Type* type) {
+    AstZeroValue* zero_value = onyx_ast_node_new(a, sizeof(AstZeroValue), Ast_Kind_Zero_Value);
+    zero_value->token = token;
+    zero_value->flags |= Ast_Flag_Comptime;
+    zero_value->type = type;
+    return zero_value;
+}
+
 void arguments_initialize(Arguments* args) {
     if (args->values == NULL)       bh_arr_new(global_heap_allocator, args->values, 2);
     if (args->named_values == NULL) bh_arr_new(global_heap_allocator, args->named_values, 2);
index 0c3520e1cdb90d6e554c1a4bfaffd40bb956739c..a102fa11a5eada16144cc04b049282ae9ac513cf 100644 (file)
@@ -109,7 +109,6 @@ static IntrinsicMap builtin_intrinsics[] = {
     { "memory_fill",  ONYX_INTRINSIC_MEMORY_FILL },
 
     { "__initialize", ONYX_INTRINSIC_INITIALIZE },
-    { "__zero_value", ONYX_INTRINSIC_ZERO_VALUE },
 
     { "clz_i32",      ONYX_INTRINSIC_I32_CLZ },
     { "ctz_i32",      ONYX_INTRINSIC_I32_CTZ },
index 6b198e7f30c67ea422970c71bf4d16664bb5697e..b7980be821ca7ff59cba6212a4a3a9a0ee1b4181 100644 (file)
@@ -635,7 +635,7 @@ CheckStatus check_call(AstCall** pcall) {
     arguments_ensure_length(&call->args, arg_count);
 
     char* err_msg = NULL;
-    fill_in_arguments(&call->args, (AstNode *) callee, &err_msg);
+    fill_in_arguments(&call->args, (AstNode *) callee, &err_msg, 0);
     if (err_msg != NULL) ERROR(call->token->pos, err_msg);
 
     bh_arr(AstArgument *) arg_arr = (bh_arr(AstArgument *)) call->args.values;
@@ -1226,6 +1226,26 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) {
     }
 
     if (!type_is_structlike_strict(sl->type)) {
+        //
+        // If there are no given arguments to a structure literal, it is treated as a 'zero-value',
+        // and can be used to create a completely zeroed value of any type.
+        if (bh_arr_length(sl->args.values) == 0 && bh_arr_length(sl->args.named_values) == 0) {
+            AstZeroValue *zv = make_zero_value(context.ast_alloc, sl->token, sl->type);
+            bh_arr_push(sl->args.values, (AstTyped *) zv);
+
+            sl->flags |= Ast_Flag_Has_Been_Checked;
+            return Check_Success;
+        }
+
+        if ((sl->flags & Ast_Flag_Has_Been_Checked) != 0) {
+            assert(sl->args.values);
+            assert(sl->args.values[0]);
+            assert(sl->args.values[0]->kind == Ast_Kind_Zero_Value);
+            return Check_Success;
+        }
+
+        //
+        // Otherwise, it is not possible to construct the type if it is not a structure.
         ERROR_(sl->token->pos,
                 "'%s' is not constructable using a struct literal.",
                 type_get_name(sl->type));
@@ -1237,7 +1257,7 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) {
     // :Idempotency
     if ((sl->flags & Ast_Flag_Has_Been_Checked) == 0) {
         char* err_msg = NULL;
-        if (!fill_in_arguments(&sl->args, (AstNode *) sl, &err_msg)) {
+        if (!fill_in_arguments(&sl->args, (AstNode *) sl, &err_msg, 1)) {
             onyx_report_error(sl->token->pos, Error_Critical, err_msg);
 
             bh_arr_each(AstTyped *, value, sl->args.values) {
@@ -1908,6 +1928,7 @@ CheckStatus check_expression(AstTyped** pexpr) {
         case Ast_Kind_Constraint_Sentinel: break;
         case Ast_Kind_Switch_Case: break;
         case Ast_Kind_Foreign_Block: break;
+        case Ast_Kind_Zero_Value: break;
 
         default:
             retval = Check_Error;
index 79114df656e5571b135988800544dcff4df1d43a..27802c51e76127d0d774d3d358d4fcdbf45ed285 100644 (file)
@@ -449,7 +449,7 @@ AstTyped* find_matching_overload_by_arguments(bh_arr(OverloadOption) overloads,
         arguments_ensure_length(&args, get_argument_buffer_size(&overload->type->Function, &args));
 
         // NOTE: If the arguments cannot be placed successfully in the parameters list
-        if (!fill_in_arguments(&args, (AstNode *) overload, NULL)) continue;
+        if (!fill_in_arguments(&args, (AstNode *) overload, NULL, 0)) continue;
         
         VarArgKind va_kind;
         TypeMatch tm = check_arguments_against_type(&args, &overload->type->Function, &va_kind, NULL, NULL, NULL);
@@ -747,7 +747,7 @@ i32 get_argument_buffer_size(TypeFunction* type, Arguments* args) {
 
 // NOTE: The values array can be partially filled out, and is the resulting array.
 // Returns if all the values were filled in.
-b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg) {
+b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg, b32 insert_zero_values) {
 
     { // Delete baked arguments
         // :ArgumentResolvingIsComplicated
@@ -808,8 +808,13 @@ b32 fill_in_arguments(Arguments* args, AstNode* provider, char** err_msg) {
     fori (idx, 0, bh_arr_length(args->values)) {
         if (args->values[idx] == NULL) args->values[idx] = (AstTyped *) lookup_default_value_by_idx(provider, idx);
         if (args->values[idx] == NULL) {
-            if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator, "No value given for %d%s argument.", idx + 1, bh_num_suffix(idx + 1));
-            success = 0;
+            if (insert_zero_values) {
+                assert(provider->token);
+                args->values[idx] = (AstTyped *) make_zero_value(context.ast_alloc, provider->token, NULL);
+            } else {
+                if (err_msg) *err_msg = bh_aprintf(global_scratch_allocator, "No value given for %d%s argument.", idx + 1, bh_num_suffix(idx + 1));
+                success = 0;
+            }
         }
     }
 
index 8fde864bb33064e49cc872e6c31c8aa1d2f13ba5..d97b811f47090d1647f16806014037610b879e91 100644 (file)
@@ -1835,13 +1835,6 @@ EMIT_FUNC(intrinsic_call, AstCall* call) {
             break;
         }
 
-        case ONYX_INTRINSIC_ZERO_VALUE: {
-            // NOTE: This probably will not have to make an allocation.
-            Type* zero_type = type_build_from_ast(context.ast_alloc, (AstType *) ((AstArgument *) call->original_args.values[0])->value);
-            emit_zero_value_for_type(mod, &code, zero_type, call->token);
-            break;
-        }
-
         case ONYX_INTRINSIC_I32_CLZ:      WI(WI_I32_CLZ); break;
         case ONYX_INTRINSIC_I32_CTZ:      WI(WI_I32_CTZ); break;
         case ONYX_INTRINSIC_I32_POPCNT:   WI(WI_I32_POPCNT); break;
@@ -3019,6 +3012,13 @@ EMIT_FUNC(expression, AstTyped* expr) {
             break;
         }
 
+        case Ast_Kind_Zero_Value: {
+            AstZeroValue *zv = (AstZeroValue *) expr;
+            assert(zv->type);
+            emit_zero_value_for_type(mod, &code, zv->type, zv->token);
+            break;
+        }
+
         default:
             bh_printf("Unhandled case: %d\n", expr->kind);
             DEBUG_HERE;
@@ -3667,6 +3667,11 @@ static b32 emit_raw_data_(OnyxWasmModule* mod, ptr data, AstTyped* node) {
         break;
     }
 
+    case Ast_Kind_Zero_Value: {
+        memset(data, 0, type_size_of(node->type));
+        break;
+    }
+
     case Ast_Kind_NumLit: {
         // NOTE: This makes a big assumption that we are running on a
         // little endian machine, since WebAssembly is little endian