WP1: HIR types & construction (@analyzer subagent)

/home/jm/data/ai/cloudlang-trees/react · 5 messages · 27 parts · · 165,701 tokens
Created Feb 10, 03:17:49 AM · Updated Feb 11, 04:54:11 AM · 1 syncs
userFeb 10, 03:17:49 AM

You are analyzing the React Compiler's HIR (High-level Intermediate Representation) type system and construction. This is RESEARCH ONLY -- do NOT edit or write any files. Only read and analyze.

The React Compiler source is at:
/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/

The CloudLang project (an OCaml compiler that decomposes TypeScript closures into Cloudflare Workers) is at:
/home/jm/data/ai/cloudlang-trees/react/

Files to read and analyze from the React Compiler:

  1. HIR/HIR.ts - Core type definitions (~1700+ lines, read it in chunks using offset/limit)
  2. HIR/Types.ts - Type system types
  3. HIR/ObjectShape.ts - Function signature / shape system
  4. HIR/BuildHIR.ts - AST -> HIR lowering
  5. HIR/HIRBuilder.ts - HIR construction helpers
  6. HIR/visitors.ts - HIR traversal utilities
  7. HIR/PrintHIR.ts - Debug printing

Also read CloudLang's types for comparison:

  • /home/jm/data/ai/cloudlang-trees/react/lib/ast.ml
  • /home/jm/data/ai/cloudlang-trees/react/lib/ir.ml

For each major component, produce documentation in this template:

# Component Name

## File
## Purpose
## Input Invariants
## Output Guarantees
## Algorithm (detailed, step-by-step)
## Key Data Structures (with type signatures)
## Edge Cases
## Mapping to CloudLang
  - What we'd adapt and how
  - What we'd skip and why  
  - OCaml type sketches for the adapted versions
## Example (before/after transformation)

Specific questions to answer:

  1. HIR Core Model: What are Place, Identifier, Instruction, InstructionValue, Terminal, BasicBlock, HIR, HIRFunction? How do they relate? Draw the ownership/containment hierarchy.

  2. Identity System: How are BlockId, InstructionId, IdentifierId, ScopeId generated and used? Why branded/opaque types?

  3. InstructionValue variants: List ALL variants with their data. For each: (a) relevant to CloudLang? (b) what data does it carry? Group by category (loads, stores, expressions, control flow, etc.)

  4. Terminal variants: List ALL variants. Same treatment.

  5. Place/Identifier distinction: Why separate? What do effect, reactive, mutableRange, scope fields buy you?

  6. BuildHIR lowering: How does it convert AST to HIR? How are control flow constructs (if/else, loops, try/catch) handled? How are scopes and variables managed?

  7. Type System (Types.ts): What types exist? How does the shape system (ObjectShape.ts) encode function signatures?

  8. Visitor patterns (visitors.ts): What traversal abstractions exist?

  9. CloudLang mapping: CloudLang has a flat 19-node ESTree AST and a Cloudflare-config IR with no HIR between them. Sketch what a CloudLang HIR would look like in OCaml types -- starting minimal (matching current 19 AST nodes) but designed for incremental expansion. It needs to support SSA, effect annotation, and mutable ranges.

Return your complete analysis as a single structured markdown document in your final message to me.

assistantFeb 10, 03:17:49 AM
glm-4.7 · zai-coding-plan
This is a research-only task. I need to read and analyze the React Compiler's HIR type system and construction, then produce comprehensive documentation comparing it to CloudLang's approach. Let me start by reading the key files from the React Compiler and CloudLang project. I'll need to read: 1. React Compiler HIR files: - HIR/HIR.ts (core type definitions - ~1700+ lines, need to read in chunks) - HIR/Types.ts (type system) - HIR/ObjectShape.ts (function signature/shape system) - HIR/BuildHIR.ts (AST -> HIR lowering) - HIR/HIRBuilder.ts (HIR construction helpers) - HIR/visitors.ts (HIR traversal) - HIR/PrintHIR.ts (debug printing) 2. CloudLang files: - lib/ast.ml - lib/ir.ml Let me start by reading these files. I'll need to read HIR.ts in chunks since it's 1700+ lines.

I'll analyze the React Compiler's HIR type system and compare it with CloudLang. Let me start by reading all the relevant files.

readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
Output
<file>
00001| /**
00002|  * Copyright (c) Meta Platforms, Inc. and affiliates.
00003|  *
00004|  * This source code is licensed under the MIT license found in the
00005|  * LICENSE file in the root directory of this source tree.
00006|  */
00007| 
00008| import {BindingKind} from '@babel/traverse';
00009| import * as t from '@babel/types';
00010| import {
00011|   CompilerDiagnostic,
00012|   CompilerError,
00013|   ErrorCategory,
00014| } from '../CompilerError';
00015| import {assertExhaustive} from '../Utils/utils';
00016| import {Environment, ReactFunctionType} from './Environment';
00017| import type {HookKind} from './ObjectShape';
00018| import {Type, makeType} from './Types';
00019| import {z} from 'zod/v4';
00020| import type {AliasingEffect} from '../Inference/AliasingEffects';
00021| import {isReservedWord} from '../Utils/Keyword';
00022| import {Err, Ok, Result} from '../Utils/Result';
00023| 
00024| /*
00025|  * *******************************************************************************************
00026|  * *******************************************************************************************
00027|  * ************************************* Core Data Model *************************************
00028|  * *******************************************************************************************
00029|  * *******************************************************************************************
00030|  */
00031| 
00032| // AST -> (lowering) -> HIR -> (analysis) -> Reactive Scopes -> (codegen) -> AST
00033| 
00034| /*
00035|  * A location in a source file, intended to be used for providing diagnostic information and
00036|  * transforming code while preserving source information (ie to emit source maps).
00037|  *
00038|  * `GeneratedSource` indicates that there is no single source location from which the code derives.
00039|  */
00040| export const GeneratedSource = Symbol();
00041| export type SourceLocation = t.SourceLocation | typeof Generate...
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/Types.ts
Output
<file>
00001| /**
00002|  * Copyright (c) Meta Platforms, Inc. and affiliates.
00003|  *
00004|  * This source code is licensed under the MIT license found in the
00005|  * LICENSE file in the root directory of this source tree.
00006|  */
00007| 
00008| import {CompilerError} from '../CompilerError';
00009| import {GeneratedSource, PropertyLiteral} from './HIR';
00010| 
00011| export type BuiltInType = PrimitiveType | FunctionType | ObjectType;
00012| 
00013| export type Type =
00014|   | BuiltInType
00015|   | PhiType
00016|   | TypeVar
00017|   | PolyType
00018|   | PropType
00019|   | ObjectMethod;
00020| export type PrimitiveType = {kind: 'Primitive'};
00021| 
00022| /*
00023|  * An {@link FunctionType} or {@link ObjectType} (also a JS object) may be associated with an
00024|  * inferred "object shape", i.e. a known property (key -> Type) map. This is
00025|  * subtly different from JS language semantics - `shape` represents both
00026|  * OwnPropertyDescriptors and properties present in the prototype chain.
00027|  *
00028|  * {@link ObjectShape.functionType} is always present on the shape of a {@link FunctionType},
00029|  * and it represents the call signature of the function. Note that Forget thinks of a
00030|  * {@link FunctionType} as any "callable object" (not to be confused with objects that
00031|  *   extend the global `Function`.)
00032|  *
00033|  * If `shapeId` is present, it is a key into the ShapeRegistry used to infer this
00034|  * FunctionType or ObjectType instance (i.e. from an Environment).
00035|  */
00036| 
00037| export type FunctionType = {
00038|   kind: 'Function';
00039|   shapeId: string | null;
00040|   return: Type;
00041|   isConstructor: boolean;
00042| };
00043| 
00044| export type ObjectType = {
00045|   kind: 'Object';
00046|   shapeId: string | null;
00047| };
00048| 
00049| export type TypeVar = {
00050|   kind: 'Type';
00051|   id: TypeId;
00052| };
00053| export type PolyType = {
00054|   kind: 'Poly';
00055| };
00056| e...
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts
Output
<file>
00001| /**
00002|  * Copyright (c) Meta Platforms, Inc. and affiliates.
00003|  *
00004|  * This source code is licensed under the MIT license found in the
00005|  * LICENSE file in the root directory of this source tree.
00006|  */
00007| 
00008| import {CompilerError} from '../CompilerError';
00009| import {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';
00010| import {assertExhaustive} from '../Utils/utils';
00011| import {
00012|   Effect,
00013|   GeneratedSource,
00014|   Hole,
00015|   makeDeclarationId,
00016|   makeIdentifierId,
00017|   makeInstructionId,
00018|   Place,
00019|   SourceLocation,
00020|   SpreadPattern,
00021|   ValueKind,
00022|   ValueReason,
00023| } from './HIR';
00024| import {
00025|   BuiltInType,
00026|   FunctionType,
00027|   makeType,
00028|   ObjectType,
00029|   PolyType,
00030|   PrimitiveType,
00031| } from './Types';
00032| import {AliasingEffectConfig, AliasingSignatureConfig} from './TypeSchema';
00033| 
00034| /*
00035|  * This file exports types and defaults for JavaScript object shapes. These are
00036|  * stored and used by a Forget `Environment`. See comments in `Types.ts`,
00037|  * `Globals.ts`, and `Environment.ts` for more details.
00038|  */
00039| 
00040| const PRIMITIVE_TYPE: PrimitiveType = {
00041|   kind: 'Primitive',
00042| };
00043| 
00044| let nextAnonId = 0;
00045| /*
00046|  * We currently use strings for anonymous ShapeIds since they are easily
00047|  * debuggable, even though `Symbol()` might be more performant
00048|  */
00049| function createAnonId(): string {
00050|   return `<generated_${nextAnonId++}>`;
00051| }
00052| 
00053| /*
00054|  * Add a non-hook function to an existing ShapeRegistry.
00055|  *
00056|  * @returns a {@link FunctionType} representing the added function.
00057|  */
00058| export function addFunction(
00059|   registry: ShapeRegistry,
00060|   properties: Iterable<[string, BuiltInType | PolyType]>,
00061|   fn: Omit<FunctionSignature, 'hookKind...
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts
Output
<file>
00001| /**
00002|  * Copyright (c) Meta Platforms, Inc. and affiliates.
00003|  *
00004|  * This source code is licensed under the MIT license found in the
00005|  * LICENSE file in the root directory of this source tree.
00006|  */
00007| 
00008| import {Binding, NodePath} from '@babel/traverse';
00009| import * as t from '@babel/types';
00010| import {CompilerError, ErrorCategory} from '../CompilerError';
00011| import {Environment} from './Environment';
00012| import {
00013|   BasicBlock,
00014|   BlockId,
00015|   BlockKind,
00016|   Effect,
00017|   GeneratedSource,
00018|   GotoVariant,
00019|   HIR,
00020|   Identifier,
00021|   IdentifierId,
00022|   Instruction,
00023|   Place,
00024|   SourceLocation,
00025|   Terminal,
00026|   VariableBinding,
00027|   makeBlockId,
00028|   makeDeclarationId,
00029|   makeIdentifierName,
00030|   makeInstructionId,
00031|   makeTemporaryIdentifier,
00032|   makeType,
00033| } from './HIR';
00034| import {printInstruction} from './PrintHIR';
00035| import {
00036|   eachTerminalSuccessor,
00037|   mapTerminalSuccessors,
00038|   terminalFallthrough,
00039| } from './visitors';
00040| 
00041| /*
00042|  * *******************************************************************************************
00043|  * *******************************************************************************************
00044|  * ************************************* Lowering to HIR *************************************
00045|  * *******************************************************************************************
00046|  * *******************************************************************************************
00047|  */
00048| 
00049| // A work-in-progress block that does not yet have a terminator
00050| export type WipBlock = {
00051|   id: BlockId;
00052|   instructions: Array<Instruction>;
00053|   kind: BlockKind;
00054| };
00055| 
00056| type Scope = LoopScope | LabelScope | SwitchScope;
00057| 
00058| type LoopScope = {
00...
11,078in / 394out / 215reasoning
assistantFeb 10, 03:18:08 AM
glm-4.7 · zai-coding-plan
Let me continue reading more files to get a complete picture.
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
Output
<file>
00501|   id: InstructionId;
00502|   loc: SourceLocation;
00503| };
00504| 
00505| export type DoWhileTerminal = {
00506|   kind: 'do-while';
00507|   loop: BlockId;
00508|   test: BlockId;
00509|   fallthrough: BlockId;
00510|   id: InstructionId;
00511|   loc: SourceLocation;
00512| };
00513| 
00514| export type WhileTerminal = {
00515|   kind: 'while';
00516|   loc: SourceLocation;
00517|   test: BlockId;
00518|   loop: BlockId;
00519|   fallthrough: BlockId;
00520|   id: InstructionId;
00521| };
00522| 
00523| export type ForTerminal = {
00524|   kind: 'for';
00525|   loc: SourceLocation;
00526|   init: BlockId;
00527|   test: BlockId;
00528|   update: BlockId | null;
00529|   loop: BlockId;
00530|   fallthrough: BlockId;
00531|   id: InstructionId;
00532| };
00533| 
00534| export type ForOfTerminal = {
00535|   kind: 'for-of';
00536|   loc: SourceLocation;
00537|   init: BlockId;
00538|   test: BlockId;
00539|   loop: BlockId;
00540|   fallthrough: BlockId;
00541|   id: InstructionId;
00542| };
00543| 
00544| export type ForInTerminal = {
00545|   kind: 'for-in';
00546|   loc: SourceLocation;
00547|   init: BlockId;
00548|   loop: BlockId;
00549|   fallthrough: BlockId;
00550|   id: InstructionId;
00551| };
00552| 
00553| export type LogicalTerminal = {
00554|   kind: 'logical';
00555|   operator: t.LogicalExpression['operator'];
00556|   test: BlockId;
00557|   fallthrough: BlockId;
00558|   id: InstructionId;
00559|   loc: SourceLocation;
00560| };
00561| 
00562| export type TernaryTerminal = {
00563|   kind: 'ternary';
00564|   test: BlockId;
00565|   fallthrough: BlockId;
00566|   id: InstructionId;
00567|   loc: SourceLocation;
00568| };
00569| 
00570| export type LabelTerminal = {
00571|   kind: 'label';
00572|   block: BlockId;
00573|   fallthrough: BlockId;
00574|   id: InstructionId;
00575|   loc: SourceLocation;
00576| };
00577| 
00578| export type OptionalTerminal = {
00579|   kind: 'optional';
00580|   /*
00581|    * Specifies whether this no...
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
Output
<file>
01001| 
01002|   // store `object.property = value`
01003|   | {
01004|       kind: 'PropertyStore';
01005|       object: Place;
01006|       property: PropertyLiteral;
01007|       value: Place;
01008|       loc: SourceLocation;
01009|     }
01010|   // load `object.property`
01011|   | PropertyLoad
01012|   // `delete object.property`
01013|   | {
01014|       kind: 'PropertyDelete';
01015|       object: Place;
01016|       property: PropertyLiteral;
01017|       loc: SourceLocation;
01018|     }
01019| 
01020|   // store `object[index] = value` - like PropertyStore but with a dynamic property
01021|   | {
01022|       kind: 'ComputedStore';
01023|       object: Place;
01024|       property: Place;
01025|       value: Place;
01026|       loc: SourceLocation;
01027|     }
01028|   // load `object[index]` - like PropertyLoad but with a dynamic property
01029|   | {
01030|       kind: 'ComputedLoad';
01031|       object: Place;
01032|       property: Place;
01033|       loc: SourceLocation;
01034|     }
01035|   // `delete object[property]`
01036|   | {
01037|       kind: 'ComputedDelete';
01038|       object: Place;
01039|       property: Place;
01040|       loc: SourceLocation;
01041|     }
01042|   | LoadGlobal
01043|   | StoreGlobal
01044|   | FunctionExpression
01045|   | {
01046|       kind: 'TaggedTemplateExpression';
01047|       tag: Place;
01048|       value: {raw: string; cooked?: string};
01049|       loc: SourceLocation;
01050|     }
01051|   | {
01052|       kind: 'TemplateLiteral';
01053|       subexprs: Array<Place>;
01054|       quasis: Array<{raw: string; cooked?: string}>;
01055|       loc: SourceLocation;
01056|     }
01057|   | {
01058|       kind: 'Await';
01059|       value: Place;
01060|       loc: SourceLocation;
01061|     }
01062|   | {
01063|       kind: 'GetIterator';
01064|       collection: Place; // the collection
01065|       loc: SourceLocation;
01066|     }
01067|   | {
01068|       kind: 'IteratorNext';
01069|       iterator...
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
Output
<file>
01501|   ValueReason.HookReturn,
01502|   ValueReason.JsxCaptured,
01503|   ValueReason.KnownReturnSignature,
01504|   ValueReason.Other,
01505|   ValueReason.ReactiveFunctionArgument,
01506|   ValueReason.ReducerState,
01507|   ValueReason.State,
01508| ]);
01509| 
01510| // The effect with which a value is modified.
01511| export enum Effect {
01512|   // Default value: not allowed after lifetime inference
01513|   Unknown = '<unknown>',
01514|   // This reference freezes the value (corresponds to a place where codegen should emit a freeze instruction)
01515|   Freeze = 'freeze',
01516|   // This reference reads the value
01517|   Read = 'read',
01518|   // This reference reads and stores the value
01519|   Capture = 'capture',
01520|   ConditionallyMutateIterator = 'mutate-iterator?',
01521|   /*
01522|    * This reference *may* write to (mutate) the value. This covers two similar cases:
01523|    * - The compiler is being conservative and assuming that a value *may* be mutated
01524|    * - The effect is polymorphic: mutable values may be mutated, non-mutable values
01525|    *   will not be mutated.
01526|    * In both cases, we conservatively assume that mutable values will be mutated.
01527|    * But we do not error if the value is known to be immutable.
01528|    */
01529|   ConditionallyMutate = 'mutate?',
01530| 
01531|   /*
01532|    * This reference *does* write to (mutate) the value. It is an error (invalid input)
01533|    * if an immutable value flows into a location with this effect.
01534|    */
01535|   Mutate = 'mutate',
01536|   // This reference may alias to (mutate) the value
01537|   Store = 'store',
01538| }
01539| export const EffectSchema = z.enum([
01540|   Effect.Read,
01541|   Effect.Mutate,
01542|   Effect.ConditionallyMutate,
01543|   Effect.ConditionallyMutateIterator,
01544|   Effect.Capture,
01545|   Effect.Store,
01546|   Effect.Freeze,
01547| ]);
01548| 
01549| export function isMutableEffect(
01550|   effect: Effect,
01551...
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
Output
<file>
00001| /**
00002|  * Copyright (c) Meta Platforms, Inc. and affiliates.
00003|  *
00004|  * This source code is licensed under the MIT license found in the
00005|  * LICENSE file in the root directory of this source tree.
00006|  */
00007| 
00008| import {NodePath, Scope} from '@babel/traverse';
00009| import * as t from '@babel/types';
00010| import invariant from 'invariant';
00011| import {
00012|   CompilerDiagnostic,
00013|   CompilerError,
00014|   CompilerSuggestionOperation,
00015|   ErrorCategory,
00016| } from '../CompilerError';
00017| import {Err, Ok, Result} from '../Utils/Result';
00018| import {assertExhaustive, hasNode} from '../Utils/utils';
00019| import {Environment} from './Environment';
00020| import {
00021|   ArrayExpression,
00022|   ArrayPattern,
00023|   BlockId,
00024|   BranchTerminal,
00025|   BuiltinTag,
00026|   Case,
00027|   Effect,
00028|   GeneratedSource,
00029|   GotoVariant,
00030|   HIRFunction,
00031|   IfTerminal,
00032|   InstructionKind,
00033|   InstructionValue,
00034|   JsxAttribute,
00035|   LoweredFunction,
00036|   ObjectPattern,
00037|   ObjectProperty,
00038|   ObjectPropertyKey,
00039|   Place,
00040|   PropertyLiteral,
00041|   ReturnTerminal,
00042|   SourceLocation,
00043|   SpreadPattern,
00044|   ThrowTerminal,
00045|   Type,
00046|   makeInstructionId,
00047|   makePropertyLiteral,
00048|   makeType,
00049|   promoteTemporary,
00050|   validateIdentifierName,
00051| } from './HIR';
00052| import HIRBuilder, {Bindings, createTemporaryPlace} from './HIRBuilder';
00053| import {BuiltInArrayId} from './ObjectShape';
00054| 
00055| /*
00056|  * *******************************************************************************************
00057|  * *******************************************************************************************
00058|  * ************************************* Lowering to HIR *************************************
00059|  * ***************************************************************...
35,379in / 201out / 12reasoning
assistantFeb 10, 03:18:15 AM
glm-4.7 · zai-coding-plan
I have a lot more reading to do. Let me continue with the remaining HIR file and the other important files. I should also read the CloudLang files.
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts
Output
<file>
00001| /**
00002|  * Copyright (c) Meta Platforms, Inc. and affiliates.
00003|  *
00004|  * This source code is licensed under the MIT license found in the
00005|  * LICENSE file in the root directory of this source tree.
00006|  */
00007| 
00008| import {assertExhaustive} from '../Utils/utils';
00009| import {CompilerError} from '..';
00010| import {
00011|   BasicBlock,
00012|   BlockId,
00013|   Instruction,
00014|   InstructionKind,
00015|   InstructionValue,
00016|   makeInstructionId,
00017|   Pattern,
00018|   Place,
00019|   ReactiveInstruction,
00020|   ReactiveScope,
00021|   ReactiveValue,
00022|   ScopeId,
00023|   SpreadPattern,
00024|   Terminal,
00025| } from './HIR';
00026| 
00027| export function* eachInstructionLValue(
00028|   instr: ReactiveInstruction,
00029| ): Iterable<Place> {
00030|   if (instr.lvalue !== null) {
00031|     yield instr.lvalue;
00032|   }
00033|   yield* eachInstructionValueLValue(instr.value);
00034| }
00035| 
00036| export function* eachInstructionLValueWithKind(
00037|   instr: ReactiveInstruction,
00038| ): Iterable<[Place, InstructionKind]> {
00039|   switch (instr.value.kind) {
00040|     case 'DeclareContext':
00041|     case 'StoreContext':
00042|     case 'DeclareLocal':
00043|     case 'StoreLocal': {
00044|       yield [instr.value.lvalue.place, instr.value.lvalue.kind];
00045|       break;
00046|     }
00047|     case 'Destructure': {
00048|       const kind = instr.value.lvalue.kind;
00049|       for (const place of eachPatternOperand(instr.value.lvalue.pattern)) {
00050|         yield [place, kind];
00051|       }
00052|       break;
00053|     }
00054|     case 'PostfixUpdate':
00055|     case 'PrefixUpdate': {
00056|       yield [instr.value.lvalue, InstructionKind.Reassign];
00057|       break;
00058|     }
00059|   }
00060| }
00061| 
00062| export function* eachInstructionValueLValue(
00063|   value: ReactiveValue,
00064| ): Iterable<Place> {
00065|   switch (value.kind) {
00066|     case 'DeclareCont...
readcompleted
react/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts
Output
<file>
00001| /**
00002|  * Copyright (c) Meta Platforms, Inc. and affiliates.
00003|  *
00004|  * This source code is licensed under the MIT license found in the
00005|  * LICENSE file in the root directory of this source tree.
00006|  */
00007| 
00008| import {CompilerError} from '../CompilerError';
00009| import {printReactiveScopeSummary} from '../ReactiveScopes/PrintReactiveFunction';
00010| import DisjointSet from '../Utils/DisjointSet';
00011| import {assertExhaustive} from '../Utils/utils';
00012| import type {
00013|   FunctionExpression,
00014|   HIR,
00015|   HIRFunction,
00016|   Identifier,
00017|   IdentifierName,
00018|   Instruction,
00019|   InstructionValue,
00020|   LValue,
00021|   ManualMemoDependency,
00022|   MutableRange,
00023|   ObjectMethod,
00024|   ObjectPropertyKey,
00025|   Pattern,
00026|   Phi,
00027|   Place,
00028|   ReactiveInstruction,
00029|   ReactiveScope,
00030|   ReactiveValue,
00031|   SourceLocation,
00032|   SpreadPattern,
00033|   Terminal,
00034|   Type,
00035| } from './HIR';
00036| import {GotoVariant, InstructionKind} from './HIR';
00037| import {AliasingEffect, AliasingSignature} from '../Inference/AliasingEffects';
00038| 
00039| export type Options = {
00040|   indent: number;
00041| };
00042| 
00043| export function printFunctionWithOutlined(fn: HIRFunction): string {
00044|   const output = [printFunction(fn)];
00045|   for (const outlined of fn.env.getOutlinedFunctions()) {
00046|     output.push(`\nfunction ${outlined.fn.id}:\n${printHIR(outlined.fn.body)}`);
00047|   }
00048|   return output.join('\n');
00049| }
00050| 
00051| export function printFunction(fn: HIRFunction): string {
00052|   const output = [];
00053|   let definition = '';
00054|   if (fn.id !== null) {
00055|     definition += fn.id;
00056|   } else {
00057|     definition += '<<anonymous>>';
00058|   }
00059|   if (fn.nameHint != null) {
00060|     definition += ` ${fn.nameHint}`;
00061|   }
00062|   if (fn.params.length !== 0) {
00063|    ...
readcompleted
lib/ast.ml
Output
<file>
00001| (** ESTree-compatible AST subset for TypeScript.
00002| 
00003|     This represents the minimal set of TypeScript constructs needed for
00004|     closure analysis and Worker decomposition. Node types follow the ESTree
00005|     specification used by @typescript-eslint/typescript-estree. *)
00006| 
00007| type var_kind = Const | Let | Var
00008| 
00009| type literal_value =
00010|   | LString of string
00011|   | LNumber of float
00012|   | LBool of bool
00013|   | LNull
00014|   | LUndefined
00015| 
00016| (** A single AST node. The variant name matches the ESTree "type" field. *)
00017| type node =
00018|   | Program of { body : node list }
00019|   | VariableDeclaration of { kind : var_kind; declarations : node list }
00020|   | VariableDeclarator of { id : node; init : node option }
00021|   | Identifier of { name : string }
00022|   | Literal of { value : literal_value }
00023|   | ArrowFunctionExpression of {
00024|       params : node list;
00025|       body : node;
00026|       async_ : bool;
00027|     }
00028|   | BlockStatement of { body : node list }
00029|   | ReturnStatement of { argument : node option }
00030|   | IfStatement of { test : node; consequent : node; alternate : node option }
00031|   | ExpressionStatement of { expression : node }
00032|   | CallExpression of { callee : node; arguments : node list }
00033|   | MemberExpression of { object_ : node; property : node }
00034|   | NewExpression of { callee : node; arguments : node list }
00035|   | BinaryExpression of { operator : string; left : node; right : node }
00036|   | LogicalExpression of { operator : string; left : node; right : node }
00037|   | AwaitExpression of { argument : node }
00038|   | RawCode of { code : string }
00039|       (** Verbatim TypeScript fragment. Used by the lowering pass for
00040|           constructs that don't have AST representation (e.g. object
00041|           literals for fetch options). Not produced by the parser. *)
00042|   | ExportNam...
readcompleted
lib/ir.ml
Output
<file>
00001| type binding =
00002|   | D1Binding of { name : string; database_id : string }
00003|   | KVBinding of { name : string; namespace_id : string }
00004|   | R2Binding of { name : string; bucket_name : string }
00005|   | ServiceBinding of { name : string; service : string }
00006| 
00007| type do_marker =
00008|   | SerialConflictHotspot
00009|   | GlobalSingletonNeeded
00010|   | EntityAffinityKeyed of { key_hint : string option }
00011|   | StrictOrderingRequired
00012|   | ConsistencyBoundaryCrossed
00013|   | RealtimeFanout
00014|   | DurableTimerNeeded
00015|   | HighFanInCoordinator
00016|   | StatelessFastPathPreferWorker
00017| 
00018| type coordination_intent =
00019|   | PerEntitySerial of { key_expr : string; reason : string }
00020|   | GlobalSingleton of { name : string; reason : string }
00021|   | RealtimeRoom of { room_key_expr : string }
00022|   | ScheduledQueue of { queue_key_expr : string }
00023| 
00024| type routing_policy =
00025|   | DeterministicName of { key_expr : string }
00026|   | ShardedName of { key_expr : string; shards : int }
00027|   | UniqueIdPool of { pool : string }
00028| 
00029| type storage_backend = DoSqlite | DoSyncKv
00030| type alarm_mode = NoAlarm | SingleAlarm | QueuedAlarm
00031| 
00032| type durability_policy = {
00033|   storage_backend : storage_backend;
00034|   alarm_mode : alarm_mode;
00035|   pitr_required : bool;
00036| }
00037| 
00038| type do_annotation = {
00039|   class_name : string;
00040|   binding_name : string;
00041|   markers : do_marker list;
00042|   intent : coordination_intent;
00043|   routing : routing_policy;
00044|   durability : durability_policy;
00045|   do_fit_score : int;
00046|   reasons : string list;
00047| }
00048| 
00049| type worker = {
00050|   name : string;
00051|   script : string;
00052|   bindings : binding list;
00053|   routes : string list;
00054|   do_annotation : do_annotation option;
00055| }
00056| 
00057| type durable_object = { class_name : string; scrip...
66,818in / 157out / 33reasoning
assistantFeb 10, 03:18:53 AM
glm-4.7 · zai-coding-plan
I now have a good understanding of the React Compiler's HIR system and CloudLang's approach. Let me compile this comprehensive analysis document. I have all the key information needed to answer the user's specific questions. Let me structure my response to answer all the questions: 1. **HIR Core Model**: What are Place, Identifier, Instruction, InstructionValue, Terminal, BasicBlock, HIR, HIRFunction? 2. **Identity System**: How are BlockId, InstructionId, IdentifierId, ScopeId generated and used? 3. **InstructionValue variants**: List ALL variants with their data 4. **Terminal variants**: List ALL variants 5. **Place/Identifier distinction**: Why separate? 6. **BuildHIR lowering**: How does it convert AST to HIR? 7. **Type System (Types.ts)**: What types exist? 8. **Visitor patterns (visitors.ts)**: What traversal abstractions exist? 9. **CloudLang mapping**: Sketch CloudLang HIR in OCaml types Let me prepare the comprehensive documentation now.

Based on my analysis of the React Compiler's HIR system and CloudLang's architecture, here is my complete research documentation:


React Compiler HIR Type System and Construction Analysis

1. HIR Core Model (HIR.ts - Core Types)

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts

Purpose

Defines the core data model for React Compiler's High-level Intermediate Representation (HIR). This is an SSA-based CFG intermediate form between Babel AST and reactive scope analysis.

Ownership/Containment Hierarchy

HIRFunction (top-level unit)
  └── body: HIR
        ├── entry: BlockId
        └── blocks: Map<BlockId, BasicBlock>
              └── BasicBlock
                    ├── kind: BlockKind
                    ├── id: BlockId
                    ├── instructions: Array<Instruction>
                    ├── terminal: Terminal
                    ├── preds: Set<BlockId>
                    └── phis: Set<Phi>

HIRFunction
  ├── params: Array<Place | SpreadPattern>
  ├── context: Array<Place> (captured vars)
  ├── returns: Place
  └── env: Environment

Key Data Structures:

// HIR - The control flow graph
export type HIR = {
  entry: BlockId;
  blocks: Map<BlockId, BasicBlock>;
};

// BasicBlock - Single entry, single exit sequence of instructions
export type BasicBlock = {
  kind: BlockKind;
  id: BlockId;
  instructions: Array<Instruction>;
  terminal: Terminal;
  preds: Set<BlockId>;
  phis: Set<Phi>;
};

// HIRFunction - A compiled function
export type HIRFunction = {
  loc: SourceLocation;
  id: ValidIdentifierName | null;
  nameHint: string | null;
  fnType: ReactFunctionType;
  env: Environment;
  params: Array<Place | SpreadPattern>;
  returnTypeAnnotation: t.FlowType | t.TSType | null;
  returns: Place;
  context: Array<Place>;
  body: HIR;
  generator: boolean;
  async: boolean;
  directives: Array<string>;
  aliasingEffects: Array<AliasingEffect> | null;
};

// Instruction - A single operation
export type Instruction = {
  id: InstructionId;
  lvalue: Place | null;
  value: InstructionValue;
  effects: Array<AliasingEffect> | null;
  loc: SourceLocation;
};

Input Invariants

  • Block entry has no predecessors (initial entry point)
  • Basic blocks have linear control flow (no branching within block)
  • Instructions in a block execute consecutively
  • Terminal is always the last element in a block

Output Guarantees

  • Blocks are in reverse postorder (predecessors before successors, except back edges)
  • Each block has correct predecessor tracking
  • Instructions have sequential IDs starting from 1
  • All Place references resolve to valid Identifiers

2. Identity System

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts (lines 1709-1781)

Purpose

Uses branded opaque types to prevent accidentally using raw integers as IDs.

// Branded opaque types
const opaqueBlockId = Symbol();
export type BlockId = number & {[opaqueBlockId]: 'BlockId'};

const opaqueScopeId = Symbol();
export type ScopeId = number & {[opaqueScopeId]: 'ScopeId'};

const opaqueIdentifierId = Symbol();
export type IdentifierId = number & {[opaqueIdentifierId]: 'IdentifierId'};

const opageDeclarationId = Symbol();
export type DeclarationId = number & {[opageDeclarationId]: 'DeclarationId'};

const opaqueInstructionId = Symbol();
export type InstructionId = number & {[opaqueInstructionId]: 'IdentifierId'};

// Constructor functions with validation
export function makeBlockId(id: number): BlockId {
  CompilerError.invariant(id >= 0 && Number.isInteger(id), {
    reason: 'Expected block id to be a non-negative integer',
    loc: GeneratedSource,
  });
  return id as BlockId;
}

Why Branded/Opaque Types?

  1. Type Safety: Prevents mixing BlockId, InstructionId, IdentifierId, etc.
  2. API Clarity: Makes it impossible to accidentally pass the wrong ID type
  3. Refactoring Safety: If ID semantics change, compiler catches mismatches

Generation and Usage

  • BlockId: Generated by env.nextBlockId during CFG construction (HIRBuilder)
  • InstructionId: Assigned after CFG completion in markInstructionIds() (sequential 1..N)
  • IdentifierId: Generated by env.nextIdentifierId during variable resolution
  • DeclarationId: Assigned once per original variable declaration (used for SSA phi nodes)
  • ScopeId: Generated during reactive scope analysis

3. InstructionValue Variants

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts (lines 899-1125)

Purpose

All possible operation types in HIR. Each represents a flattened expression where operands are always Places (no nesting).

ALL Variants (by category):

Value Loads

// LoadLocal - Load from local variable
LoadLocal = {
  kind: 'LoadLocal';
  place: Place;
  loc: SourceLocation;
};

// LoadContext - Load from captured outer scope variable
LoadContext = {
  kind: 'LoadContext';
  place: Place;
  loc: SourceLocation;
};

// LoadGlobal - Load from global or module-level binding
LoadGlobal = {
  kind: 'LoadGlobal';
  binding: NonLocalBinding;
  loc: SourceLocation;
};

CloudLang Relevance: All relevant. LoadLocal and LoadContext map to local/outer-scope reads. LoadGlobal would map to module imports or global Cloudflare APIs.

Value Stores

// DeclareLocal - const/let declaration
{
  kind: 'DeclareLocal';
  lvalue: LValue;
  type: t.FlowType | t.TSType | null;
  loc: SourceLocation;
};

// StoreLocal - Assignment to let/reassignment
StoreLocal = {
  kind: 'StoreLocal';
  lvalue: LValue;
  value: Place;
  type: t.FlowType | t.TSType | null;
  loc: SourceLocation;
};

// DeclareContext - hoisted context variable declaration
{
  kind: 'DeclareContext';
  lvalue: {
    kind: InstructionKind.Let | HoistedConst | HoistedLet | HoistedFunction;
    place: Place;
  };
  loc: SourceLocation;
};

// StoreContext - Context variable assignment
{
  kind: 'StoreContext';
  lvalue: {
    kind: InstructionKind.Reassign | Const | Let | Function;
    place: Place;
  };
  value: Place;
  loc: SourceLocation;
};

// StoreGlobal - Global assignment
StoreGlobal = {
  kind: 'StoreGlobal';
  name: string;
  value: Place;
  loc: SourceLocation;
};

CloudLang Relevance: All relevant. Need Declare/Store for locals, maybe skip global stores (CloudLang doesn't support global assignment).

Primitive Values

// Primitive - Literal values
{
  kind: 'Primitive';
  value: number | boolean | string | null | undefined;
  loc: SourceLocation;
};

// RegExpLiteral
{
  kind: 'RegExpLiteral';
  pattern: string;
  flags: string;
  loc: SourceLocation;
};

// JSXText - Text content inside JSX
JSXText = {kind: 'JSXText'; value: string; loc: SourceLocation};

CloudLang Relevance: Primitive - relevant (strings, numbers, bools). RegExpLiteral and JSXText - skip (no JSX in CloudLang).

Object Operations

// ObjectExpression - Object literal creation
{
  kind: 'ObjectExpression';
  properties: Array<ObjectProperty | SpreadPattern>;
  loc: SourceLocation;
};

// PropertyLoad - object.prop
PropertyLoad = {
  kind: 'PropertyLoad';
  object: Place;
  property: PropertyLiteral;
  loc: SourceLocation;
};

// PropertyStore - object.prop = value
{
  kind: 'PropertyStore';
  object: Place;
  property: PropertyLiteral;
  value: Place;
  loc: SourceLocation;
};

// PropertyDelete - delete object.prop
{
  kind: 'PropertyDelete';
  object: Place;
  property: PropertyLiteral;
  loc: SourceLocation;
};

// ComputedLoad - object[key]
{
  kind: 'ComputedLoad';
  object: Place;
  property: Place;
  loc: SourceLocation;
};

// ComputedStore - object[key] = value
{
  kind: 'ComputedStore';
  object: Place;
  property: Place;
  value: Place;
  loc: SourceLocation;
};

// ComputedDelete - delete object[key]
{
  kind: 'ComputedDelete';
  object: Place;
  property: Place;
  loc: SourceLocation;
};

CloudLang Relevance: ObjectExpression and Load/Store operations are all relevant for DTOs and config objects.

Array Operations

// ArrayExpression - Array literal
ArrayExpression = {
  kind: 'ArrayExpression';
  elements: Array<Place | SpreadPattern | Hole>;
  loc: SourceLocation;
};

CloudLang Relevance: Relevant for config arrays (e.g., routes, handlers).

Expressions

// BinaryExpression - a + b, x == y, etc.
{
  kind: 'BinaryExpression';
  operator: Exclude<t.BinaryExpression['operator'], '|>'>;
  left: Place;
  right: Place;
  loc: SourceLocation;
};

// UnaryExpression - !x, -y, typeof x, etc.
{
  kind: 'UnaryExpression';
  operator: Exclude<t.UnaryExpression['operator'], 'throw' | 'delete'>;
  value: Place;
  loc: SourceLocation;
};

// LogicalExpression and TernaryExpression are handled via terminals

CloudLang Relevance: BinaryExpression - highly relevant. UnaryExpression - relevant for typeof, !, etc.

Function Calls

// CallExpression - foo(arg1, arg2)
CallExpression = {
  kind: 'CallExpression';
  callee: Place;
  args: Array<Place | SpreadPattern>;
  loc: SourceLocation;
  typeArguments?: Array<t.FlowType>;
};

// NewExpression - new Foo()
NewExpression = {
  kind: 'NewExpression';
  callee: Place;
  args: Array<Place | SpreadPattern>;
  loc: SourceLocation;
};

// MethodCall - obj.method(arg1, arg2)
MethodCall = {
  kind: 'MethodCall';
  receiver: Place;
  property: Place;
  args: Array<Place | SpreadPattern>;
  loc: SourceLocation;
};

CloudLang Relevance: CallExpression - very relevant (Cloudflare API calls). NewExpression - maybe for constructing objects. MethodCall - relevant.

Functions and Classes

// FunctionExpression - Nested function definition
FunctionExpression = {
  kind: 'FunctionExpression';
  name: ValidIdentifierName | null;
  nameHint: string | null;
  loweredFunc: LoweredFunction;
  type: 'ArrowFunctionExpression' | 'FunctionExpression' | 'FunctionDeclaration';
  loc: SourceLocation;
};

// ObjectMethod - Method inside object literal
ObjectMethod = {
  kind: 'ObjectMethod';
  loc: SourceLocation;
  loweredFunc: LoweredFunction;
};

CloudLang Relevance: FunctionExpression - relevant for handler functions. ObjectMethod - maybe skip.

Destructuring

// Destructure - const {a, b} = obj; const [x, y] = arr;
Destructure = {
  kind: 'Destructure';
  lvalue: LValuePattern;
  value: Place;
  loc: SourceLocation;
};

CloudLang Relevance: Maybe skip initially (simplify), add later if needed.

Pattern Matching

// ArrayPattern - [a, b, ...rest]
ArrayPattern = {
  kind: 'ArrayPattern';
  items: Array<Place | SpreadPattern | Hole>;
  loc: SourceLocation;
};

// ObjectPattern - {a, b: x, ...rest}
ObjectPattern = {
  kind: 'ObjectPattern';
  properties: Array<ObjectProperty | SpreadPattern>;
  loc: SourceLocation;
};

// ObjectProperty - {key: value}
ObjectProperty = {
  kind: 'ObjectProperty';
  key: ObjectPropertyKey;
  type: 'property' | 'method';
  place: Place;
};

// ObjectPropertyKey
ObjectPropertyKey =
  | {kind: 'string'; name: string}
  | {kind: 'identifier'; name: string}
  | {kind: 'computed'; name: Place}
  | {kind: 'number'; name: number};

// SpreadPattern - ...rest
SpreadPattern = {kind: 'Spread'; place: Place};

// Hole - _ (pattern wildcard)
Hole = {kind: 'Hole'};

CloudLang Relevance: Initially skip, can add for complex destructuring.

JSX

// JsxExpression - <Foo prop={value}>children</Foo>
JsxExpression = {
  kind: 'JsxExpression';
  tag: Place | BuiltinTag;
  props: Array<JsxAttribute>;
  children: Array<Place> | null;
  loc: SourceLocation;
  openingLoc: SourceLocation;
  closingLoc: SourceLocation;
};

// JsxAttribute
JsxAttribute =
  | {kind: 'JsxSpreadAttribute'; argument: Place}
  | {kind: 'JsxAttribute'; name: string; place: Place};

// JsxFragment - <>children</>
{kind: 'JsxFragment'; children: Array<Place>; loc: SourceLocation};

// BuiltinTag - <div>, <span>, etc.
BuiltinTag = {kind: 'BuiltinTag'; name: string; loc: SourceLocation};

CloudLang Relevance: SKIP all JSX variants - CloudLang doesn't compile React components.

Templates and Literals

// TemplateLiteral - `hello ${name}`
{
  kind: 'TemplateLiteral';
  subexprs: Array<Place>;
  quasis: Array<{raw: string; cooked?: string}>;
  loc: SourceLocation;
};

// TaggedTemplateExpression - html`<div>...</div>`
{
  kind: 'TaggedTemplateExpression';
  tag: Place;
  value: {raw: string; cooked?: string};
  loc: SourceLocation;
};

// TypeCastExpression - x as Type
({kind: 'TypeCastExpression'; value: Place; type: Type; loc: SourceLocation} & (
  {typeAnnotation: t.FlowType; typeAnnotationKind: 'cast'} |
  {typeAnnotation: t.TSType; typeAnnotationKind: 'as' | 'satisfies'}
))

// MetaProperty - import.meta, new.target
{
  kind: 'MetaProperty';
  meta: string;
  property: string;
  loc: SourceLocation;
};

CloudLang Relevance: TemplateLiteral - relevant for string interpolation. TaggedTemplateExpression - skip. TypeCastExpression - maybe skip initially. MetaProperty - skip.

Iteration

// GetIterator - for (const x of y)
{
  kind: 'GetIterator';
  collection: Place;
  loc: SourceLocation;
};

// IteratorNext - iteration step
{
  kind: 'IteratorNext';
  iterator: Place;
  collection: Place;
  loc: SourceLocation;
};

// NextPropertyOf - for (const key in obj)
{
  kind: 'NextPropertyOf';
  value: Place;
  loc: SourceLocation;
};

CloudLang Relevance: Iteration operations are relevant for processing arrays/maps.

Update Operations

// PrefixUpdate - ++x, --y
{
  kind: 'PrefixUpdate';
  lvalue: Place;
  operation: t.UpdateExpression['operator'];
  value: Place;
  loc: SourceLocation;
};

// PostfixUpdate - x++, y--
{
  kind: 'PostfixUpdate';
  lvalue: Place;
  operation: t.UpdateExpression['operator'];
  value: Place;
  loc: SourceLocation;
};

CloudLang Relevance: Relevant for counter variables.

Async

// Await - await value
{
  kind: 'Await';
  value: Place;
  loc: SourceLocation;
};

CloudLang Relevance: SKIP - CloudLang handles async implicitly through Cloudflare API calls, no explicit await needed.

Memoization (React-specific)

// StartMemoize - useMemo/useCallback boundary
StartMemoize = {
  kind: 'StartMemoize';
  manualMemoId: number;
  deps: Array<ManualMemoDependency> | null;
  depsLoc: SourceLocation | null;
  loc: SourceLocation;
};

// FinishMemoize - End of memoized computation
FinishMemoize = {
  kind: 'FinishMemoize';
  manualMemoId: number;
  decl: Place;
  pruned?: true;
  loc: SourceLocation;
};

CloudLang Relevance: SKIP - React-specific memoization, not needed for CloudLang.

Other

// Debugger statement
{kind: 'Debugger'; loc: SourceLocation}

// Unsupported nodes that pass through
{
  kind: 'UnsupportedNode';
  node: t.Node;
  loc: SourceLocation;
};

CloudLang Relevance: Skip both - not needed for target compilation.


4. Terminal Variants

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts (lines 361-640)

Purpose

Block terminators that define control flow structure.

ALL Variants (by category):

Control Flow - Unconditional

// Goto - Unconditional jump
GotoTerminal = {
  kind: 'goto';
  block: BlockId;
  variant: GotoVariant; // Break | Continue | Try
  id: InstructionId;
  loc: SourceLocation;
};

// Unreachable - Dead code block
UnreachableTerminal = {
  kind: 'unreachable';
  id: InstructionId;
  loc: SourceLocation;
};

// Unsupported - Could not lower correctly
UnsupportedTerminal = {
  kind: 'unsupported';
  id: InstructionId;
  loc: SourceLocation;
};

CloudLang Relevance: Goto - relevant for break/continue. Unreachable - useful for optimization. Unsupported - maybe not needed.

Control Flow - Conditional

// If - if/else statement
IfTerminal = {
  kind: 'if';
  test: Place;
  consequent: BlockId;
  alternate: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

// Branch - Expression-level conditional
BranchTerminal = {
  kind: 'branch';
  test: Place;
  consequent: BlockId;
  alternate: BlockId;
  id: InstructionId;
  loc: SourceLocation;
  fallthrough: BlockId;
};

// Switch - switch statement
SwitchTerminal = {
  kind: 'switch';
  test: Place;
  cases: Array<{test: Place | null; block: BlockId}>;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

CloudLang Relevance: All three are relevant - If, Branch, Switch map directly to AST control flow.

Control Flow - Loops

// While - while loop
WhileTerminal = {
  kind: 'while';
  loc: SourceLocation;
  test: BlockId;
  loop: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
};

// DoWhile - do...while
DoWhileTerminal = {
  kind: 'do-while';
  loop: BlockId;
  test: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

// For - for (init; test; update)
ForTerminal = {
  kind: 'for';
  loc: SourceLocation;
  init: BlockId;
  test: BlockId;
  update: BlockId | null;
  loop: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
};

// ForOf - for (const x of arr)
ForOfTerminal = {
  kind: 'for-of';
  loc: SourceLocation;
  init: BlockId;
  test: BlockId;
  loop: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
};

// ForIn - for (const key in obj)
ForInTerminal = {
  kind: 'for-in';
  loc: SourceLocation;
  init: BlockId;
  loop: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
};

CloudLang Relevance: All loops are relevant. While, ForOf, ForIn are primary patterns. For is less common but useful.

Control Flow - Special

// Logical - &&, ||, ?? terminals
LogicalTerminal = {
  kind: 'logical';
  operator: t.LogicalExpression['operator'];
  test: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

// Ternary - conditional expression
TernaryTerminal = {
  kind: 'ternary';
  test: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

// Optional - optional chaining (?.)
OptionalTerminal = {
  kind: 'optional';
  optional: boolean;
  test: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

// Sequence - comma operator
SequenceTerminal = {
  kind: 'sequence';
  block: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

// Label - labeled block
LabelTerminal = {
  kind: 'label';
  block: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

CloudLang Relevance: Logical and Ternary - highly relevant. Optional - maybe skip (no optional chaining needed). Sequence and Label - skip initially.

Control Flow - Exceptions

// Try - try/catch
TryTerminal = {
  kind: 'try';
  block: BlockId;
  handlerBinding: Place | null;
  handler: BlockId;
  fallthrough: BlockId;
  id: InstructionId;
  loc: SourceLocation;
};

// MaybeThrow - Instruction that might throw
MaybeThrowTerminal = {
  kind: 'maybe-throw';
  continuation: BlockId;
  handler: BlockId | null;
  id: InstructionId;
  loc: SourceLocation;
  effects: Array<AliasingEffect> | null;
};

CloudLang Relevance: Try - relevant for error handling. MaybeThrow - maybe skip (no exception modeling needed).

Control Flow - Exit

// Return - function return
ReturnTerminal = {
  kind: 'return';
  returnVariant: ReturnVariant; // Void | Implicit | Explicit
  loc: SourceLocation;
  value: Place;
  id: InstructionId;
  fallthrough?: never;
  effects: Array<AliasingEffect> | null;
};

// Throw - throw statement
ThrowTerminal = {
  kind: 'throw';
  value: Place;
  id: InstructionId;
  loc: SourceLocation;
};

CloudLang Relevance: Return - highly relevant. Throw - relevant for error handling.

Reactive Scopes (React-specific)

// ReactiveScope - Start of reactive scope
ReactiveScopeTerminal = {
  kind: 'scope';
  fallthrough: BlockId;
  block: BlockId;
  scope: ReactiveScope;
  id: InstructionId;
  loc: SourceLocation;
};

// PrunedScope - Pruned reactive scope
PrunedScopeTerminal = {
  kind: 'pruned-scope';
  fallthrough: BlockId;
  block: BlockId;
  scope: ReactiveScope;
  id: InstructionId;
  loc: SourceLocation;
};

CloudLang Relevance: SKIP - React-specific reactive scope tracking, not needed for CloudLang.


5. Place and Identifier Distinction

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts (lines 1164-1278)

Purpose

Place is a value reference with metadata about how it's being used (effect, reactive flag). Identifier is the canonical variable definition.

Place Structure

export type Place = {
  kind: 'Identifier';  // Only variant currently
  identifier: Identifier;
  effect: Effect;       // How this reference modifies the value
  reactive: boolean;     // Is this a reactive dependency?
  loc: SourceLocation;
};

Identifier Structure

export type Identifier = {
  id: IdentifierId;           // SSA instance ID (after EnterSSA)
  declarationId: DeclarationId;  // Original declaration ID
  name: IdentifierName | null;   // Debug name (null for temps)
  mutableRange: MutableRange;  // Where this variable can be mutated
  scope: ReactiveScope | null; // Which scope computes this
  type: Type;
  loc: SourceLocation;
};

Why Separate Them?

  1. Effect Tracking: Place.effect captures how each use of a variable affects it (Read, Mutate, Freeze, Capture, etc.)
  2. Reactive Tracking: Place.reactive marks if this usage is part of a reactive dependency
  3. SSA Form: Identifier.id changes after SSA transformation, but declarationId stays constant
  4. Mutable Range Tracking: mutableRange on Identifier tracks liveness and mutability
  5. Context Distinguishing: A variable can be used with different effects in different contexts

Effect Values

export enum Effect {
  Unknown = '<unknown>',
  Freeze = 'freeze',                // Makes value immutable
  Read = 'read',                   // Read-only access
  Capture = 'capture',              // Read + store into new location
  ConditionallyMutate = 'mutate?', // May mutate
  Mutate = 'mutate',               // Definitely mutates
  Store = 'store',                 // Writes value (may alias)
}

Mutable Range

export type MutableRange = {
  start: InstructionId;  // Inclusive
  end: InstructionId;    // Exclusive
};

This tracks where a variable can be reassigned. For const, range is empty. For let, it extends until reassignment or end of scope.

CloudLang Relevance

  • Effect: Critical for tracking which values can be modified (Cloudflare APIs are immutable)
  • Reactive: Not needed - CloudLang doesn't have React-style reactivity
  • MutableRange: Useful for SSA form and optimization
  • Identifier.id vs declarationId: Needed for SSA transformation

6. BuildHIR Lowering

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts

Purpose

Converts Babel AST to HIR control flow graph. Handles all control flow constructs.

Algorithm Overview

export function lower(
  func: NodePath<t.Function>,
  env: Environment,
  bindings: Bindings | null,
  capturedRefs: Map<t.Identifier, SourceLocation>
): Result<HIRFunction, CompilerError> {
  // 1. Create HIRBuilder with environment
  const builder = new HIRBuilder(env, {bindings, context: capturedRefs});
  
  // 2. Process parameters (handling patterns like {a, b})
  func.get('params').forEach(param => {...});
  
  // 3. Lower function body (expression or block)
  if (body.isExpression()) {
    // Arrow function with implicit return
    const terminal: ReturnTerminal = {kind: 'return', returnVariant: 'Implicit', ...};
    builder.terminateWithContinuation(terminal, fallthrough);
  } else if (body.isBlockStatement()) {
    lowerStatement(builder, body);
  }
  
  // 4. Build final HIR (post-processing)
  const hir = builder.build();
  // - Reverse postorder blocks
  // - Mark instruction IDs
  // - Mark predecessors
  
  return Ok({...HIRFunction...});
}

Control Flow Construction

IfStatement

case 'IfStatement': {
  const stmt = stmtPath as NodePath<t.IfStatement>;
  const continuationBlock = builder.reserve('block');  // After if/else
  const consequentBlock = builder.enter('block', _blockId => {
    lowerStatement(builder, stmt.get('consequent'));
    return {kind: 'goto', block: continuationBlock.id, ...};
  });
  let alternateBlock: BlockId;
  const alternate = stmt.get('alternate');
  if (hasNode(alternate)) {
    alternateBlock = builder.enter('block', _blockId => {
      lowerStatement(builder, alternate);
      return {kind: 'goto', block: continuationBlock.id, ...};
    });
  } else {
    alternateBlock = continuationBlock.id;  // Direct to continuation
  }
  const test = lowerExpressionToTemporary(builder, stmt.get('test'));
  const terminal: IfTerminal = {
    kind: 'if',
    test, consequent: consequentBlock,
    alternate: alternateBlock,
    fallthrough: continuationBlock.id, ...
  };
  builder.terminateWithContinuation(terminal, continuationBlock);
}

WhileStatement

// Structure:
// entry -> test block -> (condition check)
//     -> if true: loop body -> update -> back to test
//     -> if false: fallthrough
builder.loop(null, /* continueBlock = */ testBlockId, /* breakBlock = */ fallthroughId, () => {
  const loopBody = builder.enter('block', _blockId => {
    lowerStatement(builder, stmt.get('body'));
    return {kind: 'goto', block: testBlockId, ...};
  });
  
  const test = builder.enter('value', testBlockId => {
    const testValue = lowerExpressionToTemporary(builder, stmt.get('test'));
    return {
      kind: 'branch',
      test: testValue,
      consequent: loopBody.id,
      alternate: fallthroughId,
      fallthrough: fallthroughId, ...
    };
  });
  
  builder.terminate({kind: 'goto', block: testBlockId, ...}, null);
});

SwitchStatement

// Creates:
// - test block (evaluates switch expression)
// - one block per case
// - default block (if exists)
// - fallthrough block
builder.switch(label, breakBlockId, () => {
  const switchBlock = builder.enter('value', testBlockId => {
    const testValue = lowerExpressionToTemporary(builder, stmt.get('discriminant'));
    const cases: Array<{test: Place | null; block: BlockId}> = [];
    stmt.get('cases').forEach(casePath => {
      const caseBlock = builder.enter('block', _caseId => {
        casePath.get('consequent').forEach(s => lowerStatement(builder, s));
        return {kind: 'goto', block: breakBlockId, ...};
      });
      const test = casePath.get('test');
      cases.push({
        test: hasNode(test) ? lowerExpressionToTemporary(builder, test) : null,
        block: caseBlock.id,
      });
    });
    return {
      kind: 'switch',
      test: testValue,
      cases,
      fallthrough: breakBlockId,
      ...
    };
  });
  
  builder.terminateWithContinuation({kind: 'goto', ...}, switchBlock);
});

TryStatement

case 'TryStatement': {
  // Creates:
  // - try block
  // - handler (catch) block
  // - continuation block
  const handlerBlock = builder.reserve('catch');
  const continuation = builder.reserve('block');
  const tryBlock = builder.enter('block', tryBlockId => {
    builder.enterTryCatch(handlerBlock.id, () => {
      lowerStatement(builder, stmt.get('block'));
    });
    return {kind: 'goto', block: continuation.id, ...};
  });
  
  const handlerPath = stmt.get('handler');
  if (hasNode(handlerPath)) {
    const binding = lowerParameter(builder, handlerPath.get('param'));
    builder.enterReserved(handlerBlock, () => {
      lowerStatement(builder, handlerPath.get('body'));
      return {kind: 'goto', block: continuation.id, ...};
    });
  }
  
  builder.terminateWithContinuation({
    kind: 'try',
    block: tryBlock.id,
    handlerBinding: binding ?? null,
    handler: handlerBlock.id,
    fallthrough: continuation.id,
    ...
  }, continuation);
}

Scope and Variable Management

Variable Resolution

resolveIdentifier(path: NodePath<t.Identifier | t.JSXIdentifier>): VariableBinding {
  const babelBinding = path.scope.getBinding(path.node.name);
  
  // Global or import
  if (babelBinding === null) {
    return {kind: 'Global', name: path.node.name};
  }
  
  // Module-level (imports, etc.)
  if (babelBinding === outerBinding) {
    // Check for import variants
    if (path.isImportDefaultSpecifier()) return {...ImportDefault...};
    if (path.isImportSpecifier()) return {...ImportSpecifier...};
    if (path.isImportNamespaceSpecifier()) return {...ImportNamespace...};
    return {kind: 'ModuleLocal', name: path.node.name};
  }
  
  // Local variable - resolve or create Identifier
  const resolvedBinding = this.resolveBinding(babelBinding.identifier);
  return {
    kind: 'Identifier',
    identifier: resolvedBinding,
    bindingKind: babelBinding.kind,
  };
}

Hoisting

// Variables referenced before declaration (e.g., in closures) are hoisted
// Traverses block looking for early references
for (const stmt of statements) {
  const willHoist = new Set<NodePath<t.Identifier>>();
  stmt.traverse({
    Identifier(id: NodePath<t.Identifier>) {
      const binding = id.scope.getBinding(id.node.name);
      if (hoistableIdentifiers.has(binding.identifier) && fnDepth > 0) {
        willHoist.add(id);
      }
    }
  });
  
  // Emit DeclareLocal instruction at earliest reference point
  for (const id of willHoist) {
    const identifier = builder.resolveIdentifier(id);
    const place: Place = {...};
    builder.push({
      id: makeInstructionId(0),
      lvalue: place,
      value: {kind: 'DeclareLocal', lvalue: {...}, ...},
      effects: null,
      loc: id.node.loc,
    });
  }
}

Expression Lowering

function lowerExpressionToTemporary(builder, exprPath): Place {
  const value = lowerExpressionValue(builder, exprPath);
  const temp = builder.makeTemporary(exprPath.node.loc);
  builder.push({
    id: makeInstructionId(0),
    lvalue: temp,
    value,
    effects: null,
    loc: exprPath.node.loc,
  });
  return temp;
}

// Recursively lowers nested expressions, creating temporaries for each sub-expression
// e.g., a(b(c)) becomes:
//   tmp0 = lowerExpression(c)
//   tmp1 = lowerExpression(a(tmp0))

Key Invariants

  1. All instructions have sequential IDs after build()
  2. Blocks are in reverse postorder
  3. All Place references resolve to valid Identifiers
  4. Hoisted variables have DeclareLocal before first use
  5. Loops have correct continue/break block tracking via scopes stack

Output Guarantees

  • Valid control flow graph (no invalid jumps)
  • All control flow structures (if, loops, switch) represented correctly
  • Variables resolved with correct scope
  • Hoisting handled correctly

7. Type System (Types.ts)

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/Types.ts

Purpose

Defines the type system for HIR. Simple but extensible.

Type Hierarchy

export type Type =
  | BuiltInType          // Primitive | Function | Object
  | PhiType             // Join of multiple types
  | TypeVar             // Type variable (for inference)
  | PolyType            // Polymorphic type
  | PropType            // Property access
  | ObjectMethod;        // Method type

export type BuiltInType = PrimitiveType | FunctionType | ObjectType;

export type PrimitiveType = {kind: 'Primitive'};

export type FunctionType = {
  kind: 'Function';
  shapeId: string | null;     // Key into ShapeRegistry
  return: Type;
  isConstructor: boolean;
};

export type ObjectType = {
  kind: 'Object';
  shapeId: string | null;     // Key into ShapeRegistry
};

export type TypeVar = {
  kind: 'Type';
  id: TypeId;                 // Opaque branded type
};

export type PolyType = {kind: 'Poly'};

export type PhiType = {
  kind: 'Phi';
  operands: Array<Type>;        // Types being joined
};

export type PropType = {
  kind: 'Property';
  objectType: Type;
  objectName: string;
  propertyName:
    | {kind: 'literal'; value: PropertyLiteral}
    | {kind: 'computed'; value: Type};
};

export type ObjectMethod = {kind: 'ObjectMethod'};

Type Variable Creation

let typeCounter = 0;

export function makeType(): TypeVar {
  return {
    kind: 'Type',
    id: makeTypeId(typeCounter++),
  };
}

// Branded type for type safety
const opaqueTypeId = Symbol();
export type TypeId = number & {[opaqueTypeId]: 'IdentifierId'};

export function makeTypeId(id: number): TypeId {
  CompilerError.invariant(id >= 0 && Number.isInteger(id), {
    reason: 'Expected instruction id to be a non-negative integer',
    loc: GeneratedSource,
  });
  return id as TypeId;
}

Type Equality

export function typeEquals(tA: Type, tB: Type): boolean {
  if (tA.kind !== tB.kind) return false;
  return (
    typeVarEquals(tA, tB) ||
    funcTypeEquals(tA, tB) ||
    objectTypeEquals(tA, tB) ||
    primitiveTypeEquals(tA, tB) ||
    polyTypeEquals(tA, tB) ||
    phiTypeEquals(tA, tB) ||
    propTypeEquals(tA, tB) ||
    objectMethodTypeEquals(tA, tB)
  );
}

CloudLang Relevance

  • TypeVar: Needed for type inference
  • FunctionType: Relevant for function signatures
  • ObjectType: Relevant for config objects
  • PrimitiveType: Basic types
  • PhiType: Needed for SSA phi nodes
  • PropType: Maybe skip (simpler property tracking)
  • PolyType: Maybe skip (no generics initially)
  • ObjectMethod: Maybe skip

8. Object Shape System (ObjectShape.ts)

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts

Purpose

Encodes function signatures and object shapes for type inference and effect tracking.

Shape Registry

export type ShapeRegistry = Map<string, ObjectShape>;

export type ObjectShape = {
  properties: Map<string, BuiltInType | PolyType>;
  functionType: FunctionSignature | null;
};

Function Signature

export type FunctionSignature = {
  positionalParams: Array<Effect>;
  restParam: Effect | null;
  returnType: BuiltInType | PolyType;
  returnValueKind: ValueKind;
  returnValueReason?: ValueReason;
  calleeEffect: Effect;
  hookKind: HookKind | null;
  noAlias?: boolean;
  mutableOnlyIfOperandsAreMutable?: boolean;
  impure?: boolean;
  knownIncompatible?: string | null;
  canonicalName?: string;
  aliasing?: AliasingSignature | null;  // Detailed effect specification
};

Hook Kinds

export type HookKind =
  | 'useContext' | 'useState' | 'useActionState' | 'useReducer'
  | 'useRef' | 'useEffect' | 'useLayoutEffect' | 'useInsertionEffect'
  | 'useMemo' | 'useCallback' | 'useTransition' | 'useImperativeHandle'
  | 'useEffectEvent' | 'useOptimistic' | 'Custom';

Aliasing Signature

export type AliasingSignature = {
  receiver: IdentifierId;
  params: Array<IdentifierId>;
  rest: IdentifierId | null;
  returns: IdentifierId;
  temporaries: Array<Place>;
  effects: Array<AliasingEffect>;
};

Built-in Shapes Examples

// Array.push signature with detailed aliasing
addFunction(BUILTIN_SHAPES, [], {
  positionalParams: [],
  restParam: Effect.Capture,
  returnType: PRIMITIVE_TYPE,
  calleeEffect: Effect.Store,
  returnValueKind: ValueKind.Primitive,
  aliasing: {
    receiver: '@receiver',
    params: [],
    rest: '@rest',
    returns: '@returns',
    temporaries: [],
    effects: [
      {kind: 'Mutate', value: '@receiver'},        // Mutates array
      {kind: 'Capture', from: '@rest', into: '@receiver'},  // Captures args
      {kind: 'Create', into: '@returns', value: ValueKind.Primitive, reason: ...},
    ],
  },
}, 'Array.push');

Effect Values

export enum Effect {
  Read = 'read',
  Mutate = 'mutate',
  ConditionallyMutate = 'mutate?',
  ConditionallyMutateIterator = 'mutate-iterator?',
  Capture = 'capture',
  Store = 'store',
  Freeze = 'freeze',
}

Value Kinds

export enum ValueKind {
  MaybeFrozen = 'maybefrozen',
  Frozen = 'frozen',
  Primitive = 'primitive',
  Global = 'global',
  Mutable = 'mutable',
  Context = 'context',
}

CloudLang Relevance

  • ShapeRegistry: Useful for encoding Cloudflare API signatures
  • FunctionSignature: Adapt for Cloudflare Worker / DO / R2 / D1 APIs
  • Effect: Use for tracking mutation (Cloudflare APIs are mostly immutable)
  • ValueKind: Simplified - focus on Primitive vs Mutable
  • HookKind: SKIP - React-specific

CloudLang Adaptation Example

type effect_kind =
  | Read          (* Read-only access *)
  | Mutate        (* Definitely mutates *)
  | Capture        (* Aliases/captures value *)
  | Store         (* Writes value *)

type value_kind =
  | Primitive
  | Mutable
  | Immutable

type function_signature = {
  positional_params : effect_kind list;
  rest_param : effect_kind option;
  return_type : typ;
  return_value_kind : value_kind;
  mutable_only_if_operands_are_mutable : bool;
  aliasing : aliasing_effect list;
}

type aliasing_effect =
  | Capture of { from : int; into : int }      (* @from -> @into *)
  | Alias of { from : int; into : int }         (* Alias relationship *)
  | Mutate of { value : int }                    (* Mutates @value *)
  | Freeze of { value : int }                    (* Freezes @value *)
  | Create of { into : int; value : value_kind }  (* Creates new @into *)

9. Visitor Patterns (visitors.ts)

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts

Purpose

Provides generic traversal and transformation utilities for HIR.

Key Abstractions

Iteration Over Operands

// Yield all Place values referenced by an instruction
export function* eachInstructionOperand(instr: Instruction): Iterable<Place> {
  yield* eachInstructionValueOperand(instr.value);
}

// Handle each instruction variant
export function* eachInstructionValueOperand(
  instrValue: InstructionValue,
): Iterable<Place> {
  switch (instrValue.kind) {
    case 'BinaryExpression':
      yield instrValue.left;
      yield instrValue.right;
    case 'CallExpression':
      yield instrValue.callee;
      yield* eachCallArgument(instrValue.args);
    case 'PropertyLoad':
      yield instrValue.object;
    // ... all variants
  }
}

Iteration Over L-values

// Yield all lvalue places (targets of assignment)
export function* eachInstructionLValueWithKind(
  instr: Instruction,
): Iterable<[Place, InstructionKind]> {
  switch (instr.value.kind) {
    case 'DeclareLocal':
    case 'StoreLocal':
      yield [instr.value.lvalue.place, instr.value.lvalue.kind];
    case 'Destructure':
      for (const place of eachPatternOperand(instr.value.lvalue.pattern)) {
        yield [place, instr.value.lvalue.kind];
      }
  }
  if (instr.lvalue !== null) {
    yield [instr.lvalue, InstructionKind.Reassign];  // Infer reassign
  }
}

Iteration Over Terminal Successors

// Yield all successor block IDs for control flow
export function* eachTerminalSuccessor(terminal: Terminal): Iterable<BlockId> {
  switch (terminal.kind) {
    case 'goto':
      yield terminal.block;
    case 'if':
      yield terminal.consequent;
      yield terminal.alternate;
    case 'switch':
      for (const case_ of terminal.cases) {
        yield case_.block;
      }
    case 'while':
      yield terminal.test;
    // ... all variants
  }
}

Transformation (Mapping)

// Transform all Place references in an instruction
export function mapInstructionOperands(
  instr: Instruction,
  fn: (place: Place) => Place,
): void {
  mapInstructionValueOperands(instr.value, fn);
}

// Map terminal successors
export function mapTerminalSuccessors(
  terminal: Terminal,
  fn: (block: BlockId) => BlockId,
): Terminal {
  switch (terminal.kind) {
    case 'if': {
      const consequent = fn(terminal.consequent);
      const alternate = fn(terminal.alternate);
      const fallthrough = fn(terminal.fallthrough);
      return {kind: 'if', test: terminal.test, consequent, alternate, fallthrough, ...};
    }
    // ... all variants
  }
}

Pattern Traversal

// Yield all places in a pattern
export function* eachPatternOperand(pattern: Pattern): Iterable<Place> {
  switch (pattern.kind) {
    case 'ArrayPattern':
      for (const item of pattern.items) {
        if (item.kind === 'Identifier') yield item;
        else if (item.kind === 'Spread') yield item.place;
      }
    case 'ObjectPattern':
      for (const prop of pattern.properties) {
        if (prop.kind === 'ObjectProperty') yield prop.place;
        else if (prop.kind === 'Spread') yield prop.place;
      }
  }
}

Scope Block Traversal

// Helper for traversing reactive scope boundaries
export class ScopeBlockTraversal {
  #activeScopes: Array<ScopeId> = [];
  blockInfos: Map<BlockId, BlockInfo> = new Map();

  recordScopes(block: BasicBlock): void {
    if (blockInfo?.kind === 'begin') {
      this.#activeScopes.push(blockInfo.scope.id);
    } else if (blockInfo?.kind === 'end') {
      this.#activeScopes.pop();
    }
    
    if (block.terminal.kind === 'scope' || block.terminal.kind === 'pruned-scope') {
      this.blockInfos.set(block.terminal.block, {kind: 'begin', ...});
      this.blockInfos.set(block.terminal.fallthrough, {kind: 'end', ...});
    }
  }

  isScopeActive(scopeId: ScopeId): boolean {
    return this.#activeScopes.indexOf(scopeId) !== -1;
  }

  get currentScope(): ScopeId | null {
    return this.#activeScopes.at(-1) ?? null;
  }
}

CloudLang Relevance

  • eachInstructionOperand: Very useful for data flow analysis
  • eachTerminalSuccessor: Critical for CFG traversal
  • mapInstructionOperands: Useful for SSA transformation
  • ScopeBlockTraversal: Adapt for CloudLang's "effect scopes" instead of reactive scopes

10. PrintHIR (Debug Printing)

File

/home/jm/data/ai/cloudlang-trees/react/react/compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts

Purpose

Provides human-readable debug output for HIR structures.

Example Output Format

function Foo(a: $0, b: $1): $2 {
  'use strict'
  
bb0 (block):
  [1] $0 = Primitive {value: 42}
  [2] $1 = Primitive {value: "hello"}
  [3] $2 = Binary $0 + $1
  [4] Return Explicit $2

bb1 (value):
  [5] $3 = Call $4($0)
  [6] Return Implicit $5
}

CloudLang Relevance

Adapt for debugging OCaml HIR. Similar format with OCaml syntax.


11. CloudLang Mapping

Current CloudLang Architecture

lib/ast.ml (44 lines - Minimal ESTree subset)

type var_kind = Const | Let | Var

type literal_value =
  | LString of string
  | LNumber of float
  | LBool of bool
  | LNull
  | LUndefined

type node =
  | Program of { body : node list }
  | VariableDeclaration of { kind : var_kind; declarations : node list }
  | VariableDeclarator of { id : node; init : node option }
  | Identifier of { name : string }
  | Literal of { value : literal_value }
  | ArrowFunctionExpression of { params : node list; body : node; async_ : bool }
  | BlockStatement of { body : node list }
  | ReturnStatement of { argument : node option }
  | IfStatement of { test : node; consequent : node; alternate : node option }
  | ExpressionStatement of { expression : node }
  | CallExpression of { callee : node; arguments : node list }
  | MemberExpression of { object_ : node; property : node }
  | NewExpression of { callee : node; arguments : node list }
  | BinaryExpression of { operator : string; left : node; right : node }
  | LogicalExpression of { operator : string; left : node; right : node }
  | AwaitExpression of { argument : node }
  | RawCode of { code : string }
  | ExportNamedDeclaration of { specifiers : node list }
  | ExportSpecifier of { local : node }

lib/ir.ml (68 lines - Direct Cloudflare config output)

type binding =
  | D1Binding of { name : string; database_id : string }
  | KVBinding of { name : string; namespace_id : string }
  | R2Binding of { name : string; bucket_name : string }
  | ServiceBinding of { name : string; service : string }

type worker = {
  name : string;
  script : string;
  bindings : binding list;
  routes : string list;
}

type config = resource list

Missing Layer: HIR

CloudLang has no HIR - it goes directly from 19-node AST to Cloudflare config. This limits optimization opportunities and complicates closure decomposition.

Proposed CloudLang HIR Types (OCaml)

(* Core identity types - using phantom types for safety *)
module Block_id : sig
  type t
  val make : int -> t
  val to_int : t -> int
end

module Instruction_id : sig
  type t
  val make : int -> t
  val to_int : t -> int
end

module Identifier_id : sig
  type t
  val make : int -> t
  val to_int : t -> int
end

(* Effect system - simplified from React Compiler *)
type effect_kind =
  | Unknown          (* Default, before analysis *)
  | Read             (* Read-only access *)
  | Mutate           (* Definitely mutates *)
  | Capture          (* Aliases into another location *)
  | Freeze            (* Marks as immutable *)

(* Value kinds - simplified *)
type value_kind =
  | Primitive         (* number, string, bool *)
  | Mutable           (* Can be modified *)
  | Immutable         (* Cannot be modified *)

(* Block kinds *)
type block_kind =
  | Block             (* Statement block *)
  | Value             (* Expression block *)
  | Loop              (* Loop body *)
  | Catch             (* Catch block *)

(* Source location *)
type source_loc = {
  file : string option;
  line : int option;
  column : int option;
}
type generated = Generated

(* Mutable range for tracking liveness *)
type mutable_range = {
  start : Instruction_id.t;  (* Inclusive *)
  end : Instruction_id.t;    (* Exclusive *)
}

(* Identifier - canonical variable definition *)
type identifier = {
  id : Identifier_id.t;              (* SSA instance ID *)
  declaration_id : Identifier_id.t;     (* Original declaration ID *)
  name : string option;                (* null for temporaries *)
  mutable_range : mutable_range;
  kind : value_kind;                  (* Inferred type *)
  loc : source_loc;
}

(* Place - value reference with metadata *)
type place = {
  identifier : identifier;
  effect : effect_kind;
  loc : source_loc;
}

(* Pattern for destructuring - minimal initially *)
type pattern =
  | Pattern_identifier of identifier
  | Pattern_array of pattern list
  | Pattern_object of (string * pattern) list
  | Pattern_spread of identifier

(* Instruction value variants - minimal subset for CloudLang *)
type instruction_value =
  (* Loads *)
  | Load_local of { place : place }
  | Load_global of { name : string }
  
  (* Stores *)
  | Declare_local of { lvalue : identifier; kind : var_kind }
  | Store_local of { lvalue : identifier; value : place }
  
  (* Primitives *)
  | Primitive of {
      value : literal_value;
    }
  
  (* Expressions *)
  | Binary_expression of {
      operator : string;  (* +, -, *, /, ==, etc. *)
      left : place;
      right : place;
    }
  | Unary_expression of {
      operator : string;  (* !, -, typeof, etc. *)
      value : place;
    }
  
  (* Objects/Arrays *)
  | Object_expression of {
      properties : (string * place) list;
    }
  | Array_expression of {
      elements : (place option) list;  (* None for holes *)
    }
  
  (* Property access *)
  | Property_load of {
      object : place;
      property : string;  (* Literal property *)
    }
  | Property_store of {
      object : place;
      property : string;
      value : place;
    }
  | Computed_load of {
      object : place;
      property : place;
    }
  | Computed_store of {
      object : place;
      property : place;
      value : place;
    }
  
  (* Function calls *)
  | Call_expression of {
      callee : place;
      args : place list;
    }
  | Method_call of {
      receiver : place;
      method : string;
      args : place list;
    }
  
  (* Functions *)
  | Function_expression of {
      name : string option;
      params : identifier list;
      body : hir_function;
      captures : identifier list;
    }
  
  (* Iteration - for CloudLang-specific patterns *)
  | Get_iterator of { collection : place }
  | Iterator_next of { iterator : place }
  
  (* Raw code insertion for Cloudflare-specific constructs *)
  | Raw_code of { code : string }

(* Instruction *)
type instruction = {
  id : Instruction_id.t;
  lvalue : place option;      (* None for statements without result *)
  value : instruction_value;
  loc : source_loc;
}

(* Phi node for SSA *)
type phi = {
  place : place;
  operands : (Block_id.t * place) list;  (* Map from predecessor to value *)
}

(* Basic block *)
type basic_block = {
  kind : block_kind;
  id : Block_id.t;
  instructions : instruction list;
  terminal : terminal;
  preds : Block_id.t list;
  phis : phi list;
}

(* Terminal variants *)
type terminal =
  (* Control flow - unconditional *)
  | Goto of {
      block : Block_id.t;
      variant : goto_variant;
    }
  | Unreachable
  
  (* Control flow - conditional *)
  | If of {
      test : place;
      consequent : Block_id.t;
      alternate : Block_id.t;
      fallthrough : Block_id.t;
    }
  | Switch of {
      test : place;
      cases : (place option * Block_id.t) list;  (* None for default *)
      fallthrough : Block_id.t;
    }
  
  (* Loops *)
  | While of {
      test_block : Block_id.t;
      loop_block : Block_id.t;
      fallthrough : Block_id.t;
    }
  | For_each of {
      init_block : Block_id.t;    (* Setup: GetIterator *)
      loop_block : Block_id.t;    (* Body with IteratorNext *)
      fallthrough : Block_id.t;
    }
  
  (* Control flow - special *)
  | Logical of {
      operator : string;  (* &&, ||, ?? *)
      test_block : Block_id.t;
      fallthrough : Block_id.t;
    }
  | Ternary of {
      test_block : Block_id.t;
      fallthrough : Block_id.t;
    }
  
  (* Exceptions *)
  | Try of {
      try_block : Block_id.t;
      handler_block : Block_id.t;
      fallthrough : Block_id.t;
    }
  
  (* Exit *)
  | Return of { value : place }
  | Throw of { value : place }

type goto_variant =
  | Break
  | Continue

(* HIR - Control flow graph *)
type hir = {
  entry : Block_id.t;
  blocks : basic_block Block_id.t Map.t;  (* Ordered map *)
}

(* HIR Function *)
type hir_function = {
  name : string option;
  params : identifier list;
  returns : place;
  body : hir;
  is_async : bool;
  captures : identifier list;
  loc : source_loc;
}

(* Program - top-level compilation unit *)
type hir_program = {
  functions : hir_function list;
  exports : string list;
}

Adaptation Strategy

What to Adapt:

  1. Core CFG Structure: HIR, BasicBlock, Terminal, Instruction
  2. Identity System: Branded ID types for type safety
  3. SSA Form: Phi nodes, Identifier.id vs declarationId
  4. Effect Tracking: Read/Mutate/Capture for Cloudflare API analysis
  5. Mutable Range: For liveness analysis and optimization
  6. Control Flow: If, While, ForEach, Switch, Try
  7. Expressions: Binary, Unary, Call, Property access
  8. Visitor Patterns: eachInstructionOperand, eachTerminalSuccessor

What to Skip/Defer:

  1. JSX: All JSX nodes - CloudLang doesn't target React
  2. Reactive Scopes: scope/pruned-scope terminals, ReactiveScope type
  3. Memoization: StartMemoize, FinishMemoize
  4. Optional Chaining: optional terminal
  5. Complex Patterns: ArrayPattern, ObjectPattern (initially)
  6. Destructuring: Destructure instruction (initially)
  7. Template Literals: TaggedTemplateExpression (simple templates only)
  8. Class Support: NewExpression with constructors (initially)
  9. Async/Await: Async operations modeled implicitly
  10. Global Assignment: StoreGlobal (Cloudflare APIs don't support)

CloudLang-Specific Additions:

  1. ForEach Terminal: Custom for CloudLang's iteration patterns (arrays, maps)
  2. GetIterator/IteratorNext: For CloudLang-specific iteration
  3. RawCode: Insertion points for Cloudflare-specific code
  4. Durable Object Markers: DO/D1/R2 binding annotations
  5. Coordination Intent: For distributed coordination patterns

Example Transformation

Before (AST):

// Input CloudLang code
const user = await KV.get("user:123");
const greeting = `Hello, ${user?.name || "Stranger"}!`;
return greeting;

After (HIR):

function <<anonymous>>($0: #1): $2 {
bb0 (block):
  [1] $1 = Primitive {value: "user:123"}
  [2] $3 = Call KV.get($1)  (* RawCode inserted for KV API *)
  [3] $4 = PropertyLoad object=$3 property="name"
  [4] $5 = Primitive {value: "Stranger"}
  [5] $6 = Ternary test=$5 consequent=$4 alternate=$5
  [6] $7 = Primitive {value: "Hello, "}
  [8] $8 = Primitive {value: "!"}
  [9] $9 = RawCode {code: "`${$7}${$6}${$8}`"}
  [10] Return $9
}

Incremental Expansion Path

Phase 1 (MVP):

  • Control flow: If, While
  • Expressions: Binary, Call, Property access
  • Functions: Simple closures
  • SSA: Basic phi nodes
  • Effects: Read/Mutate tracking

Phase 2:

  • Loops: ForEach
  • Arrays: Array expressions, iteration
  • Objects: Object expressions, computed access
  • Try/Catch: Error handling
  • Pattern matching: Simple destructuring

Phase 3:

  • Advanced control flow: Switch, Ternary
  • Advanced effects: Capture, Freeze
  • Optimization: Dead code elimination, constant folding
  • SSA optimization: Copy propagation, dead store elimination

Phase 4:

  • Cloudflare-specific: DO/D1/R2 annotations
  • Coordination: Per-entity serial, global singleton
  • Advanced patterns: Realtime fanout, high-fan-in coordination

Summary

The React Compiler's HIR system is a sophisticated SSA-based CFG intermediate representation designed for React-specific optimizations (reactive scope analysis, memoization). Key innovations include:

  1. Branded opaque types for compile-time ID safety
  2. Effect tracking on every Place reference
  3. Reactive scope boundaries as first-class CFG nodes
  4. Phi nodes for SSA join points
  5. Mutable ranges for liveness tracking
  6. Comprehensive visitor utilities for traversal and transformation

For CloudLang, we should:

  • Adapt the core CFG structure but strip React-specific features
  • Keep the ID branding pattern for OCaml type safety
  • Simplify effect system to focus on mutability (Cloudflare APIs are immutable)
  • Use SSA form for closure decomposition optimization
  • Build incrementally starting with 19 AST nodes mapped to minimal HIR
  • Add CloudLang-specific constructs (ForEach iteration, DO/D1/R2 bindings)

The key insight is that HIR enables analyses and optimizations that are impossible directly on AST or final IR. Adding this layer to CloudLang will significantly improve the quality of generated Cloudflare configurations.

37,551in / 14,123out / 214reasoning