# Where this is Milestone 2 of the build sequence in `plan.org`: *run `calc-me.flan` on the interpreter*. Two of four stages exist. ``` reader ✅ → parse ✅ → check ⬜ → interpret ⬜ ``` | File | What it does | |---|---| | `lib/loc.ml` | source locations + `Loc.Error`, the frontend's one exception | | `lib/form.ml` | reader output: `Sym Kw Int Float Str Byte List Vec Map` | | `lib/reader.ml` | hand-written S-expression reader, no menhir/ocamllex | | `lib/ast.ml` | AST: `texpr`, `expr`, `place`, `pattern`, `decl` | | `lib/parse.ml` | forms → AST; special forms, desugaring, declarations | | `bin/main.ml` | `flan read ` and `flan parse ` | | `test/test_flan.ml` | 110+ assertions; `calc-me.flan` and `sand.flan` are deps | `dune build && dune test` is green. `flan parse calc-me.flan` and `flan parse sand.flan` both succeed. ## Next: `lib/types.ml` and the checker 1. **Type representation.** Resolve `Ast.texpr` into a real type. Needs the declared-type environment `Parse.declared_types` already computes — that pre-pass exists and should be reused rather than rebuilt. 2. **Top-level environment.** Two passes, because top-level names are order-independent (`plan.org`, Modules): collect all signatures, then check bodies. 3. **Check `calc-me.flan`.** It needs: `i32`/`u8`/`f64`/`bool`, structs, `[u8]` slices, `(Ptr T)` with one level of auto-deref on `.field`, `(Option T)` with `Some`/`None`, `Unwrap (Usome, _)` as early-return-None, `while`, `return`, `set` on the five places, `match` on `Option`, and the milestone-2 primitive list in `plan.org`. 4. **Then the interpreter** over the typed IR. ## Watch for The two bugs found so far were both *silent misparses* — code that read fine and meant something else: - `'skip-form` became a symbol named `'skip-form` - `dotimes`/`defer`/`some` fell through to `Call`, discarding their binding and control-flow meaning - `(Some 1)` in first body position was eaten as a return type The rule that catches this class: **anything that binds a name, alters control flow, or is not yet implemented must be recognised explicitly and rejected if unsupported — never allowed to fall through to a generic case.** `parse.ml` rejects `handler-bind`, `restart-case`, `loop`/`recur`, `defmacro`, `signal`, `with-allocator`, `errdefer` and `await` for exactly this reason. Keep doing that in the checker. ## Open decisions that touch the checker None block milestone 2. `plan.org` tags each open decision with the milestone it is due by; #1 (host language) is now settled as OCaml. ## Untracked on purpose `old-ocaml/` — the pre-rewrite menhir/ocamllex frontend, kept as reference and excluded from the build by the root `dune` file. Its contents are also in git history at `2c232dd`.