소스 검색

language: assign a procedure value to a PROC variable

Assignable rejected `p := foo` (p: PROC, mapped onto ADDRESS): a
procedure value (ClProc) into a pointer/proc (ClPtr).  Accept
ClProc<->ClPtr assignment.  procconv (which also exercises
VAL(INITPROC, ...) and PROC<->ADDRESS) now passes and runs.

Corpus 394 -> 396, 0 crashes.  Suite 231/231 (t_procval).  Fixpoint OK,
3,841,894 bytes.
Eric Streit 13 시간 전
부모
커밋
321e40bcf4
8개의 변경된 파일과 59개의 추가작업 그리고 28개의 파일을 삭제
  1. 2 2
      README.md
  2. 1 0
      compiler/run_tests.sh
  3. 8 0
      compiler/src/SymTab.mod
  4. 13 0
      compiler/tests/t_procval.mod
  5. 1 1
      docs/INDEX.md
  6. 7 7
      docs/STATUS.md
  7. 7 4
      docs/analysis_gaps.md
  8. 20 14
      docs/summary_set-constants-2026-10-18.md

+ 2 - 2
README.md

@@ -47,8 +47,8 @@ docs/              STATUS.md, plan.md, plan-*.md, analysis_*.md, summary_*.md
 
 ## Status (2026-10-18)
 
-- Suite **230/230**; self-hosting **fixpoint OK** (byte-identical
-  stage2/stage3, 3,840,862 bytes); corpus **394/612 compile-OK,
+- Suite **231/231**; self-hosting **fixpoint OK** (byte-identical
+  stage2/stage3, 3,841,894 bytes); corpus **396/612 compile-OK,
   0 crashes** (`tools/v3-corpus`).
 - Active branch **`resolve-check`** (holds the AST/`Lower`/parse
   refactors and generics).

+ 1 - 0
compiler/run_tests.sh

@@ -101,6 +101,7 @@ expect_run t_constreal.mod 42
 expect_run t_constlong.mod 42
 expect_run t_arrfwd.mod 42
 expect_run t_procaddr.mod 42
+expect_run t_procval.mod 42
 expect_run t_unicode.mod 31
 expect_run t_charbounds.mod 3
 expect_run t_record.mod 160

+ 8 - 0
compiler/src/SymTab.mod

@@ -2846,6 +2846,14 @@ PROCEDURE Assignable (src, dst: TypeIndex): BOOLEAN;
     IF (ClassOf(src) = ClPtr) AND (ClassOf(dst) = ClPtr) THEN
       RETURN IsSubclass(PtrBase(src), PtrBase(dst))
     END;
+    (* a procedure value is a code address: it assigns to/from a
+       pointer (PROC is mapped onto ADDRESS) *)
+    IF (ClassOf(src) = ClProc) AND (ClassOf(dst) = ClPtr) THEN
+      RETURN TRUE
+    END;
+    IF (ClassOf(src) = ClPtr) AND (ClassOf(dst) = ClProc) THEN
+      RETURN TRUE
+    END;
     IF (ClassOf(src) = ClInt) AND (ClassOf(dst) = ClInt) THEN
       RETURN TRUE
     END;

+ 13 - 0
compiler/tests/t_procval.mod

@@ -0,0 +1,13 @@
+MODULE TProcVal;
+// A procedure value assigns to a PROC variable, and PROC converts to
+// ADDRESS (identical to ADR(foo)).  Exit 42.
+FROM SYSTEM IMPORT ADR;
+PROCEDURE foo; BEGIN END foo;
+VAR p : PROC;
+    a : ADDRESS;
+    ExitCode : INTEGER;
+BEGIN
+  p := foo;
+  a := VAL(ADDRESS, p);
+  IF a = ADR(foo) THEN ExitCode := 42 ELSE ExitCode := 1 END
+END TProcVal.

+ 1 - 1
docs/INDEX.md

@@ -30,7 +30,7 @@ bisecting *why* a decision was made, not for reading end-to-end).
 - `summary_set-constants-2026-10-18.md` — SET CONST (static masks,
   folded unions), builtin CONST folding (CAP/ABS/ODD, BOOLEAN consts),
   CONST representation conversions, forward array-index types, and
-  procedure addresses.
+  procedure values.
 - `summary_dlist-showcase-2026-10-16.md` — showcase23 + limitation fixes.
 - `summary_generics-limitations-fixed-2026-10-16.md` — the two
   template/proc-param limitations, fixed.

+ 7 - 7
docs/STATUS.md

@@ -4,10 +4,10 @@ This answers "where are we now?".
 
 ## Numbers
 
-- Suite **230/230** (`compiler/run_tests.sh`).
+- Suite **231/231** (`compiler/run_tests.sh`).
 - Self-hosting **FIXPOINT OK** — stage2 and stage3 images are
-  byte-identical (3,840,862 bytes).
-- Corpus **394 / 612** sources compile with 0 errors, **0 crashes**
+  byte-identical (3,841,894 bytes).
+- Corpus **396 / 612** sources compile with 0 errors, **0 crashes**
   (`tools/v3-corpus/corpus.sh` over the gm2 testsuite); the rest are
   genuine language gaps or unresolved imports.
 - Branch **`resolve-check`**; tree clean.
@@ -61,9 +61,9 @@ parameters, constraints, nested generics, generic classes.
   (`CAP`/`ABS`/`ODD` over immediates), `BOOLEAN` `CONST`s,
   representation-changing `CONST` conversions (`VAL(REAL, int)`,
   `VAL(LONGINT, int)`, …), **forward array-index types** (deferred,
-  patched at `EndTypeBlock`), and **procedure addresses**
-  (`ADR(proc)`/`VAL(ADDRESS, proc)` ↔ `PROC` conversions):
-  corpus 382 → 394.
+  patched at `EndTypeBlock`), and **procedure values** (`ADR(proc)`,
+  `VAL`↔`PROC` conversions, `p := foo` into a `PROC`):
+  corpus 382 → 396.
 - Clean `M2` exit codes (0 ok / 1 errors / 2 usage-IO).
 - Bug fixes: `PopPos` wiping repass diagnostics; global record data
   size (`w 0` → `l 0` for pointer/`LONGINT`/proc fields); template
@@ -91,7 +91,7 @@ parameters, constraints, nested generics, generic classes.
 ```sh
 cd compiler
 ./build.sh          # M2.atg -> scanner/parser/driver -> ./M2
-./run_tests.sh      # 230/230
+./run_tests.sh      # 231/231
 cd ..
 ./bootstrap/fixpoint.sh   # FIXPOINT OK (byte-identical stage2/stage3)
 ```

+ 7 - 4
docs/analysis_gaps.md

@@ -209,11 +209,14 @@ idx = [-2..2]` defers the array and patches its bounds at `EndTypeBlock`
 
 Also landed **procedure addresses**: `Lower`'s `ADR` now yields the code
 address for a procedure (was `0`), and the `VAL` conversion accepts
-`PROC`↔`PROC`/`PTR`; `procadr` passes and runs.  Corpus **393 -> 394**;
-suite test `t_procaddr`.
+`PROC`↔`PROC`/`PTR`; `procadr` passes and runs.  `Assignable` also now
+takes a procedure value into a `PROC`/pointer (`p := foo`), so
+`procconv` lands too.  Corpus **393 -> 396**; suite tests `t_procaddr`,
+`t_procval`.
 
 Next (recorded): forward *type* references in a `CONST` conversion
 (`subrange4`/`7`) and as a `VAR` type before its TYPE block
 (`subrange11`); `setconst3` (forward `CONST`); `minmaxreal3` (SYSTEM
-`REAL64`); `procconv`/`procconv2` (`p := proc`, `CONVERT`); the `imp*`
-qualified-import family (partly a corpus-harness transitive-`.def` gap).
+`REAL64`); `procconv2` (`CONVERT`); `tinyproc2`/`tinyproc4` (bare proc
+value as a statement); the `imp*` qualified-import family (partly a
+corpus-harness transitive-`.def` gap).

+ 20 - 14
docs/summary_set-constants-2026-10-18.md

@@ -1,18 +1,18 @@
 # Session summary — SET CONST + builtin CONST folding 2026-10-18
 
-Branch **`resolve-check`**.  Suite **230/230**; fixpoint **OK
-(3,840,862 bytes)**; corpus **394/612 compile-OK, 0 crashes**.
+Branch **`resolve-check`**.  Suite **231/231**; fixpoint **OK
+(3,841,894 bytes)**; corpus **396/612 compile-OK, 0 crashes**.
 
 Tags: `v3-set-constants`, `v3-const-builtin-fold`, `v3-const-conv-fold`,
-`v3-array-index-fwd`, `v3-proc-addr`.
+`v3-array-index-fwd`, `v3-proc-addr`, `v3-proc-val`.
 
 ## What this session did
 
 Landed the two features recorded in `docs/analysis_gaps.md` §9 by the
 previous corpus sweep — **set constants** (static masks) and **builtin
 calls in `CONST` initialisers** — then went further on `CONST`
-initialisers and forward type references.  Corpus **382 → 394**
-(+12 files, 0 crashes).
+initialisers, forward type references, and procedure values.  Corpus
+**382 → 396** (+14 files, 0 crashes).
 
 ```mod
 CONST Digits = CharSet{"0".."9"};          (* char range *)
@@ -90,14 +90,17 @@ bounds (`DeferArrayIdx`); `EndTypeBlock` patches their `[lo..hi]`
 marked, so they are unaffected.  Corpus **391 → 393**; suite test
 `t_arrfwd`.
 
-## Procedure addresses
+## Procedure values
 
 `ADR(foo)` returned `0` (Lower's `ADR` handled only vars/params), while
 `VAL(ADDRESS, foo)` gave the code address, so `procadr` compiled but
 failed at run time.  `Lower`'s `ADR` now emits the code address for a
 procedure (`LowerProcAddr`).  The grammar's `VAL` conversion was also
 missing procedure-value classes: added `PROC`↔`PROC`, `PROC`↔`PTR`.
-Corpus **393 → 394**; suite test `t_procaddr`.
+Then `Assignable` rejected `p := foo` (a procedure value into a `PROC`
+variable, mapped onto `ADDRESS`): added `PROC`↔`PTR` assignability.
+`procconv` now passes and runs.  Corpus **393 → 396**; suite tests
+`t_procaddr`, `t_procval`.
 
 ## Not fixed (recorded)
 
@@ -107,27 +110,30 @@ Corpus **393 → 394**; suite test `t_procaddr`.
   parses.
 - Forward *type* references in a `CONST` conversion (`subrange4`/`7`)
   and as a `VAR` type before its TYPE block (`subrange11`);
-  `minmaxreal3` (SYSTEM `REAL64`); `procconv` (`p := foo`, proc value to
-  a `PROC` var) / `procconv2` (`CONVERT`); the `imp*` qualified-import
-  family (partly a corpus-harness transitive-`.def` gap).
+  `minmaxreal3` (SYSTEM `REAL64`); `procconv2` (`CONVERT`);
+  `tinyproc2`/`tinyproc4` (bare procedure value as a statement); the
+  `imp*` qualified-import family (partly a corpus-harness
+  transitive-`.def` gap).
 
 ## Files
 
 `compiler/src/Lower.{def,mod}` (evaluator + `PoolSet` call + `ADR(proc)`),
 `compiler/src/QbeGen.{def,mod}` (`PoolSet`/`FlushSets`/pool state),
-`compiler/src/SymTab.{def,mod}` (forward array-index deferral),
+`compiler/src/SymTab.{def,mod}` (forward array-index deferral;
+proc-value assignability),
 `compiler/src/M2.atg` (`ConstDecl`, `Design`, `CAP`/`ABS`/`ODD` folds,
 `VAL` conversion folds, array-index defer, proc-value conversions),
 `compiler/tests/t_setconst.mod`, `t_bad_setconst.mod`,
 `t_constbuiltin.mod`, `t_constreal.mod`, `t_constlong.mod`,
-`t_arrfwd.mod`, `t_procaddr.mod`, `compiler/run_tests.sh`.
+`t_arrfwd.mod`, `t_procaddr.mod`, `t_procval.mod`,
+`compiler/run_tests.sh`.
 
 ## Resume
 
 ```sh
 cd .../m2compiler-V3
 git checkout resolve-check
-cd compiler && ./build.sh && ./run_tests.sh   # 230/230
+cd compiler && ./build.sh && ./run_tests.sh   # 231/231
 cd .. && TMP="$PWD/.scratch/fixpoint" ./bootstrap/fixpoint.sh
-M2FLAGS="" ./.scratch/corpusx.sh              # 394 OK, 0 crash
+M2FLAGS="" ./.scratch/corpusx.sh              # 396 OK, 0 crash
 ```