Scope Manager
One of the transpiler's most critical jobs is managing variable scope and state persistence across bar iterations.
Scope Manager and Variable Transformation
One of the transpiler's most critical jobs is managing variable scope and state persistence across bar iterations.
The Problem
In standard JavaScript:
let x = 10; // Re-initialized every time the function runs?If the entire indicator function runs for every bar, let x = 10 would reset x every time. Pine Script variables need to maintain history (x[1]).
The Solution: Context Object
The transpiler moves all variables into a persistent context object ($).
User Code:
let ema9 = ta.ema(close, 9);Transformed Code:
$.let.glb1_ema9 = $.init($.let.glb1_ema9, temp_result);Variable Renaming
To prevent naming collisions between scopes (e.g., a variable x in the global scope vs x in a function), the ScopeManager assigns unique prefixes:
glb1_: Global scope variables.fn{id}_: Function scope variables.if{id}_: If-block scope variables.for{id}_: For-loop scope variables.
This ensures that even if the user reuses variable names, they map to distinct properties on the context object.
ID Generation
The transpiler generates unique IDs for:
- Parameters (
p0,p1...): Passed toparam()to cache Series objects. - Function Calls (
_ta0,_ta1...): Passed to namespace functions to maintain internal state (likeprevEma). - Cache Keys: For caching intermediate results.
This allows functions like ta.ema to identify which call they are handling, even if called multiple times with the same parameters.