From: Brendan Hansen Date: Tue, 24 May 2022 01:13:34 +0000 (-0500) Subject: __zero_value(T) -> T.{} X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=0fc3c0f21181a8c77c2f1ecd4ae8ad1b440035c4;p=onyx.git __zero_value(T) -> T.{} --- diff --git a/core/alloc/auto_heap.onyx b/core/alloc/auto_heap.onyx index 05349be2..bd8cbe0b 100644 --- a/core/alloc/auto_heap.onyx +++ b/core/alloc/auto_heap.onyx @@ -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 { diff --git a/core/container/array.onyx b/core/container/array.onyx index a643a4b7..7a5bc4fc 100644 --- a/core/container/array.onyx +++ b/core/container/array.onyx @@ -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; diff --git a/core/container/bucket_array.onyx b/core/container/bucket_array.onyx index f28e89f2..14cc2847 100644 --- a/core/container/bucket_array.onyx +++ b/core/container/bucket_array.onyx @@ -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; diff --git a/core/container/iter.onyx b/core/container/iter.onyx index a2c6813d..2ca0b67e 100644 --- a/core/container/iter.onyx +++ b/core/container/iter.onyx @@ -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 { diff --git a/core/container/list.onyx b/core/container/list.onyx index 56e2f240..ec6022ec 100644 --- a/core/container/list.onyx +++ b/core/container/list.onyx @@ -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; diff --git a/core/container/map.onyx b/core/container/map.onyx index b8db2fb8..5f62d2ef 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -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; diff --git a/core/container/set.onyx b/core/container/set.onyx index 2738e292..c758f0ad 100644 --- a/core/container/set.onyx +++ b/core/container/set.onyx @@ -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; } } diff --git a/core/intrinsics/onyx.onyx b/core/intrinsics/onyx.onyx index ad706468..ff060005 100644 --- a/core/intrinsics/onyx.onyx +++ b/core/intrinsics/onyx.onyx @@ -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 diff --git a/core/net/tcp.onyx b/core/net/tcp.onyx index e845ea18..7c1c917e 100644 --- a/core/net/tcp.onyx +++ b/core/net/tcp.onyx @@ -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; diff --git a/core/os/os.onyx b/core/os/os.onyx index 6eb4c57a..dc16daca 100644 --- a/core/os/os.onyx +++ b/core/os/os.onyx @@ -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; diff --git a/examples/22_interfaces.onyx b/examples/22_interfaces.onyx index d2dcbd9e..1bf958af 100644 --- a/examples/22_interfaces.onyx +++ b/examples/22_interfaces.onyx @@ -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 }; diff --git a/include/astnodes.h b/include/astnodes.h index b337faa4..89b0f082 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -102,7 +102,9 @@ \ 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); diff --git a/misc/vscode/onyx-0.0.3.vsix b/misc/vscode/onyx-0.0.3.vsix index cbf41e65..6768cd37 100644 Binary files a/misc/vscode/onyx-0.0.3.vsix and b/misc/vscode/onyx-0.0.3.vsix differ diff --git a/misc/vscode/syntaxes/onyx.tmLanguage b/misc/vscode/syntaxes/onyx.tmLanguage index df335efd..b35555aa 100644 --- a/misc/vscode/syntaxes/onyx.tmLanguage +++ b/misc/vscode/syntaxes/onyx.tmLanguage @@ -404,6 +404,18 @@ + + match + \b([#]\s*foreign) + captures + + 1 + + name + keyword.tag.onyx entity.name.block.onyx + + + match \b(\b[[:alpha:]_]+[[:alnum:]_\.]*\b)\s*[\(] @@ -465,10 +477,6 @@ string.quoted.double.onyx patterns - - include - #string_placeholder - include #string_escaped_char diff --git a/misc/vscode/textmate-configuration.json b/misc/vscode/textmate-configuration.json index d61a8ec9..23901782 100644 --- a/misc/vscode/textmate-configuration.json +++ b/misc/vscode/textmate-configuration.json @@ -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, diff --git a/modules/ui/components/workspace.onyx b/modules/ui/components/workspace.onyx index 853c28b0..8dfadd7b 100644 --- a/modules/ui/components/workspace.onyx +++ b/modules/ui/components/workspace.onyx @@ -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 = .{ diff --git a/modules/vecmath/vector2.onyx b/modules/vecmath/vector2.onyx index cd186480..1daf4b9f 100644 --- a/modules/vecmath/vector2.onyx +++ b/modules/vecmath/vector2.onyx @@ -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 diff --git a/modules/wasm_utils/instructions.onyx b/modules/wasm_utils/instructions.onyx index 72380e3c..e5bb6cf8 100644 --- a/modules/wasm_utils/instructions.onyx +++ b/modules/wasm_utils/instructions.onyx @@ -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; } diff --git a/scripts/onyx-pkg.onyx b/scripts/onyx-pkg.onyx index 8c7183e2..ad021424 100644 --- a/scripts/onyx-pkg.onyx +++ b/scripts/onyx-pkg.onyx @@ -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" diff --git a/src/astnodes.c b/src/astnodes.c index 2d276316..a2068921 100644 --- a/src/astnodes.c +++ b/src/astnodes.c @@ -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); diff --git a/src/builtins.c b/src/builtins.c index 0c3520e1..a102fa11 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -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 }, diff --git a/src/checker.c b/src/checker.c index 6b198e7f..b7980be8 100644 --- a/src/checker.c +++ b/src/checker.c @@ -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; diff --git a/src/utils.c b/src/utils.c index 79114df6..27802c51 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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; + } } } diff --git a/src/wasm_emit.c b/src/wasm_emit.c index 8fde864b..d97b811f 100644 --- a/src/wasm_emit.c +++ b/src/wasm_emit.c @@ -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