about summary refs log tree commit diff stats
path: root/modal/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'modal/README.md')
-rw-r--r--modal/README.md112
1 files changed, 112 insertions, 0 deletions
diff --git a/modal/README.md b/modal/README.md
new file mode 100644
index 0000000..954a904
--- /dev/null
+++ b/modal/README.md
@@ -0,0 +1,112 @@
+## Modal: a tree rewriting system
+
+This repository contains a small implementation of Modal, a homoiconic tree‑rewriting language. Modal programs are collections of rewrite rules applied to a tree until no rule matches. See the original description for background and examples: [Modal in a Postcard](https://wiki.xxiivv.com/site/modal).
+
+### Core concepts
+
+- **Program**: an ordered list of rules. Rule order matters; the first matching rule is applied.
+- **Tree**: symbolic S‑expressions (atoms and lists), serialized with parentheses.
+- **Rule**: `<> left right`, where `left` and `right` are trees. Matching is structural.
+- **Registers**: variables in patterns prefixed with `?` (e.g., `?x`). They bind to subtrees during a match and are substituted on the right side.
+- **Evaluation**: scan the serialized tree left‑to‑right; at each node, try rules top‑to‑bottom; on first match, replace the matched subtree with the rule’s right side (with current bindings) and restart scanning from the beginning. Halt when a full scan finds no match.
+
+### Syntax quick reference
+
+- Atom: `word` or a quoted symbol like `(0)` used in number encoding.
+- Tree: `(head tail...)` or nested pairs to encode lists, e.g., `(a (b (c ())))`.
+- Rule: `<> (a bat) (a black cat)`.
+- Register: `?name` in the left or right side; repeated occurrences must match the same subtree.
+
+### Minimal operational semantics
+
+1. Parsing: read tokens into an AST of `Atom(value)` or `List([nodes...])`.
+2. Matching: `match(pattern, tree, env)`
+   - If `pattern` is a register `?r` and `?r` unbound: bind `env[r] = tree`.
+   - If `pattern` is a register `?r` and bound: require structural equality with `env[r]`.
+   - If both atoms: require exact equality.
+   - If both lists: same arity; match element‑wise recursively.
+   - Otherwise: fail.
+3. Rewriting: substitute registers in the right‑hand side using `env`, producing a new subtree.
+4. Driver loop:
+   - Linearize the AST positions in left‑to‑right preorder over the serialized form.
+   - For each position, try rules in order; on first success, perform rewrite and restart from the beginning.
+   - If no rewrite happened in a full pass, halt.
+
+### Numbers and common encodings
+
+- Natural numbers: unary parentheses around `0`:
+  - `0` = 0, `(0)` = 1, `((0))` = 2, `(((0)))` = 3, ...
+- Lists: nested pairs ending with `()` (nil): `(a (b (c ())))`.
+
+### Examples
+
+Rules:
+
+```modal
+<> (copy ?a) (?a ?a)
+<> (swap ?x ?y) (?y ?x)
+```
+
+Input and result:
+
+```modal
+(copy cat) (swap bat rat)
+(cat cat) (swap bat rat)
+(cat cat) (rat bat)
+```
+
+Conditionals via boolean tables and a ternary (see reference):
+
+```modal
+<> (ife #t ?t ?f) ?t
+<> (ife #f ?t ?f) ?f
+```
+
+Unary subtraction:
+
+```modal
+<> ((?a) - (?b)) (?a - ?b)
+<> (?a - 0) (difference ?a)
+```
+
+### Side effects and IO
+
+The language core is pure rewriting. Implementations may expose host effects via special registers. The reference uses `?:` to emit symbols to the console (e.g., `(print (sum ?:))`). Treat such registers as implementation‑defined hooks that consume or produce host effects during rewriting. Keep them minimal and explicit.
+
+### Implementation guide (porting to another language)
+
+- Data model:
+  - AST types: `Atom`, `List`.
+  - Rule: `{ left: Node, right: Node }`.
+  - Environment: map from register name to bound `Node`.
+- Parser:
+  - Tokenize `(` `)` and atoms; build AST; preserve atom spelling verbatim.
+  - Identify registers by leading `?` at parse or match time.
+- Matcher:
+  - Structural recursion with immutable `env`; fail fast on arity/shape mismatch.
+  - Registers are single‑assignment within a match; repeated occurrences unify.
+- Rewriter:
+  - Deep substitute registers in `right` using `env`; do not capture or mutate `env` across matches.
+- Evaluator:
+  - Left‑to‑right scan order over the current tree; rule priority is program order.
+  - On rewrite, replace exactly the matched subtree, then restart scanning from the root.
+  - Terminate when a full scan applies zero rewrites.
+- IO hooks (optional):
+  - Dispatch atoms/registers like `?:` to host functions with explicit semantics.
+  - Keep IO operations deterministic relative to rewrite steps.
+
+### Determinism and termination
+
+- Determinism depends on rule order; different orders may yield different results.
+- Termination is not guaranteed; design rules with explicit base cases.
+
+### Repository layout
+
+- `modal.c`: reference implementation (C).
+- `logic.modal`: sample rules/programs.
+
+### Further reading
+
+- Original write‑up and worked examples: [Modal in a Postcard](https://wiki.xxiivv.com/site/modal).
+
+