Przeglądaj źródła

docs: refresh readme, tutorial and feature comparison

Eric Streit 3 dni temu
rodzic
commit
5f39b2f3a5
7 zmienionych plików z 314 dodań i 80 usunięć
  1. 39 4
      README.md
  2. 162 0
      TUTORIAL.md
  3. 4 2
      docs/INDEX.md
  4. 23 11
      docs/comparison-PIM4-gm2-V3.md
  5. 9 6
      docs/features.md
  6. 10 13
      docs/git-branches-tags.md
  7. 67 44
      m2make.md

+ 39 - 4
README.md

@@ -31,22 +31,57 @@ every error also prints as `file:line:col: message` on stdout.
 `M2` itself exits **0** on success, **1** on compile errors and **2** on
 usage/IO problems (no input, unopenable file) — no aborts.
 
+## Tutorials
+
+- **`TUTORIAL.md`** — a short hands-on tour: build the compiler, compile a
+  one-shot program, split it into library/program objects, and select a
+  dialect library folder.
+- **`m2make.md`** / `tools/m2make/README.md` — the build-order tool and
+  its `--separate` mode.
+- **`docs/separate-compilation.md`** — object model, stable symbols, init
+  order and current limits.
+
+## Quick compile
+
+One-shot (all units in one image):
+
+```sh
+cd compiler
+./M2 tests/hello.mod          # writes gen_ssa/Hello.ssa
+qbe -o gen_ssa/Hello.s gen_ssa/Hello.ssa
+cc gen_ssa/Hello.s ../runtime/syslib/shim.c -o /tmp/hello -lm
+/tmp/hello
+```
+
+Separate objects (library + program; interfaces only at compile time):
+
+```sh
+# after building M2make (see TUTORIAL.md)
+tools/m2make/b_v3/M2make --separate --dialect iso \
+       --m2bin ./compiler/M2 --shim runtime/syslib/shim.c \
+       -o /tmp/hello compiler/tests/hello.mod
+/tmp/hello
+```
+
+`M2 -c` emits one unit's QBE IR; `M2make --separate` is the transitive
+`.def` resolver and object linker.  The one-shot mode remains the default
+for the test suite and corpus.
+
 ## Layout (Blaise-adapted)
 
 ```text
 compiler/src/      M2.atg, frames, FileIO, SymTab, QbeGen, Lower (+ generated)
 compiler/tests/    t_*.mod (check/reject/run) + showcase<N>.mod tours
 compiler/gen_ssa/  build outputs (gitignored)
-runtime/syslib/    always-linked runtime (SYSTEM, Storage, SysIO, …)
+runtime/syslib/    shared runtime (SysShim, FileIO, SysIO, …)
 lib/{pim,iso,common,gm2}/ opt-in dialect libraries
-runtime/syslib/    shared runtime (SysShim, FileIO, …)
 tools/             syntax helpers + v3-corpus (coverage harness)
 bootstrap/         stage1/2/3 + fixpoint.sh (self-hosting proof)
 vendor/            qbe toolchain pin
 docs/              STATUS.md, plan.md, plan-*.md, analysis_*.md, summary_*.md
 ```
 
-## Status (2026-10-23)
+## Status (2026-10-24)
 
 - Suite **303/303**; self-hosting **fixpoint OK** (byte-identical
   stage2/stage3, 3,717,887 bytes); corpus **519/612 compile-OK,
@@ -61,7 +96,7 @@ docs/              STATUS.md, plan.md, plan-*.md, analysis_*.md, summary_*.md
   records/chained fields, and multi-dimensional fixed/open arrays
   (M1–M4): flat payloads + per-level views, open-array calls, and
   payload `SIZE`/view `ADR`, flat multi-dimensional record fields and
-  constructors, pointer-based 1-D open views, an `LFLOAT` builtin, and
+  constructors, pointer-based 1-D open views, an `LFLOAT` builtin,
   dialect library folders (`lib/pim`, `lib/iso`, `lib/common`,
   `lib/gm2`), and **separate compilation** (`M2 -c` objects,
   `M2make --separate`).

+ 162 - 0
TUTORIAL.md

@@ -0,0 +1,162 @@
+# V3 tutorial — build and run Modula-2
+
+This is a short hands-on tour.  It assumes a Linux shell, `gcc`/`gm2`,
+Coco/R `CR`, and `qbe` as described in `README.md`.
+
+## 1. Build the compiler
+
+From the repository root:
+
+```sh
+cd compiler
+./build.sh          # M2.atg -> scanner/parser/driver -> ./M2
+./run_tests.sh      # 303/303
+```
+
+`M2` reads Modula-2 sources and writes QBE IR to `gen_ssa/`.
+
+## 2. Hello, world (one-shot)
+
+The one-shot mode compiles every unit named on the command line into one
+image.  The program module comes last.
+
+```sh
+cd compiler
+./M2 tests/hello.mod                 # -> gen_ssa/Hello.ssa
+qbe -o gen_ssa/Hello.s gen_ssa/Hello.ssa
+cc gen_ssa/Hello.s ../runtime/syslib/shim.c -o /tmp/hello -lm
+/tmp/hello
+```
+
+Expected output:
+
+```text
+Hello, Modula-2!
+```
+
+A global `VAR ExitCode : INTEGER` becomes the process exit code; without
+one, the program returns 0.
+
+## 3. A library and a program (one-shot)
+
+A definition/implementation pair plus a program can still be compiled in
+one invocation:
+
+```sh
+./M2 tests/sep_lib.def tests/sep_lib.mod tests/sep_prog.mod
+qbe -o gen_ssa/SepProg.s gen_ssa/SepProg.ssa
+cc gen_ssa/SepProg.s ../runtime/syslib/shim.c -o /tmp/sep -lm
+/tmp/sep
+```
+
+This produces one image and is the mode used by the test suite and the
+corpus harness.
+
+## 4. Separate compilation
+
+Separate compilation reads only the imported `.def` files when compiling a
+unit.  The library object and the program object are linked with `cc`; a
+`.def` is never passed to the linker.
+
+### Direct `M2 -c`
+
+From `compiler/`:
+
+```sh
+# Library: Lib.def is found beside Lib.mod automatically.
+./M2 -c tests/sep_lib.mod
+
+# Program: pass the imported interface explicitly.
+./M2 -c tests/sep_lib.def tests/sep_prog.mod
+
+qbe -o gen_ssa/SepLib.s   gen_ssa/SepLib.ssa
+qbe -o gen_ssa/SepProg.s  gen_ssa/SepProg.ssa
+cc -c gen_ssa/SepLib.s  -o gen_ssa/SepLib.o
+cc -c gen_ssa/SepProg.s -o gen_ssa/SepProg.o
+cc gen_ssa/SepProg.o gen_ssa/SepLib.o ../runtime/syslib/shim.c \
+   -o /tmp/sep -lm
+/tmp/sep
+```
+
+`M2 -c` requires imported interfaces on the command line.  The target’s own
+`.def` is found automatically.
+
+### `M2make --separate`
+
+`M2make` is the convenient transitive-interface resolver.  Build it once:
+
+```sh
+cd tools/m2make
+./build_m2.sh
+cd ../..
+```
+
+Then, from the repository root:
+
+```sh
+tools/m2make/b_v3/M2make --separate --dialect iso \
+    --m2bin ./compiler/M2 \
+    --shim runtime/syslib/shim.c \
+    -o /tmp/hello compiler/tests/hello.mod
+/tmp/hello
+```
+
+`M2make` scans imports transitively, passes the ordered `.def` files to each
+`M2 -c`, writes `gen_ssa/<Module>.o`, and links.  The one-shot default is
+still:
+
+```sh
+M2make -o /tmp/sep compiler/tests/sep_prog.mod
+```
+
+### What the object model guarantees
+
+- Library objects have **no `main`**.
+- The program object has the only `main`.
+- Every object exports `<Module>_init`; the program calls imported inits in
+  dependency order, then its own init.
+- Exported globals are `export data`; module procedures use
+  `<Module>__<name>`; vtables use `<Module>__<Class>__vt`.
+
+## 5. Dialect library folders
+
+Libraries are split by dialect:
+
+```text
+lib/pim/     classic PIM modules (InOut, RealInOut, …)
+lib/iso/     ISO 10514-1 modules (TextIO, IOChan, Files, …)
+lib/common/  shared Strings, Math, Storage, SysIO, CharClass
+lib/gm2/     optional gm2 compatibility modules
+runtime/syslib/  shared runtime/shim
+```
+
+Select one dialect per session:
+
+```sh
+M2make --dialect iso ... main.mod
+```
+
+or add the folders explicitly with `-I lib/iso -I lib/common -I
+runtime/syslib`.  Do not mix `lib/pim` and `lib/iso` in one session.
+
+## 6. Useful checks
+
+```sh
+cd compiler && ./run_tests.sh
+cd .. && TMP="$PWD/.scratch/fixpoint" ./bootstrap/fixpoint.sh
+tools/v3-corpus/corpus.sh
+```
+
+Current gates: suite **303/303**, fixpoint **OK (3,717,887 bytes)**,
+corpus **519/612 compile-OK, 0 crashes**.
+
+## 7. Current limits
+
+- `M2 -c` does not scan `-I` paths itself; use `M2make --separate`.
+- `M2make --separate` rebuilds all objects; there is no incremental object
+  or ABI-version cache.
+- Generic instance objects are not emitted separately yet.
+- The fixpoint gate still compares the one-shot compiler image.
+
+For details, see `docs/separate-compilation.md` and
+`docs/plan-separate-compilation.md`.

+ 4 - 2
docs/INDEX.md

@@ -6,6 +6,8 @@ bisecting *why* a decision was made, not for reading end-to-end).
 
 ## Start here
 
+- **[`TUTORIAL.md`](../TUTORIAL.md)** — hands-on build/run + separate-object
+  tutorial.
 - **`handoff-2026-10-23-next.md`** — current next-session plan
   (PACKEDSET done; exceptions, multi-dim open arrays; gates).
 - **`handoff-2026-10-22-next.md`** — previous stop-point plan (range
@@ -22,8 +24,8 @@ bisecting *why* a decision was made, not for reading end-to-end).
 - **`plan.md`** — the phased plan (Blaise-adapted).
 - **`features.md`** — the feature list.
 - **`comparison-PIM4-gm2-V3.md`** — PIM4 / GNU Modula-2 / **M2R10** /
-  **TopSpeed V3** / V3 feature comparison (2026-10-23; V3 at
-  `v3-open-arrays`; filename kept for link stability).
+  **TopSpeed V3** / V3 feature comparison (2026-10-24; V3 at
+  `v3-separate-compilation`; filename kept for link stability).
 - **`triage-corpus-2026-10-24.md`** — final corpus triage after open
   arrays: policy vs dialect vs implementation vs genuine gaps; `LFLOAT`.
 - **`analysis_gaps.md`** — language gaps + corpus notes.

+ 23 - 11
docs/comparison-PIM4-gm2-V3.md

@@ -1,8 +1,8 @@
 # PIM4 vs GNU Modula-2 vs M2R10 vs TopSpeed V3 vs V3 — feature comparison
 
-**Date:** 2026-10-24 · **V3 state:** open-array milestone + triage
-follow-up (suite 301/301, self-hosting fixpoint OK 3,573,487 bytes,
-corpus 519/612, 0 crashes).
+**Date:** 2026-10-24 · **V3 state:** open arrays, dialect library
+folders and core separate compilation (suite 303/303, self-hosting
+fixpoint OK 3,717,887 bytes, corpus 519/612, 0 crashes).
 
 **Scope and sources.**
 
@@ -115,12 +115,14 @@ change individual cells.
 |---|---|---|---|---|---|
 | Definition / implementation / program modules | ✅ | ✅ | ✅ (+ blueprints) | ✅ | ✅ |
 | Local modules | ✅ | ✅ | ❌ removed | ✅ | ✅ |
-| Separate compilation | ✅ | ✅ (object files/archives) | ✅ compilation units | ✅ | 🔄 one invocation compiles all units into one image |
+| Separate compilation | ✅ | ✅ (object files/archives) | ✅ compilation units | ✅ | ✅ core: `M2 -c` per-unit objects + `M2make --separate`; one-shot remains default |
+| Stable cross-object symbols / init order | n/a | ✅ | ✅ | ✅ | ✅ `<Module>__proc`, module-qualified pools/vtables, dependency-ordered `<Module>_init` |
+| Incremental object rebuild / ABI marker | n/a | ✅ | ✅ | ✅ | 🔄 `--separate` rebuilds all objects; no ABI version marker yet |
 | Generics | ❌ | ✅ ISO 10514-2 | ❌ external templates (`GENLIB`/`BLUEPRINT`) | ❌ | ✅ ISO 10514-2 refinement |
 | Object orientation | ❌ | ❌ | ❌ (extensible records only) | ✅ Clarion-form `CLASS`, `VIRTUAL`, inheritance | 🔄 Clarion-form `CLASS` (single inheritance, virtual dispatch), not ISO 10514-3 |
 | PIM coroutines (`PROCESS`, `NEWPROCESS`, `TRANSFER`, `IOTRANSFER`) | ✅ | ✅ | 🔄 `COROUTINE` type/`YIELD` (R10 phase II) | ✅ PIM-style | ✅ (`IOTRANSFER` degrades to a transfer) |
 | ISO `COROUTINES` module | ❌ | ✅ | ❌ | ❌ | ❌ (PIM interface only) |
-| Standard library | ❌ (none defined) | ✅ PIM + ISO libraries | ✅ redesigned R10 library | ✅ TopSpeed libraries (historical) | 🔄 subset: ISO/PIM I/O, strings, storage, SysClock, EXCEPTIONS; no termination/coroutine libs |
+| Standard library | ❌ (none defined) | ✅ PIM + ISO libraries | ✅ redesigned R10 library | ✅ TopSpeed libraries (historical) | 🔄 subset in `lib/pim`, `lib/iso`, `lib/common`, `lib/gm2`: ISO/PIM I/O, strings, storage, SysClock, EXCEPTIONS; no termination/coroutine libs |
 | Self-hosting | n/a | ✅ (part of GCC) | n/a (reference compiler under development) | n/a (historical commercial compiler) | ✅ (byte-identical 3-stage fixpoint) |
 | Backend / target | n/a | GCC (many targets) | reference compiler | x86/DOS/Windows (historical) | QBE → C (amd64 SysV today) |
 
@@ -161,7 +163,10 @@ change individual cells.
   (`SHORTREAL`, `REAL` width), plus a **65536-bit `SET` span limit**
   and a **32-bit `PACKEDSET` limit**.  Self-referential pointer records
   and chained pointer-field designators (`p^.next^.value`) are
-  supported.
+  supported.  **Separate compilation** is now available for normal
+  modules: `M2 -c` emits one object per unit, library objects have no
+  `main`, and `M2make --separate` links the objects; the one-shot mode
+  remains the default for tests and self-hosting.
 
 ## V3-specific deviations and limits
 
@@ -190,9 +195,15 @@ change individual cells.
   at ABI boundaries; row/`ARRAY OF BYTE` conversions are copy-based
   there, so row `ADR` identity through an internal 1-D call remains a
   follow-up.
-- **Single-invocation compilation:** definition, implementation and
-  program units are compiled together into one image; there is no
-  incremental object/archive format.
+- **Separate compilation:** `M2 -c` emits a QBE object per unit and
+  `M2make --separate` resolves interfaces and links with `cc`.  Library
+  objects have no `main`; every object exports `<Module>_init` and the
+  program calls imported inits in dependency order.  Stable symbols are
+  `<Module>__proc`, `<Module>_<global>`, module-qualified pools and
+  `<Module>__<Class>__vt`.  The one-shot mode remains the default for
+  the suite/corpus.  Still deferred: an `M2 -I` import scanner,
+  incremental object/ABI checks, separate generic-instance objects and
+  per-object self-hosting.
 - **OO** is the Clarion-form `CLASS` dialect (single inheritance,
   virtual dispatch), not ISO 10514-3.
 
@@ -200,8 +211,9 @@ change individual cells.
 
 - V3: `docs/STATUS.md`, `docs/features.md`, `docs/gaps/README.md`,
   `docs/analysis_gaps.md`,
-  `docs/summary_session-2026-10-23-open-arrays.md`; the gates in this
-  document were run at `v3-open-arrays`.
+  `docs/summary_session-2026-10-24-separate-compilation.md`,
+  `docs/separate-compilation.md`; the gates in this document were run
+  at `v3-separate-compilation`.
 - gm2: the GCC Modula-2 testsuite and `gm2-libs`/`gm2-libs-iso`
   definition modules in the sibling `gcc-git` tree.
 - M2R10: the published R10 grammar (m2r10-grammar.gll) and

+ 9 - 6
docs/features.md

@@ -1,4 +1,4 @@
-# m2compiler-V3 — feature status (2026-10-24; suite 301/301 green)
+# m2compiler-V3 — feature status (2026-10-24; suite 303/303 green)
 
 Pipeline: Coco/R `M2.atg` (1748 lines, 73 productions) → `gm2`-built
 `M2` → QBE `.ssa` → `qbe` → `cc` → run. `SymTab.mod` 1623 lines,
@@ -162,9 +162,11 @@ Legend: ✅ done · 🔄 partial · ⏸ not started / deferred.
   recursion (`FORWARD`), nested procedures with static-link display
   (any depth), array/record/set/pointer params, open-array `VAR`
   formals.
-- ✅ Separate compilation: `lib.def lib.mod prog.mod` → one image;
-  module init functions; opaque completion; strict 235 signature
-  checks between a definition and its implementation.
+- ✅ Separate compilation: one-shot (`lib.def lib.mod prog.mod` → one
+  image) and per-unit objects (`M2 -c` / `M2make --separate`); module
+  init functions, dependency-ordered cross-object init, stable symbols,
+  exported globals; opaque completion; strict 235 signature checks
+  between a definition and its implementation.
 - ✅ Module `FINALLY` (program/implementation/local/class bodies), with
   its own optional `EXCEPT`; finalizers run on normal main return in
   reverse initialization order.  `RETURN` in a module body/finally
@@ -172,8 +174,9 @@ Legend: ✅ done · 🔄 partial · ⏸ not started / deferred.
   finalizers.
 - ✅ Procedure-type variables / indirect calls (`t_proctype`); ✅
   composite function results (record/array/set/class, sret) and chained
-  post-call method calls (`F().M()`); ⏸ per-file object emission, import
-  cycles.
+  post-call method calls (`F().M()`); 🔄 per-file objects exist but
+  incremental/ABI checks and `M2 -I` import scanning are deferred;
+  import cycles are rejected.
 - 🔄 ISO exceptions: **M4** — `EXCEPT`/`RETRY`, handler stack,
   `SYSTEM.THROW`, `EXCEPTIONS`, `M2EXCEPTION`, signal mapping,
   `RETURN`/nested handlers, catchable index/range/CASE traps, and

+ 10 - 13
docs/git-branches-tags.md

@@ -1,9 +1,8 @@
 # Git branches and tags — how this repository is organised
 
-**Snapshot:** 2026-10-24, after core separate compilation.
-`master` = the current docs commit (separate compilation + tag map);
-`origin/master` = `6e40e26`.  M5/M6, triage, library folders and
-separate compilation are local; earlier M1–M4 work is on the remote.
+**Snapshot:** 2026-10-24, after the README/tutorial/comparison refresh.
+`master` = the current docs commit (one local docs commit);
+`origin/master` = `d9a96a4` (separate compilation and its tag map).
 327 tags (325 `v3-*` checkpoints).
 
 Mental model:
@@ -15,7 +14,7 @@ Mental model:
 
 | Branch | State | What it is |
 | --- | --- | --- |
-| **`master`** | current docs commit, 15 commits ahead of origin | The only active branch; all current work is here. |
+| **`master`** | current docs commit, 1 commit ahead of origin | The only active branch; all current work is here. |
 | `ast-stage-c` | `0f611c0` (2026-10-08), local only | Old stage branch, fully merged into master. Stale. |
 | `generics-inc1` | `6639c19`, 6 commits behind `origin/generics-inc1` | Old generics work, fully merged into master. Stale. |
 | `resolve-check` | `95ca4d6`, in sync with origin | Old branch merged into master. Stale. |
@@ -124,14 +123,12 @@ recent ones above matter for the current session.
 
 ## Current state
 
-- `master` = current docs commit (separate compilation + tag map),
-  **15 commits ahead** of `origin/master` (`6e40e26`): M5/M6, LFLOAT,
-  triage, library folders, separate compilation and this tag map.
-- `v3-open-arrays-m5/m6`, `v3-open-arrays`, `v3-lfloat`,
-  `v3-corpus-triage-2026-10-24`, `v3-library-folders`,
-  `v3-separate-compilation` and their summary/session tags are local;
-  push them with `master` when ready.  Tags through M4 are already on
-  the remote.
+- `origin/master` = `d9a96a4` (M5/M6 through the separate-compilation
+  tag map).  Local `master` is **1 commit ahead**: the
+  README/tutorial/comparison docs refresh.
+- The feature/session tags through `v3-session-2026-10-24-separate-end`
+  are available locally; push the docs commit (and any missing tags)
+  when ready.
 - Next session: start from `master` and read
   `docs/handoff-2026-10-23-next.md`; fill separate-compilation gaps
   (`M2 -I` import scanning, incremental objects, generic instances,

+ 67 - 44
m2make.md

@@ -1,60 +1,83 @@
-# Building M2make
+# M2make — build-order tutorial
 
-M2make is a front-end for the M2 Modula-2 compiler or GNU Modula-2 compiler.
-It's goal is to check the order of compilation of the different files of a project, 
-compiling only what is necessary. It only a main file like this :
+`M2make` is a small build front-end for the V3 `M2` compiler and for GNU
+Modula-2.  Given a main source file, it follows `IMPORT`/`FROM` imports,
+topologically sorts the modules, and runs the compiler in the right order.
 
+```sh
+M2make [-n] [-v] [-c m2|gm2] [-I dir] [-o out]
+       [--m2bin path] [--shim path] [--extra path]
+       [--m2flag flag] [--dialect pim|iso|gm2] [--separate] main.mod
 ```
-M2make toto.mod
-```
 
-I will use a topological sort to figure out the order of compiling,
-and which file needs to be compiled (if modified). 
+## Build
+
+The portable source is `tools/m2make/M2make.mod`; the OS bridge is
+`m2make_os.c`.  From the repository root:
+
+```sh
+cd tools/m2make
+./build_m2.sh       # dogfood build with the V3 M2 compiler
+./build_gm2.sh      # optional: build with GNU Modula-2
+```
 
-I needs to compile only what is necessary.
+Both produce a `M2make` binary; the dogfood binary is
+`tools/m2make/b_v3/M2make`.
 
-## Status (implemented in `tools/m2make`, GNU Modula-2)
+## One-shot build (default)
 
-`M2make [-n] [-v] [-c m2|gm2] [-I dir] [-o out] [--m2bin path] [--shim path] main.mod`
+```sh
+tools/m2make/b_v3/M2make \
+    --m2bin ./compiler/M2 \
+    --shim runtime/syslib/shim.c \
+    -o /tmp/prog prog.mod
+```
 
-- Follows `IMPORT`/`FROM` imports transitively from the main file,
-  topologically sorts the modules (iterative DFS, cycle reported),
-  skips the build when the output is newer than every source.
-- `m2` mode: one session (`M2` + `qbe` + `cc`), gated on M2's
-  `Parsed correctly` verdict. `gm2` mode: per-file `gm2 -fiso -c`
-  of stale units + ordered link.
-- One portable core (`M2make.mod` + `M2makeOS.def`, ISO Modula-2
-  importing only `FileIO`/`M2makeOS`) compiles with both `gm2 -fiso`
-  (`build_gm2.sh`) and the V3 `M2` driver (`build_m2.sh`); the
-  OS layer (`stat`/`system`/text input) lives in `m2make_os.c`
-  with per-compiler bindings (`M2makeC.def` for gm2,
-  `EXTERNAL` for M2). See `tools/m2make/README.md` for the exact
-  portable subset and limitations. `tests/run_tests.sh`: 18/18 green
-  with both binaries.
+For V3 this runs one M2 session over all `.def`/`.mod` files, then `qbe`,
+then `cc` with the runtime shim.  It gates on M2’s `Parsed correctly`
+verdict.
 
+## Separate-object build
 
-I will use a topological sort to figure out the order of compiling,
-and which file needs to be compiled (if modified). 
+```sh
+tools/m2make/b_v3/M2make --separate \
+    --m2bin ./compiler/M2 \
+    --shim runtime/syslib/shim.c \
+    --dialect iso \
+    -o /tmp/prog prog.mod
+```
 
-I needs to compile only what is necessary.
+Each module is compiled with `M2 -c` against the ordered interfaces to
+`gen_ssa/<Module>.o`; the program object contains `main`, library objects
+contain only their code plus `<Module>_init`.  All objects are linked with
+`cc` and the shim.  This mode currently rebuilds every object; it does not
+yet do incremental `.def`-timestamp checks.
 
+## Options
 
-<!--It also needs eventually to use a project file with these elements :-->
+- `-n` — dry run: print the build order and command.
+- `-v` — verbose: report external modules and build order.
+- `-c m2|gm2` — compiler driver (default `m2`).
+- `-I dir` — extra search directory (repeatable; the main file’s directory
+  is always searched).
+- `-o out` — output executable (default: program module name).
+- `--m2bin path` — M2 driver (default `M2`).
+- `--shim path` — C runtime shim for V3 mode (default `shim.c`).
+- `--extra path` — extra C file linked after the shim.
+- `--m2flag flag` — one extra M2 argument (the fixpoint uses
+  `-legacyopen1d`).
+- `--dialect pim|iso|gm2` — add `lib/<dialect>`, `lib/common`, `lib/gm2`
+  and `runtime/syslib` to the search path.  Use one dialect per session.
+- `--separate` — per-module objects instead of one session image.
 
-<!--[compiler]-->
-<!--	M2 or Gnu Modula-2-->
-<!--	-->
-<!--[systemlibs]-->
-<!--	system libraries to be included-->
-<!--	-->
-<!--[projectfiles]-->
-<!--	all the project files to be included in the project. -->
-<!--	-->
-<!--the last one can be deduced by M2make which will load the main file -->
-<!--and follow all the imports to be included. From that, it makes a -->
-<!--topologic sort and compiles what is necessary in the right order.-->
+## Current limits
 
-<!--[options]-->
-<!--	options to use with the compilers and to pass to the compile line.-->
+- `--separate` rebuilds every object; stale-object/ABI checks are deferred.
+- Generic instances are still resolved at client compile time.
+- The default one-shot mode remains the mode used by the suite, corpus and
+  self-hosting fixpoint.
+- `M2 -c` itself needs explicit imported interfaces; M2make is the
+  transitive resolver.
 
- 
+See `TUTORIAL.md`, `docs/separate-compilation.md`, and
+`tools/m2make/README.md` for details.