← 17. Complete grammar · Contents
18. Conformance examples
This chapter is the executable minimum corpus referenced by Section 1.5. It is not a second definition of the language: Chapters 3–16 govern when an example and its stated result disagree.
| Sections | Principal coverage |
|---|---|
| 18.1–18.4 | records, arrays, aggregate aliases and copying, calls, control flow, recursion, and bounded strings |
| 18.5–18.7 | failure propagation, immediate handling, and stateful system services |
| 18.8–18.10 | counted-loop arithmetic, required traps, and compile-time rejection |
| 18.11–18.14 | multipart input, name identity, forward parameters, and aggregate destinations |
| 18.15–18.20 | constants, numeric literals, xor, mod, assertions, and aggregate constants |
| 18.21–18.22 | open-array library interfaces and ordered integer selection |
18.1 Complete accepted program
This program exercises records, complete aggregate initializers, exact-type record assignment, a checked fixed array, an aggregate alias parameter and result, scalar locals, a counted loop, a conditional chain, a call, and observable output:
record Cell
value as u8
end
var template as Cell = (1)
var cells as Cell[4] = [(0), (0), (0), (0)]
sub cellAt(index as u8) as Cell
return cells[index]
end
sub setCell(cell as Cell, value as u8)
cell.value = value
end
sub main()
var index as u8
var code as u8
for index = 0 until 4
cells[index] = template
setCell(template, index + 1)
end
cells[0].value = cellAt(0).value
if cells[0].value = 1
writeOutputByte('Y') handle code
return
end
elseif cells[0].value = 0
writeOutputByte('N') handle code
return
end
end
endEach aggregate assignment copies template into the selected array element before template is changed for the next iteration. The expected standard output is the byte for Y, provided the output service succeeds.
18.2 Recoverable error and propagation
const badByte = 10
sub checkedByte() as u8 fails
var value as u8 = readInputByte() else fail
if value = 0
fail badByte
end
return value
end
sub emitByte() fails
var value as u8 = checkedByte() else fail
writeOutputByte(value) else fail
end
sub main() fails
emitByte() else fail
endFor the minimum conformance-corpus run, standard input supplies byte A and the output service succeeds; the expected standard output is A. More generally, success copies one input byte to output. End of input or a service error propagates its standard code, a zero byte produces badByte, and any failure reaching main performs the unhandled-error trap with that code.
18.3 Recursion and control flow
forward sub odd(value as u16) as boolean
sub even(value as u16) as boolean
if value = 0
return true
end
return odd(value - 1)
end
sub odd
while not false
if value = 0
return false
end
return even(value - 1)
end
end
sub main()
var index as u16
var code as u8
for index = 0 to 5
if odd(index)
continue
elseif index = 4
exit
end
end
writeOutputByte(u8(index)) handle code
return
end
endThe program is valid and writes byte value 4 when the output service succeeds. The condition of the loop in odd folds to true, and no exit targets that loop, so the value routine needs no return after the loop. The Chapter 18 conformance floor requires enough activation capacity for this execution; an implementation may perform activation-capacity only beyond its published, conformant limit.
18.4 Bounded-string aliasing and byte mutation
var text as string[4] = "A\0B"
var snapshot as string[4]
sub textAlias() as string[4]
return text
end
sub mutate(value as string[4])
value[1] = 'Z'
end
sub main() fails
snapshot = textAlias()
if snapshot.length = 3 and snapshot[1] = 0
mutate(textAlias())
end
if text[1] = 'Z' and snapshot[1] = 0
writeOutputByte('Y') else fail
end
endThe literal's embedded zero is an ordinary byte, so its logical length is three. Assignment materializes textAlias() by copying it into the program-level snapshot object. Passing a second result directly to mutate forwards the transient alias without copying, so mutation changes text while snapshot retains its copied zero byte. The expected standard output is Y.
18.5 Result-free call propagation
sub emitMarker() fails
writeOutputByte('R') else fail
end
sub relayMarker() fails
emitMarker() else fail
return
end
sub main() fails
relayMarker() else fail
endWhen output succeeds, emitMarker has no result, relayMarker returns successfully, and the expected standard output is R. An output failure propagates unchanged through both callers.
18.6 Same-destination error handling
const sampleFailure = 7
sub alwaysFails() as u8 fails
fail sampleFailure
end
sub main() fails
var code as u8
code = alwaysFails() handle code
writeOutputByte(code) else fail
return
end
writeOutputByte(0) else fail
endThe failed assignment performs no success-result store and then stores sampleFailure in code, even though code is both destinations. The expected standard output is byte value 7.
18.7 Bulk-output cursor state
sub main() fails
writeStorageByte('A') else fail
writeStorageByte('B') else fail
seekStorageOutput(0) else fail
writeStorageByte('Z') else fail
endThe conformance output begins empty with its cursor at zero. The first two calls append AB; the seek returns to zero; the final call overwrites the first byte without inserting or truncating. The expected bulk output is ZB, with its cursor at offset one.
18.8 Counted-loop overshoot before storage
sub main()
var index as u8
for index = 250 to 255 step 5 + 5
exit
end
endThe step expression folds to 10. This program is valid and terminates normally with index equal to 250. Without the exit, the mathematical next value is 260. It fails the to 255 next-bound test, so the loop ends without storing it and without a loop-range trap.
18.9 Specified trap cases
Each listing below is valid source. The external conformance harness supplies the stated standard-input byte and observes the trap report.
var bytes as u8[2]
sub main() fails
var index as u8 = readInputByte() else fail
bytes[index] = 1
endWith input byte 2, the required result is bounds before the store.
sub divide(value as u16, divisor as u16) as u16
return value / divisor
end
sub main() fails
var divisor as u16 = readInputByte() else fail
var result as u16 = divide(8, divisor)
endWith input byte zero, the required result is division-by-zero.
sub remainder(value as u16, divisor as u16) as u16
return value mod divisor
end
sub main() fails
var divisor as u16 = readInputByte() else fail
var result as u16 = remainder(8, divisor)
endWith input byte zero, the required result is likewise division-by-zero at mod.
18.10 Complete rejected programs
Each program is rejected for the stated independent reason.
Failable call without consumption:
sub readOne() as u8 fails
var value as u8 = readInputByte() else fail
return value
end
sub main()
var value as u8
value = readOne()
endAggregate assignment between different nominal types:
record LeftCell
value as u8
end
record RightCell
value as u8
end
var left as LeftCell
var right as RightCell
sub main()
left = right
endIncomplete structured initializer:
record Color
red as u8
green as u8
blue as u8
end
var color as Color = (1, 2)
sub main()
endAggregate local declaration:
record Cell
value as u8
end
var cell as Cell
sub cellAlias() as Cell
return cell
end
sub main()
var held as Cell = cellAlias()
endEvery local must be scalar. A valid materializing form declares held as a program variable and assigns cellAlias() to it inside a routine.
Value routine with a reachable end:
sub choose(flag as boolean) as u8
if flag
return 1
end
end
sub main()
endLater declaration used before a forward signature:
sub main()
later()
end
sub later()
endWrong entry signature:
sub main(argument as u8)
endAssignment to an active counted-loop counter:
sub main()
var index as u8
for index = 0 until 4
index = index + 1
end
endThe counter is a valid scalar local, but it is read-only while its loop is active. A program variable or parameter used as the counter, or reuse of index by a nested counted loop, is independently invalid.
Exact integer constant outside the expected range at its use:
const Big = 300
var x as u8
sub main()
x = Big
endThe constant declaration is valid. The assignment is invalid at the use of Big because 300 does not fit the destination's expected u8 type.
Hexadecimal overflow:
const value = $10000
sub main()
endBinary overflow:
const value = %10000000000000000
sub main()
endBoth programs fail lexically at the literal prefix. A hexadecimal literal has at most four digits, and a binary literal has at most sixteen.
18.11 Multipart input presentation
The conformance harness must also present the complete accepted program in Section 18.1 as at least two ordered source parts. It splits the program after a delimiter-depth-zero logical newline, assigns a distinct stable identity to each part, and otherwise preserves every source byte and the declared order. The expected output remains Y.
For the diagnostic case, the harness introduces an undeclared name in the second part. The compiler diagnostic must identify the second part's stable identity and the position of that name within the part. A separate run may use different physical files or transport chunks, but those changes must not alter tokens, declaration visibility, validity, or program behaviour.
The packaging mechanism is not part of this conformance case. Whether the host uses an explicit list or dependency discovery, it must present the same two parts in the same order. Diagnostics for the second part use main.nu as its diagnostic name.
18.12 Case-sensitive names and forward parameters
This complete program uses three distinct case variants and a forward parameter binding:
forward sub render(Player as u8) as u8
var Player as u8 = 9
var player as u8 = 1
var PLAYER as u8 = 2
sub render
return Player + player + PLAYER
end
sub main() fails
writeOutputByte(render(3)) else fail
endThe expected standard output is byte value 6. The lowercase keywords are recognized as keywords; Player, player, and PLAYER are distinct identifiers. Inside render, the forward parameter Player shadows the program variable with the same exact identity, so the argument value 3 is used. The abbreviated body obtains that parameter binding from the forward signature.
Changing the body header to sub Render makes the program invalid because no incomplete forward named Render exists. Writing SUB render is also invalid: SUB is a NAME, not the keyword sub.
18.13 Caller-supplied aggregate destination
This program copies and changes a record through aggregate parameters without declaring aggregate storage inside the routine:
record Counter
value as u8
end
var source as Counter = (1)
var destination as Counter
sub copyAndIncrement(input as Counter, output as Counter)
output = input
output.value = output.value + 1
end
sub main() fails
copyAndIncrement(source, destination)
if source.value = 1 and destination.value = 2
writeOutputByte('Y') else fail
end
endinput and output are fixed aliases to caller storage. Complete assignment copies source into destination, after which the scalar-field assignment changes only destination. The expected standard output is Y.
18.14 Aggregate selection and forwarding
This program returns and forwards an alias to one selected array element:
record Sample
value as u8
end
var samples as Sample[2] = [(3), (7)]
sub choose(items as Sample[2], index as u8) as Sample
return items[index]
end
sub forwardSelection(items as Sample[2], index as u8) as Sample
return choose(items, index)
end
sub replace(item as Sample, value as u8)
item.value = value
end
sub main() fails
replace(forwardSelection(samples, 1), 9)
if samples[1].value = 9
writeOutputByte('Y') else fail
end
endBoth result-bearing routines transfer transient aliases to storage inside samples. replace receives the forwarded alias and mutates the selected original object without an aggregate copy. The expected standard output is Y.
18.15 Inferred constant types
This program uses one exact integer constant in both integer widths and retains a separate Boolean constant:
const sharedValue = 200
const enabled = true
var byteUse as u8 = sharedValue
var wordUse as u16 = sharedValue
sub main() fails
if enabled and byteUse = 200 and wordUse = 200
writeOutputByte('Y') else fail
end
endsharedValue adopts u8 for byteUse and u16 for wordUse. enabled has type boolean. The expected standard output is Y.
18.16 Integer literal spellings
This program exercises hexadecimal and binary literals at ordinary and maximum word values:
const hexMask = $FF
const binaryMask = %10110000
const hexMaximum = $ffff
const binaryMaximum = %1111111111111111
sub main() fails
if hexMask = 255 and binaryMask = 176 and hexMaximum = 65535 and binaryMaximum = 65535
writeOutputByte(binaryMask) else fail
end
endAll three literal spellings produce the same exact integer category. The expected standard output is byte value 176.
18.17 Integer exclusive OR
This program exercises constant and runtime xor at both integer widths. It also distinguishes left association at the shared or and xor precedence level:
const folded = 3 xor 1 or 1
var byteValue as u8 = $a5
var wordValue as u16 = $f0f0
sub main() fails
byteValue = byteValue xor $ff
wordValue = wordValue xor $ffff
if folded = 3 and not byteValue = $a5 and wordValue = $0f0f
writeOutputByte(byteValue) else fail
end
endnot byteValue = $a5 means (not byteValue) = $a5; unary not binds before comparison. The expected standard output is byte value 90.
Boolean operands are invalid:
sub main()
if true xor false
end
endThe second program is rejected at xor because exclusive OR is integer-only.
18.18 Integer remainder
This program exercises constant and runtime mod at both integer widths:
const folded = 100 mod 7
var byteValue as u8 = 250
var wordValue as u16 = 1000
sub main() fails
byteValue = byteValue mod 16
wordValue = wordValue mod 256
if folded = 2 and byteValue = 10 and wordValue = 232
writeOutputByte(byteValue) else fail
end
endThe expected standard output is byte value 10.
A constant zero divisor is invalid:
const bad = 1 mod 0
sub main()
endThe second program is rejected at the zero divisor with the same division-by-zero diagnostic used by / 0.
18.19 Compile-time assertions
This program states and uses a relationship between two earlier constants:
const Rows = 8
const Columns = 16
assert Rows * Columns = 128
sub main() fails
writeOutputByte(Rows * Columns) else fail
endThe assertion is true, emits no target code, and the expected standard output is byte value 128.
A false assertion is invalid:
const Rows = 17
assert Rows <= 16
sub main()
endThe second program is rejected at assert with an assertion-failed diagnostic.
The assertion expression must be Boolean-valued:
const Rows = 8
assert Rows
sub main()
endThe third program is rejected at assert because an exact integer is not a Boolean condition.
18.20 Aggregate constants
This program reads record, array, and bounded-string constants, uses earlier aggregate constants as complete static initializer nodes, and deliberately demonstrates the non-transitive alias rule:
record Pair
left as u8
right as u16
end
const Origin as Pair = (7, 300)
const Clone as Pair = Origin
const Values as u8[3] = [1, 2, 3]
const Text as string[3] = "A\0B"
var target as Pair = Clone
sub mutate(item as Pair)
item.left = 9
end
sub main() fails
if target.left = 7 and Values[1] = 2 and Text.length = 3 and Text[2] = 'B'
mutate(Origin)
if Origin.left = 9 and target.left = 7
writeOutputByte('Y') else fail
end
end
endClone is established by copying the complete value of the earlier Origin constant during static initialization. target is then initialized from Clone before main; neither copy performs a runtime storage read. Passing Origin to mutate loses the direct-root read-only marker, so the mutation is permitted; this conformance execution uses writable proof storage and therefore observes the change. Portable programs do not depend on that mutation when a target places constants in physical read-only memory. The expected standard output is Y.
A direct constant-rooted assignment is invalid:
record Pair
value as u8
end
const Origin as Pair = (1)
sub main()
Origin.value = 2
endThe second program is rejected at Origin. The same rule rejects assignment to the whole constant, an array element, or a bounded-string byte reached directly from its constant name.
18.21 Open-array library routines
This program uses one set of routines with concrete arrays of different lengths:
const tooLong = 5
var small as u8[3] = [1, 2, 3]
var large as u8[5]
sub sum(data as u8[]) as u16
var total as u16 = 0
var i as u16
for i = 0 until data.length
total = total + u16(data[i])
end
return total
end
sub fill(data as u8[], value as u8)
var i as u16
for i = 0 until data.length
data[i] = value
end
end
sub copy(source as u8[], destination as u8[]) fails
var i as u16
if source.length > destination.length
fail tooLong
end
for i = 0 until source.length
destination[i] = source[i]
end
end
sub main() fails
writeOutputByte(u8(sum(small))) else fail
fill(large, 9)
copy(small, large) else fail
writeOutputByte(large[0]) else fail
writeOutputByte(large[4]) else fail
endThe expected standard-output bytes are 6, 1, and 9. Each T[] binding denotes the complete concrete array and retains its actual u16 element count. copy checks the destination length before writing; no source form can pass a shortened prefix or substitute another count.
18.22 Ordered integer selection
This program evaluates one u16 selector and writes 7. The values 1 and 2 share their case body, while 300 selects the later body:
sub main() fails
select u16(300)
case 1, 2
writeOutputByte(1) else fail
case 300
writeOutputByte(7) else fail
else
writeOutputByte(9) else fail
end
endThis program is rejected at true because a selector must be an integer:
sub main()
select true
case 1
end
end