Section 15C: Literals & Operators
Goal: Implement string interpolation, spread operator, range step syntax, and pipe operator
Source:
docs/ori_lang/proposals/approved/
15C.1 String Interpolation
Proposal: proposals/approved/string-interpolation-proposal.md
Add template strings with backtick delimiters and {expr} interpolation.
let name = "Alice"
let age = 30
print(msg: `Hello, {name}! You are {age} years old.`)
Two string types:
"..."— regular strings, no interpolation, braces are literal`...`— template strings with{expr}interpolation
Lexer
-
Implement: Add template string literal tokenization (backtick delimited)
- Rust Tests:
ori_lexer/src/lib.rs— template string tokenization - Ori Tests:
tests/spec/lexical/template_strings.ori - LLVM Support: LLVM codegen for template string tokenization
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— template string tokenization codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Handle
{expr}interpolation boundaries (switch lexer modes)- LLVM Support: LLVM codegen for interpolation boundaries
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— interpolation boundaries codegen - AOT Tests: No AOT coverage yet
-
Implement: Handle
{{and}}escape for literal braces- Ori Tests:
tests/spec/lexical/template_brace_escape.ori - LLVM Support: LLVM codegen for brace escaping
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— brace escaping codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement: Handle
\`escape for literal backtick- Ori Tests:
tests/spec/lexical/template_backtick_escape.ori - LLVM Support: LLVM codegen for backtick escaping
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— backtick escaping codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement: Support escapes:
\\,\n,\t,\r,\0in template strings- Ori Tests:
tests/spec/lexical/template_escapes.ori - LLVM Support: LLVM codegen for template escapes
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— template escapes codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement: Multi-line template strings (preserve whitespace exactly)
- Ori Tests:
tests/spec/lexical/template_multiline.ori - LLVM Support: LLVM codegen for multiline template strings
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— multiline codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
Parser
-
Implement: Parse template strings as sequence of
StringPart(Literal | Interpolation)- Rust Tests:
ori_parse/src/grammar/expr.rs— template string parsing - Ori Tests:
tests/spec/expressions/interpolation.ori - LLVM Support: LLVM codegen for template string parsing
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— template string parsing codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Parse interpolated expressions (full expression grammar inside
{})- Ori Tests:
tests/spec/expressions/interpolation_expressions.ori - LLVM Support: LLVM codegen for interpolated expressions
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— interpolated expressions codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement: Parse optional format specifiers
{expr:spec}- Rust Tests:
ori_parse/src/grammar/format_spec.rs— format spec parsing - Ori Tests:
tests/spec/expressions/format_specifiers.ori - LLVM Support: LLVM codegen for format specifiers
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— format specifiers codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Parse format spec grammar:
[[fill]align][width][.precision][type]- Ori Tests:
tests/spec/expressions/format_spec_grammar.ori - LLVM Support: LLVM codegen for format spec grammar
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— format spec grammar codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
Type System
-
Implement: Interpolated expressions must implement
Printable- Rust Tests:
ori_types/src/check/interpolation.rs— printable constraint - Ori Tests:
tests/spec/types/printable_interpolation.ori - LLVM Support: LLVM codegen for Printable constraint
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— Printable constraint codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Validate format spec type compatibility (e.g.,
x/X/b/oonly for int)- Rust Tests:
ori_types/src/check/format_spec.rs— format spec type validation - Ori Tests:
tests/compile-fail/format_spec_type_mismatch.ori - LLVM Support: LLVM codegen for format spec type validation
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— format spec type validation codegen
- Rust Tests:
Standard Library
-
Implement:
Formattabletrait definition- Ori Tests:
tests/spec/traits/formattable.ori - LLVM Support: LLVM codegen for Formattable trait
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— Formattable trait codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement:
FormatSpectype definition- Ori Tests:
tests/spec/types/format_spec.ori - LLVM Support: LLVM codegen for FormatSpec type
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— FormatSpec type codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement:
AlignmentandFormatTypesum types- Ori Tests:
tests/spec/types/format_enums.ori - LLVM Support: LLVM codegen for format enums
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— format enums codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement: Blanket impl
T: FormattablewhereT: Printable- Ori Tests:
tests/spec/traits/formattable_blanket.ori - LLVM Support: LLVM codegen for blanket impl
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— blanket impl codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement:
apply_formathelper for width/alignment/padding- Ori Tests:
tests/spec/stdlib/apply_format.ori - LLVM Support: LLVM codegen for apply_format
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— apply_format codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
Codegen
-
Implement: Desugar template strings to concatenation with
to_str()calls- Rust Tests:
ori_types/src/check/interpolation_desugar.rs— template desugaring - Ori Tests:
tests/spec/expressions/interpolation_desugar.ori - LLVM Support: LLVM codegen for template string desugaring
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— template string desugaring codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Desugar format specifiers to
format(value, FormatSpec {...})calls- Rust Tests:
ori_types/src/check/format_spec_desugar.rs— format spec desugaring - Ori Tests:
tests/spec/expressions/format_spec_desugar.ori - LLVM Support: LLVM codegen for format spec desugaring
- LLVM Rust Tests:
ori_llvm/tests/interpolation_tests.rs— format spec desugaring codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
15C.2 Spread Operator
Proposal: proposals/approved/spread-operator-proposal.md
Add a spread operator ... for expanding collections and structs in literal contexts.
let combined = [...list1, ...list2]
let merged = {...defaults, ...overrides}
let updated = Point { ...original, x: 10 }
Lexer
- Implement: Add
...as a token (Ellipsis)- Rust Tests:
ori_lexer/src/lib.rs— ellipsis token tests - Ori Tests:
tests/spec/lexical/spread_token.ori - LLVM Support: LLVM codegen for ellipsis token
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— ellipsis token codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
Parser
-
Implement: Parse
...expressionin list literals- Rust Tests:
ori_parse/src/grammar/expr.rs— list spread parsing - Ori Tests:
tests/spec/expressions/list_spread.ori - LLVM Support: LLVM codegen for list spread
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— list spread codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Parse
...expressionin map literals- Rust Tests:
ori_parse/src/grammar/expr.rs— map spread parsing - Ori Tests:
tests/spec/expressions/map_spread.ori - LLVM Support: LLVM codegen for map spread
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— map spread codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Parse
...expressionin struct literals- Rust Tests:
ori_parse/src/grammar/expr.rs— struct spread parsing - Ori Tests:
tests/spec/expressions/struct_spread.ori - LLVM Support: LLVM codegen for struct spread
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— struct spread codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
Type Checker
-
Implement: Verify list spread expression is
[T]matching container- Rust Tests:
ori_types/src/check/spread.rs— list spread type checking - Ori Tests:
tests/compile-fail/list_spread_type_mismatch.ori - LLVM Support: LLVM codegen for list spread type checking
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— list spread type checking codegen
- Rust Tests:
-
Implement: Verify map spread expression is
{K: V}matching container- Rust Tests:
ori_types/src/check/spread.rs— map spread type checking - Ori Tests:
tests/compile-fail/map_spread_type_mismatch.ori - LLVM Support: LLVM codegen for map spread type checking
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— map spread type checking codegen
- Rust Tests:
-
Implement: Verify struct spread is same struct type (no subset/superset)
- Rust Tests:
ori_types/src/check/spread.rs— struct spread type checking - Ori Tests:
tests/compile-fail/struct_spread_wrong_type.ori - LLVM Support: LLVM codegen for struct spread type checking
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— struct spread type checking codegen
- Rust Tests:
-
Implement: Track struct field coverage (spread + explicit must cover all fields)
- Rust Tests:
ori_types/src/check/struct_lit.rs— field coverage tracking - Ori Tests:
tests/compile-fail/struct_spread_missing_fields.ori - LLVM Support: LLVM codegen for field coverage tracking
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— field coverage tracking codegen
- Rust Tests:
Code Generation
-
Implement: Desugar list spread to concatenation (
[a] + b + [c])- Rust Tests:
ori_llvm/src/codegen/spread.rs— list spread desugaring - Ori Tests:
tests/spec/expressions/list_spread_desugar.ori - LLVM Support: LLVM codegen for list spread desugaring
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— list spread desugaring codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Desugar map spread to merge calls
- Rust Tests:
ori_llvm/src/codegen/spread.rs— map spread desugaring - Ori Tests:
tests/spec/expressions/map_spread_desugar.ori - LLVM Support: LLVM codegen for map spread desugaring
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— map spread desugaring codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Desugar struct spread to explicit field assignments
- Rust Tests:
ori_llvm/src/codegen/spread.rs— struct spread desugaring - Ori Tests:
tests/spec/expressions/struct_spread_desugar.ori - LLVM Support: LLVM codegen for struct spread desugaring
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— struct spread desugaring codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
Edge Cases
-
Implement: Empty spread produces nothing (valid)
- Ori Tests:
tests/spec/expressions/spread_empty.ori - LLVM Support: LLVM codegen for empty spread
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— empty spread codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement: Spread preserves evaluation order (left-to-right)
- Ori Tests:
tests/spec/expressions/spread_eval_order.ori - LLVM Support: LLVM codegen for spread evaluation order
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— spread evaluation order codegen - AOT Tests: No AOT coverage yet
- Ori Tests:
-
Implement: Error for spread in function call arguments
- Rust Tests:
ori_types/src/check/call.rs— spread in call error - Ori Tests:
tests/compile-fail/spread_in_function_call.ori - LLVM Support: LLVM codegen for spread in call error
- LLVM Rust Tests:
ori_llvm/tests/spread_tests.rs— spread in call error codegen
- Rust Tests:
15C.3 Range with Step
Proposal: proposals/approved/range-step-proposal.md
Add a by keyword to range expressions for non-unit step values.
0..10 by 2 // 0, 2, 4, 6, 8
10..0 by -1 // 10, 9, 8, ..., 1
0..=10 by 2 // 0, 2, 4, 6, 8, 10
Lexer
- Implement: Add
byas contextual keyword token following range operators- Rust Tests:
ori_lexer/src/lib.rs— by keyword tokenization - Ori Tests:
tests/spec/lexical/by_keyword.ori - LLVM Support: LLVM codegen for by keyword
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— by keyword codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
Parser
- Implement: Extend
range_exprto accept[ "by" shift_expr ]- Rust Tests:
ori_parse/src/grammar/expr.rs— range step parsing - Ori Tests:
tests/spec/expressions/range_step.ori - LLVM Support: LLVM codegen for range step parsing
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— range step parsing codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
Type Checker
-
Implement: Validate step expression has same type as range bounds
- Rust Tests:
ori_types/src/check/range.rs— step type checking - Ori Tests:
tests/compile-fail/range_step_type_mismatch.ori - LLVM Support: LLVM codegen for step type checking
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— step type checking codegen
- Rust Tests:
-
Implement: Restrict
byto integer ranges only (compile-time error for float)- Rust Tests:
ori_types/src/check/range.rs— int-only restriction - Ori Tests:
tests/compile-fail/range_step_float.ori - LLVM Support: LLVM codegen for int-only restriction
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— int-only restriction codegen
- Rust Tests:
Code Generation / Evaluator
-
Implement: Extend Range type with optional step field (default 1)
- Rust Tests:
ori_ir/src/types.rs— Range type extension - Ori Tests:
tests/spec/types/range_with_step.ori - LLVM Support: LLVM codegen for Range type extension
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— Range type extension codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Iterator for stepped ranges (ascending and descending)
- Rust Tests:
ori_eval/src/interpreter/iter.rs— stepped range iteration - Ori Tests:
tests/spec/expressions/range_step_iteration.ori - LLVM Support: LLVM codegen for stepped range iteration
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— stepped range iteration codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Runtime panic for zero step
- Rust Tests:
ori_eval/src/interpreter/range.rs— zero step panic - Ori Tests:
tests/spec/expressions/range_step_zero_panic.ori - LLVM Support: LLVM codegen for zero step panic
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— zero step panic codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Empty range for mismatched direction (no panic)
- Rust Tests:
ori_eval/src/interpreter/range.rs— direction mismatch - Ori Tests:
tests/spec/expressions/range_step_empty.ori - LLVM Support: LLVM codegen for direction mismatch
- LLVM Rust Tests:
ori_llvm/tests/range_step_tests.rs— direction mismatch codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
15C.4 Computed Map Keys
Proposal: proposals/approved/computed-map-keys-proposal.md
Formalize map literal key semantics: bare identifiers are literal string keys (like TypeScript/JSON), and [expression] syntax enables computed keys.
{timeout: 30} // {"timeout": 30} - bare identifier is literal string
{[key]: 30} // computed key - evaluates key variable
{if: 1, type: "user"} // reserved keywords valid as literal keys
Lexer
- Implement: Recognize
[in map key position as start of computed key- Rust Tests:
ori_lexer/src/lib.rs— computed key bracket detection - Ori Tests:
tests/spec/lexical/computed_map_key.ori - LLVM Support: LLVM codegen for computed key tokenization
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs - AOT Tests: No AOT coverage yet
- Rust Tests:
Parser
-
Implement: Parse bare identifier as literal string key in map context
- Rust Tests:
ori_parse/src/grammar/expr.rs— bare identifier key parsing - Ori Tests:
tests/spec/expressions/map_literal_keys.ori - LLVM Support: LLVM codegen for bare identifier keys
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Parse
[expression]as computed key in map context- Rust Tests:
ori_parse/src/grammar/expr.rs— computed key parsing - Ori Tests:
tests/spec/expressions/computed_map_key.ori - LLVM Support: LLVM codegen for computed key parsing
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Allow reserved keywords as bare literal keys
- Rust Tests:
ori_parse/src/grammar/expr.rs— keyword-as-key parsing - Ori Tests:
tests/spec/expressions/map_keyword_keys.ori - LLVM Support: LLVM codegen for keyword keys
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs - AOT Tests: No AOT coverage yet
- Rust Tests:
Type Checker
-
Implement: Bare identifier keys always produce
strtype- Rust Tests:
ori_types/src/check/map_lit.rs— bare key type inference - Ori Tests:
tests/spec/types/map_key_types.ori - LLVM Support: LLVM codegen for bare key types
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Computed keys must match map key type
Kin{K: V}- Rust Tests:
ori_types/src/check/map_lit.rs— computed key type checking - Ori Tests:
tests/compile-fail/computed_key_type_mismatch.ori - LLVM Support: LLVM codegen for computed key type checking
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs
- Rust Tests:
-
Implement: Error for bare literals in non-string-key maps
- Rust Tests:
ori_types/src/check/map_lit.rs— bare key in int-map error - Ori Tests:
tests/compile-fail/bare_key_non_string_map.ori - LLVM Support: LLVM codegen for bare key error
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs
- Rust Tests:
Code Generation
-
Implement: Desugar bare identifier keys to string literals
- Rust Tests:
ori_llvm/src/codegen/map.rs— bare key desugaring - Ori Tests:
tests/spec/expressions/map_key_desugar.ori - LLVM Support: LLVM codegen for bare key desugaring
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Evaluate computed key expressions at runtime
- Rust Tests:
ori_llvm/src/codegen/map.rs— computed key evaluation - Ori Tests:
tests/spec/expressions/computed_key_eval.ori - LLVM Support: LLVM codegen for computed key evaluation
- LLVM Rust Tests:
ori_llvm/tests/computed_map_tests.rs - AOT Tests: No AOT coverage yet
- Rust Tests:
15C.5 Floor Division (div) Operator Fix
Proposal: proposals/approved/grammar-sync-formalization-proposal.md
Fix parser discrepancy where div operator is in grammar but missing from parser.
Parser Fix
- Implement: Add
TokenKind::Divcase tomatch_multiplicative_op()- Rust Tests:
ori_parse/src/grammar/expr/operators.rs— div operator parsing - Ori Tests:
tests/spec/operators/div_floor.ori - LLVM Support: LLVM codegen for div operator
- LLVM Rust Tests:
ori_llvm/tests/operator_tests.rs— div codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
Operator Test Infrastructure
-
Implement: Create
tests/spec/operators/directory structure-
tests/spec/operators/precedence/— precedence relationship tests -
tests/spec/operators/associativity/— associativity tests -
tests/spec/operators/operators/— individual operator tests
-
-
Implement: Add precedence tests for adjacent levels
- Ori Tests:
tests/spec/operators/precedence/mul_over_add.ori - Ori Tests:
tests/spec/operators/precedence/add_over_shift.ori - Ori Tests:
tests/spec/operators/precedence/shift_over_range.ori
- Ori Tests:
-
Implement: Add associativity tests for binary operators
- Ori Tests:
tests/spec/operators/associativity/mul_left_assoc.ori - Ori Tests:
tests/spec/operators/associativity/add_left_assoc.ori
- Ori Tests:
15C.6 Decimal Duration and Size Literals
Proposal: proposals/approved/decimal-duration-size-literals-proposal.md
Allow decimal syntax in duration and size literals as compile-time sugar.
let t = 0.5s // 500,000,000 nanoseconds
let t = 1.56s // 1,560,000,000 nanoseconds
let s = 1.5kb // 1,500 bytes (SI units)
let s = 0.25mb // 250,000 bytes
Key changes:
- Decimal notation for duration/size literals (compile-time, no floats)
- Size units changed from binary (1024) to SI (1000)
- E0911 repurposed: “literal cannot be represented exactly”
Lexer
-
Implement: Parse decimal duration literals (
1.5s,0.25h, etc.)- Rust Tests:
ori_lexer/src/lib.rs— decimal duration tokenization - Ori Tests:
tests/spec/lexical/decimal_duration.ori - LLVM Support: LLVM codegen for decimal duration literals
- LLVM Rust Tests:
ori_llvm/tests/literal_tests.rs— decimal duration codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Parse decimal size literals (
1.5kb,0.5mb, etc.)- Rust Tests:
ori_lexer/src/lib.rs— decimal size tokenization - Ori Tests:
tests/spec/lexical/decimal_size.ori - LLVM Support: LLVM codegen for decimal size literals
- LLVM Rust Tests:
ori_llvm/tests/literal_tests.rs— decimal size codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
-
Implement: Integer arithmetic conversion (no floats involved)
- Rust Tests:
ori_lexer/src/convert.rs— integer-only decimal conversion - Ori Tests:
tests/spec/lexical/decimal_precision.ori
- Rust Tests:
-
Implement: Validation for whole-number results
- Rust Tests:
ori_lexer/src/convert.rs— non-whole number rejection - Ori Tests:
tests/compile-fail/decimal_duration_not_whole.ori - Ori Tests:
tests/compile-fail/decimal_size_not_whole.ori
- Rust Tests:
Token Changes
-
Implement: Remove
FloatDurationErrorandFloatSizeErrortoken types- Rust Tests:
ori_ir/src/token.rs— token type cleanup
- Rust Tests:
-
Implement: Store Duration/Size tokens as computed base unit value
- Rust Tests:
ori_ir/src/token.rs— token value storage
- Rust Tests:
Error Messages
- Implement: E0911 error for non-representable decimal literals
- Rust Tests:
ori_diagnostic/src/error_code.rs— E0911 update - Ori Tests:
tests/compile-fail/e0911_decimal_precision.ori
- Rust Tests:
Size Unit Change
- Implement: Change Size unit multipliers from 1024 to 1000
- Rust Tests:
ori_lexer/src/convert.rs— SI unit multipliers - Ori Tests:
tests/spec/types/size_si_units.ori - LLVM Support: LLVM codegen with SI units
- LLVM Rust Tests:
ori_llvm/tests/literal_tests.rs— SI unit codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
15C.7 Null Coalesce Operator (??)
Source: grammar.ebnf § coalesce_expr, spec/14-expressions.md § Operators
The null coalesce operator ?? provides a default value when an Option is None.
let name = maybe_name ?? "Anonymous"
let count = get_count() ?? 0
Status: Parser complete (tokenization, AST), evaluator incomplete.
Evaluator
- Implement: Evaluate
??forOption<T>— extract Some value or use default- Rust Tests:
ori_eval/src/interpreter/mod.rs— coalesce evaluation - Ori Tests:
tests/spec/expressions/coalesce.ori - LLVM Support: LLVM codegen for null coalesce operator
- LLVM Rust Tests:
ori_llvm/tests/coalesce_tests.rs— coalesce codegen - AOT Tests: No AOT coverage yet
- Rust Tests:
Type Checker
-
Implement: Infer type for
a ?? b— result isTwherea: Option<T>andb: T- Rust Tests:
ori_types/src/infer/ (operators)— coalesce type inference - Ori Tests:
tests/spec/types/coalesce_inference.ori
- Rust Tests:
-
Implement: Error for non-Option left operand
- Rust Tests:
ori_types/src/infer/ (tests)— coalesce type error - Ori Compile-Fail Tests:
tests/compile-fail/coalesce_non_option.ori
- Rust Tests:
Edge Cases
-
Implement: Short-circuit evaluation — don’t evaluate right side if left is Some
- Ori Tests:
tests/spec/expressions/coalesce_short_circuit.ori
- Ori Tests:
-
Implement: Chained coalesce —
a ?? b ?? c- Ori Tests:
tests/spec/expressions/coalesce_chained.ori
- Ori Tests:
15C.8 Compound Assignment Operators
Proposal: proposals/approved/compound-assignment-proposal.md
Add compound assignment operators (+=, -=, *=, /=, %=, @=, &=, |=, ^=, <<=, >>=, &&=, ||=) that desugar to x = x op y at the parser level.
let sum = 0;
for item in items {
sum += item.value;
}
Lexer
-
Implement: Add 13 new raw token tags to
ori_lexer_core/src/tag/mod.rsPlusEq,MinusEq,StarEq,SlashEq,PercentEq,AtEq,AmpEq,PipeEq,CaretEq,ShlEq,ShrEq,AmpAmpEq,PipePipeEq- Rust Tests:
ori_lexer_core/src/tag/tests.rs— lexeme and display tests - Rust Tests:
ori_lexer_core/src/raw_scanner/tests.rs— scanning tests
-
Implement: Update raw scanner to scan compound assignment tokens
- Two-char:
+=,-=,*=,/=,%=,@=,&=,|=,^= - Three-char:
<<=,>>=,&&=,||= - Rust Tests:
ori_lexer_core/src/raw_scanner/tests.rs— replaceno_compound_assignmenttest
- Two-char:
-
Implement: Map raw tags to
TokenKindin cooker- Rust Tests:
ori_lexer/src/cooker/tests.rs— compound assignment cooking
- Rust Tests:
Parser
-
Implement: Parse compound assignment and desugar to
Assign { target, value: Binary/And/Or }- Trait-based ops: map
PlusEq→BinaryOp::Add, etc. - Logical ops: map
AmpAmpEq→ExprKind::And,PipePipeEq→ExprKind::Or - Rust Tests:
ori_parse/src/grammar/expr/tests.rs— compound assignment parsing - Ori Tests:
tests/spec/operators/compound_assignment/basic.ori - Ori Tests:
tests/spec/operators/compound_assignment/field_access.ori - Ori Tests:
tests/spec/operators/compound_assignment/subscript.ori - Ori Tests:
tests/spec/operators/compound_assignment/logical.ori
- Trait-based ops: map
-
Implement: Remove compound assignment from “common mistake” detection
- Remove
+=,-=,*=,/=,%=frommistakes.rs - Remove
&&=,||=frommistakes.rs - Keep
??=as mistake (still unsupported) - Rust Tests:
ori_parse/src/error/tests.rs— update detection tests
- Remove
Error Messages
-
Implement: Error for compound assignment on immutable binding (
$)- Message: “cannot use compound assignment on immutable binding
$y. Remove$for mutability:let y = ...” - Ori Tests:
tests/compile-fail/compound_assign_immutable.ori
- Message: “cannot use compound assignment on immutable binding
-
Implement: Error for compound assignment as expression
- Message: “compound assignment is a statement, not an expression”
- Ori Tests:
tests/compile-fail/compound_assign_as_expression.ori
LLVM Support
- LLVM Support: No changes needed — parser desugars before reaching LLVM codegen
- LLVM Rust Tests:
ori_llvm/tests/compound_assign_tests.rs— verify desugared form compiles correctly - AOT Tests: No AOT coverage yet
- LLVM Rust Tests:
15C.9 MatMul Operator (@)
Proposal: proposals/approved/matmul-operator-proposal.md
Add @ as a binary operator for matrix multiplication. Desugars to MatMul trait method matrix_multiply(). Same precedence as *///%/div (level 4, multiplicative). The @ token is disambiguated by syntactic context (item position = function declaration, expression position = matmul, pattern position = at-binding).
IR
- Implement: Add
MatMulvariant toBinaryOp+ arms inas_symbol(),precedence(),trait_method_name(),trait_name()- Rust Tests:
ori_ir/src/ast/tests.rs
- Rust Tests:
Parser
- Implement: Add
TokenKind::Atto multiplicative precedence level in expression parser- Rust Tests:
ori_parse/src/grammar/expr/tests.rs— matmul parsing - Ori Tests:
tests/spec/operators/matmul/basic.ori - Ori Tests:
tests/spec/operators/matmul/precedence.ori
- Rust Tests:
Evaluator
- Implement: Add
BinaryOp::MatMulerror arms to primitive type handlers (no primitive implementsMatMul)- Rust Tests:
ori_eval/src/tests/— matmul error on primitives
- Rust Tests:
Standard Library
- Implement: Add
MatMultrait definition tolibrary/std/prelude.ori- Ori Tests:
tests/spec/traits/operators/matmul_trait.ori
- Ori Tests:
LLVM
- LLVM Support: Falls through via trait dispatch — no special-casing needed
- AOT Tests:
ori_llvm/tests/aot/operators.rs— matmul trait dispatch
- AOT Tests:
15C.10 Power Operator (**)
Proposal: proposals/approved/power-operator-proposal.md
Add ** as a right-associative binary operator for exponentiation. Desugars to Pow trait method power(). Binds tighter than unary - (precedence level 2): -x ** 2 = -(x ** 2). Compound assignment **= included.
Lexer
- Implement: Add
StarStarandStarStarEqraw token tags toori_lexer_core/src/tag/mod.rs- Rust Tests:
ori_lexer_core/src/tag/tests.rs— lexeme and display tests
- Rust Tests:
- Implement: Update raw scanner to recognize
**and**=(longest-match:*→ peek*→ peek=)- Rust Tests:
ori_lexer_core/src/raw_scanner/tests.rs— power token scanning
- Rust Tests:
- Implement: Map
StarStar→TokenKind::PowandStarStarEq→ compound assignment in cooker- Rust Tests:
ori_lexer/src/cooker/tests.rs— power token cooking
- Rust Tests:
IR
- Implement: Add
Powvariant toBinaryOp+ arms inas_symbol(),precedence(),trait_method_name(),trait_name()- Rust Tests:
ori_ir/src/ast/tests.rs— BinaryOp::Pow methods
- Rust Tests:
Parser
- Implement: Add
parse_power_expr()betweenparse_unary_expr()andparse_postfix_expr()— right-associativeunary_exprcallspower_expr;power_exprcallspostfix_expr- Rust Tests:
ori_parse/src/grammar/expr/tests.rs— power expression parsing - Ori Tests:
tests/spec/operators/power/basic.ori - Ori Tests:
tests/spec/operators/power/right_assoc.ori—2 ** 3 ** 2 = 512 - Ori Tests:
tests/spec/operators/power/unary_minus.ori—-2 ** 2 = -4 - Ori Tests:
tests/spec/operators/power/precedence.ori—a * b ** 2 = a * (b ** 2)
- Implement: Parse
**=compound assignment (desugar tox = x ** y)- Ori Tests:
tests/spec/operators/power/compound_assign.ori
- Ori Tests:
Type Checker
- Implement: Falls through via
BinaryOp::trait_name()returning"Pow"— no special-casing- Ori Tests:
tests/compile-fail/power_no_impl.ori— “typestrdoes not implementPow”
- Ori Tests:
Evaluator
- Implement: Built-in
int ** intdispatch (binary exponentiation, panic on negative exponent)- Rust Tests:
ori_eval/src/tests/— int power evaluation - Ori Tests:
tests/spec/operators/power/int_power.ori - Ori Tests:
tests/spec/operators/power/negative_exponent_panic.ori - Ori Tests:
tests/spec/operators/power/zero_pow_zero.ori—0 ** 0 = 1
- Rust Tests:
- Implement: Built-in
float ** floatdispatch (delegates to libmpow())- Rust Tests:
ori_eval/src/tests/— float power evaluation - Ori Tests:
tests/spec/operators/power/float_power.ori
- Rust Tests:
- Implement: Mixed-type dispatch:
float ** int,int ** float→float- Ori Tests:
tests/spec/operators/power/mixed_types.ori
- Ori Tests:
- Implement: Overflow follows standard overflow behavior (panic in debug)
- Ori Tests:
tests/spec/operators/power/overflow.ori
- Ori Tests:
Standard Library
- Implement: Add
Powtrait definition tolibrary/std/prelude.ori- Trait:
trait Pow<Rhs = Self> { type Output = Self; @power (self, rhs: Rhs) -> Self.Output } - Built-in impls:
Pow for int,Pow for float,Pow<int> for float,Pow<float> for int - Ori Tests:
tests/spec/traits/operators/pow_trait.ori - Ori Tests:
tests/spec/traits/operators/pow_user_defined.ori
- Trait:
LLVM
- LLVM Support: Primitive impls via
llvm.powintrinsic; user types via trait dispatch- AOT Tests:
ori_llvm/tests/aot/operators.rs— power operator codegen
- AOT Tests:
15C.11 Pipe Operator (|>)
Proposal: proposals/approved/pipe-operator-proposal.md
Add |> for left-to-right function composition with implicit fill. The piped value fills the single parameter that has no default and is not provided in the call. Method calls on the piped value use .method() syntax. Lambda pipe steps (|> (x -> expr)) handle expression-level operations.
data
|> filter(predicate: x -> x > 0)
|> map(transform: x -> x * 2)
|> sum
Lexer
- Implement: Add
PipeArrowraw token tag toori_lexer_core/src/tag/mod.rs- Rust Tests:
ori_lexer_core/src/tag/tests.rs— lexeme and display tests
- Rust Tests:
- Implement: Update raw scanner to recognize
|>(disambiguate from|)- Rust Tests:
ori_lexer_core/src/raw_scanner/tests.rs— pipe token scanning
- Rust Tests:
- Implement: Map
PipeArrow→TokenKind::Pipein cooker- Rust Tests:
ori_lexer/src/cooker/tests.rs— pipe token cooking
- Rust Tests:
IR
- Implement: Add
Pipeexpression variant toExprKind(LHS expression + pipe step)- Pipe step variants: function call (implicit fill), method call (
.method), lambda - Rust Tests:
ori_ir/src/ast/tests.rs— Pipe expression AST node
- Pipe step variants: function call (implicit fill), method call (
Parser
- Implement: Parse
|>at precedence 16 (below??at 15); producePipeAST node- Grammar:
pipe_expr = coalesce_expr { "|>" pipe_step } . - Pipe step:
.method()|postfix_expr [call_args]|lambda - Rust Tests:
ori_parse/src/grammar/expr/tests.rs— pipe expression parsing - Ori Tests:
tests/spec/expressions/pipe/basic.ori— simple pipe chains - Ori Tests:
tests/spec/expressions/pipe/method_call.ori—.method()on piped value - Ori Tests:
tests/spec/expressions/pipe/lambda.ori— lambda pipe steps - Ori Tests:
tests/spec/expressions/pipe/precedence.ori—a + b |> f=(a + b) |> f - Ori Tests:
tests/spec/expressions/pipe/nested.ori—a |> f(x: b |> g)
- Grammar:
Type Checker
-
Implement: Resolve implicit fill — identify single unspecified param (no default, not in call)
- Desugar to let-binding + ordinary function call
- Rust Tests:
ori_types/src/infer/expr/tests.rs— pipe implicit fill resolution - Ori Tests:
tests/spec/expressions/pipe/implicit_fill.ori— fills correct param - Ori Tests:
tests/spec/expressions/pipe/defaults.ori— params with defaults excluded - Ori Tests:
tests/spec/expressions/pipe/punning.ori—x |> f(weight:, bias:)
-
Implement: Error diagnostics for pipe
- Zero unspecified: “all parameters already specified; nothing for pipe to fill”
- Multiple unspecified: “ambiguous pipe target; specify all parameters except one”
- Ori Tests:
tests/compile-fail/pipe_all_specified.ori - Ori Tests:
tests/compile-fail/pipe_ambiguous.ori - Ori Tests:
tests/compile-fail/pipe_zero_params.ori
-
Implement: Desugar
.method()pipe steps to__pipe.method(args)call- Ori Tests:
tests/spec/expressions/pipe/method_desugar.ori
- Ori Tests:
-
Implement: Desugar lambda pipe steps to
(lambda)(__pipe)call- Ori Tests:
tests/spec/expressions/pipe/lambda_desugar.ori
- Ori Tests:
-
Implement: Handle
?on pipe steps — applies to desugared call result- Ori Tests:
tests/spec/expressions/pipe/error_propagation.ori
- Ori Tests:
Formatter
- Implement: Format pipe chains with line-break-per-step, indented under first operand
- Rust Tests:
ori_fmt/src/formatter/tests.rs— pipe chain formatting
- Rust Tests:
LLVM
- LLVM Support: No changes needed — type checker desugars before reaching LLVM codegen
- AOT Tests:
ori_llvm/tests/aot/pipe.rs— verify desugared form compiles correctly
- AOT Tests:
15C.13 Byte Literals and Hex Escapes
Proposal: proposals/approved/byte-literals-proposal.md
Add b'x' byte literal syntax and \xHH hex escapes. Byte literals produce type byte (0–255). \xHH is also added to char literals (restricted to \x00–\x7F).
let space: byte = b' ';
let esc: byte = b'\x1B';
let max: byte = b'\xFF';
let tab_char: char = '\x09';
Raw Scanner
- Implement: Modify identifier dispatch in
ori_lexer_core/src/raw_scanner/mod.rs— peek for'afterbto start byte literal scanning- Rust Tests:
ori_lexer_core/src/raw_scanner/tests.rs— byte literal boundary detection
- Rust Tests:
- Implement: Add
RawTag::ByteLiteralandRawTag::UnterminatedByteLiteralvariants- Rust Tests:
ori_lexer_core/src/tag/tests.rs— lexeme and display tests
- Rust Tests:
- Implement: Add
scan_byte_literal()method instrings.rs— reuseskip_escape_body()with\xextension- Rust Tests:
ori_lexer_core/src/raw_scanner/tests.rs— byte literal scanning (escapes, unterminated, multi-char)
- Rust Tests:
- Implement: Extend
skip_escape_body()to handle\x— consume exactly 2 hex digits- Rust Tests:
ori_lexer_core/src/raw_scanner/tests.rs— hex escape boundary detection
- Rust Tests:
Cooker
- Implement: Add
cook_byte_literal()method inescape_cooking.rs— stripsb'...', callsunescape_byte_v2()- Rust Tests:
ori_lexer/src/cooker/tests.rs— byte literal cooking
- Rust Tests:
- Implement: Add
unescape_byte_v2()function incook_escape/mod.rs— handles\\\'\n\t\r\0\xHH; rejects\u{...}and\"; producesu8- Rust Tests:
ori_lexer/src/cook_escape/tests.rs— byte escape processing
- Rust Tests:
- Implement: Extend
unescape_char_v2()to handle\xHH— restricted to\x00–\x7F; error for\x80–\xFF- Rust Tests:
ori_lexer/src/cook_escape/tests.rs— char hex escape processing
- Rust Tests:
Token Kind
- Implement: Add
TokenKind::Byte(u8)variant toori_ir/src/token/kind.rs- Rust Tests:
ori_ir/src/token/tests.rs— display, discriminant
- Rust Tests:
Parser
- Implement: Parse
TokenKind::Byte(u8)as literal expression inori_parse- Rust Tests:
ori_parse/src/grammar/expr/tests.rs— byte literal parsing - Ori Tests:
tests/spec/literals/byte_literal.ori
- Rust Tests:
Type Checker
- Implement: Infer
bytetype for byte literal expressions inori_types- Rust Tests:
ori_types/src/infer/expr/tests.rs— byte literal type inference - Ori Tests:
tests/spec/types/byte_literal_type.ori
- Rust Tests:
Evaluator
- Implement: Evaluate byte literals to
Value::Byte(u8)inori_eval- Rust Tests:
ori_eval/src/interpreter/tests.rs— byte literal evaluation - Ori Tests:
tests/spec/literals/byte_literal_eval.ori
- Rust Tests:
LLVM Codegen
- LLVM Support: Emit byte literal as
i8constant inori_llvm- LLVM Rust Tests:
ori_llvm/tests/aot/literals.rs— byte literal codegen - AOT Tests:
tests/spec/literals/byte_literal_aot.ori
- LLVM Rust Tests:
Error Messages
- Implement: Error for
\u{...}in byte literal — “byte literal cannot contain unicode escape”- Ori Tests:
tests/compile-fail/byte_literal_unicode_escape.ori
- Ori Tests:
- Implement: Error for
\"in byte literal — “invalid escape in byte literal”- Ori Tests:
tests/compile-fail/byte_literal_double_quote_escape.ori
- Ori Tests:
- Implement: Error for non-ASCII character in byte literal — “non-ASCII character in byte literal”
- Ori Tests:
tests/compile-fail/byte_literal_non_ascii.ori
- Ori Tests:
- Implement: Error for
\x80–\xFFin char literal — “\x value exceeds ASCII range in char literal (use \u{…})”- Ori Tests:
tests/compile-fail/char_literal_hex_out_of_range.ori
- Ori Tests:
15C.12 Section Completion Checklist
- All implementation items have checkboxes marked
[ ] - All spec docs updated
- CLAUDE.md updated with syntax changes
- Migration tools working
- All tests pass:
./test-all.sh
Exit Criteria: Literal and operator syntax proposals implemented