soma.cell

Tiny template renderer — substitute [[key]] placeholders

Fills each [[key]] in a template with its value. Keys and values are passed as two parallel lists (a Map *parameter* can't be key-iterated like a memory slot, so explicit lists are the portable idiom). We use square brackets because Soma string interpolation owns {curly} braces. Run: soma run template.cell --signal greet "Bob" "Paris"

A Soma program from the text part of the verified corpus: 43 lines, cells Template, TemplateTest. It passes soma check with soma 3.2.4.

How it is built

The cell Template declares 2 signals in its face: fill(tmpl: String, names: List<String>, vals: List<String>) -> String and greet(name: String, place: String) -> String. Handlers: fill (line 18) and greet (line 27).

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

Generated from soma describe on this file.

The source

template.cell

// ============================================================================
// Tiny template renderer — substitute [[key]] placeholders
// ============================================================================
//
// Fills each [[key]] in a template with its value. Keys and values are passed
// as two parallel lists (a Map *parameter* can't be key-iterated like a memory
// slot, so explicit lists are the portable idiom). We use square brackets
// because Soma string interpolation owns {curly} braces.
//
// Run: soma run template.cell --signal greet "Bob" "Paris"

cell Template {
    face {
        signal fill(tmpl: String, names: List<String>, vals: List<String>) -> String
        signal greet(name: String, place: String) -> String
    }

    on fill(tmpl: String, names: List<String>, vals: List<String>) {
        let out = tmpl
        for i in range(0, len(names)) {
            let placeholder = "[[" + names[i] + "]]"
            out = replace(out, placeholder, vals[i])
        }
        return out
    }

    on greet(name: String, place: String) {
        return fill("Hello [[name]], welcome to [[place]]!",
                    list("name", "place"),
                    list(name, place))
    }
}

cell test TemplateTest {
    rules {
        assert fill("Hi [[name]]", list("name"), list("Alice")) == "Hi Alice"
        assert fill("[[a]]+[[b]]=[[c]]", list("a","b","c"), list("1","2","3")) == "1+2=3"
        assert greet("Bob", "Paris") == "Hello Bob, welcome to Paris!"
        assert fill("no placeholders", list("x"), list("9")) == "no placeholders"
        assert fill("[[x]] [[x]]", list("x"), list("hi")) == "hi hi"
    }
}

What the toolchain says

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

$ soma check template.cell
✓ All checks passed.
$ soma test template.cell
test TemplateTest ...
  ✓ assert fill("Hi [[name]]", list("name"), list("Alice")) == "Hi Alice"
  ✓ assert fill("[[a]]+[[b]]=[[c]]", list("a","b","c"), list("1","2","3")) == "1+2=3"
  ✓ assert greet("Bob", "Paris") == "Hello Bob, welcome to Paris!"
  ✓ assert fill("no placeholders", list("x"), list("9")) == "no placeholders"
  ✓ assert fill("[[x]] [[x]]", list("x"), list("hi")) == "hi hi"

5 tests: 5 passed, 0 failed
$ soma verify template.cell
Verifying template.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

len, list, range, replace

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