Skip to content

Commit 1f2d487

Browse files
docs(syntax): Allign docs and clean redaction.
1 parent 07eebb5 commit 1f2d487

1 file changed

Lines changed: 55 additions & 54 deletions

File tree

docs/pages/implementation/syntax.md

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ Each instruction is a tagged 4-byte record:
1515

1616
```rust
1717
pub struct Instruction {
18-
pub opcode: OpCode, // 1 byte (with #[repr(u8)] planned)
19-
pub operand: u16, // 2 bytes
18+
pub opcode: OpCode, // 1 byte (with #[repr(u8)] planned)
19+
pub operand: u16, // 2 bytes
2020
}
2121
```
2222

23-
The operand is a 16-bit slot, its meaning depends on the opcode. Common shapes:
23+
The operand is a 16-bit slot; its meaning depends on the opcode. Common shapes:
2424

2525
| OpCode | Operand interpretation |
2626
|---------------------------|------------------------------------------------------|
@@ -44,20 +44,20 @@ Operands and the constant pool, name table, and instruction stream per chunk are
4444
`expr_bp(min_bp)` runs the Pratt loop. `parse_atom` advances one token and routes by kind:
4545

4646
```text
47-
Name -> name() (handles assignment, walrus, calls)
48-
String -> emit Str constant; concatenate adjacent String tokens
49-
Int / Float -> emit numeric constant; literal beyond 2⁴⁷ is a parse error
50-
True/False/None/Ellipsisv-> emit dedicated load opcode
51-
FstringStart -> fstring()
52-
Lbrace -> brace_literal() (dict, set, comprehension)
53-
Lsqb -> list_literal() (list, comprehension)
54-
Lpar -> grouped expr, tuple, generator, or empty tuple
55-
Lambda -> parse_lambda()
47+
Name -> name() (handles assignment, walrus, calls)
48+
String -> emit Str constant; concatenate adjacent String tokens
49+
Int / Float -> emit numeric constant; literal beyond 2⁴⁷ is a parse error
50+
True/False/None/Ellipsis -> emit dedicated load opcode
51+
FstringStart -> fstring()
52+
Lbrace -> brace_literal() (dict, set, comprehension)
53+
Lsqb -> list_literal() (list, comprehension)
54+
Lpar -> grouped expr, tuple, generator, or empty tuple
55+
Lambda -> parse_lambda()
5656
```
5757

58-
After an atom, `postfix_tail()` handles trailers, subscript, attribute, call, iterating until none apply. Lets `fns[0](-3)`, `obj.method()`, `(lambda x: x)(3)`, `compose(f, g)(x)` parse uniformly.
58+
After an atom, `postfix_tail()` handles trailers (subscript, attribute, call), iterating until none apply. Lets `fns[0](-3)`, `obj.method()`, `(lambda x: x)(3)`, `compose(f, g)(x)` parse uniformly.
5959

60-
`*args` / `**kwargs` are accepted in **call** position only, starred unpacking inside literals (`[*a, *b]`, `{**d1, **d2}`, `(1, *xs, 2)`) is not supported.
60+
`*args` / `**kwargs` are accepted in **call** position only; starred unpacking inside literals (`[*a, *b]`, `{**d1, **d2}`, `(1, *xs, 2)`) is not supported.
6161

6262
## Operator precedence
6363

@@ -88,7 +88,7 @@ Comparison chaining (`a < b < c`) is handled by `infix_bp`: when a comparison op
8888
a and b
8989
9090
LoadName a
91-
JumpIfFalseOrPop -> end
91+
JumpIfFalseOrPop -> end
9292
LoadName b
9393
end:
9494
```
@@ -108,12 +108,12 @@ y = x # y_1, references x_2
108108
```text
109109
chunk.names = ["x_1", "x_2", "y_1"]
110110
chunk.instructions:
111-
LoadConst 0 (1)
112-
StoreName 0 (x_1)
113-
LoadConst 1 (2)
114-
StoreName 1 (x_2)
115-
LoadName 1 (x_2)
116-
StoreName 2 (y_1)
111+
LoadConst 0 (1)
112+
StoreName 0 (x_1)
113+
LoadConst 1 (2)
114+
StoreName 1 (x_2)
115+
LoadName 1 (x_2)
116+
StoreName 2 (y_1)
117117
```
118118

119119
Undefined names target version 0 (`x_0`), filled by the host before execution (VM seeds globals like `print_0`). Still unbound at load time -> `NameError`.
@@ -132,9 +132,9 @@ Each `Phi` carries the target slot (new version after join) in its operand; sour
132132

133133
```python
134134
if cond:
135-
x = 1
135+
x = 1
136136
else:
137-
x = 2
137+
x = 2
138138
print(x)
139139
```
140140

@@ -153,34 +153,34 @@ LoadName x_3
153153
CallPrint 1
154154
```
155155

156-
Runtime resolves `Phi` by reading whichever source slot is `Some`, exactly one branch executed.
156+
Runtime resolves `Phi` by reading whichever source slot is `Some` exactly one branch executed.
157157

158158
## Statement dispatch
159159

160160
`stmt()` peeks the leading token and routes:
161161

162162
```text
163-
if -> if_stmt (with elif chain, optional else)
164-
for -> for_stmt_inner (sync iter, optional else)
165-
while -> while_stmt (with break/continue patches)
166-
match -> match_stmt
167-
def -> func_def_inner
168-
class -> class_def (__init__, attributes, methods)
169-
with -> with_stmt_inner (multi-target, async variant)
170-
try -> try_stmt (except, else, finally, raise)
171-
import -> import_stmt (compile-time resolver lookup)
172-
from -> parse_from_stmt (named / star imports, same path)
173-
type -> type-alias declaration
174-
yield -> yield expr / yield from
175-
async -> async def / for / with
176-
@ -> decorator stack + def or class (peeks `class` after the @-list)
163+
if -> if_stmt (with elif chain, optional else)
164+
for -> for_stmt_inner (sync iter, optional else)
165+
while -> while_stmt (with break/continue patches)
166+
match -> match_stmt
167+
def -> func_def_inner
168+
class -> class_def (__init__, attributes, methods)
169+
with -> with_stmt_inner (multi-target, async variant)
170+
try -> try_stmt (except, else, finally, raise)
171+
import -> import_stmt (compile-time resolver lookup)
172+
from -> parse_from_stmt (named / star imports, same path)
173+
type -> type-alias declaration
174+
yield -> yield expr / yield from
175+
async -> async def / for / with
176+
@ -> decorator stack + def or class (peeks `class` after the @-list)
177177
return -> expr + ReturnValue
178-
raise -> expr + Raise / RaiseFrom
179-
break -> emits Jump, back-patched to the loop exit
180-
continue -> jump to current loop_start
178+
raise -> expr + Raise / RaiseFrom
179+
break -> emits Jump, back-patched to the loop exit
180+
continue -> jump to current loop_start
181181
del / global / nonlocal / pass -> direct emit
182182
assert -> Assert opcode; the `, msg` form lowers to a conditional raise of AssertionError(msg)
183-
Name -> name_stmt (assignment, augmented, indexed, attribute, call)
183+
Name -> name_stmt (assignment, augmented, indexed, attribute, call)
184184
```
185185

186186
Each statement returns a bool: did it leave a value on the stack. Driver emits `PopTop` after expression-shaped statements (`x.method()`, `1 + 2` at module level), not after statement-shaped (assignment, control flow).
@@ -195,14 +195,14 @@ Lambdas and `def` both compile their body into a *fresh* SSAChunk:
195195

196196
```rust
197197
self.with_fresh_chunk(|s| {
198-
s.ssa_versions = outer_versions.clone();
199-
for p in &params { s.ssa_versions.insert(p.clone(), 0); }
200-
s.expr(); // or compile_block_body for def
201-
s.chunk.emit(OpCode::ReturnValue, 0);
198+
s.ssa_versions = outer_versions.clone();
199+
for p in &params { s.ssa_versions.insert(p.clone(), 0); }
200+
s.expr(); // or compile_block_body for def
201+
s.chunk.emit(OpCode::ReturnValue, 0);
202202
});
203203
```
204204

205-
Free variables (non-parameters with no local binding) are looked up in the outer chunk. `MakeFunction` captures matching slots from the enclosing scope into `captures` (snapshotted, no cell objects). Nested `def`/`lambda` push their free names back into the parent's name table, capture propagates through any depth (`A -> B -> C` where `C` references a var in `A`).
205+
Free variables (non-parameters with no local binding) are looked up in the outer chunk. `MakeFunction` captures matching slots from the enclosing scope into `captures` (snapshotted, no cell objects). Nested `def`/`lambda` push their free names back into the parent's name table; capture propagates through any depth (`A -> B -> C` where `C` references a var in `A`).
206206

207207
Parameter slots: `Normal`, `Star` (`*args`), `DoubleStar` (`**kwargs`). Lone `*` separator marks following params as keyword-only. Defaults live in `HeapObj::Func.defaults` and apply to the last-N positional slots. Annotations (`x: T`, `-> T`) parse and drain to `chunk.annotations` (tooling-only).
208208

@@ -213,9 +213,10 @@ Parameter slots: `Normal`, `Star` (`*args`), `DoubleStar` (`**kwargs`). Lone `*`
213213
Parsed for source compatibility, discarded at runtime:
214214

215215
```python
216-
counter: int = 0 # annotation 'int' parsed and stored, slot still gets 0
217-
def f(x: int) -> int: # annotations on params and return parsed and skipped
218-
return x
216+
counter: int = 0 # annotation 'int' parsed and stored, slot still gets 0
217+
def f(x: int) -> int:
218+
# annotations on params and return parsed and skipped
219+
return x
219220
```
220221

221222
Recorded in `chunk.annotations: HashMap<String, String>` for tooling; no code emitted. `f.__annotations__` is not exposed at runtime, but `f.__name__` is (resolved in `resolve_attr`, also on type objects and classes).
@@ -238,17 +239,17 @@ Lowers to:
238239

239240
```text
240241
LoadConst "hello "
241-
LoadName name_v
242+
LoadName name_v
242243
FormatValue 0
243244
LoadConst ", age "
244-
LoadName age_v
245+
LoadName age_v
245246
FormatValue 0
246247
BuildString 5
247248
```
248249

249250
`FormatValue`'s 16-bit operand is a small flags field:
250-
* bit 0, set when a format spec string is on the stack just below the value (collected as the raw text between `:` and `}` and emitted as a constant).
251-
* bits 1,2, conversion: `0` none, `1` `!r`, `2` `!s`, `3` `!a`.
251+
- bit 0, set when a format spec string is on the stack just below the value (collected as the raw text between `:` and `}` and emitted as a constant).
252+
- bits 12, conversion: `0` none, `1` `!r`, `2` `!s`, `3` `!a`.
252253

253254
VM applies conversion first, then the spec mini-language `[[fill]align][sign][#][0][width][,][.precision][type]` with type chars `s d b o x X f F e E g G n % c`. `n` aliases `d` (no locale). `=` self-documenting form (`{expr=}`) emits a literal `expr=` prefix. Adjacent string literals concatenate at parse time. Spec parse failures -> `ValueError` at runtime.
254255

0 commit comments

Comments
 (0)