about summary refs log tree commit diff stats
path: root/modal/ocaml/_build/default/README.md
blob: c508a8505143b58515833c678401b3098a47eb81 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
## OCaml Modal Interpreter

A minimal, AST-based Modal interpreter. See the language overview in the project root `README.md` and reference `ocaml/REF.txt`. Original docs: [Modal in a Postcard](https://wiki.xxiivv.com/site/modal).

### Build

```
opam switch create . ocaml-base-compiler.5.2.1 --no-install && opam install . --deps-only -y && dune build @install
```

### Run

Pass a rules file and an optional input expression:

```
dune exec modal -- examples/logic.modal "(eq fox bat) (eq bat bat)"
```

Or rely on input lines inside the file (lines starting with `..`):

```
dune exec modal -- examples/devices.modal
```

Flags:
- `-q`: quiet (suppress device prints; still prints final tree)
- `-a`: allow file/stdin devices (`(?_)`, `(?~)`)
- `-n`: large cycle cap (effectively “no limit”)

### Implementation highlights

- AST rewrite engine with left-to-right preorder scan; rule order is significant.
- Dynamic rules during evaluation using explicit list forms:
  - Define: `(<>) (left) (right)`
  - Undefine: `(><) (left) (right)`
- Registers: `?name` unify on the left and substitute on the right.
- Devices (side-effect hooks):
  - `(?: ...)` print or ALU: `(?: + 1 2 3)` → `6`; otherwise concatenates arguments to stdout, returns `()`.
  - `(?_) path` import file (requires `-a`); returns parsed AST if possible else an atom.
  - `(?~)` read stdin (requires `-a`); returns atom of contents or `EOF`.
  - `(?^) x` join atoms from `x` into a single atom.
  - `(?.) x` unwrap list `x` into its elements.
  - `(?*) x` explode atom `x` into list of character atoms; lists pass through unchanged.
- Cycle cap and flags implemented in the evaluator.

Notes on semantics vs C version:
- This interpreter uses an AST scan rather than a raw token stream. Most programs work as expected; exact stream-boundary edge cases may differ.
- Lambda `?(...)` is not implemented yet; easy to add if needed.

### Examples

```
# Devices (printing, ALU, join/unwrap/explode)
dune exec modal -- examples/devices.modal

# Dynamic rules (define/undefine during evaluation)
dune exec modal -- -q examples/dynamic_rules.modal

# Arithmetic (via ?:)
dune exec modal -- examples/arith.modal
```