Skip to content

Commit b051f59

Browse files
hyperpolymathclaude
andcommitted
docs: clarify codegen environment rules for top-level const and fn bindings (closes #89)
Add const_decl, extern_type_decl, extern_fn_decl to the top_level grammar in SPEC.md 2.1. Add sections 2.9 and 2.10 covering their syntax. Add section 8 (Codegen Module Environment) documenting the func_indices dual-use encoding: non-negative keys are Wasm function indices, negative keys are -(global_idx+1) for constants. Update the func_indices field comment in lib/codegen.ml to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 04501be commit b051f59

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

docs/specs/SPEC.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ row_var = ".." lower_ident
2525
### 1.2 Keywords
2626

2727
```
28-
fn let mut own ref type struct enum trait impl effect handle
28+
fn let const extern mut own ref type struct enum trait impl effect handle
2929
resume handler match if else while for return break continue in
3030
true false where total module use pub as unsafe assume transmute
3131
forget Nat Int Bool Float String Type Row
@@ -68,6 +68,7 @@ Special: \ (row restriction)
6868
```ebnf
6969
program = [module_decl] {import_decl} {top_level}
7070
top_level = fn_decl | type_decl | trait_decl | impl_block | effect_decl
71+
| const_decl | extern_type_decl | extern_fn_decl
7172
```
7273

7374
### 2.2 Type Declarations
@@ -194,6 +195,27 @@ impl_block = "impl" [type_params] [trait_ref "for"] type_expr
194195
[where_clause] "{" {impl_item} "}"
195196
```
196197

198+
### 2.9 Constant Declarations
199+
200+
```ebnf
201+
const_decl = [visibility] "const" LOWER_IDENT ":" type_expr "=" expr ";"
202+
```
203+
204+
Top-level `const` bindings are evaluated at compile time and emitted as
205+
immutable WebAssembly globals. Both function names and const names are
206+
registered in the codegen name environment (see §5.1).
207+
208+
### 2.10 Extern Declarations
209+
210+
```ebnf
211+
extern_type_decl = "extern" "type" UPPER_IDENT ";"
212+
extern_fn_decl = "extern" "fn" LOWER_IDENT "(" [param_list] ")" ["->" type_expr] ";"
213+
```
214+
215+
`extern type` declares an opaque host-provided type. `extern fn` declares a
216+
function whose implementation is supplied by the host environment at link time
217+
(a WebAssembly import). Both are top-level only and carry no body.
218+
197219
## 3. Type System
198220

199221
### 3.1 Judgement Forms
@@ -524,6 +546,42 @@ Compiles to (ownership removed):
524546
(call $close (local.get $file)))
525547
```
526548

549+
## 8. Codegen Module Environment
550+
551+
This section describes how the WebAssembly code generator (`lib/codegen.ml`)
552+
builds its name environment. It is implementation documentation aimed at
553+
contributors; the language semantics are fully specified in §2–4.
554+
555+
### 8.1 Name Environment (`func_indices`)
556+
557+
The codegen context maintains a single association list `func_indices :
558+
(string * int) list` that maps every top-level name visible at call sites to an
559+
integer key. Two distinct kinds of binding share this table:
560+
561+
| Source declaration | Key value | Meaning |
562+
|--------------------|-----------|---------|
563+
| `fn f(…) { … }` | `k ≥ 0` | WebAssembly function index (import + defined functions combined) |
564+
| `const C: T = e` | `-(g+1)` where `g` is the global index | Negative sentinel; caller must emit `global.get g` not `call k` |
565+
566+
The negative-index encoding lets call-site code distinguish constants from
567+
functions with a single sign test before emitting the appropriate instruction.
568+
569+
**Population order.** Both `TopFn` and `TopConst` are processed by `gen_decl`
570+
in declaration order (the single pass in `gen_program`). Each inserts its name
571+
into `func_indices` before any later declaration can reference it. Forward
572+
references to functions are therefore not supported in the current
573+
single-pass design.
574+
575+
### 8.2 Extern Bindings
576+
577+
`TopExternFn` declarations are added to the WebAssembly import section and
578+
their names are registered in `func_indices` with the resulting import function
579+
index. `TopExternType` declarations register an opaque type name and generate
580+
no code.
581+
582+
The WebAssembly module name for an `extern fn` import defaults to `"env"` unless
583+
overridden by a `@module("…")` pragma on the declaration (not yet implemented).
584+
527585
## Appendix: Grammar Reference
528586

529587
See the full specification at `affinescript-spec.md` for:

lib/codegen.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ type context = {
2828
locals : (string * int) list; (** local variable name to index map *)
2929
next_local : int; (** next available local index *)
3030
loop_depth : int; (** current loop nesting depth *)
31-
func_indices : (string * int) list; (** function name to index map *)
31+
func_indices : (string * int) list;
32+
(** Top-level name environment shared by functions and constants.
33+
- [k >= 0]: Wasm function index (imports + defined functions).
34+
- [k < 0]: Constant (global): actual global index is [-(k+1)].
35+
Both [TopFn] and [TopConst] insert into this table in declaration order. *)
3236
lambda_funcs : func list; (** lifted lambda functions *)
3337
next_lambda_id : int; (** next lambda function ID *)
3438
heap_ptr : int option; (** global index for heap pointer, if initialized *)

0 commit comments

Comments
 (0)