feat: execute value-returning compile-time metadata helpers
This commit is contained in:
@@ -132,6 +132,8 @@ ordinary procedures also accept `undefined` as the initializer of a mutable loca
|
|||||||
|
|
||||||
procedures returning fixed arrays or records/tuples containing `type`, such as `types proc() [2]type { return [i16, bool] }` or `config proc() struct { child type, count usize } { return { child = i16, count = 2 } }`, execute entirely at compile time. every argument is explicitly supplied, constant, cached and erased; nested/aliased results, empty shapes and dependent `$N` lengths retain exact shape and mutability. compile-time producers accept ordinary type-array/type-record inputs, and runtime generic procedures accept erased `$` parameters with these shapes. direct projections generate signatures, constructors, storage and defaults; explicit `$()` calls inside producers retain owned values. cache identity uses canonical type leaves without merging distinct nominal types, and copies cannot mutate cached inputs/results. imported diagnostics, shared type-control execution limits and repeatable compilation work through interpreter/native execution. ordinary parameters remain excluded from dependent signatures; use `$N` for lengths. runtime type-array/type-record storage and reflection remain open.
|
procedures returning fixed arrays or records/tuples containing `type`, such as `types proc() [2]type { return [i16, bool] }` or `config proc() struct { child type, count usize } { return { child = i16, count = 2 } }`, execute entirely at compile time. every argument is explicitly supplied, constant, cached and erased; nested/aliased results, empty shapes and dependent `$N` lengths retain exact shape and mutability. compile-time producers accept ordinary type-array/type-record inputs, and runtime generic procedures accept erased `$` parameters with these shapes. direct projections generate signatures, constructors, storage and defaults; explicit `$()` calls inside producers retain owned values. cache identity uses canonical type leaves without merging distinct nominal types, and copies cannot mutate cached inputs/results. imported diagnostics, shared type-control execution limits and repeatable compilation work through interpreter/native execution. ordinary parameters remain excluded from dependent signatures; use `$N` for lengths. runtime type-array/type-record storage and reflection remain open.
|
||||||
|
|
||||||
|
ordinary parameters containing `type` also make a procedure compile-time-only, even when its result is a runtime value. for example, `count proc(types []type) usize { return types.len }` computes `count([i16, bool])` without runtime metadata. every input must be explicitly supplied and constant; use `$` parameters when later signature annotations depend on them. helpers can return owned scalar, aggregate and string values, recurse over metadata and use checked `try`/`catch` with scoped cleanup. plain and fallible `void` support bare returns and successful fallthrough. ordinary runtime dependencies and incomplete metadata arguments remain diagnostic; mutable metadata borrowing and general type-valued execution remain open.
|
||||||
|
|
||||||
readonly type-valued slices (`[]type` and slices of metadata records/arrays) also cross compile-time procedure boundaries as owned snapshots. contextual array literals, including `[]`, construct them; explicit views of immutable readonly arrays and existing metadata slices support checked `usize` bounds, empty end views, indexing and `.len`. nested slices, ordinary/inline by-value iteration, erased `$` inputs and optional/fallible channels retain exact nominal leaves and content-based specialization identity. snapshots generate runtime types/defaults, but metadata itself has no runtime storage. mutable slice types, sentinels and views of mutable array places remain rejected rather than silently losing borrowing semantics; copy an array into an immutable binding before taking an owned view. construction shares the type-control step bound, and uninitialized leaves cannot cross procedure boundaries.
|
readonly type-valued slices (`[]type` and slices of metadata records/arrays) also cross compile-time procedure boundaries as owned snapshots. contextual array literals, including `[]`, construct them; explicit views of immutable readonly arrays and existing metadata slices support checked `usize` bounds, empty end views, indexing and `.len`. nested slices, ordinary/inline by-value iteration, erased `$` inputs and optional/fallible channels retain exact nominal leaves and content-based specialization identity. snapshots generate runtime types/defaults, but metadata itself has no runtime storage. mutable slice types, sentinels and views of mutable array places remain rejected rather than silently losing borrowing semantics; copy an array into an immutable binding before taking an owned view. construction shares the type-control step bound, and uninitialized leaves cannot cross procedure boundaries.
|
||||||
|
|
||||||
optional `if`/`while` captures also execute in type-producing bodies: `if count |length| { return [length]i16 }` generates storage from an optional `usize`. ordinary checked IR validates each executed guard; present payloads become immutable owned constants with exact scalar/aggregate types and strings, and absent optionals skip the body. while guards observe updated locals on each iteration; captures stay body-local across break/continue and early return. generated lengths/defaults, imported producers, cache identity and repeated compilation preserve these values. null data/function pointers materialize as null; callbacks retain source declaration identity, while nonnull data pointers and unsupported slice types retain the constant-materialization escape boundary.
|
optional `if`/`while` captures also execute in type-producing bodies: `if count |length| { return [length]i16 }` generates storage from an optional `usize`. ordinary checked IR validates each executed guard; present payloads become immutable owned constants with exact scalar/aggregate types and strings, and absent optionals skip the body. while guards observe updated locals on each iteration; captures stay body-local across break/continue and early return. generated lengths/defaults, imported producers, cache identity and repeated compilation preserve these values. null data/function pointers materialize as null; callbacks retain source declaration identity, while nonnull data pointers and unsupported slice types retain the constant-materialization escape boundary.
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ initialize undefined storage or select another variant.
|
|||||||
readonly type-valued slices own nested metadata leaves across compile-time calls,
|
readonly type-valued slices own nested metadata leaves across compile-time calls,
|
||||||
checked immutable-array/slice views, by-value iteration and erased arguments;
|
checked immutable-array/slice views, by-value iteration and erased arguments;
|
||||||
mutable metadata borrowing remains open.
|
mutable metadata borrowing remains open.
|
||||||
|
ordinary metadata-input procedures also compute owned runtime values, including
|
||||||
|
reflected field names/counts, recursive helpers and fallible cleanup.
|
||||||
`field!` selects record/tuple/enum and sequence members using compile-time names,
|
`field!` selects record/tuple/enum and sequence members using compile-time names,
|
||||||
including runtime places and type-control updates without runtime reflection.
|
including runtime places and type-control updates without runtime reflection.
|
||||||
`struct_type!` generates ordinary/C-layout records from constant name/type/default
|
`struct_type!` generates ordinary/C-layout records from constant name/type/default
|
||||||
@@ -169,6 +171,7 @@ test discovery and FFI remain outside these completed slices.
|
|||||||
- [x] fallible type-storage checkpoint: explicit success/error channels containing types use owned compile-time snapshots, including nested optional/record/array payloads, whole-value updates, independent copies, constant-input procedures and erased generic inputs. `try` validates error subsets and propagates through enclosing producers; `catch` binds immutable exact error payloads and selects generated types or runtime handlers. composed metadata errors preserve named variants, nominal leaves and cache identity. returned snapshots precede scoped LIFO `defer`/`errdefer` cleanup; fallible `void` supports bare returns and successful fallthrough. incomplete/uninitialized channels, invalid payloads/compositions, capture mutation and runtime dependencies retain diagnostics. imported private types, source/session disposal and repeat compilation preserve ownership through interpreter/native execution. runtime metadata storage, general type-valued execution and broader materialization remain open.
|
- [x] fallible type-storage checkpoint: explicit success/error channels containing types use owned compile-time snapshots, including nested optional/record/array payloads, whole-value updates, independent copies, constant-input procedures and erased generic inputs. `try` validates error subsets and propagates through enclosing producers; `catch` binds immutable exact error payloads and selects generated types or runtime handlers. composed metadata errors preserve named variants, nominal leaves and cache identity. returned snapshots precede scoped LIFO `defer`/`errdefer` cleanup; fallible `void` supports bare returns and successful fallthrough. incomplete/uninitialized channels, invalid payloads/compositions, capture mutation and runtime dependencies retain diagnostics. imported private types, source/session disposal and repeat compilation preserve ownership through interpreter/native execution. runtime metadata storage, general type-valued execution and broader materialization remain open.
|
||||||
- [x] readonly type-slice checkpoint: `[]type` and slices of type-valued records/arrays use owned compile-time snapshots. contextual literals, immutable readonly array views, nested slice views, checked `usize` bounds/indexing, `.len`, empty shapes and ordinary/inline by-value iteration preserve exact nominal leaves. constant-input procedure parameters/results, erased generic inputs, optional/fallible nesting and normalized cache keys generate runtime storage/defaults through interpreter/native execution. mutable annotations/backing, metadata sentinels, invalid ranges/indices, readonly writes, incomplete leaves and runtime dependencies retain diagnostics. imported private types, source/session disposal, shared construction bounds and repeat compilation preserve ownership. mutable metadata borrowing, runtime metadata storage, general type-valued execution and broader constant materialization remain open.
|
- [x] readonly type-slice checkpoint: `[]type` and slices of type-valued records/arrays use owned compile-time snapshots. contextual literals, immutable readonly array views, nested slice views, checked `usize` bounds/indexing, `.len`, empty shapes and ordinary/inline by-value iteration preserve exact nominal leaves. constant-input procedure parameters/results, erased generic inputs, optional/fallible nesting and normalized cache keys generate runtime storage/defaults through interpreter/native execution. mutable annotations/backing, metadata sentinels, invalid ranges/indices, readonly writes, incomplete leaves and runtime dependencies retain diagnostics. imported private types, source/session disposal, shared construction bounds and repeat compilation preserve ownership. mutable metadata borrowing, runtime metadata storage, general type-valued execution and broader constant materialization remain open.
|
||||||
- [x] tagged type-storage checkpoint: tagged unions containing type leaves own active payload snapshots through typed/contextual construction, direct and nested field/index updates, immutable by-value matches and whole-value variant replacement. constant-input procedure arguments/results, erased generic inputs and normalized cache keys preserve nominal leaves and saved copies while generating runtime storage/defaults through interpreter/native execution. undefined union locals and nested record/array storage require whole-value initialization; inactive reads/writes, malformed explicit tags, nominal initializer conflicts, readonly updates, incomplete results and narrow overflow retain diagnostics. explicit sparse tag enums may contain unused members without adding match cases. imported private types, source/session disposal and repeat compilation preserve ownership. untagged metadata layouts remain invalid; mutable metadata borrowing, runtime metadata storage, general type-valued execution and broader constant materialization remain open.
|
- [x] tagged type-storage checkpoint: tagged unions containing type leaves own active payload snapshots through typed/contextual construction, direct and nested field/index updates, immutable by-value matches and whole-value variant replacement. constant-input procedure arguments/results, erased generic inputs and normalized cache keys preserve nominal leaves and saved copies while generating runtime storage/defaults through interpreter/native execution. undefined union locals and nested record/array storage require whole-value initialization; inactive reads/writes, malformed explicit tags, nominal initializer conflicts, readonly updates, incomplete results and narrow overflow retain diagnostics. explicit sparse tag enums may contain unused members without adding match cases. imported private types, source/session disposal and repeat compilation preserve ownership. untagged metadata layouts remain invalid; mutable metadata borrowing, runtime metadata storage, general type-valued execution and broader constant materialization remain open.
|
||||||
|
- [x] metadata-input execution checkpoint: procedures with ordinary type-valued parameters execute entirely at compile time even when returning runtime-representable values. all inputs remain explicit constants; owned scalar/record/array/string results, recursive readonly metadata iteration, reflected field names/counts and private nominal leaves work through interpreter/native execution. plain/fallible `void` retain bare-return/fallthrough semantics; ordinary fallible results propagate through `try`/`catch` and run scoped `defer`/`errdefer`. runtime dependencies and incomplete payloads retain diagnostics; source/session disposal and repeat compilation preserve ownership. dependent signature parameters still require `$`; general type-valued execution, mutable metadata borrowing and broader constant materialization remain open.
|
||||||
- [ ] remaining gate: general type-valued compile-time execution, broader constant materialization (including address-bearing untagged unions, nonnull data pointers and mutable slices), plus remaining existing-library acceptance for broader `meta` operations and `io.print`. formatting parsing and broader imported C-binding support may interleave with later gates.
|
- [ ] remaining gate: general type-valued compile-time execution, broader constant materialization (including address-bearing untagged unions, nonnull data pointers and mutable slices), plus remaining existing-library acceptance for broader `meta` operations and `io.print`. formatting parsing and broader imported C-binding support may interleave with later gates.
|
||||||
- [ ] remaining source constructs: multiline strings. boolean and optional-capture conditional expressions, yielding value blocks, `yield`, compound updates and bitwise operators are covered above. examples: `source/parser/parse.hon`, `source/llvm/runtime.hon`.
|
- [ ] remaining source constructs: multiline strings. boolean and optional-capture conditional expressions, yielding value blocks, `yield`, compound updates and bitwise operators are covered above. examples: `source/parser/parse.hon`, `source/llvm/runtime.hon`.
|
||||||
- [ ] standard-library milestone: compile/run a multi-package program exercising existing allocation and IO, including error cleanup; no replacement miniature standard library.
|
- [ ] standard-library milestone: compile/run a multi-package program exercising existing allocation and IO, including error cleanup; no replacement miniature standard library.
|
||||||
|
|||||||
@@ -1405,6 +1405,7 @@ tagged_type_metadata_recompiles_owned_private_nominal_payloads test {
|
|||||||
` Selected :: lib.Selected(lib.make())
|
` Selected :: lib.Selected(lib.make())
|
||||||
` value Selected :: { value = 40 }
|
` value Selected :: { value = 40 }
|
||||||
` if (lib.read(lib.make(), value) != 42) return -4
|
` if (lib.read(lib.make(), value) != 42) return -4
|
||||||
|
` if (lib.score(lib.make(), 40) != 42) return -6
|
||||||
` snapshot Storage() :: {
|
` snapshot Storage() :: {
|
||||||
` original = { values = [{ value = 19 }, { value = 21 }] },
|
` original = { values = [{ value = 19 }, { value = 21 }] },
|
||||||
` nested = { values = [true] },
|
` nested = { values = [true] },
|
||||||
@@ -1460,6 +1461,13 @@ tagged_type_metadata_recompiles_owned_private_nominal_payloads test {
|
|||||||
`read proc($input Metadata, value Selected(input)) i16 {
|
`read proc($input Metadata, value Selected(input)) i16 {
|
||||||
` return value.value + i16(input.payload.count)
|
` return value.value + i16(input.payload.count)
|
||||||
`}
|
`}
|
||||||
|
`score proc(input Metadata, bias i16) i16 {
|
||||||
|
` saved :: input
|
||||||
|
` changed := input
|
||||||
|
` changed.payload.children[0] = bool
|
||||||
|
` if (saved.payload.children[0]? != Child) return -1
|
||||||
|
` return i16(saved.payload.count) + bias
|
||||||
|
`}
|
||||||
,
|
,
|
||||||
)
|
)
|
||||||
defer arraylist.deinit(&imported)
|
defer arraylist.deinit(&imported)
|
||||||
|
|||||||
@@ -143,6 +143,11 @@ elaborate proc(
|
|||||||
if (class == .function) {
|
if (class == .function) {
|
||||||
if (type_storage_annotation(&original, resolution.storage.bindings,
|
if (type_storage_annotation(&original, resolution.storage.bindings,
|
||||||
ast.function_decl(&original, id).return_type, 0)) needed = true
|
ast.function_decl(&original, id).return_type, 0)) needed = true
|
||||||
|
for (0..ast.function_param_count(&original, id)) |position| {
|
||||||
|
parameter :: ast.param(&original, ast.function_param(&original, id, position))
|
||||||
|
if (!parameter.comptime and type_storage_annotation(&original,
|
||||||
|
resolution.storage.bindings, parameter.type, 0)) needed = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (class == .statement and ast.stmt_kind(&original, id) == .declaration
|
if (class == .statement and ast.stmt_kind(&original, id) == .declaration
|
||||||
and type_storage_annotation(&original, resolution.storage.bindings,
|
and type_storage_annotation(&original, resolution.storage.bindings,
|
||||||
@@ -1853,8 +1858,13 @@ type_storage_annotation proc(tree @ast.Tree, bindings []sema.Binding, input ast.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@hide:file
|
@hide:file
|
||||||
compiletime_result proc(state @State, annotation ast.NodeId) bool {
|
compiletime_call proc(state @State, function ast.NodeId) bool {
|
||||||
return type_record_storage(state, annotation, 0)
|
if (type_record_storage(state, ast.function_decl(&state.tree, function).return_type, 0)) return true
|
||||||
|
for (0..ast.function_param_count(&state.tree, function)) |i| {
|
||||||
|
parameter :: ast.param(&state.tree, ast.function_param(&state.tree, function, i))
|
||||||
|
if (!parameter.comptime and type_record_storage(state, parameter.type, 0)) return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@hide:file
|
@hide:file
|
||||||
@@ -1907,8 +1917,8 @@ specialize_call proc(state @mut State, call, function, expected ast.NodeId) void
|
|||||||
state.depth += 1
|
state.depth += 1
|
||||||
defer state.depth -= 1
|
defer state.depth -= 1
|
||||||
count :: ast.function_param_count(&state.tree, function)
|
count :: ast.function_param_count(&state.tree, function)
|
||||||
# type-containing results have no runtime call: every input is specialized.
|
# ordinary metadata inputs and metadata results require a fully constant call.
|
||||||
type_result :: compiletime_result(state, ast.function_decl(&state.tree, function).return_type)
|
type_result :: compiletime_call(state, function)
|
||||||
runtime := usize(0)
|
runtime := usize(0)
|
||||||
for (0..count) |i| {
|
for (0..count) |i| {
|
||||||
if (!type_result and !ast.param(&state.tree, ast.function_param(&state.tree, function, i)).comptime) runtime += 1
|
if (!type_result and !ast.param(&state.tree, ast.function_param(&state.tree, function, i)).comptime) runtime += 1
|
||||||
@@ -2110,7 +2120,7 @@ specialize_call proc(state @mut State, call, function, expected ast.NodeId) void
|
|||||||
@hide:file
|
@hide:file
|
||||||
instantiate proc(state @mut State, index usize, call ast.NodeId) void ! Error {
|
instantiate proc(state @mut State, index usize, call ast.NodeId) void ! Error {
|
||||||
function :: state.instances.items[index].function
|
function :: state.instances.items[index].function
|
||||||
type_result :: compiletime_result(state, ast.function_decl(&state.tree, function).return_type)
|
type_result :: compiletime_call(state, function)
|
||||||
count :: state.original_count
|
count :: state.original_count
|
||||||
clone_start :: ast.node_count(&state.tree)
|
clone_start :: ast.node_count(&state.tree)
|
||||||
mapping :: state.mapping
|
mapping :: state.mapping
|
||||||
@@ -3027,8 +3037,9 @@ return_type_value proc(state @mut State, block, first_owned, result_type ast.Nod
|
|||||||
@hide:file
|
@hide:file
|
||||||
type_void_completion proc(state @mut State, annotation, at ast.NodeId) ast.NodeId ! Error {
|
type_void_completion proc(state @mut State, annotation, at ast.NodeId) ast.NodeId ! Error {
|
||||||
type :: try canonical_type(state, annotation)
|
type :: try canonical_type(state, annotation)
|
||||||
if (type == no_node or ast.expr_kind(&state.tree, type) != .fallible_type) return no_node
|
if (type == no_node) return no_node
|
||||||
child :: try canonical_type(state, ast.binary_expr(&state.tree, type).left)
|
child :: if (ast.expr_kind(&state.tree, type) == .fallible_type)
|
||||||
|
try canonical_type(state, ast.binary_expr(&state.tree, type).left) else type
|
||||||
resolved :: binding(state, child)
|
resolved :: binding(state, child)
|
||||||
if (resolved.kind != .builtin or resolved.data.builtin != .void) return no_node
|
if (resolved.kind != .builtin or resolved.data.builtin != .void) return no_node
|
||||||
value :: try ast.add_literal(state.builder, .void, ast.node_span(&state.tree, at))
|
value :: try ast.add_literal(state.builder, .void, ast.node_span(&state.tree, at))
|
||||||
@@ -5258,7 +5269,7 @@ execute_type_statement_body proc(state @mut State, execution @mut TypeExecution,
|
|||||||
execution.returned = try type_execution_value(state, expression, execution.result_type)
|
execution.returned = try type_execution_value(state, expression, execution.result_type)
|
||||||
if (execution.returned != no_node
|
if (execution.returned != no_node
|
||||||
and !try type_array_initialized(state, execution.returned, value)) return .invalid
|
and !try type_array_initialized(state, execution.returned, value)) return .invalid
|
||||||
if (execution.returned != no_node and type_record_storage(state, execution.result_type, 0)) {
|
if (execution.returned != no_node) {
|
||||||
type :: try canonical_type(state, execution.result_type)
|
type :: try canonical_type(state, execution.result_type)
|
||||||
if (type != no_node and ast.expr_kind(&state.tree, type) == .fallible_type) {
|
if (type != no_node and ast.expr_kind(&state.tree, type) == .fallible_type) {
|
||||||
payload :: ast.typed_constant(&state.tree, execution.returned).value
|
payload :: ast.typed_constant(&state.tree, execution.returned).value
|
||||||
@@ -6788,5 +6799,5 @@ flexible proc(state @State, id ast.NodeId) bool {
|
|||||||
|
|
||||||
@hide:file
|
@hide:file
|
||||||
template proc(state @State, id ast.NodeId) bool {
|
template proc(state @State, id ast.NodeId) bool {
|
||||||
return ast.function_generic(&state.tree, id) or compiletime_result(state, ast.function_decl(&state.tree, id).return_type)
|
return ast.function_generic(&state.tree, id) or compiletime_call(state, id)
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
+119
@@ -11,6 +11,100 @@ HONEY = ROOT / "build/honey"
|
|||||||
|
|
||||||
# Explicit expectations guard against frontend bugs shared by both execution paths.
|
# Explicit expectations guard against frontend bugs shared by both execution paths.
|
||||||
CASES = {
|
CASES = {
|
||||||
|
"ordinary_metadata_inputs_compute_owned_runtime_results": (
|
||||||
|
"""
|
||||||
|
Config :: struct { child type, count usize }
|
||||||
|
Result :: struct { values [2]i16, name []u8 }
|
||||||
|
amount proc(input Config, extra usize) usize {
|
||||||
|
copy := input
|
||||||
|
saved :: copy
|
||||||
|
copy.count = copy.count + extra
|
||||||
|
if (saved.child != i16 or saved.count != 40) return 0
|
||||||
|
return copy.count
|
||||||
|
}
|
||||||
|
compute proc(input Config) Result {
|
||||||
|
return { values = [i16(amount(input, 2)), 19], name = "owned" }
|
||||||
|
}
|
||||||
|
identity proc(T type, value i16) i16 {
|
||||||
|
if (T != i16) return 0
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
main proc() i16 {
|
||||||
|
result :: compute(Config { child = i16, count = 40 })
|
||||||
|
if (result.name.len != 5 or result.name[4] != 100) return -1
|
||||||
|
return identity(i16, result.values[0])
|
||||||
|
}
|
||||||
|
""", b"42\n", None,
|
||||||
|
),
|
||||||
|
"ordinary_metadata_inputs_select_recursive_helpers_and_void": (
|
||||||
|
"""
|
||||||
|
validate proc(T type, early bool) void {
|
||||||
|
if (T != i16) compile_error!("wrong child")
|
||||||
|
if (early) return
|
||||||
|
}
|
||||||
|
count proc(types []type, index usize) usize {
|
||||||
|
validate(i16, index == 0)
|
||||||
|
if (index == types.len) return 0
|
||||||
|
bias :: if (types[index] == i16) usize(21) else usize(0)
|
||||||
|
return bias + count(types, index + 1)
|
||||||
|
}
|
||||||
|
main proc() usize { return count([i16, bool, i16], 0) }
|
||||||
|
""", b"42\n", None,
|
||||||
|
),
|
||||||
|
"ordinary_metadata_inputs_preserve_fallible_cleanup": (
|
||||||
|
"""
|
||||||
|
Error :: enum { failed }
|
||||||
|
fail proc(T type) i16 ! Error {
|
||||||
|
errdefer if (T != i16) unreachable
|
||||||
|
defer if (T != i16) unreachable
|
||||||
|
return .failed
|
||||||
|
}
|
||||||
|
forward proc(T type) i16 ! Error {
|
||||||
|
errdefer if (T != i16) unreachable
|
||||||
|
return try fail(T)
|
||||||
|
}
|
||||||
|
succeed proc(T type) void ! Error {
|
||||||
|
errdefer unreachable
|
||||||
|
if (T == i16) return
|
||||||
|
}
|
||||||
|
main proc() i16 {
|
||||||
|
succeed(i16) catch { return -1 }
|
||||||
|
succeed(bool) catch { return -2 }
|
||||||
|
return forward(i16) catch |error| {
|
||||||
|
yield if (error == .failed) i16(42) else i16(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""", b"42\n", None,
|
||||||
|
),
|
||||||
|
"ordinary_metadata_inputs_run_error_cleanup": (
|
||||||
|
"""
|
||||||
|
Error :: enum { failed }
|
||||||
|
fail proc(T type) i16 ! Error {
|
||||||
|
errdefer unreachable
|
||||||
|
return .failed
|
||||||
|
}
|
||||||
|
main proc() i16 { return fail(i16) catch 0 }
|
||||||
|
""", b"", b"reached unreachable statement",
|
||||||
|
),
|
||||||
|
"ordinary_metadata_inputs_reject_runtime_dependencies": (
|
||||||
|
"""
|
||||||
|
count proc(T type, value usize) usize { return value }
|
||||||
|
runtime proc(value usize) usize { return count(i16, value) }
|
||||||
|
main proc() usize { return runtime(42) }
|
||||||
|
""", b"", b"generic argument must be a compile-time value",
|
||||||
|
),
|
||||||
|
"ordinary_metadata_inputs_reject_incomplete_payloads": (
|
||||||
|
"""
|
||||||
|
Config :: struct { child type, count usize }
|
||||||
|
count proc(input Config) usize { return input.count }
|
||||||
|
Produce proc() type {
|
||||||
|
input Config := undefined
|
||||||
|
input.count = 42
|
||||||
|
return [count(input)]i16
|
||||||
|
}
|
||||||
|
main proc() usize { value Produce() :: []; return value.len }
|
||||||
|
""", b"", b"read before initialization",
|
||||||
|
),
|
||||||
"unreachable_is_a_demanded_source_trap_without_cleanup": (
|
"unreachable_is_a_demanded_source_trap_without_cleanup": (
|
||||||
"""
|
"""
|
||||||
fail proc() i16 {
|
fail proc() i16 {
|
||||||
@@ -11290,6 +11384,31 @@ def check_typeinfo_packages(temporary, executable):
|
|||||||
(project / "std" / package).symlink_to(ROOT / "std" / package, target_is_directory=True)
|
(project / "std" / package).symlink_to(ROOT / "std" / package, target_is_directory=True)
|
||||||
|
|
||||||
cases = {
|
cases = {
|
||||||
|
"ordinary_metadata_helpers_return_values_and_names": (
|
||||||
|
"""
|
||||||
|
import "@std/meta"
|
||||||
|
Record :: struct { first i16, second bool }
|
||||||
|
field_name proc(info meta.TypeInfo, index usize) []u8 {
|
||||||
|
return match info {
|
||||||
|
.record |record|: record.fields[index].name,
|
||||||
|
else: compile_error!("expected record"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count proc(fields []meta.FieldInfo) usize {
|
||||||
|
total usize := 0
|
||||||
|
for fields |field| {
|
||||||
|
if (field.type == i16) total += 19
|
||||||
|
else total += 23
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
main proc() usize {
|
||||||
|
name :: field_name(typeinfo!(Record), 1)
|
||||||
|
if (name.len != 6 or name[0] != 115) return 0
|
||||||
|
return count(typeinfo!(Record).record.fields)
|
||||||
|
}
|
||||||
|
""", b"42\n", None,
|
||||||
|
),
|
||||||
"categories_specialize_generic_calls": (
|
"categories_specialize_generic_calls": (
|
||||||
"""
|
"""
|
||||||
reflection :: import "@std/meta"
|
reflection :: import "@std/meta"
|
||||||
|
|||||||
Reference in New Issue
Block a user