Skip to content

Section 19 of 26

Unicode text is authored directly; escapes retain their original spans.

plots and completion

For a visual companion to the syntax below, browse the generated Plot diagrams.

A plot is live by default. The language has two paired altitude stories: type -> form for value meaning and portable representation, and plot -> plan -> play for authored work, admitted realization, and execution. A plot is not its plan or play, and a form is not the semantic type it represents.

plot live-example (
    >> reading: Temperature...
    label: Text... >>
) {
    reading >> (. > 30°C ? "hot" : "fine") >> label
}

A trailing full stop after the closing brace declares semantic completion on structural drain:

plot finite-example (
    >> input: Text
    output: Text >>
) {
    input >> text/upper >> output
}.

The finite example plot as connected gears

Semantic full stop: } versus }.

The full stop belongs to the plot as a whole, not to the sequence of statements inside its back.

Canonical law:

}     structural drain = quiescence; the play remains live for later admitted work
}.    structural drain = semantic fulfillment; the play terminates normally as completed

More precisely:

A trailing . on the plot declares that when its admitted realization reaches structural drain under the ordinary scheduler law, that drain is a sufficient completion witness for the plot's authored meaning.

The period does not mean “stop executing now,” and it is not an executable statement, gear, cord, effect, cancellation request, or timeout.

It also does not mean “terminate whenever nothing happens to be runnable this instant.” Temporary lack of runnable work, an outstanding admitted activation, waiting input/provider work, or any other condition that has not reached the scheduler's actual structural-drain state is not promoted to completion by punctuation.

Without the trailing full stop, the same structural drain is quiescence. The exact play remains alive and may continue when later admitted input or activation arrives.

With the trailing full stop, the same structural drain is semantic completion. The play may terminate normally with completed disposition.

Thus the punctuation changes checked meaning, plan completion policy, and lifecycle behavior:

plot ... { ... }     live plot
plot ... { ... }.    finite-on-drain plot

This is intentionally punctuation on the plot boundary. Do not encode semantic completion as a freestanding . statement inside the body.

The current parser rejects a standalone body .; put completion punctuation after the closing brace.

The English keyword complete is not Conduitese and must be rejected rather than retained as a compatibility alias.

A standalone ... is not a runnable body statement. In documentation it may mark an omitted implementation; in an authored port type, T... has the distinct checked meaning of a flow.

Provenance: #3939 plus this canonical amendment in #4109.

cords and fore direction: >>

>> is the one canonical authored cord/direction token.

source >> transform >> sink

plot upper (
    >> input: Text
    output: Text >>
) {
    input >> text/upper >> output
}

The upper plot as connected gears

Where a paired fore is useful:

plot upper (
    input: Text >> output: Text
) {
    input >> text/upper >> output
}

The same upper topology with a paired fore

The ordinary operators >, <, >=, and <= belong to comparison/constraint mathematics, not graph carriage.

Reserve expression shifts:

>>    cord / fore direction
>>>   right shift in pure expressions
<<<   left shift in pure expressions

Historical > cord source remains historical evidence. Do not make > a current compatibility spelling.

Provenance: #3967.


Pure one-input expressions

A pure expression has one current runtime input, written:

.        whole input
.field   record field
.0       tuple element

and may reference immutable lexical/startup values.

Pure expressions are finite and may not hide:

Examples:

reading >> (.temperature > 30°C ? "hot" : "fine") >> label
flags >> ((. >>> 8) & 0xff) >> byte

Ternary

Canonical pure value-selection sugar:

condition ? yes : no

The condition is Boolean, branches unify to one exact finite result type/bound, and only the selected pure branch evaluates.

Ternary is not graph routing.

Provenance: #3964, #3969.


Systems-grade scalar expressions

Pure expressions admit exact fixed-width integer types when width is semantic:

U8 U16 U32 U64 U128
I8 I16 I32 I64 I128

Canonical integer literal families include decimal, hexadecimal, binary and octal with optional readability separators:

255
0xff
0x8000_0000
0b1000_0001
0o755

Do not import C integer promotions, host-sized usize/isize, target-dependent wrapping, UB, or silent truncation.

Canonical Boolean operators:

!a
a && b
a || b

Canonical bitwise operators for admitted exact integer/bitset types:

a & b
a | b
a ^ b

Shift spelling remains:

>>>   right shift
<<<   left shift
>>    Cord / Fore direction, never an expression shift

Right-shift behavior follows checked signedness. Out-of-range shift counts require one portable checked refusal/result law rather than host-language masking/UB.

Ergonomic number law:

Make unsafe ambiguity impossible; do not make machine widths homework.

Use exact widths where representation is meaning (register/wire/device/ABI). Ordinary arithmetic/counts/quantities should normally use semantic numeric types with planner/compiler-selected safe representation inside exact bounds.

Required precedence, highest to lowest:

primary / projection
unary
* / %
+ -
<<< >>>
< <= > >=
== !=
&
^
|
&&
||
?:
>> Cord outside expression islands

No operator meaning may depend on whitespace.

Provenance: #3964, #3967, #4014.


Immutable locals

Canonical local binding:

limit = 30°C
matrix = { a: 1, b: 0, c: 0, d: 1 }

A complete example captures an immutable local threshold:

plot threshold (
    >> value: U32
    result: Boolean >>
) {
    limit = 100
    value >> (. > limit) >> result
}

= declares an immutable lexical relationship. It is not assignment and not temporal sequencing.

No shadowing of startup parameters, ports, gear names, locals, or imported aliases in the same scope.

Local dependency cycles refuse. Runtime-flow capture requires explicit graph/value machinery and must not turn locals into hidden state.

Provenance: #4052.


Exactly-one graph routing

The current checked grammar uses PATTERN >> ROUTE inside a matched route. These are source fragments whose endpoint names and exact types must be in scope:

notice >> ? {
    [Notice.delivery == "visible"] >> display
    [Notice.delivery == "spoken"] >> speak
    _ >> silence
}

event >> ? {
    [MusicEvent.note] >> play-note
    [MusicEvent.rest] >> keep-silence
}

A field-equality route carries the whole record. A variant route carries the selected case payload. The route connects that carried value directly to its first destination; no payload placeholder is needed. Equality patterns must name one exact record type and field, have distinct checked values, and end with an otherwise track. Variant routes must enumerate every case exactly once. Mixing these pattern families refuses.

At the beginning of an arm, _ before >> means otherwise. The current checker also accepts a leading route-stage _ as a carried-value placeholder: [MusicEvent.note] >> _ >> play-note is equivalent to the direct route above. It rejects _ later in that track. This existing placeholder is not a discard operation. The proposed distinction between a . payload placeholder and a bare _ discard is not implemented by this grammar; do not use it as current runnable source. Likewise, colon arms and arbitrary Boolean graph guards are not accepted here. Use when(...) for a checked Boolean filter.

Exactly-one routing keeps unselected work inactive; checked expansion still retains every possible route in the graph. The selector tests cover exhaustive cases, equality routes, carried values, overlap and missing otherwise refusal. These tests establish checking and expansion, not a claim that every arbitrary destination has an installed target back.

Provenance: #3938, #4062; current parser/checker conformance.


Unary filter sugar: when

Canonical unary value filter:

temperature >> when(. > limit) >> alarm

It lowers to one ordinary checked pure-filter gear. A rejected flow item does not appear downstream; a rejected ordinary value produces the finite optional result.

It has one current runtime input . and may capture immutable lexical/startup values.

It does not hide a second temporal input or temporal join.

For flows it preserves modality/terminal law:

T...  -> T...
T...| -> T...|

For one T, rejecting the value must have an explicit zero-or-one/optional law, naturally T?; it must not pretend to remain unconditional T -> T.

There is no pre-release where compatibility alias.

Provenance: #4044.


Source gears

A source gear is ordinary checked work whose activation may originate from an admitted external condition rather than an upstream runtime data cord.

Examples: timer, input device, network receive, sensor observation.

There is no callback syntax and no second event-loop runtime. External readiness enters the same bounded scheduler/kernel activation model and obeys ordinary pressure, terminal and lifecycle law.

Provenance: #4060.


Pure semantic kind-call sugar

Reviewed pure semantic kinds may use function-shaped expression sugar:

sine = math/sin(angle)

For a catalog kind, this lowers to ordinary semantic kind application. The checker derives eligibility from the selected kind contract. Built-in finite observations and widening, such as sequence/length, bytes/at, and value/u64, are separately checked expression operations; their function-shaped spelling does not require a fictitious installed catalog kind.

Eligibility is derived from checked semantic properties. Authors do not write “pinky promise this is pure.”

Effectful, stateful, suspending or authority-bearing kinds refuse in pure expression context.

Provenance: #4053, #4070, #4071.


Complete expression plots

The expression-body spelling and an explicit pipeline have the same checked meaning in the canonical expansion tests:

plot scale (
    factor: U8 = 2
    >> value: U8
    result: U8 >>
) = (. * factor)

plot scale-explicit (
    factor: U8 = 2
    >> value: U8
    result: U8 >>
) {
    value >> (. * factor) >> result
}

The runtime input is .; factor is an immutable startup value. Arithmetic that cannot be proven safe keeps its portable runtime check. For example, scaling a U8 by 2 does not authorize silent wrapping on overflow.

These complete expressions demonstrate the remaining operator families; their carrier, overflow, zero-divisor, and shift-count checks remain part of the finite expression contract:

plot quotient (
    value: U32 >> result: U32
) = (. / 2)
plot remainder (
    value: U32 >> result: U32
) = (. % 2)
plot next (
    value: U32 >> result: U32
) = (. + 1)
plot previous (
    value: I32 >> result: I32
) = (. - 1)
plot negative (
    value: I32 >> result: I32
) = (-.)
plot bits (
    value: U32 >> result: U32
) = (((. >>> 8) & 0xff) | ((. ^ 0xff) <<< 1))
plot accepted (
    value: I32 >> result: Boolean
) = (!(. < 0) && . <= 100 || . == 200)
plot different (
    value: I32 >> result: Boolean
) = (. != 0 && . >= -10 && . > -20)

Width changes are explicit and must represent the complete source domain. This example comes from the integer widening tests:

plot widen (
    value: U8 >> result: U64
) = (value/u64(value/u16(.)) * 256 + 33)

Input 255 produces 65313. Narrowing, same-width conversion and signed-to-unsigned conversion are refused by this widening surface.

Text and source spelling

# Unicode text is authored directly; escapes retain their original spans.
plot greeting {
    message = "Hello, β.\n\t\"quoted\" \\ path"
    message >> face/text("Message")
}.

Double-quoted text admits the reviewed newline, tab, quote and backslash escapes. UTF-8 byte bounds and scalar source positions remain distinct. Unknown escapes refuse; no implicit Unicode normalization changes an authored spelling. The quoted source tests check decoded-to-original span correspondence. # starts a source comment outside quoted text.

Glyph composition and exact selectors

These scoped fragments name ordinary gears through the standard glyph prelude:

a >< b >< c >> merged
left &> right >> paired
first ?> second >> winner
current-left <> current-right >> latest-pair
note @ save-request >> snapshot

They mean merge, zip, race, combine-latest, and Current sampling respectively. The actual input/output types and temporal relationships come from each exact fore; these fragments do not define a universal pair or race contract. Mixed adjacent glyphs need explicit grouping. sans glyphs disables the default prelude; explicit glyph imports remain available.

Exact structured selectors are also ordinary checked cord stages:

feedback >> project(Feedback.status) >> presentation
pitches >> index(PitchTable[1]) >> synth
events >> select(MusicEvent.note, unmatched=drop) >> notes
events >> select(MusicEvent.note, unmatched=refuse) >> required-note

project checks the named record field. index checks an exact collection's static index. select chooses a variant payload, explicitly dropping or refusing unmatched cases. This select is distinct from the bounded predicate activation coordinator. See the structured selector tests and bounded behavior examples.

Lexical helpers and shared pools

A nested plot is a lexical declaration, not a runtime closure:

plot outer (
    >> value: Text
    result: Text >>
) {
    plot helper (
        >> value: Text
        result: Text >>
    ) {
        value >> result
    }

    value >> helper() >> result
}

Nested declarations do not implicitly capture runtime ports or Current. Reusable behavior receives its runtime data through an exact fore. The lexical plot tests cover scoped resolution and refusal boundaries.

A shared pool declaration creates one bounded pool identity that can be passed as an explicit startup value. This signature specimen follows the pool checking fixtures:

plot peer (
    recv: Text...| >> send: Text...|
) {
}

plot room {
    pool peers: peer(size = 2)
}

The empty peer body demonstrates the declaration contract only. A pool is not an ordinary runtime endpoint; source >> peers is refused. Size must be a positive finite admitted count. Consumers receive the same pool through an explicit Pool startup parameter, rather than accidentally allocating separate pools. See the shared pool expansion tests.