You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Lpar -> grouped expr, tuple, generator, or empty tuple
55
+
Lambda -> parse_lambda()
56
56
```
57
57
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.
59
59
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.
61
61
62
62
## Operator precedence
63
63
@@ -88,7 +88,7 @@ Comparison chaining (`a < b < c`) is handled by `infix_bp`: when a comparison op
88
88
a and b
89
89
90
90
LoadName a
91
-
JumpIfFalseOrPop -> end
91
+
JumpIfFalseOrPop -> end
92
92
LoadName b
93
93
end:
94
94
```
@@ -108,12 +108,12 @@ y = x # y_1, references x_2
108
108
```text
109
109
chunk.names = ["x_1", "x_2", "y_1"]
110
110
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)
117
117
```
118
118
119
119
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
132
132
133
133
```python
134
134
if cond:
135
-
x =1
135
+
x =1
136
136
else:
137
-
x =2
137
+
x =2
138
138
print(x)
139
139
```
140
140
@@ -153,34 +153,34 @@ LoadName x_3
153
153
CallPrint 1
154
154
```
155
155
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.
157
157
158
158
## Statement dispatch
159
159
160
160
`stmt()` peeks the leading token and routes:
161
161
162
162
```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)
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)
177
177
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
181
181
del / global / nonlocal / pass -> direct emit
182
182
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)
184
184
```
185
185
186
186
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:
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`).
206
206
207
207
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).
Parsed for source compatibility, discarded at runtime:
214
214
215
215
```python
216
-
counter: int=0# annotation 'int' parsed and stored, slot still gets 0
217
-
deff(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
+
deff(x: int) -> int:
218
+
# annotations on params and return parsed and skipped
219
+
return x
219
220
```
220
221
221
222
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:
238
239
239
240
```text
240
241
LoadConst "hello "
241
-
LoadName name_v
242
+
LoadName name_v
242
243
FormatValue 0
243
244
LoadConst ", age "
244
-
LoadName age_v
245
+
LoadName age_v
245
246
FormatValue 0
246
247
BuildString 5
247
248
```
248
249
249
250
`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).
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.
0 commit comments