summary_session-2026-09-29-oop.md 4.2 KB

Session save — 2026-09-29: the OOP arc (Clarion CLASS, complete)

Suite 147/147; self-hosting fixpoint OK (bootstrap/fixpoint.sh, image 2,313,762 bytes). master, tree clean except the user's uncommitted compiler/toto.mod.

This session took Clarion CLASS from "declared + checked only, ends in 230" to a complete single-inheritance object system with dynamic dispatch — in four tagged steps, each re-verified against the byte-identical fixpoint.

Steps, tags and commits

Step Tag Commit What
CHAR-array + + ConvResults v3-charcat-convresults 5e2056f (warm-up: string + test + ISO ConvResults)
Showcase 17 v3-showcase17 807ff9c CLASS + strings + conversions together
CLASS lowering v3-class-lowering ed02804 fields, methods, THIS, single inheritance
VIRTUAL dispatch v3-virtual-dispatch 98d3067 vtables + subtype pointers
Showcase 18 v3-showcase18 f584e62 polymorphic Shape hierarchy
CLASS finished v3-class-finish 3804256 sibling calls + init body
Showcase 19 v3-showcase19 9f1f278 init body + sibling-call chain

1. CLASS lowering (v3-class-lowering)

  • Layout — a class is a record: ComputeOffsets gives declaration-order offsets; single inheritance lays the child's fields after the parent's, and FindField/FieldOffset walk the parent chain. obj.field and WITH obj reuse the record path.
  • Receiver — each method gets a hidden THIS VAR parameter, pushed as the current WITH base, so a bare field name means THIS^.field.
  • Calls — obj.M(args) binds statically; the receiver is the hidden first argument; CLASS IMPLEMENTATION reuses the declared method symbol (matching call-site and definition uids).
  • Docs: docs/summary_class-lowering.md.

2. VIRTUAL dispatch (v3-virtual-dispatch)

  • vtable — each class with virtuals owns a slice of a shared pool; the parent's slots are inherited first, a same-named virtual method overrides in place, new ones append.
  • vptr — the introducing class gets an 8-byte vtable pointer (offset 0, or after the parent's fields); subclasses share it, so an object's vptr identifies its dynamic class.
  • emission — data $vt_<typeindex> = { l $Method_uid, … }; a declared-but-unimplemented method is l 0.
  • dispatch — a virtual call loads the vptr, fetches the slot, and calls indirectly; subtyping lets POINTER TO Derived assign to POINTER TO Base.
  • Docs: docs/summary_virtual-dispatch.md.

3. CLASS finished (v3-class-finish)

  • Sibling-method calls — inside a CLASS IMPLEMENTATION, a bare method name is a call on THIS (chains work; a virtual sibling still dispatches through the vtable).
  • Class BEGIN … END init body — emitted as <Class>_init and run once at startup.
  • Multiple parents stay 230 (single inheritance by design).
  • Docs: docs/summary_class-finish.md.

Showcases

  • Showcase17 — a Bounded counter class + ConvResults + CHAR-array + → showcase17 total=42.
  • Showcase18 — Circle/Square with a virtual Area(), driven through an array of POINTER TO Shape → showcase18 areas sum=139.
  • Showcase19 — an init body setting a global plus a sibling-call chain → showcase19 total=42.

Tests (147)

Added across the arc: t_charcat, convresults_prog (+ conv_prog/ showcase14 moved to IntVal/RealVal), t_classmethod, t_classinherit, TClassDefProg (t_classdef.mod → t_classdef.def), t_virtual, t_classsibling, t_classinit (t_class promoted from reject), and Showcase17/18/19.

Where CLASS stands

✅ fields, methods (value/VAR formals, results), single inheritance, WITH, hidden THIS, VIRTUAL dynamic dispatch (vtables) with subtype pointers, sibling calls, init bodies. ⏸ multiple parents only (deliberate).

Resume

cd .../m2compiler-V3
./bootstrap/fixpoint.sh                       # FIXPOINT OK
cd compiler && ./build.sh && ./run_tests.sh   # 147/147

Remaining polish (beyond OOP)

  • VAL(LONGINT|REAL, x) and long→int narrowing.
  • More stdlib (SysClock, richer Strings/Math).
  • Files/IOChan extras (seek/pool nuances), deeper variant-record support.