Scope and ownership
LinkThis page defines Topaz 6.0 expressions. Examples run against public Topaz 5.21.3 and keep the expected 6.0 results. Source evidence identifies implementation behavior. Each example records execution separately.
This page owns expression grouping, operators, ranges, and member and index access. It also specifies the retirement of pipeline, composition, and expression-placeholder syntax. Functions and generics owns call argument binding. Collections and comprehensions owns collection construction. Type and library entries own individual members. Pattern matching owns wildcard patterns. Failure and propagation owns postfix ? behavior.
Selected source forms
LinkGrouped = "(" Expression ")" ;Unary = ("-" | "!") Unary | Power ;Power = Postfix ["**" Unary] ;RangeShape = Additive (".." | "..<") Additive ["by" Additive] ;IndexSuffix = "[" Expression "]" ;MemberSuffix = "." MemberName ;OptionalMemberSuffix = "?." MemberName ;
This handwritten excerpt shows selected source forms. The precedence record supplies the grouping between operator families. It omits call argument lists, collection construction, and other page-owned syntax; parsing alone does not establish operand legality.
Source evidence
- parseParenthesizedExpression at
b48527d0a174· 1036-1091 - parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647
Grouping and postfix forms
Empty parentheses form the unit literal (). Parentheses around one expression explicitly group that expression. A parenthesized comma list is rejected during parsing with TPZ2001. Postfix extensions attach to the preceding expression in source order.
Parentheses select a grouping for an expression. The unit literal () is documented in Literals and templates. Function argument binding, collection construction, propagation, and nominal updates keep their own owners; their suffixes appear here only to locate their grouping.
Why
Explicit grouping makes operand relationships visible. An ordered postfix chain gives each extension one receiver.
Source evidence
- parseParenthesizedExpression at
b48527d0a174· 1036-1091 - parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647
Explicit control operands
A control operand has a required outer pair of parentheses. The construct consumes that pair and parses its contents with the ordinary expression grammar. Record construction, record update, and lambdas keep the same forms they have in a binding or call argument. Their result types are checked separately.
| Position | Canonical form |
|---|---|
| if test | if (test) { body } |
| if-let value | if let Pattern = (value) { body } |
| while test | while (test) { body } |
| while-let value | while let Pattern = (value) { body } |
| for iterable | for Pattern in (iterable) { body } |
| using value | using name = (value) { body } |
| match scrutinee | match (value) { cases } |
| match guard | case Pattern if (test) => body |
| comprehension iterable | [for Pattern in (iterable) => value] |
| comprehension filter | [for Pattern in (iterable) if (test) => value] |
Omitting the required pair is rejected during parsing with TPZ2001. Extra parentheses inside the pair retain ordinary grouping. The existing concurrent(timeout: expression) argument list already delimits its timeout expression. A loop has no operand.
Why
An undelimited input and the same input inside the required parentheses supply the same condition, matched value, iteration source, or resource. The boundary preserves that intent and lets each position use ordinary expression grammar. Record construction and updates retain their existing forms, and lambdas retain one parenthesized parameter list. Parentheses inside an operand group that expression. The explicit boundary prevents a record body or a lambda arrow from taking the place of the following control body or case arrow.
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204 - issues/31 at
26da6a582932
Precedence and associativity
LinkPrecedence and associativity
Higher rows bind more tightly. These rows specify parser grouping. Operand-type acceptance is checked separately.
| Rank | Forms | Association | Binary parser level |
|---|---|---|---|
| 1 | call suffix, index suffix, member suffix, optional-, propagation suffix, record- | Successive postfix extensions | Separate parser production |
| 2 | ** | Right | Separate parser production |
| 3 | prefix -, ! | Recursive prefix | Separate parser production |
| 4 | *, /, % | Left | 9 |
| 5 | +, - | Left | 8 |
| 6 | ., . | Left | 7 |
| 7 | ==, !=, <, <=, >, >=, in | Left | 6 |
| 8 | && | Left | 5 |
| 9 | \|\| | Left | 4 |
| 10 | ?? | Left | 3 |
A prefix on the left applies outside power. The right operand of ** admits unary syntax. The range row accepts the by step clause.
| Expression | Grouping |
|---|---|
- | - |
2 ** 3 ** 2 | 2 ** (3 ** 2) |
a ?? b ?? c | (a ?? b) ?? c |
The structured table describes grouping. A parsed combination can still fail type checking. Equality, ordering, and in share one level, and ?? groups to the left.
Power accepts a unary expression on its right. Thus - groups as -, while 2 ** - parses with a negative exponent. The integer exponent restriction is a separate runtime condition.
Why
A fixed precedence table makes expression grouping independent of whitespace. The same grouping applies before operand types are checked.
Source evidence
- binaryPrecedence and binaryName at
b48527d0a174· 62-97 - parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647
Unary, binary, and logical operators
LinkUnary operators
| Operators | Operand types | Result | Operation |
|---|---|---|---|
! | bool | bool | Logical negation |
- | int, float, Big, Decimal | Operand type | - negates the value |
Prefix + is rejected during parsing with TPZ2001. Use the operand directly. Binary + remains addition.
Literal sign rules are defined by Literals and templates. Other operand families remain Pending.
Literal bounds are covered by Literals and templates. This rule covers operators applied to values. Unary minus negates a value and does not introduce another numeric type.
Why
An ordinary expression already denotes its value, so an identity prefix would add another spelling. Numeric negation preserves the operand type.
Source evidence
- inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - parseUnary still admits the plus prefix at
9b1bbdeceba9· 1436-1459 - issues/31 at
b48527d0a174
Arithmetic operands and results
The following operand pairs produce the listed result types.
| Operators | Left operand | Right operand | Result | Operation |
|---|---|---|---|---|
+, -, *, /, ** | int | int | int | Arithmetic |
+, -, *, /, ** | float | float | float | Arithmetic |
% | int | int | int | Arithmetic |
+ | string | string | string | Concatenation |
+, -, * | Big | Big | Big | Arithmetic |
+, -, * | Decimal | Decimal | Decimal | Arithmetic |
Mixed int/float operands are rejected during checking. Integer and Length value boundaries are specified below.
Arithmetic examples use small integers so grouping is visible independently of overflow boundaries. BigInt and Decimal division APIs belong to their library entries. The Types and Literals pages own type forms, literal bounds, and units.
The Decimal value contract defines exact decimal arithmetic and canonical scale. Explicit BigInt division and remainder follow the BigInt contract. Duration arithmetic and range failures follow the Duration value rule.
Evaluation follows the operand and assignment order.
Why
Requiring matching numeric types avoids implicit changes in precision. Explicit result types let arithmetic participate in the same type checks as other expressions.
Source evidence
- inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - int_div, int_rem, and int_pow at
b48527d0a174· 39-96
Integer and Length value boundaries
Integer arithmetic stays within - through 9223372036854775807. Division truncates toward zero. A nonzero remainder has the dividend's sign. Integer 0 ** 0 is 1.
| Boundary | Runtime diagnostic |
|---|---|
| Integer or Length division by zero, or integer remainder by zero | TPZ4002 |
| Integer overflow, including minimum int divided or reduced modulo -1 | TPZ4004 |
| Integer power with a negative exponent | TPZ4005 |
| Integer exponent greater than 4294967295, even with base 0 or 1 | TPZ4004 |
| Unrepresentable Length result or a non-finite scaling operand | TPZ4004 |
Length operations use the following operand pairs. U denotes the same unit on both Length operands. Mixed units are rejected during checking.
| Operators | Left | Right | Result |
|---|---|---|---|
+, - | Length<U> | Length<U> | Length<U> |
/ | Length<U> | Length<U> | float |
* | Length<U> | int- | Length<U> |
* | int- | Length<U> | Length<U> |
/ | Length<U> | int | Length<U> |
Length multiplication and integer division round to the nearest representable fixed-precision value, with ties choosing the even value. Dividing two Length values gives their floating-point ratio.
When a constant initializer reaches a numeric fault, checking rejects it with TPZ5001 and a message beginning constant expression error:.
The physical length contract defines stored scaled points and explicit unit conversions.
Why
Checked arithmetic prevents silent wraparound in computed sizes. Matching length units prevents accidental mixing of document measurements. Ties-to-even rounding avoids a consistent bias at exact halfway values.
Source evidence
- Checked int arithmetic and fault codes at
151141d7bb44· 13-105 - Typed and boxed arithmetic and unary routing at
151141d7bb44· 426-538 - Length operand pairing at
151141d7bb44· 849-868 - Checked Length arithmetic and ties-to-even rounding at
151141d7bb44· 187-288 - Length binary operator dispatch at
151141d7bb44· 321-365 - Length error to runtime diagnostic mapping at
151141d7bb44· 42-55 - Constant integer arithmetic faults at
151141d7bb44· 1682-1770 - constantExpressionFault TPZ5001 at
151141d7bb44· 1262-1275 - foldLengthBinary at
151141d7bb44· 1796-1818
Comparison and membership
==, != compare equality, and <, <=, >, >= compare order. The operands must have compatible, comparable types. These operations produce bool. Comparison capabilities are defined by Protocols and implementations. A declared nominal Eq or Order conformance supplies both its protocol-qualified method and the corresponding operators. Nested derived comparisons use that same conformance.
Write element membership as element in container. in produces bool for Array<T>, Set<T>, Range<int>. The value must be compatible with the container's element type. Range membership requires both bounds and step alignment. Map, string are rejected as membership containers during checking.
Substring search and Map key lookup follow their distinct library contracts.
The comparison operators produce Boolean results after the relevant type and capability checks. General compatibility and protocol resolution are documented by Types and Protocols and implementations. For a range, membership also considers its step.
The Decimal comparison contract defines exact equality and ordering independently of input padding.
Why
Set. and in ask the same question about whether an equal element belongs to a set. The in operator expresses that membership intent for arrays, sets, and integer ranges. Range membership includes step alignment so it agrees with iteration. Substring search and Map key lookup retain their distinct input and result contracts.
Source evidence
- inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - binary_value membership and range_items at
b48527d0a174· 328-418 - inferBinaryExpression in branch at
271329b482bc· 999-1033 - issues/31 at
26da6a582932
Logical operators and coalescing
The left operand is evaluated first. The following cases skip the right operand and produce the indicated value. Otherwise, the right operand is evaluated and supplies the result.
| Operator | Left type | Right type | Skip right when left is | Result when skipped | Evaluate right when left is |
|---|---|---|---|---|---|
&& | bool | bool | false | false | true |
\|\| | bool | bool | true | true | false |
?? | Option<T> | T | Some(value) | value | None() |
?? | T \| null | T | non- | left | null |
The short-circuit decision follows evaluation of the left operand. In the example, any call to mark would print an extra line; that line is absent from the independent expected output.
Why
Skipping an unused operand avoids its effects and failures. This lets a guard or fallback depend on the value already computed.
Source evidence
- inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - emitBinary at
b48527d0a174· 483-503 - short_circuit_lhs and index_value at
b48527d0a174· 653-730
Derived equality and operators use the inner manual equality
Linkimport std.io { writeLine }record Token { key: int, noise: int }impl Eq<Token> {function equals(a: Token, b: Token) -> bool { a.key == b.key }}record Box derives Eq { item: Token }let a = Box { item: Token { key: 1, noise: 10 } }let b = Box { item: Token { key: 1, noise: 20 } }let c = Box { item: Token { key: 2, noise: 10 } }writeLine("{Eq.equals(a, b)}")writeLine("{a == b}")writeLine("{Eq.equals(a, c)}")writeLine("{a != c}")
true true false true
Expected result
Expected result
Execution completes. Exit code 0.
truetruefalsetrue
Source evidence
- compiler/crates/topaz_self_frontend/topaz/checker/diagnostics_derives.tpz at
72a59a31125f· 42-204 - compiler/crates/topaz_self_frontend/topaz/checker/protocols_methods.tpz at
72a59a31125f· 529-541 - compiler/crates/topaz_value/src/value/compare.rs at
72a59a31125f· 85-180 - compiler/crates/topaz_value/src/value/compare.rs at
72a59a31125f· 198-353 - compiler/crates/topaz_value/src/value/json/schema.rs at
72a59a31125f· 212-226 - compiler/crates/topaz_value/src/value/json/codec.rs at
72a59a31125f· 1-47 - compiler/crates/topaz_value/src/value/guards.rs at
72a59a31125f· 88-96 - pull/44 at
72a59a31125f
A manual equality hides an opaque field from outer operators
Linkimport std.io { writeLine }record Callback { key: int, run: () -> int }impl Eq<Callback> {function equals(a: Callback, b: Callback) -> bool { a.key == b.key }}record Box derives Eq { item: Callback }let a = Box { item: Callback { key: 1, run: () => 7 } }let b = Box { item: Callback { key: 1, run: () => 9 } }writeLine("{a == b}")writeLine("{Eq.equals(a, b)}")
true true
Expected result
Expected result
Execution completes. Exit code 0.
truetrue
Source evidence
- compiler/crates/topaz_self_frontend/topaz/checker/diagnostics_derives.tpz at
72a59a31125f· 42-204 - compiler/crates/topaz_self_frontend/topaz/checker/protocols_methods.tpz at
72a59a31125f· 529-541 - compiler/crates/topaz_value/src/value/compare.rs at
72a59a31125f· 85-180 - compiler/crates/topaz_value/src/value/compare.rs at
72a59a31125f· 198-353 - compiler/crates/topaz_value/src/value/json/schema.rs at
72a59a31125f· 212-226 - compiler/crates/topaz_value/src/value/json/codec.rs at
72a59a31125f· 1-47 - compiler/crates/topaz_value/src/value/guards.rs at
72a59a31125f· 88-96 - pull/44 at
72a59a31125f
Derived ordering and operators use the inner manual ordering
Linkimport std.io { writeLine }record Rank { score: int }impl Order<Rank> {function compare(a: Rank, b: Rank) -> int {if (a.score > b.score) { -1 } else if (a.score < b.score) { 1 } else { 0 }}}record Box derives Order { item: Rank }let a = Box { item: Rank { score: 9 } }let b = Box { item: Rank { score: 3 } }writeLine("{Order.compare(a, b)}")writeLine("{a < b}")writeLine("{Order.compare(b, a)}")writeLine("{b > a}")
-1 true 1 true
Expected result
Expected result
Execution completes. Exit code 0.
-1true1true
Source evidence
- compiler/crates/topaz_self_frontend/topaz/checker/diagnostics_derives.tpz at
72a59a31125f· 42-204 - compiler/crates/topaz_self_frontend/topaz/checker/protocols_methods.tpz at
72a59a31125f· 529-541 - compiler/crates/topaz_value/src/value/compare.rs at
72a59a31125f· 85-180 - compiler/crates/topaz_value/src/value/compare.rs at
72a59a31125f· 198-353 - compiler/crates/topaz_value/src/value/json/schema.rs at
72a59a31125f· 212-226 - compiler/crates/topaz_value/src/value/json/codec.rs at
72a59a31125f· 1-47 - compiler/crates/topaz_value/src/value/guards.rs at
72a59a31125f· 88-96 - pull/44 at
72a59a31125f
Operand and assignment evaluation order
Binary expressions evaluate their operands from left to right. The same order applies within nested operands. The first runtime fault terminates evaluation, so later operands do not run. The short-circuit rule still determines whether a right operand runs.
| Assignment form | Evaluation order |
|---|---|
x = value() | Evaluate the right value, then write x. |
a[index()] = value() | Evaluate the receiver, evaluate the index, validate the slot, evaluate the right value, then write the slot. |
record. | Evaluate the right value, then read the named record root, update the field, and write the root. |
a[index()]. | Evaluate the receiver and index, validate the slot, evaluate the right value, then read the record, update the field, and write the slot. |
x += value() and other compound arithmetic assignments | Evaluate the target and read its old value, evaluate the right value, apply the operation, then write the result. |
A fault in an earlier assignment step prevents later steps. Assignment does not give a named record field a read before its right-hand value.
The short-circuit rule determines which operands run. Function calls keep their argument evaluation order.
Why
One operand order makes effects and the first fault reproducible. Existing assignment forms retain their evaluation order.
Source evidence
- issues/31 at
1cbf38d3d422 - emitPathAssignment and emitAssignment at
1cbf38d3d422· 3359-3486 - emitBinary at
1cbf38d3d422· 557-625
Ranges and access
LinkRanges and steps
Both endpoints are required and have type int. The result has type Range<int>.
| Operator | Upper bound |
|---|---|
. | inclusive |
. | exclusive |
The by clause supplies an int step. Its default is 1. The sequence begins at the first endpoint and advances by adding the step. A positive step advances toward an increasing end value. A negative step advances toward a decreasing end value. Bounds in the wrong direction produce an empty range.
Membership requires bounds and step alignment. A zero step is invalid. A statically detected zero step is rejected during checking. A zero step that reaches evaluation causes a runtime fault. Iteration is defined by Blocks and control flow.
The by clause is part of the range expression. An inclusive upper bound is included only if the sequence reaches it. Blocks and control flow describes how for consumes a range; collection construction is documented separately.
Why
Explicit bounds and steps define the visited integers without materializing an array. Membership and iteration use the same sequence.
Source evidence
- parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647 - inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - emitRange at
b48527d0a174· 1816-1830 - binary_value membership and range_items at
b48527d0a174· 328-418
Member, index, and optional access
object. follows the selected type or library entry's member contract. array[index] accepts an int index into Array<T> and produces T. Indices start at 0. Other index types are rejected during checking. Negative or out-of-bounds indices cause a runtime fault.
object?. accepts Option<T>, T | null.
| Receiver | Member access and result |
|---|---|
None() | Skip access and produce None() |
null | Skip access and produce null |
Some(value) | Access the wrapped value and produce one Option layer, flattening an existing Option result |
non- | Access the value and produce the member result |
| Receiver type | Result type |
|---|---|
Option<T> | Option<member- with one-layer flattening |
T \| null | member- |
A member name selects a field or member whose individual contract belongs to its type or library entry. The access example uses an existing array's length property only to show optional access. Array construction, mutation, and the property's API contract are outside this page.
Evaluation follows the operand and assignment order.
Why
Optional access skips a member lookup when its receiver is absent. Bounds checks prevent an invalid array position from producing an ordinary element value.
Source evidence
- parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647 - inferComposeExpression and inferIndexExpression at
b48527d0a174· 1168-1283 - optionalReceiver, wrapOptionalResult, and inferOptionalMemberAccess at
b48527d0a174· 1067-1297 - wrap_optional and optional_member at
b48527d0a174· 423-451 - short_circuit_lhs and index_value at
b48527d0a174· 653-730
Choose Unicode scalars or grapheme clusters explicitly
text. returns Array<string> in source order. Each element contains one Unicode scalar value. Empty text returns an empty array. The operation preserves the stored scalars without normalization. Joining its elements with an empty separator reproduces the original string.
text. follows the Unicode grapheme contract. Use the returned array's length and indexing operations for the chosen text unit.
Loop inputs follow the iteration rule. Choose scalar values or grapheme clusters explicitly before iterating over text.
Why
A scalar and a grapheme cluster are different text units. Explicit names preserve scalar algorithms while allowing document editing to keep combining marks, Hangul syllables, and emoji sequences together. Unicode 16 matches the language character data and gives every host the same boundaries. Returning an Array reuses its count and index operations without additional string spellings.
Source evidence
- Default extended grapheme cluster boundaries at
Unicode-16.0· UAX29-C1-1; section 3.1.1; section 6.1 - stringMemberType supports scalars and has no graphemes member at
271329b482bc· 911-949
Calls and function composition
LinkOrdinary calls and saved values
Write calls as callee(arguments) and members as value.. Bind an intermediate value with let when it must be evaluated once or reused.
Method chains and successive let bindings read from the input through its transformations in order.
|> is rejected during parsing with TPZ2001. This includes bare-callable, inserted-argument, placeholder, and member-shortcut stages. A standalone expression _ is also rejected during parsing.
When migrating a pipeline with effects, bind the input first, then evaluate the callee and written arguments in their required order. The resulting ordinary call follows Functions and generics.
Use a named binding when one computed value is needed more than once. A wildcard _ belongs to a pattern and has no expression meaning. Ordinary calls use the argument binding rules in Functions and generics.
Why
A pipeline and a method chain both present a value followed by the transformations that consume it. When the transformations are ordinary functions, successive let bindings present the same input-to-result reading order. These forms preserve the intended data flow and make evaluation and reuse explicit. Written call arguments keep each consumed value visible. Bind effectful input, callee, and argument expressions in their required order when replacing a pipeline.
Source evidence
- parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647 - inferBarePipeStage, inferPipeCallStage, and inferPipe at
b48527d0a174· 1460-1688 - currentPipeValue at
b48527d0a174· 1364-1421 - emitPipe and emitPipeStage at
b48527d0a174· 1418-1476 - parseAtom retains the expression placeholder at
271329b482bc· 1245-1272 - emitPipe saves the lead before stage and written arguments at
271329b482bc· 1418-1476 - issues/31 at
26da6a582932
Compose calls in a function body
Compose calls in a function body, for example (value: T) => second(first(value)). Input, intermediate, and result types follow ordinary function and call rules.
The body can name successive results with let in data-flow order.
The >> composition operator is rejected during parsing with TPZ2001. Bind function values before constructing the lambda when their evaluation or capture must happen once.
To preserve composition-time evaluation, first bind each function value once and in the desired order. Capture those immutable bindings in the function body. Later calls then reuse the same function values.
Why
A composition operator and a function body both describe a transformation whose result becomes the next transformation input. Successive let bindings inside the body read in that same data-flow order, and ordinary call typing preserves the intermediate types. Binding function values before constructing the body preserves evaluation and capture that must happen once.
Source evidence
- parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647 - inferComposeExpression and inferIndexExpression at
b48527d0a174· 1168-1283 - SELF composition construction at
b48527d0a174· 290-294 - call_composed at
b48527d0a174· 292-304 - parseAtom retains the expression placeholder at
271329b482bc· 1245-1272 - emitPipe saves the lead before stage and written arguments at
271329b482bc· 1418-1476 - issues/31 at
26da6a582932
Examples and expected results
LinkEach example is a complete source file with an independent expected result and an assertion plan. No execution receipt is attached. Missing boundary coverage remains explicit; a future observation that differs from an intended result requires triage and an implementation limitation when appropriate, rather than replacement of the expectation.
Grouping arithmetic and power
Linkimport std.ioio.writeLine("{2 + 3 * 4}")io.writeLine("{(2 + 3) * 4}")io.writeLine("{20 - 5 - 3}")io.writeLine("{2 ** 3 ** 2}")io.writeLine("{-2 ** 2}")io.writeLine("{(-2) ** 2}")
14 20 12 512 -4 4
Expected result
Expected result
Execution completes. Exit code 0.
142012512-44
Observed assertions · passed · 5.21.3
Exit code 0.
142012512-44
No stderr.
- Passed · expected 0; observed 0
- Passed · stdout matches the authored expectation
- Passed · stderr matches the authored expectation
- Passed · stdout matches the authored expectation
- Passed · stdout matches the authored expectation
The expected result is specified from the source contract. This exact fixture has not been run on a public Topaz 5.21.x CLI.
Source evidence
- binaryPrecedence and binaryName at
b48527d0a174· 62-97 - parsePostfix, parseUnary, infix parsers, and parseExpressionBp at
b48527d0a174· 1335-1647 - inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - Integer expression interpolation at
b48527d0a174· 1-1 - parseString expression interpolation at
b48527d0a174· 374-398 - First-program fixture with import std.io and io.writeLine at
b48527d0a174· 1330-1360
Skipping a right operand
Linkimport std.iofunction mark() -> bool {io.writeLine("evaluated")true}io.writeLine("{false && mark()}")io.writeLine("{true || mark()}")let present: Option<int> = Some(7)let absent: Option<int> = None()io.writeLine("{present ?? 9}")io.writeLine("{absent ?? 9}")
false true 7 9
Expected result
Expected result
Execution completes. Exit code 0.
falsetrue79
Observed assertions · passed · 5.21.3
Exit code 0.
falsetrue79
No stderr.
- Passed · expected 0; observed 0
- Passed · stdout matches the authored expectation
- Passed · stderr matches the authored expectation
The expected result is specified from the source contract. This exact fixture has not been run on a public Topaz 5.21.x CLI.
Source evidence
- inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - emitBinary at
b48527d0a174· 483-503 - short_circuit_lhs and index_value at
b48527d0a174· 653-730 - Integer expression interpolation at
b48527d0a174· 1-1 - parseString expression interpolation at
b48527d0a174· 374-398 - First-program fixture with import std.io and io.writeLine at
b48527d0a174· 1330-1360
Apply ordinary calls and a function body
Linkimport std.iofunction increment(n: int) -> int { n + 1 }function double(n: int) -> int { n * 2 }function subtract(a: int, b: int) -> int { a - b }let composed = (n: int) => double(increment(n))io.writeLine("{double(increment(3))}")io.writeLine("{composed(3)}")io.writeLine("{subtract(10, 3)}")io.writeLine("{subtract(3, 10)}")
8 8 7 -7
Expected result
Expected result
Execution completes. Exit code 0.
887-7
This fixture uses ordinary calls and a lambda. Its expected values are unchanged. Product execution of this revised fixture remains pending.
Source evidence
- inferBarePipeStage, inferPipeCallStage, and inferPipe at
b48527d0a174· 1460-1688 - inferComposeExpression and inferIndexExpression at
b48527d0a174· 1168-1283 - emitPipe and emitPipeStage at
b48527d0a174· 1418-1476 - Integer expression interpolation at
b48527d0a174· 1-1 - parseString expression interpolation at
b48527d0a174· 374-398 - First-program fixture with import std.io and io.writeLine at
b48527d0a174· 1330-1360 - SELF composition construction at
b48527d0a174· 290-294 - call_composed at
b48527d0a174· 292-304
Membership respects a range's step
Linkimport std.iolet odd = 1..<6 by 2io.writeLine("{1 in odd}")io.writeLine("{2 in odd}")io.writeLine("{5 in odd}")io.writeLine("{6 in odd}")
true false true false
Expected result
Expected result
Execution completes. Exit code 0.
truefalsetruefalse
Observed assertions · passed · 5.21.3
Exit code 0.
truefalsetruefalse
No stderr.
- Passed · expected 0; observed 0
- Passed · stdout matches the authored expectation
- Passed · stderr matches the authored expectation
- Passed · stdout matches the authored expectation
The expected result is specified from the source contract. This exact fixture has not been run on a public Topaz 5.21.x CLI.
Source evidence
- inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121 - emitRange at
b48527d0a174· 1816-1830 - binary_value membership and range_items at
b48527d0a174· 328-418 - Integer expression interpolation at
b48527d0a174· 1-1 - parseString expression interpolation at
b48527d0a174· 374-398 - First-program fixture with import std.io and io.writeLine at
b48527d0a174· 1330-1360
Indexing and optional member access
Linkimport std.iolet values = [4, 5]let present: Option<Array<int>> = Some(values)let absent: Option<Array<int>> = None()io.writeLine("{values[0]}")io.writeLine("{present?.length ?? 0}")io.writeLine("{absent?.length ?? 0}")
4 2 0
Expected result
Expected result
Execution completes. Exit code 0.
420
Observed assertions · passed · 5.21.3
Exit code 0.
420
No stderr.
- Passed · expected 0; observed 0
- Passed · stdout matches the authored expectation
- Passed · stderr matches the authored expectation
The expected result is specified from the source contract. This exact fixture has not been run on a public Topaz 5.21.x CLI.
Source evidence
- inferComposeExpression and inferIndexExpression at
b48527d0a174· 1168-1283 - optionalReceiver, wrapOptionalResult, and inferOptionalMemberAccess at
b48527d0a174· 1067-1297 - wrap_optional and optional_member at
b48527d0a174· 423-451 - short_circuit_lhs and index_value at
b48527d0a174· 653-730 - Integer expression interpolation at
b48527d0a174· 1-1 - parseString expression interpolation at
b48527d0a174· 374-398 - First-program fixture with import std.io and io.writeLine at
b48527d0a174· 1330-1360 - optional_member_array_length_boundary at
b48527d0a174
Rejecting a parenthesized comma list
Linklet value = (1, 2)
No stdout.
error[TPZ2001]: parentheses group a single expression; `(a, b)` comma lists are not Topaz syntax --> example.tpz:1:15 | 1 | let value = (1, 2) | ^ example.tpz: 1 diagnostic
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001parenthesized-comma-list atexample.tpz:1:15
Observed assertions · passed · 5.21.3
Exit code 1.
No stdout.
error[TPZ2001]: parentheses group a single expression; `(a, b)` comma lists are not Topaz syntax--> example.tpz:1:15|1 | let value = (1, 2)| ^example.tpz: 1 diagnostic
- Passed · expected nonzero; observed 1
- Passed · checking TPZ2001; cause parenthesized-comma-list; primary location asserted; additional diagnostics allow
This fixture expects rejection at the comma because parentheses group a single expression. It is run through check so parsing is reached, and requires the parsing diagnostic and its location. The exact public CLI observation is pending.
Source evidence
- parseParenthesizedExpression at
b48527d0a174· 1036-1091
Signed division, zero power, and Length arithmetic
Linkimport std.iolet quotient = -7 / 3let remainder = -7 % 3let zeroPower = 0 ** 0io.writeLine("{quotient} {remainder} {zeroPower}")io.writeLine("{(1pt + 2pt) == 3pt}")io.writeLine("{(1pt * 2) == 2pt}")io.writeLine("{(2 * 1pt) == 2pt}")io.writeLine("{(1pt / 2) == 0.5pt}")io.writeLine("{3pt / 2pt}")
-2 -1 1 true true true true 1.5
Expected result
Expected result
Execution completes. Exit code 0.
-2 -1 1truetruetruetrue1.5
The expected result follows from current SELF source. Execution against public Topaz 5.21.3 is pending CI.
Source evidence
- Checked int arithmetic and fault codes at
151141d7bb44· 13-105 - Typed and boxed arithmetic and unary routing at
151141d7bb44· 426-538 - Length operand pairing at
151141d7bb44· 849-868 - Checked Length arithmetic and ties-to-even rounding at
151141d7bb44· 187-288 - Length binary operator dispatch at
151141d7bb44· 321-365 - Length error to runtime diagnostic mapping at
151141d7bb44· 42-55 - Constant integer arithmetic faults at
151141d7bb44· 1682-1770 - constantExpressionFault TPZ5001 at
151141d7bb44· 1262-1275 - foldLengthBinary at
151141d7bb44· 1796-1818
Integer division by zero is rejected in a constant
Linkconst bad = 1 / 0
Expected result
Expected result
Rejection during check. Nonzero exit.
TPZ5001constant-integer-division-zero atexample.tpz:1:13
The expected result follows from current SELF source. Execution against public Topaz 5.21.3 is pending CI.
Source evidence
- Checked int arithmetic and fault codes at
151141d7bb44· 13-105 - Typed and boxed arithmetic and unary routing at
151141d7bb44· 426-538 - Length operand pairing at
151141d7bb44· 849-868 - Checked Length arithmetic and ties-to-even rounding at
151141d7bb44· 187-288 - Length binary operator dispatch at
151141d7bb44· 321-365 - Length error to runtime diagnostic mapping at
151141d7bb44· 42-55 - Constant integer arithmetic faults at
151141d7bb44· 1682-1770 - constantExpressionFault TPZ5001 at
151141d7bb44· 1262-1275 - foldLengthBinary at
151141d7bb44· 1796-1818
An overflowing integer constant is rejected
Linkconst bad = 9223372036854775807 + 1
Expected result
Expected result
Rejection during check. Nonzero exit.
TPZ5001constant-integer-addition-overflow atexample.tpz:1:13
The expected result follows from current SELF source. Execution against public Topaz 5.21.3 is pending CI.
Source evidence
- Checked int arithmetic and fault codes at
151141d7bb44· 13-105 - Typed and boxed arithmetic and unary routing at
151141d7bb44· 426-538 - Length operand pairing at
151141d7bb44· 849-868 - Checked Length arithmetic and ties-to-even rounding at
151141d7bb44· 187-288 - Length binary operator dispatch at
151141d7bb44· 321-365 - Length error to runtime diagnostic mapping at
151141d7bb44· 42-55 - Constant integer arithmetic faults at
151141d7bb44· 1682-1770 - constantExpressionFault TPZ5001 at
151141d7bb44· 1262-1275 - foldLengthBinary at
151141d7bb44· 1796-1818
An integer exponent must be non-negative
Linkconst bad = 2 ** -1
Expected result
Expected result
Rejection during check. Nonzero exit.
TPZ5001constant-integer-negative-exponent atexample.tpz:1:13
The expected result follows from current SELF source. Execution against public Topaz 5.21.3 is pending CI.
Source evidence
- Checked int arithmetic and fault codes at
151141d7bb44· 13-105 - Typed and boxed arithmetic and unary routing at
151141d7bb44· 426-538 - Length operand pairing at
151141d7bb44· 849-868 - Checked Length arithmetic and ties-to-even rounding at
151141d7bb44· 187-288 - Length binary operator dispatch at
151141d7bb44· 321-365 - Length error to runtime diagnostic mapping at
151141d7bb44· 42-55 - Constant integer arithmetic faults at
151141d7bb44· 1682-1770 - constantExpressionFault TPZ5001 at
151141d7bb44· 1262-1275 - foldLengthBinary at
151141d7bb44· 1796-1818
Length division by zero is rejected in a constant
Linkconst bad = 1pt / 0
Expected result
Expected result
Rejection during check. Nonzero exit.
TPZ5001constant-length-division-zero atexample.tpz:1:13
The expected result follows from current SELF source. Execution against public Topaz 5.21.3 is pending CI.
Source evidence
- Checked int arithmetic and fault codes at
151141d7bb44· 13-105 - Typed and boxed arithmetic and unary routing at
151141d7bb44· 426-538 - Length operand pairing at
151141d7bb44· 849-868 - Checked Length arithmetic and ties-to-even rounding at
151141d7bb44· 187-288 - Length binary operator dispatch at
151141d7bb44· 321-365 - Length error to runtime diagnostic mapping at
151141d7bb44· 42-55 - Constant integer arithmetic faults at
151141d7bb44· 1682-1770 - constantExpressionFault TPZ5001 at
151141d7bb44· 1262-1275 - foldLengthBinary at
151141d7bb44· 1796-1818
An unrepresentable Length constant is rejected
Linkconst bad = 1pt * 9223372036854775807
Expected result
Expected result
Rejection during check. Nonzero exit.
TPZ5001constant-length-unrepresentable atexample.tpz:1:13
The expected result follows from current SELF source. Execution against public Topaz 5.21.3 is pending CI.
Source evidence
- Checked int arithmetic and fault codes at
151141d7bb44· 13-105 - Typed and boxed arithmetic and unary routing at
151141d7bb44· 426-538 - Length operand pairing at
151141d7bb44· 849-868 - Checked Length arithmetic and ties-to-even rounding at
151141d7bb44· 187-288 - Length binary operator dispatch at
151141d7bb44· 321-365 - Length error to runtime diagnostic mapping at
151141d7bb44· 42-55 - Constant integer arithmetic faults at
151141d7bb44· 1682-1770 - constantExpressionFault TPZ5001 at
151141d7bb44· 1262-1275 - foldLengthBinary at
151141d7bb44· 1796-1818
Rejecting unary plus before an integer
Linklet value = +1
Expected result
Write 1 to use the integer value.
Source evidence
- parseUnary still admits the plus prefix at
9b1bbdeceba9· 1436-1459
Rejecting unary plus before a bound value
Linklet value = 1let copy = +value
Expected result
Use the bound value directly.
Source evidence
- parseUnary still admits the plus prefix at
9b1bbdeceba9· 1436-1459
Rejecting unary plus before a float
Linklet value = +1.5
Expected result
Write 1. to use the floating value.
Source evidence
- parseUnary still admits the plus prefix at
9b1bbdeceba9· 1436-1459
Using ordinary values, negation, and binary addition
Linkimport std.iolet value = 3io.writeLine("{1}")io.writeLine("{1.5}")io.writeLine("{value}")io.writeLine("{-value}")io.writeLine("{value + 2}")
1 1.5 3 -3 5
Expected result
Expected result
Execution completes. Exit code 0.
11.53-35
Ordinary values need no identity prefix. Unary minus and binary addition retain their arithmetic meanings.
Source evidence
- inferRangeExpression, inferBinaryExpression, and inferUnaryExpression at
b48527d0a174· 689-1121
Use in for arrays, sets, and ranges
Linkimport std.iolet values = [1, 3]let members = set { 1, 3 }let odds = 1..<5 by 2io.writeLine("{1 in values}:{2 in values}")io.writeLine("{1 in members}:{2 in members}")io.writeLine("{1 in odds}:{2 in odds}")
true:false true:false true:false
Expected result
Expected result
Execution completes. Exit code 0.
true:falsetrue:falsetrue:false
Source evidence
- inferBinaryExpression in branch at
271329b482bc· 999-1033
A Map is not an element-membership container
Linklet found = "key" in map { "key": 1 }
No stdout.
Expected result
Expected result
Rejection during check. Nonzero exit.
TPZ5001map-not-element-membership
The required primary-location contract is Pending.
Source evidence
- inferBinaryExpression in branch at
271329b482bc· 999-1033
Substring search is not element membership
Linklet found = "a" in "abc"
No stdout.
Expected result
Expected result
Rejection during check. Nonzero exit.
TPZ5001string-not-element-membership
The required primary-location contract is Pending.
Source evidence
- inferBinaryExpression in branch at
271329b482bc· 999-1033
Keep combining marks, Hangul, and emoji in their grapheme clusters
Linkimport std.iolet text = "é가👩💻🇰🇷"let clusters = text.graphemes()io.writeLine("{text.scalars().length}:{clusters.length}")io.writeLine("{clusters[0] == "é"}")io.writeLine("{clusters[1] == "가"}")io.writeLine("{clusters[2] == "👩💻"}")io.writeLine("{clusters[3] == "🇰🇷"}")io.writeLine("{clusters.join("") == text}")
9:4 true true true true true
Expected result
Expected result
Execution completes. Exit code 0.
9:4truetruetruetruetrue
Source evidence
- Default extended grapheme cluster boundaries at
Unicode-16.0· UAX29-C1-1; section 3.1.1; section 6.1 - stringMemberType supports scalars and has no graphemes member at
271329b482bc· 911-949
Segment empty text, CRLF, leading marks, and regional indicators
Linkimport std.iolet empty = "".graphemes()let lineBreak = "\r\n".graphemes()let marks = "́̂".graphemes()let flags = "🇰🇷🇯".graphemes()io.writeLine("{empty.length}:{lineBreak.length}:{marks.length}:{flags.length}")io.writeLine("{lineBreak[0] == "\r\n"}")io.writeLine("{marks[0].scalars().length}")io.writeLine("{flags[0] == "🇰🇷"}:{flags[1] == "🇯"}")
0:1:1:2 true 2 true:true
Expected result
Expected result
Execution completes. Exit code 0.
0:1:1:2true2true:true
Source evidence
- Default extended grapheme cluster boundaries at
Unicode-16.0· UAX29-C1-1; section 3.1.1; section 6.1 - stringMemberType supports scalars and has no graphemes member at
271329b482bc· 911-949
Reject a pipeline into a bare callable
Linkfunction increment(n: int) -> int { n + 1 }let value = 3 |> increment
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001removed-call-sugar
The required primary-location contract is Pending.
Source evidence
- parseAtom retains the expression placeholder at
271329b482bc· 1245-1272
Reject implicit pipeline argument insertion
Linkfunction add(a: int, b: int) -> int { a + b }let value = 3 |> add(4)
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001removed-call-sugar
The required primary-location contract is Pending.
Source evidence
- parseAtom retains the expression placeholder at
271329b482bc· 1245-1272
Reject a pipeline placeholder
Linkfunction subtract(a: int, b: int) -> int { a - b }let value = 3 |> subtract(10, _)
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001removed-call-sugar
The required primary-location contract is Pending.
Source evidence
- parseAtom retains the expression placeholder at
271329b482bc· 1245-1272
Reject a pipeline member shortcut
Linklet item = { answer: 7 }let value = item |> .answer
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001removed-call-sugar
The required primary-location contract is Pending.
Source evidence
- parseAtom retains the expression placeholder at
271329b482bc· 1245-1272
Reject the composition operator
Linkfunction increment(n: int) -> int { n + 1 }function double(n: int) -> int { n * 2 }let composed = increment >> double
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001removed-call-sugar
The required primary-location contract is Pending.
Source evidence
- parseAtom retains the expression placeholder at
271329b482bc· 1245-1272
Reject a standalone expression placeholder
Linklet value = _
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001removed-expression-placeholder
The required primary-location contract is Pending.
Source evidence
- parseAtom retains the expression placeholder at
271329b482bc· 1245-1272
Save values to preserve call and composition effects
Linkimport std.iofunction input() -> int {io.writeLine("input")3}function subtract(a: int, b: int) -> int { a - b }function stage() -> (int, int) -> int {io.writeLine("callee")subtract}function argument() -> int {io.writeLine("argument")10}let saved = input()let callee = stage()let written = argument()io.writeLine("{callee(written, saved)}")function increment(n: int) -> int { n + 1 }function double(n: int) -> int { n * 2 }function first() -> (int) -> int {io.writeLine("first")increment}function second() -> (int) -> int {io.writeLine("second")double}let left = first()let right = second()let composed = (n: int) => right(left(n))io.writeLine("{composed(3)}:{composed(5)}")
input callee argument 7 first second 8:12
Expected result
Expected result
Execution completes. Exit code 0.
inputcalleeargument7firstsecond8:12
Source evidence
- emitPipe saves the lead before stage and written arguments at
271329b482bc· 1418-1476
Reject an undelimited if operand
Linklet value = if true { 1 } else { 0 }
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:1:16
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited if let operand
Linklet value = if let Some(item) = Some(1) { item } else { 0 }
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:1:33
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited while operand
Linkwhile false { () }
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:1:7
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited while let operand
Linklet mut value: Option<int> = None()while let Some(item) = value { value = None() }
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:2:24
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited for operand
Linkfor item in [1] { let _ = item }
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:1:13
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited using operand
Linkfunction manage(file: File) -> () {using resource = file {}}
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:2:20
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited match operand
Linklet value = match 1 { case _ => 2 }
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:1:19
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited match guard operand
Linklet value = match (1) {case 1 if true => 1case _ => 0}
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:2:13
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited comprehension iterable operand
Linklet values = [for item in [1] => item]
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:1:27
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Reject an undelimited comprehension filter operand
Linklet values = [for item in ([1]) if true => item]
No stdout.
Expected result
Expected result
Rejection during parse. Nonzero exit.
TPZ2001control-operand-parentheses atexample.tpz:1:36
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Delimited tests, iterators, scrutinees, and guards
Linkimport std.iolet mut count = 0if (true) { count += 1 }if let Some(value) = (Some(1)) { count += value }while (count < 3) { count += 1 }let mut pending: Option<int> = Some(1)while let Some(value) = (pending) { pending = None() }for value in ([1, 2]) { count += value }let chosen = match (count) {case 6 if (((flag: bool) => flag)(true)) => 6case _ => 0}let collected = [for value in ([1, 2]) if (((flag: bool) => flag)(value > 0)) => value]io.writeLine("{chosen}")io.writeLine("{collected.length}")
6 2
Expected result
Expected result
Execution completes. Exit code 0.
62
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Record construction and update use ordinary operand grammar
Linkimport std.iorecord Flag { enabled: bool }let state = { enabled: true }let first = if (Flag { enabled: true }.enabled) { 1 } else { 0 }let second = if (state { enabled: false }.enabled) { 1 } else { 2 }let third = match (Flag { enabled: true }) {case Flag { enabled: true } => truecase _ => false}io.writeLine("{first},{second},{third}")
1,2,true
Expected result
Expected result
Execution completes. Exit code 0.
1,2,true
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204 - issues/31 at
1cbf38d3d422
The using expression has the same required boundary
Linkfunction manage(file: File) -> () {using resource = (file) {let handle: File = resource}}
No stdout.
Expected result
Expected result
Checking accepts the program. Exit code 0.
Source evidence
- parseNestedExpression; parseExpressionWithoutNakedLambda; parseExpressionBeforeBlock at
72a59a31125f· 1649-1699 - expect uses the existing TPZ2001 expected-token failure at
72a59a31125f· 195-204
Read transformations in data-flow order
Linkimport std.iofunction increment(value: int) -> int { value + 1 }function double(value: int) -> int { value * 2 }function transform(value: int) -> int {let increased = increment(value)double(increased)}let values = [1, 2]let chained = values.map(increment).map(double)let increased = values.map(increment)let staged = increased.map(double)let composed = values.map(transform)io.writeLine("{chained[0]},{chained[1]}")io.writeLine("{staged[0]},{staged[1]}")io.writeLine("{composed[0]},{composed[1]}")
4,6 4,6 4,6
Expected result
Expected result
Execution completes. Exit code 0.
4,64,64,6
Source evidence
- issues/31 at
26da6a582932
Binary and nested operands print from left to right
Linkimport std.iofunction value(label: string, number: int) -> int {io.writeLine(label)number}let result = value("left", 1) + value("middle", 2) * value("right", 3)io.writeLine("{result}")
left middle right 7
Expected result
Expected result
Execution completes. Exit code 0.
leftmiddleright7
Source evidence
- issues/31 at
1cbf38d3d422
The left operand faults before the right operand runs
Linkimport std.iofunction left(divisor: int) -> int {io.writeLine("left")1 / divisor}function right(number: int) -> int {io.writeLine("right")9223372036854775807 + number}left(0) + right(1)
left
Expected result
Expected result
Rejection during run. Nonzero exit.
TPZ4002diagnostic-tpz4002 atexample.tpz:4:5
left
Both calls would fault if evaluated. The left call produces TPZ4002, and the right call produces no output.
Source evidence
- issues/31 at
1cbf38d3d422
Index assignment evaluates the index before its value
Linkimport std.iofunction index() -> int {io.writeLine("index")0}function value() -> int {io.writeLine("value")7}let mut values = [1]values[index()] = value()io.writeLine("{values[0]}")let mut number = 1number += value()io.writeLine("{number}")
index value 7 value 8
Expected result
Expected result
Execution completes. Exit code 0.
indexvalue7value8
Source evidence
- issues/31 at
1cbf38d3d422