Skip to content
Topaz6.0 · Before release
Download

Search documentation

Specification 6.0 · Not released · Tested product 5.21.3

Use arrow keys to choose a result. Press Enter to open.

Type an API name, diagnostic number, rule, or project topic.

    Language · chapter 02 · 25 rules

    Literals and templates

    Literal spellings, values, string interpolation, and tagged templates.

    Scope and ownership

    Link

    Literals write values directly in source. This chapter covers their spellings, type families, escapes, interpolation, and template tags.

    Edition: Topaz 5.21 language mode. Source authority: SELF compiler revision af88afbc1d99a8c0220b5984f9d74f895f8156f2. Each executable example records its independent expectation and verification result.

    Lexical structure owns identifiers, token separation, comments, and source positions. Expressions and operators owns unary signs and grouping. Types owns general compatibility and inference. Concurrency owns the behavior of concurrent and its timeout. Library entries own conversion functions and operations on template values.

    Integers and floats

    Link
    EBNF
    1. DecimalDigit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
    2. BinaryDigit = "0" | "1" ;
    3. HexDigit = DecimalDigit | "a" | "b" | "c" | "d" | "e" | "f" ;
    4. DecimalDigits = DecimalDigit ("_"? DecimalDigit)* ;
    5. BinaryDigits = BinaryDigit ("_"? BinaryDigit)* ;
    6. HexDigits = HexDigit ("_"? HexDigit)* ;
    7. IntegerLiteral = DecimalDigits
    8. | "0x" HexDigits
    9. | "0b" BinaryDigits ;
    10. FloatLiteral = DecimalDigits "." DecimalDigits ;

    This manually transcribed excerpt describes numeric tokens in language mode 5.21. Adjacent elements belong to the same token. It omits operator grammar and contextual type rules.

    Source evidence
    Ruletopaz.literals.rule.integer-spellings

    Integer spellings

    An integer literal uses one of these radix forms.

    RadixPrefixDigits
    10none0123456789
    160x0123456789abcdef
    20b01

    Radix prefixes and hexadecimal letters are lowercase. An uppercase spelling produces TPZ2001 during parsing.

    A leading - is a unary expression operator applied to a literal.

    Why

    Decimal notation expresses magnitudes while binary and hexadecimal notation expose groups of bits. Changing the case of a radix prefix or hexadecimal digit changes neither the value nor the chosen radix. Lowercase removes that spelling choice while preserving the different purposes of the radix forms. A shared integer type keeps arithmetic independent of the chosen radix.

    Source evidence
    Ruletopaz.literals.rule.numeric-separators

    Numeric digit separators

    In a numeric digit run, _ separates two digits of the selected radix. The run starts and ends with a digit and cannot contain repeated separators. Parsing a malformed numeric token produces TPZ2001.

    Why

    Digit separators make long magnitudes easier to read. Requiring a digit on each side prevents separators from becoming prefixes or suffixes.

    Source evidence
    Ruletopaz.literals.rule.integer-range

    Integer values and the signed range

    An integer literal has a literal type compatible with int. Values range from -9223372036854775808 through 9223372036854775807. The signed minimum is accepted as -9223372036854775808. An out-of-range integer value produces TPZ5001 during checking.

    Why

    A fixed signed range gives integer values the same bounds across hosts. Rejecting an unrepresentable literal prevents silent truncation before the program runs.

    Source evidence
    Ruletopaz.literals.rule.decimal-floats

    Decimal float spellings and types

    A float literal has decimal digits on both sides of .. Exponent notation is rejected as a malformed numeric token with TPZ2001 during parsing. A float literal has a literal type compatible with float.

    Why

    A decimal point distinguishes a floating literal from an integer literal. Digits on both sides separate it from member and range punctuation. Positional decimal spelling matches finite-float rendering, which expands the shortest decimal representation into positional notation. Excluding exponent notation keeps source and display on that shared convention. The values use binary64.

    Source evidence
    Ruletopaz.literals.rule.floating-point

    Decimal float rounding, overflow, and signed zero

    Decimal float literals round to the nearest binary64 value. An exact tie selects the value with an even final significand bit. Overflow produces infinity. Underflow can produce a subnormal value or zero. Unary minus retains the sign of zero. Interpolation writes the infinities as inf and -inf, and the two zeros as 0.0 and -0.0. Decimal spelling still requires a point with digits on both sides; exponent spelling is rejected.

    Why

    Binary64 gives floating literals a common numeric representation. Defined rounding and signed zero make boundary values reproducible across the literal and arithmetic paths.

    Source evidence

    Booleans, null, and unit

    Link
    EBNF
    1. BooleanLiteral = "true" | "false" ;
    2. NullLiteral = "null" ;
    3. UnitLiteral = "(" ")" ;

    Parentheses containing an expression belong to the expression grammar.

    Source evidence
    Ruletopaz.literals.rule.scalar-types

    Boolean, null, and unit types

    SpellingType
    trueboolean literal type compatible with bool
    falseboolean literal type compatible with bool
    nullnull literal type
    ()unit type ()

    Why

    Boolean values, absence, and unit represent distinct concepts. Their separate types prevent an absent value or a completed action from becoming an implicit Boolean.

    Source evidence

    For null compatibility, the contextual typing of None(), and restrictions on the binding name None, see Types and Bindings and scope.

    Duration literals

    Link
    EBNF
    1. DurationLiteral = DecimalDigits DurationUnit ;
    2. DurationUnit = "ms" | "s" | "m" ;

    DecimalDigits is defined in the numeric grammar above.

    Concurrency owns the complete concurrent expression and timeout behavior.

    Source evidence
    Ruletopaz.literals.rule.duration-form

    Duration literals are ordinary values

    A duration literal attaches a lowercase ms, s, m suffix to a decimal integer magnitude. It denotes an ordinary Duration value, including in bindings, function arguments and results, parenthesized expressions, and concurrent(timeout: ...). Duration has no type arguments and does not implicitly convert to or from int or float. The same literal conversion and range checks apply in every expression position. Operations follow the Duration values rule.

    Arithmetic, comparison, display, and toMillis follow Duration operations.

    Why

    A unit suffix states the time scale beside the magnitude. The same literal denotes Duration in an ordinary expression and in a timeout; binding or parenthesizing that value does not change its admission. Duration remains distinct from numeric types so an integer cannot silently acquire a time unit.

    Source evidence
    Ruletopaz.literals.rule.duration-values

    Duration values and operations

    SuffixUnitMilliseconds per unit
    msmillisecond1
    ssecond1000
    mminute60000

    A Duration stores from 0 through 18446744073709551615 milliseconds. An out-of-range duration literal produces TPZ5001 during checking.

    Two Duration values support addition and subtraction. Multiplication takes a Duration and an int in either order, as in d * n and n * d. Construct a duration from an integer with 1ms * n. Duration has no division and no function for converting a number to Duration.

    Eq compares millisecond counts for equality. Order compares those counts numerically. Display produces a decimal millisecond literal such as 1500ms, which reads back as the same value. toMillis() -> int returns the millisecond count. Duration has no JSON capability in 6.0.

    An overflowing sum or product, a subtraction below zero, any negative integer multiplier, or a millisecond count outside the int range stops with runtime TPZ4004. These faults follow the fault cleanup rule.

    Runtime range failures use TPZ4004. Timeout evaluation follows concurrent deadlines.

    Why

    Every Duration stores milliseconds, so operations use one unit. A literal and integer multiplication provide one way to construct a duration from a number. The millisecond display reads back as the same value.

    Source evidence

    Length literals

    Link
    EBNF
    1. LengthLiteral = DecimalMagnitude LengthUnit ;
    2. DecimalMagnitude = DecimalDigits ("." DecimalDigits)? ;
    3. LengthUnit = "pt" | "mm" | "cm" | "in" | "em" ;

    DecimalDigits is defined in the numeric grammar above.

    Source evidence
    Ruletopaz.literals.rule.length-literals

    Length spellings and types

    A length literal attaches its lowercase unit directly to a decimal integer or decimal fraction. Radix and exponent notation are not length-literal forms.

    SuffixLiteral type
    ptLength<Pt>
    mmLength<Mm>
    cmLength<Cm>
    inLength<In>
    emLength<Em>

    The suffix determines the compiler-owned length type. Literal formation rejects an unrepresentable result with TPZ5001 during checking.

    Why

    Typed units let page dimensions and font-relative dimensions enter layout APIs directly. Keeping em distinct from physical lengths prevents a font size from being assumed implicitly.

    Source evidence

    Length conversions and arithmetic belong to their API entries. See Pending contracts for precision and exact literal endpoints.

    Ruletopaz.literals.rule.length-precision

    Length rounding and literal boundaries

    A Length literal is converted from its exact decimal value, including its sign. It rounds to the nearest multiple of the unit step below. An exact midpoint selects the even multiple.

    UnitStep in that unitMinimum input, includedUpper input limit, excluded
    pt1/65536-18446744073709551617/13107218446744073709551615/131072
    mm127/23592960-2342736497361113055359/47185920156182433157407537007/3145728
    cm127/235929600-2342736497361113055359/471859200156182433157407537007/31457280
    in1/4718592-18446744073709551617/94371846148914691236517205/3145728
    em1/65536-18446744073709551617/13107218446744073709551615/131072

    The fractions are exact mathematical values. Write a decimal value followed immediately by its unit in source. A literal outside this interval produces TPZ5001 during checking. Equality and the public unit-conversion methods observe the rounded result.

    Why

    Exact decimal conversion fixes a document dimension before layout. A shared point grid aligns physical unit conversions, and ties-to-even rounding avoids directional bias at exact midpoints.

    Source evidence

    Strings and interpolation

    Link
    EBNF
    1. StringLiteral = SingleLineString | MultilineString ;
    2. SingleLineString = '"' SingleLinePart* '"' ;
    3. MultilineString = '"""' MultilinePart* '"""' ;
    4. SingleLinePart = SingleLineText | Escape | Interpolation ;
    5. MultilinePart = MultilineText | Escape | Interpolation ;
    6. Escape = '\' ("n" | "r" | "t" | '\' | '"' | "{" | "}") ;
    7. Interpolation = "{" Expression "}" ;

    SingleLineText and MultilineText are scanner-delimited text runs. A physical LF, CRLF, or CR is a line break. Inside a single-line string, text and interpolation reject physical line breaks. Multiline text uses them for opening removal and indentation, then stores LF. Escapes and inserted string values retain their carriage returns.

    Source evidence
    Ruletopaz.literals.rule.string-parts

    String delimiters and interpolation

    String formOpening and closing delimiter
    single-line"
    multiline"""

    An unescaped { begins interpolation containing an expression followed by }. An empty interpolation produces TPZ2001 during parsing.

    Why

    Interpolation joins evaluated values with literal text through one string grammar. Multiline delimiters allow document text to retain visible line structure in source.

    Source evidence
    • scanString at af88afbc1d99 · 343-434
    • parseString at af88afbc1d99 · 332-410
    Ruletopaz.literals.rule.string-escapes

    String escape values

    Single-line and multiline strings use these escapes, including strings tagged r, sh, sql.

    EscapeValueCode point
    \nline feedU+000A
    \rcarriage returnU+000D
    \ttabU+0009
    \\backslashU+005C
    \"quotation markU+0022
    \{opening braceU+007B
    \}closing braceU+007D

    An unknown escape produces TPZ0004 during lexing for every tag. Write an escaped backslash when a literal backslash is intended.

    Why

    One escape grammar gives a backslash the same meaning in strings and every template tag. Explicit escapes distinguish delimiters from text.

    Source evidence
    Ruletopaz.literals.rule.single-line-boundaries

    Single-line string boundaries

    A single-line string cannot cross a physical LF, CRLF, or CR line break, including inside interpolation. Crossing one produces TPZ0003 during lexing. An escaped carriage return or a carriage return in an inserted string remains character data.

    Why

    A physical line break ends an unfinished single-line string before later source is consumed as text. Equivalent file line endings must produce the same rejection.

    Source evidence
    Ruletopaz.literals.rule.string-types

    String literal and interpolation types

    Ordinary strings use the following type selection.

    InterpolationType
    absentstring literal type
    presentstring

    Why

    A fixed literal has a known value that type checking can retain. Interpolation depends on evaluated expressions, so its result uses the general string type.

    Source evidence
    Ruletopaz.literals.rule.interpolation-values

    ByteBuffer interpolation

    Interpolating a value whose type contains ByteBuffer in a string or tagged template produces TPZ5001 during checking.

    Why

    ByteBuffer is mutable storage rather than text. Rejecting its implicit display keeps byte decoding and the choice of character encoding explicit.

    Source evidence

    See Pending contracts for value formatting, evaluation order, and the number of evaluations.

    Ruletopaz.literals.rule.interpolation-evaluation

    Ordinary string interpolation order and conversion

    In an ordinary string, each interpolation expression is evaluated once in source order. A nested interpolation completes before the next outer expression. The value then uses the standard renderer, with no automatic call to a user-defined show method. Inserted spaces and newlines remain unchanged.

    Value familyConversion
    ScalarsStrings insert their text. Integers and floats use numeric text. Booleans, null, and unit use their literal spellings.
    Arrays and structural recordsElements and named fields render recursively, separated by commas.
    Option and ResultThe constructor name surrounds the rendered payload. None has no payload.
    Nominal valuesRecords, enum variants, and newtypes retain their nominal identity and recursively render their contents.
    Collections and rangesMap and Set use their standard collection displays. Ranges show their endpoints and optional step.
    Functions and resourcesFunctions, files, namespaces, and opaque values use their standard display labels.
    Library valuesBytes use hexadecimal text. Path, Regex, Date, URL, BigInt, Decimal, and other built-in values use their standard representations.
    TemplatesDisplay a summary with the tag and counts of parts and values.

    A value whose type contains ByteBuffer produces TPZ5001 during checking, including inside arrays, records, unions, and nominal fields.

    Why

    Evaluating each expression once in source order makes effects predictable. Preserving inserted whitespace lets document content determine its own line and spacing structure.

    Source evidence
    Ruletopaz.literals.rule.string-scalar-data

    Preserved Unicode string data

    Literal text, inserted strings, and template text preserve their Unicode scalar sequence after the specified escape, physical-line-break, indentation, and blank-line processing. They do not apply Unicode normalization or remove Default_Ignorable_Code_Point scalars. Composed and decomposed text can therefore produce different UTF-8 bytes. A name inside an interpolation follows the identifier rules because it is part of the expression.

    Why

    Text values may carry externally supplied spelling, file contents, or protocol bytes. Implicit Unicode normalization or removal of invisible scalars would lose that data. Names use NFC to give bindings a canonical source spelling. A string preserves its scalar sequence after the separately specified source-text transformations.

    Source evidence

    Multiline strings

    Link
    Ruletopaz.literals.rule.multiline-opening

    Multiline opening line break

    In a multiline string, one physical LF, CRLF, or CR line break immediately after the opening delimiter is removed from the value. CRLF is one line break.

    Why

    Removing the opening line break lets a document text block start on the line after its delimiter without adding an empty first line.

    Source evidence
    Ruletopaz.literals.rule.multiline-indent

    Multiline closing indentation

    When the closing delimiter follows spaces and tabs on its own line, that exact prefix is removed from each nonblank text line. Physical LF, CRLF, and CR each start a new line for this check. A nonblank line without that prefix produces TPZ0006 during lexing. The closing indentation is also removed.

    Why

    Removing the closing delimiter prefix separates source indentation from document indentation. Checking every physical line-ending form prevents file conversion from bypassing the indentation check.

    Source evidence
    Ruletopaz.literals.rule.multiline-newlines

    Multiline newline values

    Physical LF, CRLF, and CR line breaks in multiline text become LF. CRLF becomes one LF. A newline before the closing indentation remains in the value. Normalization applies to source text before escape decoding and value insertion. An escaped carriage return or a carriage return in an inserted string remains character data. Interpolation expressions use the source expression grammar.

    Why

    Treating physical LF, CRLF, and CR alike keeps document text stable when a file changes line-ending format. Escapes and inserted values preserve intentional carriage-return data.

    Source evidence
    Ruletopaz.literals.rule.multiline-boundaries

    Whitespace and interpolation in multiline strings

    A multiline source text line containing just spaces (U+0020) and tabs (U+0009) contributes an empty line. Its line break remains. This applies with or without closing indentation, in ordinary and tagged strings. Removal happens before escape decoding and value insertion. Escaped and inserted whitespace remains data. Nonblank indentation compares the exact source prefix, without expanding tabs. An interpolated value cannot supply missing indentation. A prefix mismatch produces TPZ0006 during lexing. Physical LF, CRLF, and CR start new text lines and become LF in the string value.

    Why

    Blank source lines remain empty when an editor changes their indentation. This keeps document text independent of formatting. Source whitespace is removed before escapes and interpolation, so explicit character data remains intact. Exact nonblank prefixes avoid dependence on an editor tab width.

    Source evidence

    Tagged templates

    Link
    EBNF
    1. TemplateLiteral = TemplateTag StringLiteral ;
    2. TemplateTag = "r" | "sh" | "sql" ;

    StringLiteral is defined above. Every tag uses its complete escape grammar, including the same delimiter and interpolation-brace escapes.

    Tag-specific processing and operations on the resulting template value belong to their library entries.

    Source evidence
    Ruletopaz.literals.rule.template-tags

    Registered template tags

    The template tags are r, sh, sql. Write the tag immediately before a single-line or triple-quoted string. A different immediately attached identifier produces TPZ2002 during parsing.

    Why

    The registry keeps template consumers explicit and catches misspelled tags. Paths use the ordinary Path.from call, which accepts both literal and computed strings and returns the same validated Path type. The former p tag produced a template with slash-only display conversion, so it is removed rather than retain a second path-looking spelling with different validation. This follows the Path.from-only owner decision and the one-way-to-say-it criterion. Joining path parts safely is expressed by Path.join. Reading text as a path is expressed by Path.from. A path template tag adds no distinct intent to either operation.

    Source evidence
    Ruletopaz.literals.rule.template-types

    Template value types

    A registered tagged template is checked as a template value.

    Why

    A distinct template type preserves the boundary between structured text and an ordinary string. Consumers can inspect the tag and literal parts before interpreting them.

    Source evidence

    Each registered tag uses the string escape grammar above. Construction, accessors, and display are defined below. Construct a path with Path.from applied to an ordinary string; p is not a registered template tag.

    Ruletopaz.literals.rule.template-runtime

    Tagged-template construction and display

    Registered tags construct template values from cooked text parts and expressions evaluated once in source order. There is one more text part than interpolation values. tag returns the tag as a string. parts returns an array value of the literal text segments under value semantics. Interpolated values remain separate and have no public accessor.

    TagConstruction and string-interpolation display
    rKeeps the pattern structure without compiling or validating a regular expression. Display reports the tag and counts of parts and values.
    shKeeps text and values separate without executing a command. Display reports the tag and counts.
    sqlKeeps query text and values separate without executing a query or inserting values into query text. Display reports the tag and counts.

    A template value cannot be passed where string is required. Use ordinary string interpolation to obtain its display. All tags use the shared string escape grammar. For example, r"\\d" preserves a regex backslash, and \{ and \} preserve literal braces.

    Why

    Keeping inserted values separate from text lets a consumer interpret their roles without reconstructing them from a string. Construction does not execute the embedded command or query. Joining path parts safely is expressed by Path.join. Reading text as a path is expressed by Path.from. A path template tag adds no distinct intent to either operation.

    Source evidence

    Constructing paths

    Link
    Ruletopaz.literals.rule.path-construction

    Construct a normalized Path with Path.from

    Path.from follows the Path construction contract. That rule defines normalization, input failures and removed construction members.

    Why

    Path.from gives literal, interpolated and computed text one conversion to a relative path. Its construction contract owns normalization and input failures. The old cwdRelative and project factories performed the same pure normalization. Their different error prefixes did not express a distinct operation. The old normalize member returned its receiver. Path.join safely combines path parts, while Path.from reads text as a path. The removed p tag added no distinct intent to either operation.

    Source evidence

    Examples and counterexamples

    Link

    Integer bases and decimal floats

    Link
    example.tpzInteger bases and decimal floats
    1. let decimal: int = 1_000
    2. let hexadecimal: int = 0xca_fe
    3. let binary: int = 0b1010_0101
    4. let fraction: float = 1_234.5_6
    5. let minimum: int = -9223372036854775808
    6. let maximum: int = 9223372036854775807
    7. let value: int = 1_0
    Expected outputexit 0
    $ topaz check example.tpz · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Source evidence

    Repeated digit separator

    Link
    example.tpzRepeated digit separatorOpen in Playground
    1. let value = 1__0
    Recorded outputexit 1
    No stdout.
    error[TPZ2001]: malformed numeric literal
     --> example.tpz:1:13
      |
    1 | let value = 1__0
      |             ^^^^
    
    example.tpz: 1 diagnostic
    
    $ topaz check example.tpz --compiler self · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 malformed-numeric-literal at example.tpz:1:13
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ2001]: malformed numeric literal
    2. --> example.tpz:1:13
    3. |
    4. 1 | let value = 1__0
    5. | ^^^^
    6. example.tpz: 1 diagnostic
    • Passed · checking TPZ2001; cause malformed-numeric-literal; primary location asserted; additional diagnostics allow
    • Passed · expected nonzero; observed 1

    The intended cause is the repeated underscore inside the numeric token. Replace it with one underscore or remove it.

    Source evidence

    Exponent spelling

    Link
    example.tpzExponent spellingOpen in Playground
    1. let value = 1e3
    Recorded outputexit 1
    No stdout.
    error[TPZ2001]: malformed numeric literal
     --> example.tpz:1:13
      |
    1 | let value = 1e3
      |             ^^^
    
    example.tpz: 1 diagnostic
    
    $ topaz check example.tpz --compiler self · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 malformed-numeric-literal at example.tpz:1:13
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ2001]: malformed numeric literal
    2. --> example.tpz:1:13
    3. |
    4. 1 | let value = 1e3
    5. | ^^^
    6. example.tpz: 1 diagnostic
    • Passed · checking TPZ2001; cause malformed-numeric-literal; primary location asserted; additional diagnostics allow
    • Passed · expected nonzero; observed 1

    Use 1000.0 when the intended value is one thousand as a float.

    Source evidence

    Integer magnitude above the signed range

    Link
    example.tpzInteger magnitude above the signed rangeOpen in Playground
    1. let value = 9223372036854775808
    Recorded outputexit 1
    No stdout.
    error[TPZ5001]: integer literal `9223372036854775808` is out of range
     --> example.tpz:1:13
      |
    1 | let value = 9223372036854775808
      |             ^^^^^^^^^^^^^^^^^^^
    
    example.tpz: 1 type diagnostic
    
    $ topaz check example.tpz --compiler self · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 integer-literal-out-of-range at example.tpz:1:13
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ5001]: integer literal `9223372036854775808` is out of range
    2. --> example.tpz:1:13
    3. |
    4. 1 | let value = 9223372036854775808
    5. | ^^^^^^^^^^^^^^^^^^^
    6. example.tpz: 1 type diagnostic
    • Passed · checking TPZ5001; cause integer-literal-out-of-range; primary location asserted; additional diagnostics allow
    • Passed · expected nonzero; observed 1
    Source evidence

    Boolean, null, and unit values

    Link
    example.tpzBoolean, null, and unit values
    1. let enabled: bool = true
    2. let disabled: bool = false
    3. let absent = null
    4. let completed: () = ()
    Recorded outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    No stderr.

    • Passed · expected 0; observed 0
    Source evidence

    Duration in its timeout context

    Link
    example.tpzDuration in its timeout context
    1. let result = concurrent(timeout: 1_500ms) {
    2. value: 1
    3. } else {
    4. { value: 0 }
    5. }
    Recorded outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    No stderr.

    • Passed · expected 0; observed 0
    Source evidence

    A Duration value outside a timeout

    Link
    example.tpzA Duration value outside a timeoutOpen in Playground
    1. let delay = 3s
    2. let saved: Duration = (delay)
    Expected outputexit 0
    No stdout.
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    The stable example identity formerly tested the SELF-only context restriction. Its old fixture, assertion plan and receipt remain historical evidence. The current version expects an ordinary Duration binding to succeed; the original receipt is not evidence of this revised contract.

    Source evidence
    • parseAtom at af88afbc1d99 · 1245-1255
    • pull/41 at 271329b482bc

    Length suffixes and types

    Link
    example.tpzLength suffixes and types
    1. let points: Length<Pt> = 12pt
    2. let millimeters: Length<Mm> = 2.5mm
    3. let centimeters: Length<Cm> = 1cm
    4. let inches: Length<In> = 0.5in
    5. let relative: Length<Em> = 1.25em
    Recorded outputexit 0
    example.tpz: types-ok (1 module)
    example.tpz: resolve-ok (1 module)
    
    $ topaz check example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. example.tpz: types-ok (1 module)
    2. example.tpz: resolve-ok (1 module)

    No stderr.

    • Passed · expected 0; observed 0
    Source evidence

    Escapes and an interpolated value

    Link
    example.tpzEscapes and an interpolated value
    1. import std.io
    2. let count = 3
    3. io.writeLine("Topaz {count}: \"\{ok\}\"\\")
    4. io.writeLine("first\nsecond\tend")
    Recorded outputexit 0
    Topaz 3: "{ok}"\
    first
    second	end
    
    $ topaz run example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. Topaz 3: "{ok}"\
    2. first
    3. second end
    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. Topaz 3: "{ok}"\
    2. first
    3. second end

    No stderr.

    • Passed · expected 0; observed 0
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    Unknown escape

    Link
    example.tpzUnknown escapeOpen in Playground
    1. let text = "bad\q"
    Recorded outputexit 1
    No stdout.
    error[TPZ0004]: invalid escape `\q` in a string literal
     --> example.tpz:1:16
      |
    1 | let text = "bad\q"
      |                ^^
    
    example.tpz: 1 diagnostic
    
    $ topaz check example.tpz --compiler self · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0004 invalid-string-escape at example.tpz:1:16
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ0004]: invalid escape `\q` in a string literal
    2. --> example.tpz:1:16
    3. |
    4. 1 | let text = "bad\q"
    5. | ^^
    6. example.tpz: 1 diagnostic
    • Passed · checking TPZ0004; cause invalid-string-escape; primary location asserted; additional diagnostics allow
    • Passed · expected nonzero; observed 1

    Replace the unknown escape with a supported escape or write an escaped backslash when a literal backslash is intended.

    Source evidence

    Multiline indentation and final newline

    Link
    example.tpzMultiline indentation and final newline
    1. import std.io
    2. io.writeLine("""
    3. first
    4. second
    5. """)
    Recorded outputexit 0
    first
    second
    
    
    $ topaz run example.tpz · recorded with topaz 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. first
    2. second
    Observed assertions · passed · 5.21.3

    Exit code 0.

    Observed stdout
    1. first
    2. second

    No stderr.

    • Passed · expected 0; observed 0
    • Passed · stdout matches the authored expectation
    • Passed · stdout matches the authored expectation
    • Passed · stdout matches the authored expectation
    • Passed · stderr matches the authored expectation
    Source evidence

    The four registered template tags

    Link
    example.tpzThe four registered template tagsOpen in Playground
    1. let regexTemplate = r"a+"
    2. let shellTemplate = sh"echo hello"
    3. let sqlTemplate = sql"select {1}"
    Expected outputexit 0
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Source evidence

    Tag outside the registry

    Link
    example.tpzTag outside the registryOpen in Playground
    1. let value = html"hello"
    Recorded outputexit 1
    No stdout.
    error[TPZ2002]: unknown template tag `html`; the registry is `p`, `r`, `sh`, `sql`
     --> example.tpz:1:13
      |
    1 | let value = html"hello"
      |             ^^^^
    
    example.tpz: 1 diagnostic
    
    $ topaz check example.tpz --compiler self · recorded with topaz 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2002 unknown-template-tag at example.tpz:1:13
    Observed assertions · passed · 5.21.3

    Exit code 1.

    No stdout.

    Observed stderr
    1. error[TPZ2002]: unknown template tag `html`; the registry is `p`, `r`, `sh`, `sql`
    2. --> example.tpz:1:13
    3. |
    4. 1 | let value = html"hello"
    5. | ^^^^
    6. example.tpz: 1 diagnostic
    • Passed · checking TPZ2002; cause unknown-template-tag; primary location asserted; additional diagnostics allow
    • Passed · expected nonzero; observed 1

    The counterexample uses the tag html. The program does not invoke an HTML operation.

    Source evidence
    • parseString at af88afbc1d99 · 332-410

    Blank source lines stay empty while CRLF and CR become LF

    Link
    example.tpzBlank source lines stay empty while CRLF and CR become LFOpen in Playground
    1. import std.io
    2. let part = "x"
    3. let value = """
    4. A{part}
    5. B C
    6. """
    7. io.writeLine(value.encodeUtf8().toHex())
    Expected outputexit 0
    41780a0a420a430a
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 41780a0a420a430a
    Source evidence

    A tab prefix is not two spaces

    Link
    example.tpzA tab prefix is not two spacesOpen in Playground
    1. let value = """
    2. first
    3. """
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0006 multiline-closing-indent-mismatch at example.tpz:2:1
    Source evidence

    Interpolation cannot supply source indentation

    Link
    example.tpzInterpolation cannot supply source indentationOpen in Playground
    1. let padding = " "
    2. let value = """
    3. {padding}body
    4. """
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0006 multiline-closing-indent-mismatch at example.tpz:3:1
    Source evidence

    Observe ties-to-even through equality and unit conversion

    Link
    example.tpzObserve ties-to-even through equality and unit conversionOpen in Playground
    1. import std.io
    2. let half = 0.00000762939453125pt
    3. let oneAndHalf = 0.00002288818359375pt
    4. let two = 0.000030517578125pt
    5. io.writeLine("{half == 0pt}|{oneAndHalf == two}|{-half == 0pt}")
    6. io.writeLine("{(25.4mm).toPt() == 72pt}|{(2.54cm).toPt() == 72pt}|{(1in).toPt() == 72pt}")
    7. io.writeLine("{0.00000762939453125em == 0em}|{0.00002288818359375em == 0.000030517578125em}")
    Expected outputexit 0
    true|true|true
    true|true|true
    true|true
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. true|true|true
    2. true|true|true
    3. true|true
    Source evidence

    Decimal values inside both limits for every unit

    Link
    example.tpzDecimal values inside both limits for every unitOpen in Playground
    1. let good0 = -140737488355328.000007629394531250000000000000pt
    2. let good1 = 140737488355327.999992370605468749999999999999pt
    3. let good2 = -49649058392018.488891580369737413194444444444mm
    4. let good3 = 49649058392018.488886197408040364583333333333mm
    5. let good4 = -4964905839201.848889158036973741319444444444cm
    6. let good5 = 4964905839201.848888619740804036458333333333cm
    7. let good6 = -1954687338268.444444550408257378472222222222in
    8. let good7 = 1954687338268.444444338480631510416666666666in
    9. let good8 = -140737488355328.000007629394531250000000000000em
    10. let good9 = 140737488355327.999992370605468749999999999999em
    Expected outputexit 0
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Source evidence

    Observe rounding, infinity, subnormals, and signed zero

    Link
    example.tpzObserve rounding, infinity, subnormals, and signed zeroOpen in Playground
    1. import std.io
    2. let tieEven = 1.00000000000000011102230246251565404236316680908203125
    3. let tieNext = 1.00000000000000033306690738754696212708950042724609375
    4. let overflow = 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0
    5. let tiny = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
    6. let subnormal = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
    7. let twiceSubnormal = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
    8. io.writeLine("{tieEven == 1.0}|{tieNext == 1.0000000000000004}")
    9. io.writeLine("{overflow}|{-overflow}")
    10. io.writeLine("{tiny}|{-tiny}|{1.0 / tiny}|{1.0 / -tiny}")
    11. io.writeLine("{subnormal > 0.0}|{subnormal < twiceSubnormal}|{subnormal + subnormal == twiceSubnormal}")
    Expected outputexit 0
    true|true
    inf|-inf
    0.0|-0.0|inf|-inf
    true|true|true
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. true|true
    2. inf|-inf
    3. 0.0|-0.0|inf|-inf
    4. true|true|true
    Source evidence

    Exponent spelling is not a decimal float literal

    Link
    example.tpzExponent spelling is not a decimal float literalOpen in Playground
    1. let value = 1.0e3
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 malformed-numeric-literal at example.tpz:1:13
    Source evidence

    Nested interpolations evaluate each occurrence once

    Link
    example.tpzNested interpolations evaluate each occurrence onceOpen in Playground
    1. import std.io
    2. function mark(n: int) -> int { io.writeLine("mark {n}")
    3. n }
    4. let value = "outer {mark(1)}|{"inner {mark(2)}"}|{mark(3)}"
    5. io.writeLine(value)
    Expected outputexit 0
    mark 1
    mark 2
    mark 3
    outer 1|inner 2|3
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. mark 1
    2. mark 2
    3. mark 3
    4. outer 1|inner 2|3
    Source evidence

    Display scalars and nested values with the standard renderer

    Link
    example.tpzDisplay scalars and nested values with the standard rendererOpen in Playground
    1. import std.io
    2. let row = { count: 3 }
    3. let selected: Option<int> = Some(3)
    4. let missing: Option<int> = None()
    5. let ok: Result<int, string> = Ok(4)
    6. let err: Result<int, string> = Err("no")
    7. io.writeLine("{7}|{2.5}|{true}|{()}|{null}")
    8. io.writeLine("{[1, 2]}|{row}|{selected}|{missing}|{ok}|{err}")
    Expected outputexit 0
    7|2.5|true|()|null
    [1, 2]|{ count: 3 }|Some(3)|None|Ok(4)|Err(no)
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 7|2.5|true|()|null
    2. [1, 2]|{ count: 3 }|Some(3)|None|Ok(4)|Err(no)
    Source evidence

    An aggregate containing ByteBuffer cannot be interpolated

    Link
    example.tpzAn aggregate containing ByteBuffer cannot be interpolatedOpen in Playground
    1. let buffer = ByteBuffer.allocate(1)
    2. let nested = [buffer]
    3. let value = "{nested}"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 byte-buffer-interpolation at example.tpz:3:15
    Source evidence

    Inspect templates without executing or validating their contents

    Link
    example.tpzInspect templates without executing or validating their contentsOpen in Playground
    1. import std.io
    2. import std.path { Path }
    3. function mark(n: int) -> int { io.writeLine("mark {n}")
    4. n }
    5. let segment = "a\\b"
    6. let path = match (Path.from("dir\\{segment}/{mark(1)}")) {
    7. case Ok(value) => value.toString()
    8. case Err(error) => error
    9. }
    10. let pattern = r"[{mark(2)}"
    11. let command = sh"echo {mark(3)}"
    12. let query = sql"SELECT {mark(4)}"
    13. io.writeLine("{path}")
    14. io.writeLine("{pattern}|{command}|{query}")
    15. io.writeLine("{query.tag}|{query.parts.length}|{query.parts[0]}|{query.parts[1]}")
    16. let mut parts = query.parts
    17. parts[0] = "changed"
    18. io.writeLine("{query.parts[0]}")
    Expected outputexit 0
    mark 1
    mark 2
    mark 3
    mark 4
    dir/a/b/1
    <r template, 2 part(s), 1 interpolation(s)>|<sh template, 2 part(s), 1 interpolation(s)>|<sql template, 2 part(s), 1 interpolation(s)>
    sql|2|SELECT |
    SELECT 
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. mark 1
    2. mark 2
    3. mark 3
    4. mark 4
    5. dir/a/b/1
    6. <r template, 2 part(s), 1 interpolation(s)>|<sh template, 2 part(s), 1 interpolation(s)>|<sql template, 2 part(s), 1 interpolation(s)>
    7. sql|2|SELECT |
    8. SELECT

    The parts accessor returns an array value under value semantics. Changing parts leaves query.parts unchanged.

    Source evidence

    A template value cannot initialize string

    Link
    example.tpzA template value cannot initialize stringOpen in Playground
    1. let value: string = sql"SELECT 1"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 template-is-not-string at example.tpz:1:21
    Source evidence

    Tagged interpolation rejects ByteBuffer too

    Link
    example.tpzTagged interpolation rejects ByteBuffer tooOpen in Playground
    1. let buffer = ByteBuffer.allocate(1)
    2. let value = sql"SELECT {buffer}"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 byte-buffer-interpolation at example.tpz:2:25
    Source evidence

    Reject a value past the negative pt limit

    Link
    example.tpzReject a value past the negative pt limitOpen in Playground
    1. let bad0 = -140737488355328.000007629394531250000000000001pt
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the positive pt limit

    Link
    example.tpzReject a value past the positive pt limitOpen in Playground
    1. let bad1 = 140737488355327.999992370605468750000000000000pt
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the negative mm limit

    Link
    example.tpzReject a value past the negative mm limitOpen in Playground
    1. let bad2 = -49649058392018.488891580369737413194444444445mm
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the positive mm limit

    Link
    example.tpzReject a value past the positive mm limitOpen in Playground
    1. let bad3 = 49649058392018.488886197408040364583333333334mm
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the negative cm limit

    Link
    example.tpzReject a value past the negative cm limitOpen in Playground
    1. let bad4 = -4964905839201.848889158036973741319444444445cm
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the positive cm limit

    Link
    example.tpzReject a value past the positive cm limitOpen in Playground
    1. let bad5 = 4964905839201.848888619740804036458333333334cm
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the negative in limit

    Link
    example.tpzReject a value past the negative in limitOpen in Playground
    1. let bad6 = -1954687338268.444444550408257378472222222223in
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the positive in limit

    Link
    example.tpzReject a value past the positive in limitOpen in Playground
    1. let bad7 = 1954687338268.444444338480631510416666666667in
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the negative em limit

    Link
    example.tpzReject a value past the negative em limitOpen in Playground
    1. let bad8 = -140737488355328.000007629394531250000000000001em
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Reject a value past the positive em limit

    Link
    example.tpzReject a value past the positive em limitOpen in Playground
    1. let bad9 = 140737488355327.999992370605468750000000000000em
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5001 length-literal-not-representable at example.tpz:1:12
    Source evidence

    Every tag cooks the same single-line escapes

    Link
    example.tpzEvery tag cooks the same single-line escapesOpen in Playground
    1. import std.io
    2. let pattern = r"\n\r\t\\\"\{\}"
    3. io.writeLine(pattern.parts[0])
    4. let command = sh"\n\r\t\\\"\{\}"
    5. io.writeLine(command.parts[0])
    6. let query = sql"\n\r\t\\\"\{\}"
    7. io.writeLine(query.parts[0])
    Expected outputexit 0
    
    
    	\"{}
    
    
    	\"{}
    
    
    	\"{}
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. \"{}
    2. \"{}
    3. \"{}

    The standard-output expectation checks the actual LF, CR, tab, backslash, quotation-mark, and brace characters in each cooked text part.

    Source evidence

    Every tag cooks the same multiline escapes

    Link
    example.tpzEvery tag cooks the same multiline escapesOpen in Playground
    1. import std.io
    2. let pattern = r"""
    3. \n\r\t\\\"\{\}
    4. """
    5. io.writeLine(pattern.parts[0])
    6. let command = sh"""
    7. \n\r\t\\\"\{\}
    8. """
    9. io.writeLine(command.parts[0])
    10. let query = sql"""
    11. \n\r\t\\\"\{\}
    12. """
    13. io.writeLine(query.parts[0])
    Expected outputexit 0
    
    
    	\"{}
    
    
    
    	\"{}
    
    
    
    	\"{}
    
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. \"{}
    2. \"{}
    3. \"{}

    The standard-output expectation checks the actual LF, CR, tab, backslash, quotation-mark, and brace characters in each cooked text part.

    Source evidence

    Unknown escape in a r template

    Link
    example.tpzUnknown escape in a r templateOpen in Playground
    1. let value = r"\d"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0004 invalid-string-escape at example.tpz:1:15

    Use a supported escape or double the backslash to keep it as literal text.

    Source evidence

    Unknown escape in a sh template

    Link
    example.tpzUnknown escape in a sh templateOpen in Playground
    1. let value = sh"\q"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0004 invalid-string-escape at example.tpz:1:16

    Use a supported escape or double the backslash to keep it as literal text.

    Source evidence

    Unknown escape in a sql template

    Link
    example.tpzUnknown escape in a sql templateOpen in Playground
    1. let value = sql"\q"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0004 invalid-string-escape at example.tpz:1:17

    Use a supported escape or double the backslash to keep it as literal text.

    Source evidence

    Preserve a regex backslash and literal braces

    Link
    example.tpzPreserve a regex backslash and literal bracesOpen in Playground
    1. import std.io
    2. let pattern = r"\\d+\{n\}"
    3. io.writeLine(pattern.parts[0])
    Expected outputexit 0
    \d+{n}
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. \d+{n}
    Source evidence

    Unknown escape in a multiline r template

    Link
    example.tpzUnknown escape in a multiline r templateOpen in Playground
    1. let pattern = r"""
    2. \d
    3. """
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0004 invalid-string-escape at example.tpz:2:1
    Source evidence

    Reject uppercase hex prefix

    Link
    example.tpzReject uppercase hex prefixOpen in Playground
    1. let value = 0Xff
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 malformed-numeric-literal at example.tpz:1:13
    Source evidence

    Reject uppercase binary prefix

    Link
    example.tpzReject uppercase binary prefixOpen in Playground
    1. let value = 0B1010
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 malformed-numeric-literal at example.tpz:1:13
    Source evidence

    Reject uppercase hex digit

    Link
    example.tpzReject uppercase hex digitOpen in Playground
    1. let value = 0xA
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 malformed-numeric-literal at example.tpz:1:13
    Source evidence

    Reject mixed case hex digit

    Link
    example.tpzReject mixed case hex digitOpen in Playground
    1. let value = 0xaF
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2001 malformed-numeric-literal at example.tpz:1:13
    Source evidence

    Read lowercase radix literals

    Link
    example.tpzRead lowercase radix literals
    1. import std.io { writeLine }
    2. writeLine("{0xff}")
    3. writeLine("{0b1010}")
    4. writeLine("{0xabcdef}")
    Expected outputexit 0
    255
    10
    11259375
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 255
    2. 10
    3. 11259375
    Source evidence

    Reject physical LF in single-line text

    Link
    example.tpzReject physical LF in single-line textOpen in Playground
    1. let value = "left
    2. right"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0003 diagnostic-tpz0003 at example.tpz:1:13
    Source evidence

    Reject physical LF in single-line interpolation

    Link
    example.tpzReject physical LF in single-line interpolationOpen in Playground
    1. let value = "{1
    2. + 2}"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0003 single-line-interpolation-line-break at example.tpz:1:13
    Source evidence

    Reject physical CRLF in single-line text

    Link
    example.tpzReject physical CRLF in single-line textOpen in Playground
    1. let value = "left
    2. right"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0003 diagnostic-tpz0003 at example.tpz:1:13
    Source evidence

    Reject physical CRLF in single-line interpolation

    Link
    example.tpzReject physical CRLF in single-line interpolationOpen in Playground
    1. let value = "{1
    2. + 2}"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0003 single-line-interpolation-line-break at example.tpz:1:13
    Source evidence

    Reject physical CR in single-line text

    Link
    example.tpzReject physical CR in single-line textOpen in Playground
    1. let value = "left right"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0003 diagnostic-tpz0003 at example.tpz:1:13
    Source evidence

    Reject physical CR in single-line interpolation

    Link
    example.tpzReject physical CR in single-line interpolationOpen in Playground
    1. let value = "{1 + 2}"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0003 single-line-interpolation-line-break at example.tpz:1:13
    Source evidence

    Reject physical CR in a string nested inside single-line interpolation

    Link
    example.tpzReject physical CR in a string nested inside single-line interpolationOpen in Playground
    1. let value = "{""" inner"""}"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0003 single-line-interpolation-line-break at example.tpz:1:13
    Source evidence

    Physical CRLF uses the same multiline text and indentation

    Link
    example.tpzPhysical CRLF uses the same multiline text and indentationOpen in Playground
    1. import std.io
    2. let value = """
    3. first
    4. second
    5. """
    6. io.writeLine(value.encodeUtf8().toHex())
    Expected outputexit 0
    66697273740a7365636f6e640a
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 66697273740a7365636f6e640a
    Source evidence

    Physical CR uses the same multiline text and indentation

    Link
    example.tpzPhysical CR uses the same multiline text and indentationOpen in Playground
    1. import std.io
    2. let value = """ first second """
    3. io.writeLine(value.encodeUtf8().toHex())
    Expected outputexit 0
    66697273740a7365636f6e640a
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 66697273740a7365636f6e640a
    Source evidence

    Reject missing indentation after a physical CR

    Link
    example.tpzReject missing indentation after a physical CROpen in Playground
    1. let value = """
    2. first second
    3. """
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during lex. Nonzero exit.

    • TPZ0006 multiline-closing-indent-mismatch at example.tpz:3:1
    Source evidence

    Escaped carriage returns remain character data

    Link
    example.tpzEscaped carriage returns remain character dataOpen in Playground
    1. import std.io
    2. let opening = """\rhead"""
    3. let single = "S\rE"
    4. let multi = """
    5. M\rN
    6. """
    7. io.writeLine(opening.encodeUtf8().toHex())
    8. io.writeLine(single.encodeUtf8().toHex())
    9. io.writeLine(multi.encodeUtf8().toHex())
    Expected outputexit 0
    0d68656164
    530d45
    4d0d4e0a
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 0d68656164
    2. 530d45
    3. 4d0d4e0a
    Source evidence

    An inserted carriage return decoded from bytes remains character data

    Link
    example.tpzAn inserted carriage return decoded from bytes remains character dataOpen in Playground
    1. import std.io
    2. let data = match (Bytes.fromHex("0d")) {
    3. case Ok(bytes) => match (bytes.decodeUtf8()) {
    4. case Ok(value) => value
    5. case Err(_) => ""
    6. }
    7. case Err(_) => ""
    8. }
    9. let opening = """{data}head"""
    10. let single = "L{data}R"
    11. let multi = """
    12. L{data}R
    13. """
    14. io.writeLine(opening.encodeUtf8().toHex())
    15. io.writeLine(single.encodeUtf8().toHex())
    16. io.writeLine(multi.encodeUtf8().toHex())
    Expected outputexit 0
    0d68656164
    4c0d52
    4c0d520a
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 0d68656164
    2. 4c0d52
    3. 4c0d520a
    Source evidence

    Blank source lines ignore indentation

    Link
    example.tpzBlank source lines ignore indentationOpen in Playground
    1. import std.io
    2. let indented = """
    3. A
    4. B
    5. """
    6. let unindented = """A
    7. B"""
    8. let tagged = r"""
    9. A
    10. B
    11. """
    12. io.writeLine(indented.encodeUtf8().toHex())
    13. io.writeLine(unindented.encodeUtf8().toHex())
    14. io.writeLine(tagged.parts[0].encodeUtf8().toHex())
    Expected outputexit 0
    410a0a0a420a
    410a0a42
    410a0a420a
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 410a0a0a420a
    2. 410a0a42
    3. 410a0a420a
    Source evidence

    Escaped and inserted whitespace remains data

    Link
    example.tpzEscaped and inserted whitespace remains dataOpen in Playground
    1. import std.io
    2. let inserted = " \t"
    3. let value = """
    4. A
    5. \t
    6. {inserted}
    7. B
    8. """
    9. io.writeLine(value.encodeUtf8().toHex())
    Expected outputexit 0
    410a090a20090a420a
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 410a090a20090a420a
    Source evidence

    Path construction uses Path.from instead of the p tag

    Link
    example.tpzPath construction uses Path.from instead of the p tagOpen in Playground
    1. let value = p"notes"
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2002 unknown-template-tag at example.tpz:1:13
    Source evidence

    Path construction uses Path.from instead of the p tag

    Link
    example.tpzPath construction uses Path.from instead of the p tagOpen in Playground
    1. let value = p"""
    2. notes
    3. """
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during parse. Nonzero exit.

    • TPZ2002 unknown-template-tag at example.tpz:1:13
    Source evidence

    Path.from normalizes literal and interpolated text

    Link
    example.tpzPath.from normalizes literal and interpolated textOpen in Playground
    1. import std.io
    2. import std.path { Path }
    3. function normalized(text: string) -> string {
    4. match (Path.from(text)) {
    5. case Ok(value) => value.toString()
    6. case Err(error) => error
    7. }
    8. }
    9. let directory = "notes"
    10. io.writeLine(normalized("./{directory}//draft/../chapter.tpz"))
    11. io.writeLine(normalized("notes\\draft\\..\\chapter.tpz"))
    12. io.writeLine(normalized("notes/.."))
    13. io.writeLine(normalized("Notes/가.TPZ"))
    Expected outputexit 0
    notes/chapter.tpz
    notes/chapter.tpz
    .
    Notes/가.TPZ
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. notes/chapter.tpz
    2. notes/chapter.tpz
    3. .
    4. Notes/가.TPZ
    Source evidence

    Invalid path text is an Err result

    Link
    example.tpzInvalid path text is an Err resultOpen in Playground
    1. import std.io
    2. import std.path { Path }
    3. function outcome(text: string) -> string {
    4. match (Path.from(text)) {
    5. case Ok(_) => "Ok"
    6. case Err(_) => "Err"
    7. }
    8. }
    9. io.writeLine("empty: {outcome("")}")
    10. io.writeLine("absolute: {outcome("/notes")}")
    11. io.writeLine("drive: {outcome("C:notes")}")
    12. io.writeLine("escape: {outcome("../notes")}")
    Expected outputexit 0
    empty: Err
    absolute: Err
    drive: Err
    escape: Err
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. empty: Err
    2. absolute: Err
    3. drive: Err
    4. escape: Err
    Source evidence

    Use Path.from instead of Path.cwdRelative

    Link
    example.tpzUse Path.from instead of Path.cwdRelativeOpen in Playground
    1. import std.path { Path }
    2. let value = Path.cwdRelative("notes")
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5006 path-member-removed at example.tpz:2:18
    Source evidence

    Use Path.from instead of Path.project

    Link
    example.tpzUse Path.from instead of Path.projectOpen in Playground
    1. import std.path { Path }
    2. let value = Path.project("notes")
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5006 path-member-removed at example.tpz:2:18
    Source evidence

    A Path is already normalized

    Link
    example.tpzA Path is already normalizedOpen in Playground
    1. import std.path { Path }
    2. function keep(value: Path) -> Path { value.normalize() }
    Expected outputNonzero exit
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Rejection during check. Nonzero exit.

    • TPZ5006 path-member-removed at example.tpz:2:44
    Source evidence

    Use an existing Path directly

    Link
    example.tpzUse an existing Path directlyOpen in Playground
    1. import std.path { Path }
    2. function keep(value: Path) -> Path { value }
    Expected outputexit 0
    No stdout.
    $ topaz check example.tpz --compiler self --format json · target product 5.21.3
    Expected result

    Expected result

    Checking accepts the program. Exit code 0.

    Source evidence

    Preserve composed, decomposed, and invisible string data

    Link
    example.tpzPreserve composed, decomposed, and invisible string dataOpen in Playground
    1. import std.io
    2. let composed = "é"
    3. let decomposed = "é"
    4. let hangul = "가"
    5. let invisible = "a͏‍️"
    6. let inserted = "{decomposed}"
    7. io.writeLine(composed.encodeUtf8().toHex())
    8. io.writeLine(decomposed.encodeUtf8().toHex())
    9. io.writeLine(hangul.encodeUtf8().toHex())
    10. io.writeLine(invisible.encodeUtf8().toHex())
    11. io.writeLine(inserted.encodeUtf8().toHex())
    Expected outputexit 0
    c3a9
    65cc81
    e18480e185a1
    61cd8fe2808defb88f
    65cc81
    
    $ topaz run example.tpz --compiler self · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. c3a9
    2. 65cc81
    3. e18480e185a1
    4. 61cd8fe2808defb88f
    5. 65cc81
    Source evidence

    Add and subtract Duration values

    Link
    example.tpzAdd and subtract Duration values
    1. import std.io { writeLine }
    2. let sum = 1s + 500ms
    3. let difference = 2s - 500ms
    4. writeLine("{sum}")
    5. writeLine("{difference}")
    Expected outputexit 0
    1500ms
    1500ms
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1500ms
    2. 1500ms
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Multiply a Duration by an int in either order

    Link
    example.tpzMultiply a Duration by an int in either order
    1. import std.io { writeLine }
    2. let count = 3
    3. let left = 500ms * count
    4. let right = count * 500ms
    5. let constructed = 1ms * count
    6. writeLine("{left}")
    7. writeLine("{right}")
    8. writeLine("{constructed}")
    Expected outputexit 0
    1500ms
    1500ms
    3ms
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1500ms
    2. 1500ms
    3. 3ms
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Compare Duration values by milliseconds

    Link
    example.tpzCompare Duration values by milliseconds
    1. import std.io { writeLine }
    2. let first = 1s
    3. let same = 1000ms
    4. let later = 2s
    5. writeLine("{Eq.equals(first, same)}")
    6. writeLine("{Order.compare(first, later) < 0}")
    7. writeLine("{first == same}")
    8. writeLine("{first != later}")
    9. writeLine("{first < later}")
    10. writeLine("{first <= same}")
    11. writeLine("{later > first}")
    12. writeLine("{same >= first}")
    Expected outputexit 0
    true
    true
    true
    true
    true
    true
    true
    true
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. true
    2. true
    3. true
    4. true
    5. true
    6. true
    7. true
    8. true
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Display millisecond literals and extract int milliseconds

    Link
    example.tpzDisplay millisecond literals and extract int milliseconds
    1. import std.io { writeLine }
    2. let delay = 1500ms
    3. let minute = 1m
    4. let second = 1s
    5. let zero = 0ms
    6. let endpoint = 18446744073709551615ms
    7. let intEndpoint = 9223372036854775807ms
    8. writeLine(Show.show(delay))
    9. writeLine("{delay.toMillis()}")
    10. writeLine("{minute.toMillis()}")
    11. writeLine("{second.toMillis()}")
    12. writeLine("{zero}")
    13. writeLine("{endpoint}")
    14. writeLine("{intEndpoint.toMillis()}")
    Expected outputexit 0
    1500ms
    1500
    60000
    1000
    0ms
    18446744073709551615ms
    9223372036854775807
    
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Execution completes. Exit code 0.

    Expected stdout
    1. 1500ms
    2. 1500
    3. 60000
    4. 1000
    5. 0ms
    6. 18446744073709551615ms
    7. 9223372036854775807
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Reject a Duration subtraction below zero

    Link
    example.tpzReject a Duration subtraction below zero
    1. let earlier = 1ms
    2. let later = 2ms
    3. let difference = earlier - later
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ4004 duration-negative-difference at example.tpz:3:18
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Reject a Duration sum outside its millisecond range

    Link
    example.tpzReject a Duration sum outside its millisecond range
    1. let largest = 18446744073709551615ms
    2. let result = largest + 1ms
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ4004 duration-overflow at example.tpz:2:14
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Reject a Duration product outside its millisecond range

    Link
    example.tpzReject a Duration product outside its millisecond range
    1. let large = 9223372036854775807ms
    2. let result = large * 3
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ4004 duration-overflow at example.tpz:2:14
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Reject multiplication by a negative int

    Link
    example.tpzReject multiplication by a negative int
    1. let delay = 1ms
    2. let count = -1
    3. let result = delay * count
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ4004 duration-negative-multiplier at example.tpz:3:14
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Reject a millisecond count outside int

    Link
    example.tpzReject a millisecond count outside int
    1. let delay = 9223372036854775808ms
    2. let count = delay.toMillis()
    Expected outputNonzero exit
    No stdout.
    $ topaz run example.tpz · target product 5.21.3
    Expected result

    Expected result

    Rejection during run. Nonzero exit.

    • TPZ4004 duration-to-millis-overflow at example.tpz:2:13
    Source evidence
    • issues/31 at 1cbf38d3d422
    • parseAtom at af88afbc1d99 · 1245-1255

    Pending contracts

    Link

    Related reference

    Link

    Lexical structure owns token boundaries and reserved spellings. General type compatibility belongs to Types; arithmetic and grouping belong to Expressions and operators. The enclosing timeout form belongs to Concurrency. Diagnostic entries own complete causes and remedies for each qualified diagnostic.

    Unexpected token

    TPZ5001

    Invalid escape sequence

    Unterminated string

    Template indentation mismatch

    Unknown template tag

    Unknown member or field

    Integer overflow

    Menu

    Download