Files
hakorune/docs/private/roadmap/phases/phase-24-ultimate-language-design/sugar-syntax-proposals.md

15 KiB

Sugar Syntax Proposals - 22 Ergonomics Enhancements

Generated by: Task Agent 1 (Language Features Analysis) Date: 2025-10-12 Philosophy: Desugar everything to Box operations, maintain MIR 16-instruction set


📊 Priority Matrix

Priority Difficulty Count Examples
High Easy 3 List comprehension, Null coalescing assignment, Range operator
High Medium 3 Null-safe operator, Arrow functions, String interpolation
Medium Easy 4 Multiple return, Default parameters, Named parameters, With expression
Medium Medium 6 Pattern matching in let, Spread operator, Destructuring, Guard clauses, Switch expression, Do expression
Low Medium 3 Pipeline operator enhancement, For...in sugar, Partial application
Low Hard 3 Async/await sugar, Generator functions, Tail call optimization

🚀 High Priority - Easy Implementation

1. List Comprehension

Impact: 60-70% code reduction in data processing Difficulty: Easy (desugar to loop + ArrayBox)

// Syntax
[expression for variable in iterable if condition]

// Example
local evens = [x * 2 for x in numbers if x % 2 == 0]

// Desugars to:
local evens = new ArrayBox()
local __iter = numbers.iterator()
loop(__iter.has_next()) {
    local x = __iter.next()
    if x % 2 == 0 {
        evens.push(x * 2)
    }
}

Implementation strategy:

  1. Parser recognizes [... for ... in ... if ...] pattern
  2. AST node: ListComprehension { expr, var, iter, condition }
  3. Desugar in MIR builder to loop + conditional + push

2. Null Coalescing Assignment

Impact: Eliminate boilerplate null checks Difficulty: Easy (desugar to if + assignment)

// Syntax
variable ??= default_value

// Example
local config
config ??= load_default_config()  // Only assigns if config is null

// Desugars to:
if config == null {
    config = load_default_config()
}

Implementation strategy:

  1. Parser recognizes ??= operator
  2. AST node: NullCoalescingAssign { lhs, rhs }
  3. Desugar to null check + conditional assignment

3. Range Operator

Impact: Clean array slicing and iteration Difficulty: Easy (RangeBox or builtin)

// Syntax
start..end          // Exclusive end
start..=end         // Inclusive end
array[start..end]   // Slice syntax

// Example
local range = 0..10           // RangeBox(0, 10)
local slice = array[2..5]     // array.slice(2, 5)

loop(i in 0..10) {            // Iterator sugar
    print(i)
}

// Desugars to:
local range = RangeBox.new(0, 10)
local slice = array.slice(2, 5)

local i = 0
loop(i < 10) {
    print(i)
    i = i + 1
}

Implementation strategy:

  1. Introduce RangeBox core type
  2. Parser recognizes .. and ..= operators
  3. Array indexing with range → slice() method call
  4. for x in range sugar → loop + counter

🔥 High Priority - Medium Implementation

4. Null-Safe Operator

Impact: Crash prevention, cleaner code Difficulty: Medium (short-circuit evaluation)

// Syntax
object?.method()
object?.field

// Example
local street = person?.address?.street  // Returns null if any intermediate is null

// Desugars to:
local street
if person != null {
    local __temp1 = person.address
    if __temp1 != null {
        street = __temp1.street
    } else {
        street = null
    }
} else {
    street = null
}

Implementation strategy:

  1. Parser recognizes ?. operator
  2. AST node: NullSafe { object, chain }
  3. Desugar to nested null checks with short-circuit
  4. MIR: use branch + phi nodes for null propagation

5. Arrow Functions

Impact: Cleaner callbacks and functional programming Difficulty: Medium (closure capture)

// Syntax
(params) => expression
(params) => { statements }

// Example
local doubled = array.map(x => x * 2)
local filtered = array.filter(x => x > 10)

// Desugars to:
box __Lambda1 {
    call(x) {
        return x * 2
    }
}

local doubled = array.map(new __Lambda1())

Implementation strategy:

  1. Parser recognizes => operator
  2. AST node: ArrowFunction { params, body }
  3. Desugar to anonymous box with call() method
  4. Capture environment variables as box fields

6. String Interpolation

Impact: Eliminate ugly concatenation Difficulty: Medium (expression parsing inside strings)

// Syntax
`string with ${expression}`

// Example
local message = `Hello, ${name}! You have ${count} messages.`

// Desugars to:
local message = new StringBox("Hello, ")
    .concat(name.to_string())
    .concat("! You have ")
    .concat(count.to_string())
    .concat(" messages.")

Implementation strategy:

  1. Parser recognizes `...${...}...` pattern
  2. AST node: StringInterpolation { parts: Vec<StringOrExpr> }
  3. Desugar to StringBox concatenation chain
  4. Call .to_string() on interpolated expressions

💡 Medium Priority - Easy Implementation

7. Multiple Return Values

Impact: Cleaner function signatures Difficulty: Easy (TupleBox or multiple assignments)

// Syntax
return value1, value2, value3

// Example
divide(a, b) {
    if b == 0 {
        return null, "Division by zero"
    }
    return a / b, null
}

local result, error = divide(10, 2)

// Desugars to:
divide(a, b) {
    if b == 0 {
        return TupleBox.new(null, "Division by zero")
    }
    return TupleBox.new(a / b, null)
}

local __tuple = divide(10, 2)
local result = __tuple.get(0)
local error = __tuple.get(1)

Implementation strategy:

  1. Introduce TupleBox core type
  2. return a, b, creturn TupleBox.new(a, b, c)
  3. local a, b, c = expr → destructuring assignment

8. Default Parameters

Impact: Fewer function overloads Difficulty: Easy (desugar to null check)

// Syntax
function(param = default_value)

// Example
greet(name = "World") {
    print(`Hello, ${name}!`)
}

greet()           // "Hello, World!"
greet("Alice")    // "Hello, Alice!"

// Desugars to:
greet(name) {
    if name == null {
        name = "World"
    }
    print(`Hello, ${name}!`)
}

Implementation strategy:

  1. Parser recognizes param = default in function signature
  2. AST node: DefaultParam { name, default_expr }
  3. Desugar to null check at function entry

9. Named Parameters

Impact: Better API ergonomics Difficulty: Easy (MapBox or ordered params)

// Syntax
function(name: value, other: value)

// Example
create_user(name: "Alice", age: 30, admin: true)

// Desugars to:
local __args = new MapBox()
__args.set("name", "Alice")
__args.set("age", 30)
__args.set("admin", true)
create_user(__args)

Implementation strategy:

  1. Parser recognizes name: value syntax in call
  2. Collect into MapBox
  3. Function receives MapBox and extracts values

10. With Expression

Impact: Cleaner resource management (already have cleanup) Difficulty: Easy (combine with existing cleanup)

// Syntax
with resource = expression {
    // use resource
}  // automatic cleanup

// Example
with file = FileBox.open("data.txt") {
    local content = file.read()
    print(content)
}  // file.close() called automatically

// Desugars to:
local file = FileBox.open("data.txt")
cleanup {
    file.close()
}
local content = file.read()
print(content)

Implementation strategy:

  1. Parser recognizes with variable = expr { ... } pattern
  2. Desugar to variable binding + cleanup block
  3. Reuse existing cleanup mechanism

🎯 Medium Priority - Medium Implementation

11. Pattern Matching in Let

Impact: Destructure complex data structures Difficulty: Medium (pattern matching engine)

// Syntax
local Pattern = expression

// Example
local Ok(value) = result    // Panic if result is Err
local [first, rest...] = array
local {name, age} = person

// Desugars to:
match result {
    Ok(value) => {
        local value = value
    }
    _ => panic("Pattern match failed")
}

Implementation strategy:

  1. Extend existing match implementation
  2. Allow patterns in local statements
  3. Generate runtime check + panic if no match

12. Spread Operator

Impact: Clean array/object merging Difficulty: Medium (iterate + copy)

// Syntax
[...array1, ...array2]
{...object1, ...object2}

// Example
local merged = [...arr1, item, ...arr2]
local combined = {name: "Alice", ...defaults}

// Desugars to:
local merged = new ArrayBox()
local __iter1 = arr1.iterator()
loop(__iter1.has_next()) {
    merged.push(__iter1.next())
}
merged.push(item)
local __iter2 = arr2.iterator()
loop(__iter2.has_next()) {
    merged.push(__iter2.next())
}

Implementation strategy:

  1. Parser recognizes ...expr in array/map literals
  2. Desugar to iterator loops + push operations
  3. For maps, use .entries() + .set() chain

13. Destructuring Assignment

Impact: Cleaner variable extraction Difficulty: Medium (pattern matching)

// Syntax
local [a, b, c] = array
local {name, age} = person

// Example
local [first, second, rest...] = [1, 2, 3, 4, 5]
// first = 1, second = 2, rest = [3, 4, 5]

// Desugars to:
local first = array.get(0)
local second = array.get(1)
local rest = array.slice(2, array.length())

Implementation strategy:

  1. Parser recognizes patterns in local statements
  2. AST node: Destructure { pattern, expr }
  3. Desugar to individual assignments

14. Guard Clauses

Impact: Reduce nesting Difficulty: Medium (early return transformation)

// Syntax
guard condition else return/break/continue

// Example
function process(value) {
    guard value != null else return null
    guard value > 0 else return -1

    return value * 2
}

// Desugars to:
function process(value) {
    if value == null {
        return null
    }
    if value <= 0 {
        return -1
    }

    return value * 2
}

Implementation strategy:

  1. Parser recognizes guard ... else ... pattern
  2. AST node: Guard { condition, action }
  3. Desugar to inverted condition + action

15. Switch Expression

Impact: Cleaner value-producing conditionals Difficulty: Medium (extend match to primitives)

// Syntax
switch value {
    case1 => result1,
    case2 => result2,
    _ => default
}

// Example
local grade = switch score {
    90..=100 => "A",
    80..=89 => "B",
    70..=79 => "C",
    _ => "F"
}

// Desugars to:
local grade
if score >= 90 && score <= 100 {
    grade = "A"
} else if score >= 80 && score <= 89 {
    grade = "B"
} else if score >= 70 && score <= 79 {
    grade = "C"
} else {
    grade = "F"
}

Implementation strategy:

  1. Extend match to work with expressions
  2. Support range patterns
  3. Desugar to if-else chain with phi nodes

16. Do Expression

Impact: Expression-oriented programming Difficulty: Medium (block as expression)

// Syntax
local value = do {
    statements...
    final_expression
}

// Example
local result = do {
    local temp = calculate()
    local adjusted = temp * 2
    adjusted + 10
}

// Desugars to:
local temp = calculate()
local adjusted = temp * 2
local result = adjusted + 10

Implementation strategy:

  1. Parser recognizes do { ... } as expression
  2. AST node: DoExpression { stmts, final_expr }
  3. Desugar to inline statements + final assignment

🔮 Low Priority - Medium/Hard Implementation

17. Pipeline Operator Enhancement (already exists, enhance)

Current: a |> b |> c Enhancement: Support method chaining syntax

// Current
data |> transform1 |> transform2 |> transform3

// Enhanced
data
  |> transform1(?, arg)
  |> obj.method(?)
  |> ?.optional_method()

// Desugars to:
local __pipe1 = transform1(data, arg)
local __pipe2 = obj.method(__pipe1)
local __pipe3 = __pipe2?.optional_method()

18. For...In Sugar

Impact: Cleaner iteration syntax Difficulty: Medium

// Syntax
for variable in iterable {
    // body
}

// Example
for item in array {
    print(item)
}

// Desugars to:
local __iter = array.iterator()
loop(__iter.has_next()) {
    local item = __iter.next()
    print(item)
}

19. Partial Application

Impact: Functional programming patterns Difficulty: Medium

// Syntax
function(?, arg2, ?)  // ? is placeholder

// Example
local add_10 = add(?, 10)
add_10(5)  // Returns 15

// Desugars to:
box __Partial_add_10 {
    call(arg1) {
        return add(arg1, 10)
    }
}
local add_10 = new __Partial_add_10()

20. Async/Await Sugar Enhancement

Impact: Better async ergonomics (already have nowait/await) Difficulty: Medium

// Current
nowait future = async_operation()
local result = await future

// Enhanced
async function fetch_data() {
    local response = await http.get(url)
    local data = await response.json()
    return data
}

// Desugars to existing nowait/await

21. Generator Functions

Impact: Lazy iteration Difficulty: Hard (requires state machine transformation)

// Syntax
function* generator() {
    yield value1
    yield value2
}

// Example
function* fibonacci() {
    local a = 0
    local b = 1
    loop(true) {
        yield a
        local temp = a
        a = b
        b = temp + b
    }
}

// Desugars to:
box FibonacciGenerator from IteratorBox {
    a: IntegerBox
    b: IntegerBox

    birth() {
        me.a = 0
        me.b = 1
    }

    next() {
        local current = me.a
        local temp = me.a
        me.a = me.b
        me.b = temp + me.b
        return current
    }
}

22. Tail Call Optimization (Automatic)

Impact: Enable recursive functional programming Difficulty: Hard (MIR-level transformation)

// Automatically detect tail calls and convert to loops

// Example
factorial(n, acc = 1) {
    if n <= 1 {
        return acc
    }
    return factorial(n - 1, n * acc)  // Tail call
}

// Desugars to:
factorial(n, acc = 1) {
    loop(true) {
        if n <= 1 {
            return acc
        }
        local __temp_n = n - 1
        local __temp_acc = n * acc
        n = __temp_n
        acc = __temp_acc
    }
}

🎯 Implementation Priority Recommendation

Week 1-2: Quick wins

  1. List comprehension
  2. String interpolation
  3. Null coalescing assignment
  4. Range operator

Week 3-4: High-value ergonomics

  1. Null-safe operator
  2. Arrow functions
  3. Multiple return values
  4. Default parameters

Week 5-6: Medium-value features

  1. Pattern matching in let
  2. Destructuring
  3. Spread operator
  4. Guard clauses

Week 7+: Advanced features

  1. Partial application
  2. Enhanced pipeline
  3. Generator functions (if needed)
  4. Tail call optimization (LLVM backend only)

📈 Expected Outcomes

Code reduction: 60-70% in typical cases Ergonomics: Python-level comfort with Rust-level power Learning curve: Gentle (all sugar desugars to familiar Box operations) Migration path: All existing code continues to work


Validation Criteria

Each sugar syntax must:

  1. Desugar to existing MIR 16-instruction set
  2. Follow "Everything is Box" principle
  3. Have clear error messages
  4. Be documented with examples
  5. Have comprehensive tests
  6. Not introduce runtime overhead (except where semantically required)

Next: See macro-system-proposals.md for compile-time code generation proposals.