main
md 567 lines 23.2 KB
Rendered Raw
1 # Rust Port: ReactiveFunction and Reactive Passes
2
3 Current status: **Phase 2 In Progress** — Reactive types, crate skeleton, TS/Rust debug printers, and BuildReactiveFunction are implemented. 1458/1717 fixtures pass (85%). Remaining failures are mostly earlier-pass error propagation differences and a few loop scheduling edge cases.
4
5 ## Overview
6
7 This document covers porting the reactive function representation and all passes from `BuildReactiveFunction` through `CodegenReactiveFunction` from TypeScript to Rust.
8
9 The reactive function is a tree-structured IR derived from the HIR CFG. `BuildReactiveFunction` converts the flat CFG into a nested tree where control flow constructs (if/switch/loops/try) and reactive scopes are represented as nested blocks rather than block references. Subsequent passes prune, merge, and transform scopes, then codegen converts the tree to output AST.
10
11 ## 1. Rust Type Representation
12
13 **Location**: New file `compiler/crates/react_compiler_hir/src/reactive.rs`, re-exported from `lib.rs`
14
15 All types derive `Debug, Clone`.
16
17 ### ReactiveFunction
18
19 ```rust
20 /// Tree representation of a compiled function, converted from the CFG-based HIR.
21 /// TS: ReactiveFunction in HIR.ts
22 pub struct ReactiveFunction {
23 pub loc: Option<SourceLocation>,
24 pub id: Option<String>,
25 pub name_hint: Option<String>,
26 pub params: Vec<ParamPattern>,
27 pub generator: bool,
28 pub is_async: bool,
29 pub body: ReactiveBlock,
30 pub directives: Vec<String>,
31 // No env field — passed separately per established Rust convention
32 }
33 ```
34
35 ### ReactiveBlock and ReactiveStatement
36
37 ```rust
38 /// TS: ReactiveBlock = Array<ReactiveStatement>
39 pub type ReactiveBlock = Vec<ReactiveStatement>;
40
41 /// TS: ReactiveStatement (discriminated union with 'kind' field)
42 pub enum ReactiveStatement {
43 Instruction(ReactiveInstruction),
44 Terminal(ReactiveTerminalStatement),
45 Scope(ReactiveScopeBlock),
46 PrunedScope(PrunedReactiveScopeBlock),
47 }
48 ```
49
50 ### ReactiveInstruction and ReactiveValue
51
52 ```rust
53 /// TS: ReactiveInstruction
54 pub struct ReactiveInstruction {
55 pub id: EvaluationOrder, // TS InstructionId = Rust EvaluationOrder
56 pub lvalue: Option<Place>,
57 pub value: ReactiveValue,
58 pub effects: Option<Vec<AliasingEffect>>,
59 pub loc: Option<SourceLocation>,
60 }
61
62 /// Extends InstructionValue with compound expression types that were
63 /// separate blocks+terminals in HIR but become nested expressions here.
64 /// TS: ReactiveValue = InstructionValue | ReactiveLogicalValue | ...
65 pub enum ReactiveValue {
66 /// All ~35 base instruction value kinds
67 Instruction(InstructionValue),
68
69 /// TS: ReactiveLogicalValue
70 LogicalExpression {
71 operator: LogicalOperator,
72 left: Box<ReactiveValue>,
73 right: Box<ReactiveValue>,
74 loc: Option<SourceLocation>,
75 },
76
77 /// TS: ReactiveTernaryValue
78 ConditionalExpression {
79 test: Box<ReactiveValue>,
80 consequent: Box<ReactiveValue>,
81 alternate: Box<ReactiveValue>,
82 loc: Option<SourceLocation>,
83 },
84
85 /// TS: ReactiveSequenceValue
86 SequenceExpression {
87 instructions: Vec<ReactiveInstruction>,
88 id: EvaluationOrder,
89 value: Box<ReactiveValue>,
90 loc: Option<SourceLocation>,
91 },
92
93 /// TS: ReactiveOptionalCallValue
94 OptionalExpression {
95 id: EvaluationOrder,
96 value: Box<ReactiveValue>,
97 optional: bool,
98 loc: Option<SourceLocation>,
99 },
100 }
101 ```
102
103 ### Terminals
104
105 ```rust
106 pub struct ReactiveTerminalStatement {
107 pub terminal: ReactiveTerminal,
108 pub label: Option<ReactiveLabel>,
109 }
110
111 pub struct ReactiveLabel {
112 pub id: BlockId,
113 pub implicit: bool,
114 }
115
116 pub enum ReactiveTerminalTargetKind {
117 Implicit,
118 Labeled,
119 Unlabeled,
120 }
121
122 pub enum ReactiveTerminal {
123 Break {
124 target: BlockId,
125 id: EvaluationOrder,
126 target_kind: ReactiveTerminalTargetKind,
127 loc: Option<SourceLocation>,
128 },
129 Continue {
130 target: BlockId,
131 id: EvaluationOrder,
132 target_kind: ReactiveTerminalTargetKind,
133 loc: Option<SourceLocation>,
134 },
135 Return {
136 value: Place,
137 id: EvaluationOrder,
138 loc: Option<SourceLocation>,
139 },
140 Throw {
141 value: Place,
142 id: EvaluationOrder,
143 loc: Option<SourceLocation>,
144 },
145 Switch {
146 test: Place,
147 cases: Vec<ReactiveSwitchCase>,
148 id: EvaluationOrder,
149 loc: Option<SourceLocation>,
150 },
151 DoWhile {
152 loop_block: ReactiveBlock, // "loop" is a Rust keyword
153 test: ReactiveValue,
154 id: EvaluationOrder,
155 loc: Option<SourceLocation>,
156 },
157 While {
158 test: ReactiveValue,
159 loop_block: ReactiveBlock,
160 id: EvaluationOrder,
161 loc: Option<SourceLocation>,
162 },
163 For {
164 init: ReactiveValue,
165 test: ReactiveValue,
166 update: Option<ReactiveValue>,
167 loop_block: ReactiveBlock,
168 id: EvaluationOrder,
169 loc: Option<SourceLocation>,
170 },
171 ForOf {
172 init: ReactiveValue,
173 test: ReactiveValue,
174 loop_block: ReactiveBlock,
175 id: EvaluationOrder,
176 loc: Option<SourceLocation>,
177 },
178 ForIn {
179 init: ReactiveValue,
180 loop_block: ReactiveBlock,
181 id: EvaluationOrder,
182 loc: Option<SourceLocation>,
183 },
184 If {
185 test: Place,
186 consequent: ReactiveBlock,
187 alternate: Option<ReactiveBlock>,
188 id: EvaluationOrder,
189 loc: Option<SourceLocation>,
190 },
191 Label {
192 block: ReactiveBlock,
193 id: EvaluationOrder,
194 loc: Option<SourceLocation>,
195 },
196 Try {
197 block: ReactiveBlock,
198 handler_binding: Option<Place>,
199 handler: ReactiveBlock,
200 id: EvaluationOrder,
201 loc: Option<SourceLocation>,
202 },
203 }
204
205 pub struct ReactiveSwitchCase {
206 pub test: Option<Place>,
207 pub block: Option<ReactiveBlock>, // TS: ReactiveBlock | void
208 }
209 ```
210
211 ### Scope Blocks
212
213 ```rust
214 pub struct ReactiveScopeBlock {
215 pub scope: ScopeId, // Arena pattern: scope data in Environment
216 pub instructions: ReactiveBlock,
217 }
218
219 pub struct PrunedReactiveScopeBlock {
220 pub scope: ScopeId,
221 pub instructions: ReactiveBlock,
222 }
223 ```
224
225 ### Reused Existing Types
226
227 All of these are already defined in `react_compiler_hir`:
228 - `Place`, `InstructionValue`, `AliasingEffect`, `LogicalOperator`, `ParamPattern`
229 - `BlockId`, `ScopeId`, `IdentifierId`, `EvaluationOrder`, `TypeId`, `FunctionId`
230 - `SourceLocation` (from `react_compiler_diagnostics`)
231 - `ReactiveScope`, `ReactiveScopeDependency`, `ReactiveScopeDeclaration`, `ReactiveScopeEarlyReturn`
232
233 ### Key Design Decisions
234
235 1. **ReactiveValue wraps InstructionValue**: `ReactiveValue::Instruction(InstructionValue)` wraps the existing ~35-variant enum. Passes that match specific kinds use `ReactiveValue::Instruction(InstructionValue::FunctionExpression { .. })`.
236
237 2. **Box for recursive types**: `ReactiveValue` fields use `Box<ReactiveValue>` for recursion. `ReactiveBlock` (Vec) naturally heap-allocates, breaking the size cycle for terminals.
238
239 3. **ScopeId, not cloned scope**: `ReactiveScopeBlock` stores `ScopeId`. Scope data lives in `env.scopes[scope_id]`. Passes that read/write scope data access it through the environment.
240
241 4. **No Environment on ReactiveFunction**: Passes take `env: &Environment` or `env: &mut Environment` as a separate parameter, following the established Rust pattern.
242
243 5. **EvaluationOrder, not InstructionId**: The TS `InstructionId` (evaluation order counter) maps to Rust `EvaluationOrder`. Rust's `InstructionId` is the flat instruction table index (not used in reactive types).
244
245 ## 2. New Crate: `react_compiler_reactive_scopes`
246
247 ```
248 compiler/crates/react_compiler_reactive_scopes/
249 Cargo.toml
250 src/
251 lib.rs
252 build_reactive_function.rs
253 print_reactive_function.rs
254 visitors.rs
255 assert_well_formed_break_targets.rs
256 assert_scope_instructions_within_scopes.rs
257 prune_unused_labels.rs
258 prune_non_escaping_scopes.rs
259 prune_non_reactive_dependencies.rs
260 prune_unused_scopes.rs
261 merge_reactive_scopes_that_invalidate_together.rs
262 prune_always_invalidating_scopes.rs
263 propagate_early_returns.rs
264 prune_unused_lvalues.rs
265 promote_used_temporaries.rs
266 extract_scope_declarations_from_destructuring.rs
267 stabilize_block_ids.rs
268 rename_variables.rs
269 prune_hoisted_contexts.rs
270 validate_preserved_manual_memoization.rs
271 ```
272
273 **Cargo.toml dependencies**: `react_compiler_hir`, `react_compiler_diagnostics`, `indexmap`
274
275 Add to workspace `Cargo.toml` members and as dependency of `react_compiler`.
276
277 Maps to TS directory: `src/ReactiveScopes/`
278
279 ## 3. Debug Printing
280
281 ### Approach: New Verbose Format (like DebugPrintHIR)
282
283 Create a new verbose `DebugPrintReactiveFunction` format that prints every field of every type recursively, analogous to `DebugPrintHIR`. Both TS and Rust need new implementations.
284
285 ### TS Side
286
287 Create `compiler/packages/babel-plugin-react-compiler/src/HIR/DebugPrintReactiveFunction.ts`:
288
289 - Entry point: `export function printDebugReactiveFunction(fn: ReactiveFunction): string`
290 - Uses the same `DebugPrinter` class from `DebugPrintHIR.ts`
291 - Prints function metadata: id, name_hint, generator, async, loc, params (full Place detail), directives
292 - Recursively prints `fn.body` (ReactiveBlock):
293 - `ReactiveInstruction`: id, lvalue (full Place with identifier declaration), value, effects, loc
294 - `ReactiveScopeBlock`/`PrunedReactiveScopeBlock`: full scope detail (id, range, dependencies with paths and locs, declarations with identifier info, reassignments, earlyReturnValue, merged, loc), then nested instructions
295 - `ReactiveTerminalStatement`: label info, terminal kind, all fields including nested blocks
296 - `ReactiveValue` compound types: kind, all fields recursively; `Instruction` variant delegates to `formatInstructionValue`
297 - Appends outlined functions and Environment errors (same pattern as DebugPrintHIR)
298 - Reuses shared formatters: `formatPlace`, `formatIdentifier`, `formatType`, `formatLoc`, `formatAliasingEffect`, `formatInstructionValue`
299 - Export from `compiler/packages/babel-plugin-react-compiler/src/HIR/index.ts`
300
301 ### Rust Side
302
303 `compiler/crates/react_compiler_reactive_scopes/src/print_reactive_function.rs`:
304
305 - Entry point: `pub fn debug_reactive_function(func: &ReactiveFunction, env: &Environment) -> String`
306 - Uses the `DebugPrinter` struct pattern from `compiler/crates/react_compiler/src/debug_print.rs`
307 - Must produce output identical to the TS `printDebugReactiveFunction`
308
309 ### Shared Print Helpers
310
311 Extract these as `pub` from `compiler/crates/react_compiler/src/debug_print.rs` (currently private):
312 - `format_place(place, env) -> String`
313 - `format_identifier(id, env) -> String`
314 - `format_type(type_id, env) -> String`
315 - `format_loc(loc) -> String`
316 - `format_aliasing_effect(effect) -> String`
317 - `format_instruction_value(value, env, indent) -> Vec<String>`
318 - The `DebugPrinter` struct itself (or extract to a shared module)
319
320 ## 4. Test Infrastructure Changes
321
322 ### `compiler/scripts/test-rust-port.ts`
323
324 1. **Import** `printDebugReactiveFunction` from the new TS file
325
326 2. **Handle `kind: 'reactive'`** — replace the `throw new Error(...)` at lines 297-305:
327 ```typescript
328 } else if (entry.kind === 'reactive') {
329 log.push({
330 kind: 'entry',
331 name: entry.name,
332 value: printDebugReactiveFunction(entry.value),
333 });
334 }
335 ```
336
337 3. **Handle `kind: 'ast'`** — keep the TODO error for now (codegen is deferred)
338
339 4. **ID normalization** — the existing `normalizeIds` function handles `bb\d+`, `@\d+`, `Identifier(\d+)`, `Type(\d+)`, `\w+\$\d+`, `mutableRange` patterns. Should work for reactive output. Verify after BuildReactiveFunction is ported; may need additional patterns for scope-specific fields in the verbose format.
340
341 ### Rust Pipeline (`pipeline.rs`)
342
343 After `PropagateScopeDependenciesHIR`, transition from HIR to ReactiveFunction:
344
345 ```rust
346 let mut reactive_fn = react_compiler_reactive_scopes::build_reactive_function(&hir, &env);
347 let debug = react_compiler_reactive_scopes::debug_reactive_function(&reactive_fn, &env);
348 context.log_debug(DebugLogEntry::new("BuildReactiveFunction", debug));
349
350 react_compiler_reactive_scopes::assert_well_formed_break_targets(&reactive_fn)?;
351 context.log_debug(DebugLogEntry::new("AssertWellFormedBreakTargets", "ok".to_string()));
352
353 react_compiler_reactive_scopes::prune_unused_labels(&mut reactive_fn);
354 let debug = react_compiler_reactive_scopes::debug_reactive_function(&reactive_fn, &env);
355 context.log_debug(DebugLogEntry::new("PruneUnusedLabels", debug));
356
357 // ... etc for each pass
358 ```
359
360 ## 5. Phased Porting Plan
361
362 ### Phase 1 — Foundation
363
364 1. Create `reactive.rs` in `react_compiler_hir` with all types from Section 1
365 2. Create `react_compiler_reactive_scopes` crate skeleton with `Cargo.toml` and empty `lib.rs`
366 3. Create TS `DebugPrintReactiveFunction.ts` with verbose format
367 4. Extract shared print helpers from `debug_print.rs` as public
368 5. Port verbose format to Rust `print_reactive_function.rs`
369 6. Update `test-rust-port.ts` to handle `kind: 'reactive'`
370
371 ### Phase 2 — BuildReactiveFunction
372
373 The critical pass (~700 lines). Converts HIR CFG to ReactiveFunction tree.
374
375 - **Source**: `compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/BuildReactiveFunction.ts`
376 - **Target**: `compiler/crates/react_compiler_reactive_scopes/src/build_reactive_function.rs`
377 - **Key structures to port**:
378 - `Context` class: tracks `emitted: Set<BlockId>`, `scopeFallthroughs: Set<BlockId>`, `#scheduled: Set<BlockId>`, `#catchHandlers: Set<BlockId>`, `#controlFlowStack: Array<ControlFlowTarget>`
379 - `Driver` class: `traverseBlock`, `visitBlock`, `visitValueBlock`, `visitValueBlockTerminal`, `visitTestBlock`, `extractValueBlockResult`, `wrapWithSequence`, `visitBreak`, `visitContinue`
380 - **Signature**: `pub fn build_reactive_function(hir: &HirFunction, env: &Environment) -> ReactiveFunction`
381 - **Wire into pipeline.rs**
382 - **Test**: `bash compiler/scripts/test-rust-port.sh BuildReactiveFunction`
383
384 ### Phase 3 — Validation Passes
385
386 - `assert_well_formed_break_targets` (~30 lines) — checks break/continue targets exist
387 - `assert_scope_instructions_within_scopes` (~80 lines) — validates scope ranges contain instructions
388
389 ### Phase 4 — Simple Transforms (pipeline order)
390
391 1. `prune_unused_labels` (~50 lines) — removes unnecessary labels emitted by BuildReactiveFunction
392 2. `prune_non_reactive_dependencies` (~40 lines) — removes non-reactive deps from scopes
393 3. `prune_unused_scopes` (~60 lines) — converts scopes without outputs to pruned-scopes
394 4. `prune_always_invalidating_scopes` (~80 lines) — removes always-invalidating scopes
395 5. `prune_unused_lvalues` (~70 lines) — nulls out unused lvalues
396 6. `stabilize_block_ids` (~60 lines) — renumbers block IDs for stable output
397
398 ### Phase 5 — Complex Transforms (pipeline order)
399
400 1. `prune_non_escaping_scopes` (~500 lines) — most complex reactive pass, removes scopes for non-escaping values
401 2. `merge_reactive_scopes_that_invalidate_together` (~400 lines) — merges adjacent scopes with same deps
402 3. `propagate_early_returns` (~200 lines) — handles early returns inside reactive scopes
403 4. `promote_used_temporaries` (~400 lines) — promotes temporaries to named variables
404 5. `extract_scope_declarations_from_destructuring` (~150 lines) — handles destructuring in scope declarations
405 6. `rename_variables` (~200 lines) — renames variables for output, returns `HashSet<String>`
406 7. `prune_hoisted_contexts` (~100 lines) — removes hoisted context declarations
407
408 ### Phase 6 — Codegen (deferred, separate plan)
409
410 - `codegen_function` (~2000+ lines) — converts ReactiveFunction to CodegenFunction (Babel AST)
411 - Depends on Babel AST output types being available in Rust
412 - Will be planned separately
413
414 ## 6. Pass Signatures
415
416 ```rust
417 // Construction:
418 pub fn build_reactive_function(hir: &HirFunction, env: &Environment) -> ReactiveFunction;
419
420 // Debug printing:
421 pub fn debug_reactive_function(func: &ReactiveFunction, env: &Environment) -> String;
422
423 // Validation (read-only):
424 pub fn assert_well_formed_break_targets(func: &ReactiveFunction) -> Result<(), CompilerDiagnostic>;
425 pub fn assert_scope_instructions_within_scopes(func: &ReactiveFunction, env: &Environment) -> Result<(), CompilerDiagnostic>;
426
427 // Transforms (no env needed):
428 pub fn prune_unused_labels(func: &mut ReactiveFunction);
429 pub fn stabilize_block_ids(func: &mut ReactiveFunction);
430
431 // Transforms (read env for scope/identifier data):
432 pub fn prune_non_escaping_scopes(func: &mut ReactiveFunction, env: &Environment);
433 pub fn prune_non_reactive_dependencies(func: &mut ReactiveFunction, env: &Environment);
434 pub fn prune_unused_scopes(func: &mut ReactiveFunction, env: &Environment);
435 pub fn prune_always_invalidating_scopes(func: &mut ReactiveFunction, env: &Environment);
436 pub fn prune_unused_lvalues(func: &mut ReactiveFunction, env: &Environment);
437 pub fn promote_used_temporaries(func: &mut ReactiveFunction, env: &Environment);
438 pub fn prune_hoisted_contexts(func: &mut ReactiveFunction, env: &Environment);
439
440 // Transforms (mutate env — create temporaries, modify scope data):
441 pub fn merge_reactive_scopes_that_invalidate_together(func: &mut ReactiveFunction, env: &mut Environment);
442 pub fn propagate_early_returns(func: &mut ReactiveFunction, env: &mut Environment);
443 pub fn rename_variables(func: &mut ReactiveFunction, env: &mut Environment) -> HashSet<String>;
444 pub fn extract_scope_declarations_from_destructuring(func: &mut ReactiveFunction, env: &mut Environment);
445
446 // Validation (optional, gated on config):
447 pub fn validate_preserved_manual_memoization(func: &ReactiveFunction, env: &Environment) -> Result<(), CompilerDiagnostic>;
448 ```
449
450 ## 7. Visitor/Transform Framework
451
452 Use closure-based traversal helpers and direct recursion, matching the existing Rust codebase style (standalone functions, not trait hierarchies).
453
454 ```rust
455 /// Read-only traversal of all statements in a block (recursive into nested blocks)
456 pub fn visit_reactive_block(block: &ReactiveBlock, visitor: &mut impl FnMut(&ReactiveStatement));
457
458 /// Mutating traversal with drain-and-rebuild pattern
459 pub fn transform_reactive_block(
460 block: &mut ReactiveBlock,
461 transform: &mut impl FnMut(ReactiveStatement) -> TransformResult,
462 );
463
464 pub enum TransformResult {
465 Keep(ReactiveStatement),
466 Remove,
467 Replace(ReactiveStatement),
468 ReplaceMany(Vec<ReactiveStatement>),
469 }
470
471 /// Iterate over all Place operands in a ReactiveValue
472 pub fn each_reactive_value_operand(value: &ReactiveValue) -> impl Iterator<Item = &Place>;
473
474 /// Map over all blocks contained in a ReactiveTerminal
475 pub fn map_terminal_blocks(terminal: &mut ReactiveTerminal, f: impl FnMut(&mut ReactiveBlock));
476 ```
477
478 The drain-and-rebuild pattern for transforms:
479 1. `let stmts: Vec<_> = block.drain(..).collect();`
480 2. For each statement, call the transform closure
481 3. Collect results into a new Vec
482 4. Assign back to `*block`
483
484 This avoids borrow checker issues with in-place mutation while iterating.
485
486 ## 8. Skill Updates
487
488 ### `compiler/.claude/skills/compiler-orchestrator/SKILL.md`
489
490 Expand pass table rows #32-#49:
491
492 | # | Log Name | Kind | Notes |
493 |---|----------|------|-------|
494 | 32 | BuildReactiveFunction | reactive | |
495 | 33 | AssertWellFormedBreakTargets | debug | Validation |
496 | 34 | PruneUnusedLabels | reactive | |
497 | 35 | AssertScopeInstructionsWithinScopes | debug | Validation |
498 | 36 | PruneNonEscapingScopes | reactive | |
499 | 37 | PruneNonReactiveDependencies | reactive | |
500 | 38 | PruneUnusedScopes | reactive | |
501 | 39 | MergeReactiveScopesThatInvalidateTogether | reactive | |
502 | 40 | PruneAlwaysInvalidatingScopes | reactive | |
503 | 41 | PropagateEarlyReturns | reactive | |
504 | 42 | PruneUnusedLValues | reactive | |
505 | 43 | PromoteUsedTemporaries | reactive | |
506 | 44 | ExtractScopeDeclarationsFromDestructuring | reactive | |
507 | 45 | StabilizeBlockIds | reactive | |
508 | 46 | RenameVariables | reactive | |
509 | 47 | PruneHoistedContexts | reactive | |
510 | 48 | ValidatePreservedManualMemoization | debug | Conditional |
511 | 49 | Codegen | ast | |
512
513 Remove "BLOCKED" status from #32. Add crate mapping: `src/ReactiveScopes/` -> `react_compiler_reactive_scopes`.
514
515 ### `compiler/.claude/skills/compiler-port/SKILL.md`
516
517 - **Step 0**: Remove the block on `kind: 'reactive'` passes (currently says "report that test-rust-port only supports `hir` kind passes currently and stop")
518 - **Step 1**: Add `src/ReactiveScopes/` -> `react_compiler_reactive_scopes` to the TS-to-Rust crate mapping table
519 - **Step 2**: Add reactive types file to context gathering list
520
521 ### `compiler/.claude/agents/port-pass.md`
522
523 - Add note that reactive passes take `&mut ReactiveFunction` + `&Environment`/`&mut Environment` (not `&mut HirFunction`)
524 - Test command remains: `bash compiler/scripts/test-rust-port.sh <PassName>`
525
526 ## 9. Key Files
527
528 | File | Action |
529 |------|--------|
530 | `compiler/crates/react_compiler_hir/src/reactive.rs` | Create: all reactive types |
531 | `compiler/crates/react_compiler_hir/src/lib.rs` | Edit: `pub mod reactive; pub use reactive::*;` |
532 | `compiler/crates/react_compiler_reactive_scopes/` | Create: new crate |
533 | `compiler/crates/Cargo.toml` (workspace) | Edit: add member |
534 | `compiler/crates/react_compiler/Cargo.toml` | Edit: add dependency |
535 | `compiler/crates/react_compiler/src/debug_print.rs` | Edit: extract shared helpers as `pub` |
536 | `compiler/crates/react_compiler/src/entrypoint/pipeline.rs` | Edit: wire reactive passes |
537 | `compiler/packages/.../src/HIR/DebugPrintReactiveFunction.ts` | Create: verbose debug printer |
538 | `compiler/packages/.../src/HIR/index.ts` | Edit: export |
539 | `compiler/scripts/test-rust-port.ts` | Edit: handle `kind: 'reactive'` |
540 | `compiler/.claude/skills/compiler-orchestrator/SKILL.md` | Edit: expand pass table |
541 | `compiler/.claude/skills/compiler-port/SKILL.md` | Edit: remove reactive block, add crate mapping |
542 | `compiler/.claude/agents/port-pass.md` | Edit: add reactive pass patterns |
543
544 ## 10. TS Source Files Reference
545
546 | Pass | TS Source |
547 |------|-----------|
548 | BuildReactiveFunction | `src/ReactiveScopes/BuildReactiveFunction.ts` |
549 | AssertWellFormedBreakTargets | `src/ReactiveScopes/AssertWellFormedBreakTargets.ts` |
550 | PruneUnusedLabels | `src/ReactiveScopes/PruneUnusedLabels.ts` |
551 | AssertScopeInstructionsWithinScopes | `src/ReactiveScopes/AssertScopeInstructionsWithinScopes.ts` |
552 | PruneNonEscapingScopes | `src/ReactiveScopes/PruneNonEscapingScopes.ts` |
553 | PruneNonReactiveDependencies | `src/ReactiveScopes/PruneNonReactiveDependencies.ts` |
554 | PruneUnusedScopes | `src/ReactiveScopes/PruneUnusedScopes.ts` |
555 | MergeReactiveScopesThatInvalidateTogether | `src/ReactiveScopes/MergeReactiveScopesThatInvalidateTogether.ts` |
556 | PruneAlwaysInvalidatingScopes | `src/ReactiveScopes/PruneAlwaysInvalidatingScopes.ts` |
557 | PropagateEarlyReturns | `src/ReactiveScopes/PropagateEarlyReturns.ts` |
558 | PruneUnusedLValues | `src/ReactiveScopes/PruneTemporaryLValues.ts` |
559 | PromoteUsedTemporaries | `src/ReactiveScopes/PromoteUsedTemporaries.ts` |
560 | ExtractScopeDeclarationsFromDestructuring | `src/ReactiveScopes/ExtractScopeDeclarationsFromDestructuring.ts` |
561 | StabilizeBlockIds | `src/ReactiveScopes/StabilizeBlockIds.ts` |
562 | RenameVariables | `src/ReactiveScopes/RenameVariables.ts` |
563 | PruneHoistedContexts | `src/ReactiveScopes/PruneHoistedContexts.ts` |
564 | ValidatePreservedManualMemoization | `src/Validation/ValidatePreservedManualMemoization.ts` |
565 | Visitors/Transform | `src/ReactiveScopes/visitors.ts` |
566 | PrintReactiveFunction | `src/ReactiveScopes/PrintReactiveFunction.ts` |
567 | CodegenReactiveFunction | `src/ReactiveScopes/CodegenReactiveFunction.ts` |