PineTS Transpiler Architecture
The transpiler is responsible for converting user-written “PineTS” code (which mimics Pine Script syntax) into executable JavaScript that runs within the PineTS runtime environment.
The Pipeline
The transpilation process follows a multi-pass pipeline:
Input Code String/Function
↓
┌─────────────────────────┐
│ 0. Wrapper Check │
│ • Detect if code is │
│ already wrapped in │
│ a function │
│ • Auto-wrap unwrapped│
│ code in (context) │
│ => { ... } │
└───────┬─────────────────┘
↓
┌─────────────────────────┐
│ 1. Parse to AST │ (using acorn)
│ (ECMAScript AST) │
└───────┬─────────────────┘
↓
┌─────────────────────────┐
│ 2. Pre-Processing │
│ • Transform nested │
│ arrow functions │
│ • Normalize native │
│ imports (aliasing) │
│ • Inject implicit │
│ imports (context.*)│
│ • Identify context- │
│ bound variables │
└───────┬─────────────────┘
↓
┌─────────────────────────┐
│ 3. Analysis Pass │
│ • Register functions │
│ • Track parameters │
│ • Build scope tree │
│ • Destructure arrays │
└───────┬─────────────────┘
↓
┌─────────────────────────┐
│ 4. Transformation │
│ • Variable scoping │
│ • Series wrapping │
│ • Expression Unwrapping│ (Hoisting)
│ • param() injection │
│ • ID generation │
└───────┬─────────────────┘
↓
┌─────────────────────────┐
│ 5. Post-Processing │
│ • Transform == to │
│ $.math.__eq() │
└───────┬─────────────────┘
↓
┌─────────────────────────┐
│ 6. Code Generation │ (using astring)
│ (Final JS code) │
└─────────────────────────┘
Pipeline Details
-
Pre-Processing:
- Wrapper Check: Ensures code is wrapped in a function:
(context) => { ... }. - Implicit Imports: Injects
const { close } = context.dataetc. if missing. - Normalization: Prevents renaming of native symbols (e.g.
const { close: c } = ...->const { close } = ...).
- Wrapper Check: Ensures code is wrapped in a function:
-
Parsing:
- Uses
acornto parse code into an ESTree-compatible AST.
- Uses
-
Analysis Pass (
AnalysisPass.ts):- Scans the AST to build a Scope Tree.
- Registers function declarations and parameters.
- Identifies “Context-Bound” variables (variables that come from
context.dataorcontext.pine).
-
Transformation Pass (
MainTransformer.ts):- Traverses the AST and modifies nodes based on rules.
- Variable Renaming: Transforms
let x = 10into$.let.glb1_x = ...using theScopeManager. - Series Wrapping: Wraps inputs to functions with
param(). - Expression Unwrapping: Hoists complex expressions into temporary variables to ensure correct execution order.
-
Post-Processing:
- Transforms equality checks (
==,===) into$.math.__eq()calls to handleNaNcorrectly.
- Transforms equality checks (
-
Code Generation:
- Uses
astringto generate the final JavaScript string from the modified AST.
- Uses
Key Components
- ScopeManager: Tracks variable scopes, renames variables to avoid collisions (
glb1_,fn2_), and manages unique IDs. - Transformers: Specialized classes (
ExpressionTransformer,StatementTransformer) that handle specific AST node types.