soma.cell

E0120: frame

E0120 frame — a skeleton's frame that names something the skeleton does not have, or a flesh that does something its signal's frame does not grant (a write, a read, a call, an emit or a machine edge).

A compile-time error of soma check, the checker of the Soma programming language (soma explain E0120).

The rule

In a skeleton, each signal's frame says what its body may do: reads, writes, moves s -> t, calls, emits; a signal with no clause is a pure function of its parameters. soma check reports E0120 when a flesh body does something its frame does not grant (here pay writes log while only ship may), or when a frame names a slot, an edge or a signal the skeleton does not have. Fix the body when it oversteps the design; change the skeleton only when the design itself is wrong (and run soma skeleton app.cell --amend if it is frozen).

A program that triggers it

wrong.cell

skeleton Orders {
    memory {
        log: Map<String, String> [persistent]
    }
    state flow {
        initial: placed
        placed -> paid
        paid -> shipped
    }
    face {
        signal pay(id: String) -> String     moves placed -> paid
        signal ship(id: String) -> String    moves paid -> shipped   writes log
    }
}

flesh Orders {
    on pay(id) {
        transition(id, "placed", "paid")
        log.set(id, "paid")
        return "paid"
    }
    on ship(id) {
        transition(id, "paid", "shipped")
        log.set(id, "shipped")
        return "shipped"
    }
}

What soma check prints:

$ soma check wrong.cell
error: `Orders.pay` writes `log`, outside its frame (no `writes`) — if the design means it, add it to `signal pay` in `skeleton Orders`: `writes log`
  --> wrong.cell:17:5
   |
17 |     on pay(id) {
   |     ^
  = code: E0120
✗ 1 error(s), 0 warning(s).

The fix field of soma check --json: if the design means it, add it to `signal pay` in `skeleton Orders`: `writes log`

Line 19 is removed.

wrong.cell → right.cell

--- wrong.cell
+++ right.cell
@@ -17,5 +17,4 @@
     on pay(id) {
         transition(id, "placed", "paid")
-        log.set(id, "paid")
         return "paid"
     }

With the fix, soma check accepts the program:

$ soma check right.cell
✓ All checks passed.