|
|
@@ -0,0 +1,65 @@
|
|
|
+# Step: CLASS finished (sibling calls + init body)
|
|
|
+
|
|
|
+Tag `v3-class-finish`. Suite **146/146**; fixpoint **OK**
|
|
|
+(image **2,313,762 bytes**).
|
|
|
+
|
|
|
+Removes the last two implementable `230`s in the Clarion class area
|
|
|
+(the third, multiple parents, stays a deliberate limitation).
|
|
|
+
|
|
|
+## Sibling-method calls
|
|
|
+
|
|
|
+Inside a `CLASS IMPLEMENTATION` body, a **bare method name** is a call
|
|
|
+on `THIS`:
|
|
|
+
|
|
|
+```modula-2
|
|
|
+CLASS IMPLEMENTATION Acc;
|
|
|
+ PROCEDURE Add(v : INTEGER); BEGIN total := total + v END Add;
|
|
|
+ PROCEDURE AddTwice(a, b : INTEGER);
|
|
|
+ BEGIN Add(a); Add(b) END AddTwice; (* sibling calls *)
|
|
|
+END Acc;
|
|
|
+```
|
|
|
+
|
|
|
+- `SymTab` tracks the innermost open implementation (`PushImplClass`/
|
|
|
+ `PopImplClass`/`CurImplClass`); `ClassImplRest` pushes it.
|
|
|
+- `Design`: when an identifier is not found in the ordinary scopes but
|
|
|
+ the current implementation class has a method of that name, it binds
|
|
|
+ the method, arms `THIS` as the receiver (`QbeGen.ThisBase` +
|
|
|
+ `ArmRecv`), and marks a static (or virtual, if `VIRTUAL`) call.
|
|
|
+
|
|
|
+## Class `BEGIN … END` init body
|
|
|
+
|
|
|
+A class's initialisation body now compiles and runs **once at
|
|
|
+startup**, as `<Class>_init` (registered in the same list as module
|
|
|
+init functions, called from `main`):
|
|
|
+
|
|
|
+```modula-2
|
|
|
+CLASS IMPLEMENTATION C;
|
|
|
+ ...
|
|
|
+BEGIN
|
|
|
+ g := 41 (* runs at startup *)
|
|
|
+END C;
|
|
|
+```
|
|
|
+
|
|
|
+A body that references instance fields has no receiver and still
|
|
|
+reports 230 (class statics do not exist in V3).
|
|
|
+
|
|
|
+## Multiple parents — deliberate
|
|
|
+
|
|
|
+`CLASS Multi (A, B)` (more than one parent) remains 230: the design is
|
|
|
+single inheritance only (`docs/OOP.txt`). `showcase5.mod` keeps that
|
|
|
+rejection under test.
|
|
|
+
|
|
|
+## Tests
|
|
|
+
|
|
|
+- `t_classsibling.mod` (7): sibling calls.
|
|
|
+- `t_classinit.mod` (42): the init body sets a global before `main`.
|
|
|
+- `t_class.mod` promoted from a reject test to a run test (0).
|
|
|
+- `showcase5.mod` still rejects (multiple parents).
|
|
|
+
|
|
|
+## Files
|
|
|
+
|
|
|
+`compiler/src/SymTab.def`/`.mod` (`implStk`, `PushImplClass`/
|
|
|
+`PopImplClass`/`CurImplClass`), `compiler/src/M2.atg` (`ClassImplRest`
|
|
|
+push/pop + init body, `Design` sibling-call branch),
|
|
|
+`compiler/tests/{t_classsibling,t_classinit}.mod`,
|
|
|
+`compiler/run_tests.sh`, `docs/{features,OOP}.txt`.
|