soma.cell

Number to words — spell out integers 0..999

Composes English number words from ones/teens/tens tables. Demonstrates list-literal lookup tables indexed by digit, integer division with floor, and string assembly with trim to drop stray spaces. Run: soma run number_to_words.cell --signal spell 342

A Soma program from the text part of the verified corpus: 66 lines, cells NumberToWords, NumberToWordsTest. It passes soma check with soma 3.2.4.

How it is built

The cell NumberToWords declares 1 signal in its face: spell(n: Int) -> String. Handlers: spell (line 41). Private helpers: _ones, _teens, _tens and _two_digits.

The file also holds 1 test cell (NumberToWordsTest) with 8 assertions, run by soma test.

Generated from soma describe on this file.

The source

number_to_words.cell

// ============================================================================
// Number to words — spell out integers 0..999
// ============================================================================
//
// Composes English number words from ones/teens/tens tables. Demonstrates
// list-literal lookup tables indexed by digit, integer division with floor,
// and string assembly with trim to drop stray spaces.
//
// Run: soma run number_to_words.cell --signal spell 342

cell NumberToWords {
    face {
        signal spell(n: Int) -> String
    }

    on _ones(d: Int) {
        let t = list("zero","one","two","three","four","five","six","seven","eight","nine")
        return t[d]
    }

    on _teens(d: Int) {
        let t = list("ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen")
        return t[d]
    }

    on _tens(d: Int) {
        let t = list("","","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety")
        return t[d]
    }

    // Spell 0..99
    on _two_digits(n: Int) {
        if n < 10 { return _ones(n) }
        if n < 20 { return _teens(n - 10) }
        let tens = floor(n / 10)
        let ones = n % 10
        if ones == 0 { return _tens(tens) }
        return _tens(tens) + "-" + _ones(ones)
    }

    on spell(n: Int) {
        if n == 0 { return "zero" }
        if n < 100 { return _two_digits(n) }
        let hundreds = floor(n / 100)
        let rest = n % 100
        let out = _ones(hundreds) + " hundred"
        if rest > 0 {
            out = out + " " + _two_digits(rest)
        }
        return out
    }
}

cell test NumberToWordsTest {
    rules {
        assert spell(0) == "zero"
        assert spell(7) == "seven"
        assert spell(13) == "thirteen"
        assert spell(20) == "twenty"
        assert spell(42) == "forty-two"
        assert spell(100) == "one hundred"
        assert spell(342) == "three hundred forty-two"
        assert spell(905) == "nine hundred five"
    }
}

What the toolchain says

Run on a fresh copy of the program at build time; the outputs are pasted unedited.

$ soma check number_to_words.cell
✓ All checks passed.
$ soma test number_to_words.cell
test NumberToWordsTest ...
  ✓ assert spell(0) == "zero"
  ✓ assert spell(7) == "seven"
  ✓ assert spell(13) == "thirteen"
  ✓ assert spell(20) == "twenty"
  ✓ assert spell(42) == "forty-two"
  ✓ assert spell(100) == "one hundred"
  ✓ assert spell(342) == "three hundred forty-two"
  ✓ assert spell(905) == "nine hundred five"

8 tests: 8 passed, 0 failed
$ soma verify number_to_words.cell
Verifying number_to_words.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)

Builtins used

floor, list

Source file: /corpus/text/number_to_words.cell · examples/corpus/text/number_to_words.cell