Padding & alignment — left/right pad to a fixed width
Builds padding by appending a fill character until the target width is met. Used to right-align numbers and left-align labels into fixed columns. Demonstrates while-loop string growth and truncation via substring. Run: soma run pad_align.cell --signal pad_left "42" 5
A Soma program from the text part of the verified corpus: 52 lines, cells PadAlign, PadAlignTest. It passes soma check with soma 3.2.4.
How it is built
The cell PadAlign declares 3 signals in its face: pad_left(s: String, width: Int) -> String, pad_right(s: String, width: Int) -> String and zero_pad(n: Int, width: Int) -> String. Handlers: pad_left (line 18), pad_right (line 26) and zero_pad (line 34).
The file also holds 1 test cell (PadAlignTest) with 5 assertions, run by soma test.
The source
pad_align.cell
// ============================================================================
// Padding & alignment — left/right pad to a fixed width
// ============================================================================
//
// Builds padding by appending a fill character until the target width is met.
// Used to right-align numbers and left-align labels into fixed columns.
// Demonstrates while-loop string growth and truncation via substring.
//
// Run: soma run pad_align.cell --signal pad_left "42" 5
cell PadAlign {
face {
signal pad_left(s: String, width: Int) -> String
signal pad_right(s: String, width: Int) -> String
signal zero_pad(n: Int, width: Int) -> String
}
on pad_left(s: String, width: Int) {
let out = s
while len(out) < width {
out = " " + out
}
return out
}
on pad_right(s: String, width: Int) {
let out = s
while len(out) < width {
out = out + " "
}
return out
}
on zero_pad(n: Int, width: Int) {
let out = to_string(n)
while len(out) < width {
out = "0" + out
}
return out
}
}
cell test PadAlignTest {
rules {
assert pad_left("42", 5) == " 42"
assert pad_right("ab", 4) == "ab "
assert zero_pad(7, 3) == "007"
assert zero_pad(123, 2) == "123"
assert len(pad_left("x", 10)) == 10
}
}What the toolchain says
$ soma check pad_align.cell
warning: `out` grows by concatenation inside a loop — each step copies the whole value, so the loop is quadratic (8 MB took 32 s, a list + join() 30 ms): push the pieces to a List and `join(parts, "")` once
--> pad_align.cell:21:13
|
21 | out = " " + out
| ^
warning: `out` grows by concatenation inside a loop — each step copies the whole value, so the loop is quadratic (8 MB took 32 s, a list + join() 30 ms): push the pieces to a List and `join(parts, "")` once
--> pad_align.cell:29:13
|
29 | out = out + " "
| ^
warning: `out` grows by concatenation inside a loop — each step copies the whole value, so the loop is quadratic (8 MB took 32 s, a list + join() 30 ms): push the pieces to a List and `join(parts, "")` once
--> pad_align.cell:37:13
|
37 | out = "0" + out
| ^
✓ 3 warning(s), no errors.$ soma test pad_align.cell
test PadAlignTest ...
✓ assert pad_left("42", 5) == " 42"
✓ assert pad_right("ab", 4) == "ab "
✓ assert zero_pad(7, 3) == "007"
✓ assert zero_pad(123, 2) == "123"
✓ assert len(pad_left("x", 10)) == 10
5 tests: 5 passed, 0 failed$ soma verify pad_align.cell
Verifying pad_align.cell...
PadAlign/termination:
⚠ handler `pad_left`: while-loop without provable termination bound (write `while [loop_bound(N)] cond { … }`, or a for-loop over a bounded range)
⚠ handler `pad_right`: while-loop without provable termination bound (write `while [loop_bound(N)] cond { … }`, or a for-loop over a bounded range)
⚠ handler `zero_pad`: while-loop without provable termination bound (write `while [loop_bound(N)] cond { … }`, or a for-loop over a bounded range)
0 passed, 3 warnings, 0 failures
Temporal: 0 passed, 0 failed
VERIFY OK