v4 Capstone: Full Pipeline
Work through examples, try the reasoning yourself, then put it into practice.
View SlidesBefore you start
- Complete v4 lexical, parsing, semantic, and lowering changes.
- Retain v3 callable-value and heap regression cases.
What you will practice
- Validate lazy evaluation and loop cleanup through BC2 transport.
- Make internal loop state observable despite nil program results.
- Enforce semantic failure before runtime side effects.
In this lesson
Lesson
3 min readv4 Capstone: Full Pipeline
The v4 integration path is still Lex → Parse → Analyze → Compile → Encode → Decode → NewVM().Run. It handles one Program; linking and module initialization begin in v5. The helper return shapes match v3: Compile and Encode return their artifacts directly; other failing helpers return errors, and Analyze returns a diagnostic slice whose first entry is surfaced.
Worked reconstruction
let total=0;
for (let i=0; i<4; i=i+1) {
if (i==1) { continue; }
total=total+i;
}
if (total!=5) { 1/0; }
false && (1/0);
The loop adds 0, 2, and 3. Continue still executes post, so i advances past 1. The assertion observes total without exposing the VM's private environment. The last expression compiles both operands but skips its division at runtime; its boolean result is popped as an expression statement. Success returns nil, not total=5 and not the final false value.
Separate three kinds of skipping
The parser still reads the RHS of &&/||. The analyzer still visits it. Only runtime evaluation is skipped on the selected branch. Therefore replacing the last RHS with missing() changes success into a semantic error. Replacing it with malformed syntax fails even earlier. Bytecode inspection can confirm that valid skipped RHS code is present but not executed.
Integration gate
Exercise a for continue with post, a for without post, a while continue, a break in a nested block, and an inner loop break that leaves the outer loop alive. Also retain the earlier closure/collection tests: adding path cleanup must not lose captured environments. A nested function containing an unscoped break must fail analysis even when its declaration occurs inside an outer loop.
Run the decoded BC2 object, not the original compiler object as a fallback. Return earlier failures immediately, and create a fresh VM per invocation. When debugging a failed assertion, inspect the AST clauses, target addresses, and scope exits before changing arithmetic operations.
Debugging lab
A program with top-level break and a later 1/0 returns division-by-zero. Another returns the final expression’s boolean after false && (1/0);. Locate the wrong boundary in each implementation.
Compare your diagnosis after attempting the lab
The first ignored the analyzer gate and executed invalid source. The second omitted expression-statement POP or invented an implicit program-result convention. Correct ordinary top-level completion returns nil.
Transfer task
Create a nested-loop program with a returned closure capturing an outer binding. Add independent assertions for its loop total and closure result, then insert an undefined name in a skipped RHS and predict the new first failure.
Carry forward
Carry the single-program BC2 baseline into v5. The new risk will be relocating separately compiled artifacts, not reinterpreting existing boolean or loop semantics.
Build compile-and-run-v4. Keep a before/after trace of one failing test. Use the checkpoint to diagnose specific skills; passing it does not replace implementing and testing the artifact.
Practice sequence
Use the order below for a guided path, or choose an item to revisit. A pass records a successful attempt; try a fresh example later to check what you can reconstruct.
- Step 1
Compile and Run v4 (Capstone)
- Step 2
v4 Capstone: Full Pipeline Checkpoint
Predict fresh artifacts, diagnose a broken invariant, and test a version boundary. Select one answer per multiple-choice question; numeric responses use the stated integer format. Use review links to revisit the relevant representation, then attempt the independent transfer task.