pinets 0.9.13 → 0.9.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pinets.min.browser.es.js +50 -48
- package/dist/pinets.min.browser.es.js.map +1 -1
- package/dist/pinets.min.browser.js +50 -48
- package/dist/pinets.min.browser.js.map +1 -1
- package/dist/pinets.min.cjs +27 -25
- package/dist/pinets.min.cjs.map +1 -1
- package/dist/pinets.min.es.js +51 -49
- package/dist/pinets.min.es.js.map +1 -1
- package/dist/types/Context.class.d.ts +30 -1
- package/dist/types/namespaces/Core.d.ts +1 -5
- package/dist/types/namespaces/PineTypeObject.d.ts +13 -1
- package/dist/types/namespaces/Str.d.ts +6 -0
- package/dist/types/namespaces/box/BoxHelper.d.ts +6 -4
- package/dist/types/namespaces/label/LabelHelper.d.ts +1 -1
- package/dist/types/namespaces/line/LineHelper.d.ts +1 -1
- package/dist/types/namespaces/linefill/LinefillHelper.d.ts +1 -1
- package/dist/types/namespaces/polyline/PolylineHelper.d.ts +4 -3
- package/dist/types/namespaces/request/methods/security.d.ts +1 -1
- package/dist/types/namespaces/request/methods/security_lower_tf.d.ts +1 -1
- package/dist/types/namespaces/silentInSecondary.d.ts +31 -0
- package/dist/types/namespaces/table/TableHelper.d.ts +1 -1
- package/dist/types/transpiler/analysis/AnalysisPass.d.ts +18 -0
- package/dist/types/transpiler/analysis/ScopeManager.d.ts +111 -0
- package/dist/types/transpiler/pineToJS/codegen.d.ts +35 -16
- package/dist/types/transpiler/pineToJS/lexer.d.ts +8 -0
- package/dist/types/transpiler/pineToJS/parser.d.ts +9 -0
- package/dist/types/transpiler/settings.d.ts +1 -0
- package/package.json +1 -1
|
@@ -132,7 +132,35 @@ export declare class Context {
|
|
|
132
132
|
* @param value - The value to set
|
|
133
133
|
*/
|
|
134
134
|
set(target: any, value: any): void;
|
|
135
|
+
/**
|
|
136
|
+
* Resolve an iterable for `for x in collection` codegen.
|
|
137
|
+
* Handles PineArrayObject (unwrap to inner JS array) and plain JS arrays uniformly.
|
|
138
|
+
* Returns the value itself if it's already iterable (Map, Set, etc.).
|
|
139
|
+
*
|
|
140
|
+
* Centralizing this here means the transpiler can emit a uniform shape regardless of
|
|
141
|
+
* whether the iterable is a built-in returning a plain array (e.g. box.all) or a UDT
|
|
142
|
+
* field holding a PineArrayObject — and future collection types only need to update
|
|
143
|
+
* this helper, not the codegen.
|
|
144
|
+
*/
|
|
145
|
+
iter(source: any): any;
|
|
146
|
+
/**
|
|
147
|
+
* Resolve an iterable yielding [index, value] tuples for `for [i, x] in collection`
|
|
148
|
+
* destructuring codegen. PineArrayObject's [Symbol.iterator] yields scalar values, so
|
|
149
|
+
* we must explicitly call `.entries()` on the underlying array.
|
|
150
|
+
*/
|
|
151
|
+
entries(source: any): IterableIterator<[number, any]>;
|
|
135
152
|
private _callStack;
|
|
153
|
+
/**
|
|
154
|
+
* Cumulative call-path stack. Each entry is the full path from the root to
|
|
155
|
+
* the current call, formed by joining the syntactic call-site ids with '|'.
|
|
156
|
+
*
|
|
157
|
+
* Pine semantics is per-call-PATH (not per-syntactic-call-site): a function
|
|
158
|
+
* with internal `var` state, called via two distinct paths through a wrapper,
|
|
159
|
+
* must keep state independent per path. Keying lctx by the path (rather than
|
|
160
|
+
* the immediate site id) makes `$$.var.*` slots and `$$.id + '_taN'` ta
|
|
161
|
+
* callsite ids correctly path-scoped without any transpiler changes.
|
|
162
|
+
*/
|
|
163
|
+
private _pathStack;
|
|
136
164
|
/**
|
|
137
165
|
* Pushes a call ID onto the stack
|
|
138
166
|
* @param id - The call ID
|
|
@@ -143,7 +171,8 @@ export declare class Context {
|
|
|
143
171
|
*/
|
|
144
172
|
popId(): void;
|
|
145
173
|
/**
|
|
146
|
-
* Returns the current call
|
|
174
|
+
* Returns the current call PATH (cumulative ids joined by '|') from the top
|
|
175
|
+
* of the stack. Used as the lctx key for the current function call.
|
|
147
176
|
*/
|
|
148
177
|
peekId(): string;
|
|
149
178
|
/**
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { PineTypeObject } from './PineTypeObject';
|
|
2
1
|
import type { IndicatorOptions } from '../types/PineTypes';
|
|
3
2
|
export declare function parseIndicatorOptions(args: any[]): Partial<IndicatorOptions>;
|
|
4
3
|
/**
|
|
@@ -84,8 +83,5 @@ export declare class Core {
|
|
|
84
83
|
int(series: any): number;
|
|
85
84
|
float(series: any): number;
|
|
86
85
|
string(series: any): any;
|
|
87
|
-
Type(definition: Record<string, string | [string, any]>):
|
|
88
|
-
new: (...args: any[]) => PineTypeObject;
|
|
89
|
-
copy: (object: PineTypeObject) => PineTypeObject;
|
|
90
|
-
};
|
|
86
|
+
Type(definition: Record<string, string | [string, any]>): any;
|
|
91
87
|
}
|
|
@@ -2,7 +2,19 @@ export declare class PineTypeObject {
|
|
|
2
2
|
private _definition;
|
|
3
3
|
context: any;
|
|
4
4
|
get __def__(): Record<string, string>;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Back-reference to the UDT factory that produced this instance.
|
|
7
|
+
* Used by `request.security_lower_tf`'s pure-builtin fast path to
|
|
8
|
+
* detect UDTs whose field defaults are all bare price builtins
|
|
9
|
+
* (e.g. `type candle { float o = open; float h = high; … }`) — when
|
|
10
|
+
* detected, the secondary's per-LTF-bar values can be synthesised
|
|
11
|
+
* directly from the candle stream without running any user script.
|
|
12
|
+
* Optional and nullable: instances created outside `Type().new` (or
|
|
13
|
+
* for legacy / direct constructions) leave this undefined and the
|
|
14
|
+
* fast path simply doesn't engage.
|
|
15
|
+
*/
|
|
16
|
+
_udt?: any;
|
|
17
|
+
constructor(_definition: Record<string, string>, context: any, _udt?: any);
|
|
6
18
|
copy(): PineTypeObject;
|
|
7
19
|
toString(): string;
|
|
8
20
|
}
|
|
@@ -20,5 +20,11 @@ export declare class Str {
|
|
|
20
20
|
match(source: string, pattern: string): RegExpMatchArray;
|
|
21
21
|
split(source: string, separator: string): PineArrayObject;
|
|
22
22
|
substring(source: string, begin_pos: number, end_pos: number): string;
|
|
23
|
+
/**
|
|
24
|
+
* Format a UNIX millisecond timestamp using Java SimpleDateFormat-style tokens
|
|
25
|
+
* (yyyy, MM, dd, HH, mm, ss, EEE, EEEE, MMM, MMMM, a, h, S, Z, etc.).
|
|
26
|
+
* Text inside single quotes is treated as a literal; '' produces a literal '.
|
|
27
|
+
*/
|
|
28
|
+
format_time(time: any, format?: string, timezone?: string): string;
|
|
23
29
|
format(message: string, ...args: any[]): string;
|
|
24
30
|
}
|
|
@@ -10,9 +10,11 @@ export declare class BoxHelper {
|
|
|
10
10
|
private _resolvePoint;
|
|
11
11
|
private _resolve;
|
|
12
12
|
/**
|
|
13
|
-
* Resolve a color value, preserving
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Resolve a color value, preserving na markers so renderers can detect "no color".
|
|
14
|
+
* Pine emits na either as NaN (from `bgcolor = na`) or as null (from
|
|
15
|
+
* `bgcolor = color(na)` — `color(na)` returns null per PineColor.any). Both
|
|
16
|
+
* must survive — replacing them with a default would force renderers to paint
|
|
17
|
+
* a visible color where the script asked for none.
|
|
16
18
|
*/
|
|
17
19
|
private _resolveColor;
|
|
18
20
|
private _createBox;
|
|
@@ -22,7 +24,7 @@ export declare class BoxHelper {
|
|
|
22
24
|
*/
|
|
23
25
|
private _enforceMaxCount;
|
|
24
26
|
new(...args: any[]): BoxObject;
|
|
25
|
-
any(...args: any[]): BoxObject;
|
|
27
|
+
any(...args: any[]): BoxObject | null;
|
|
26
28
|
set_left(id: BoxObject, left: number): void;
|
|
27
29
|
set_right(id: BoxObject, right: number): void;
|
|
28
30
|
set_top(id: BoxObject, top: number): void;
|
|
@@ -17,7 +17,7 @@ export declare class LabelHelper {
|
|
|
17
17
|
private _createLabel;
|
|
18
18
|
private _enforceMaxCount;
|
|
19
19
|
new(...args: any[]): LabelObject;
|
|
20
|
-
any(...args: any[]): LabelObject;
|
|
20
|
+
any(...args: any[]): LabelObject | null;
|
|
21
21
|
set_x(id: LabelObject, x: number): void;
|
|
22
22
|
set_y(id: LabelObject, y: number): void;
|
|
23
23
|
set_xy(id: LabelObject, x: number, y: number): void;
|
|
@@ -18,7 +18,7 @@ export declare class LineHelper {
|
|
|
18
18
|
private _createLine;
|
|
19
19
|
private _enforceMaxCount;
|
|
20
20
|
new(...args: any[]): LineObject;
|
|
21
|
-
any(...args: any[]): LineObject;
|
|
21
|
+
any(...args: any[]): LineObject | null;
|
|
22
22
|
set_x1(id: LineObject, x: number): void;
|
|
23
23
|
set_y1(id: LineObject, y: number): void;
|
|
24
24
|
set_x2(id: LineObject, x: number): void;
|
|
@@ -12,7 +12,7 @@ export declare class LinefillHelper {
|
|
|
12
12
|
*/
|
|
13
13
|
private _resolve;
|
|
14
14
|
new(line1: LineObject, line2: LineObject, color: any): LinefillObject;
|
|
15
|
-
any(...args: any[]): LinefillObject;
|
|
15
|
+
any(...args: any[]): LinefillObject | null;
|
|
16
16
|
set_color(id: LinefillObject, color: any): void;
|
|
17
17
|
get_line1(id: LinefillObject): LineObject | undefined;
|
|
18
18
|
get_line2(id: LinefillObject): LineObject | undefined;
|
|
@@ -11,8 +11,9 @@ export declare class PolylineHelper {
|
|
|
11
11
|
*/
|
|
12
12
|
private _resolve;
|
|
13
13
|
/**
|
|
14
|
-
* Resolve a color value, preserving
|
|
15
|
-
*
|
|
14
|
+
* Resolve a color value, preserving na markers (NaN from `na`, null from
|
|
15
|
+
* `color(na)`) so renderers can detect "no color" instead of forcing a
|
|
16
|
+
* default via the `||` operator.
|
|
16
17
|
*/
|
|
17
18
|
private _resolveColor;
|
|
18
19
|
/**
|
|
@@ -21,7 +22,7 @@ export declare class PolylineHelper {
|
|
|
21
22
|
private _extractPoints;
|
|
22
23
|
new(...args: any[]): PolylineObject;
|
|
23
24
|
private _enforceMaxCount;
|
|
24
|
-
any(...args: any[]): PolylineObject;
|
|
25
|
+
any(...args: any[]): PolylineObject | null;
|
|
25
26
|
delete(id: PolylineObject): void;
|
|
26
27
|
get all(): PolylineObject[];
|
|
27
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function security(context: any): (
|
|
1
|
+
export declare function security(context: any): (...rawArgs: any[]) => Promise<any>;
|
|
@@ -7,4 +7,4 @@ import { PineArrayObject } from '../../array/PineArrayObject';
|
|
|
7
7
|
* @param context
|
|
8
8
|
* @returns
|
|
9
9
|
*/
|
|
10
|
-
export declare function security_lower_tf(context: any): (
|
|
10
|
+
export declare function security_lower_tf(context: any): (...rawArgs: any[]) => Promise<number | PineArrayObject | any[][]>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@silentInSecondary` — method decorator.
|
|
3
|
+
*
|
|
4
|
+
* Marks a helper method as a no-op when invoked on a secondary context
|
|
5
|
+
* (i.e. the auxiliary PineTS instance that `request.security` /
|
|
6
|
+
* `request.security_lower_tf` spawns to compute the captured expression
|
|
7
|
+
* at another symbol/timeframe).
|
|
8
|
+
*
|
|
9
|
+
* Drawings, plots, alerts and similar side-effect-only operations are
|
|
10
|
+
* never observable from a secondary context — its sole job is to populate
|
|
11
|
+
* `secContext.params[expression_name]` with the value of the captured
|
|
12
|
+
* expression bar-by-bar. Silencing those operations on secondaries cuts
|
|
13
|
+
* the per-bar work substantially without changing the captured value
|
|
14
|
+
* (the only output that callers ever read).
|
|
15
|
+
*
|
|
16
|
+
* Constructor-style methods (e.g. `label.new`, `line.new`, `box.new`)
|
|
17
|
+
* return `null`; setters / mutators / deletes return `undefined`. The
|
|
18
|
+
* existing helper code is null-safe end-to-end:
|
|
19
|
+
* - `get_*` methods already return `NaN`/`""` when the receiver is null.
|
|
20
|
+
* - The transpiler emits method calls on UDT-typed receivers as
|
|
21
|
+
* `obj?.method?.(...)`, so `null?.set_x1?.(...)` short-circuits.
|
|
22
|
+
* - Built-in setters like `LineHelper.set_x1(id, x)` already guard
|
|
23
|
+
* `if (id && !id._deleted) ...` and no-op on null.
|
|
24
|
+
*
|
|
25
|
+
* Pre-condition: target classes use the conventional
|
|
26
|
+
* `constructor(private context: any) {}`
|
|
27
|
+
* shape, so `this.context.isSecondaryContext` is uniformly accessible.
|
|
28
|
+
* (`Core.ts` `AlertHelper`, `Plots.ts` `PlotHelper`/`HlineHelper`/
|
|
29
|
+
* `FillHelper`, and the drawing helpers all conform.)
|
|
30
|
+
*/
|
|
31
|
+
export declare function silentInSecondary(_target: any, _propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
@@ -8,7 +8,7 @@ export declare class TableHelper {
|
|
|
8
8
|
syncToPlot(): void;
|
|
9
9
|
private _resolve;
|
|
10
10
|
new(...args: any[]): TableObject;
|
|
11
|
-
any(...args: any[]): TableObject;
|
|
11
|
+
any(...args: any[]): TableObject | null;
|
|
12
12
|
cell(...args: any[]): void;
|
|
13
13
|
delete(id: TableObject): void;
|
|
14
14
|
clear(...args: any[]): void;
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import ScopeManager from './ScopeManager';
|
|
2
2
|
export declare function transformNestedArrowFunctions(ast: any): void;
|
|
3
|
+
/**
|
|
4
|
+
* Pre-walk the AST to populate the UDT registry on the ScopeManager.
|
|
5
|
+
*
|
|
6
|
+
* Two registries are populated:
|
|
7
|
+
* 1. UDT type names — collected from `const X = Type({field: ['type', default], ...})`
|
|
8
|
+
* which pine2js emits from Pine `type X` declarations. The field-type metadata
|
|
9
|
+
* is stored alongside (V2 data model) for future use-site type-aware rewrites.
|
|
10
|
+
*
|
|
11
|
+
* 2. UDT instance variables — variables initialized via `<X>.new(...)` or
|
|
12
|
+
* `<X>.copy(...)` where X ∈ udtTypeNames. Each instance is tagged with its
|
|
13
|
+
* UDT type name (V2 shape).
|
|
14
|
+
*
|
|
15
|
+
* The instance check intentionally consults `isUdtTypeName(X)` rather than just
|
|
16
|
+
* "X is an Identifier", so built-in factory calls like `array.from(...)`,
|
|
17
|
+
* `polyline.new(...)`, `chart.point.from_index(...)` are excluded — those are
|
|
18
|
+
* handled by their own runtime layers and must NOT be treated as UDT instances.
|
|
19
|
+
*/
|
|
20
|
+
export declare function preProcessUdtRegistry(ast: any, scopeManager: ScopeManager): void;
|
|
3
21
|
export declare function preProcessContextBoundVars(ast: any, scopeManager: ScopeManager): void;
|
|
4
22
|
export declare function transformArrowFunctionParams(node: any, scopeManager: ScopeManager, isRootFunction?: boolean): void;
|
|
5
23
|
export declare function runAnalysisPass(ast: any, scopeManager: ScopeManager): string | undefined;
|
|
@@ -22,6 +22,72 @@ export declare class ScopeManager {
|
|
|
22
22
|
private reservedNames;
|
|
23
23
|
private userFunctions;
|
|
24
24
|
private userMethods;
|
|
25
|
+
/**
|
|
26
|
+
* Regular user-declared functions (i.e. NOT methods). Tracked separately
|
|
27
|
+
* from `userFunctions` so a UFCS-style direct call to a method-only
|
|
28
|
+
* declaration (`foo(receiver, args)` where `foo` was declared as
|
|
29
|
+
* `method foo(...)`) can be retargeted to the prefixed JS name.
|
|
30
|
+
*
|
|
31
|
+
* If a Pine name has both a regular function and a method form, the
|
|
32
|
+
* regular function takes precedence for direct `name(args)` calls and
|
|
33
|
+
* the method is reachable via dot-syntax `obj.name(args)`.
|
|
34
|
+
*/
|
|
35
|
+
private regularUserFunctions;
|
|
36
|
+
/**
|
|
37
|
+
* Registry of user-defined UDT type names → their field map (fieldName → fieldType).
|
|
38
|
+
* Populated from `const X = Type({fieldA: ['type', default], ...})` declarations
|
|
39
|
+
* (which pine2js emits from Pine `type X` declarations).
|
|
40
|
+
*
|
|
41
|
+
* V2 data model: stores field-type metadata. V1 logic only consults
|
|
42
|
+
* `isUdtTypeName` for now; field metadata is ready for future use-site
|
|
43
|
+
* type-aware rewrites (nested UDT chains, mixed scalar/array fields, etc.).
|
|
44
|
+
*/
|
|
45
|
+
private udtTypeNames;
|
|
46
|
+
/**
|
|
47
|
+
* Registry of user variables that hold UDT instances → the UDT type name.
|
|
48
|
+
* Populated from `let bar = X.new(...)` / `bar = X.copy(...)` where
|
|
49
|
+
* `X ∈ udtTypeNames`. Stores the type name (V2 shape) so future passes
|
|
50
|
+
* can do typed-field lookups via `getUdtTypeFields(typeName)` without
|
|
51
|
+
* a refactor. V1 logic only consults `isUdtInstance`.
|
|
52
|
+
*/
|
|
53
|
+
private udtInstances;
|
|
54
|
+
/**
|
|
55
|
+
* Registry of user-defined function names → UDT type they return.
|
|
56
|
+
* Populated by inspecting each FunctionDeclaration's return paths during
|
|
57
|
+
* the UDT pre-pass. A function is registered only when ALL return paths
|
|
58
|
+
* unambiguously produce the SAME UDT type.
|
|
59
|
+
*
|
|
60
|
+
* Used by the instance populator so that `bar = makeBar()` registers
|
|
61
|
+
* `bar` as a UDT instance when `makeBar` is known to return one.
|
|
62
|
+
*/
|
|
63
|
+
private functionReturnTypes;
|
|
64
|
+
/**
|
|
65
|
+
* Registry of user-defined function names → tuple of UDT type names they
|
|
66
|
+
* return. Each slot holds either the UDT type name at that position, or
|
|
67
|
+
* `undefined` when that position is not (unambiguously) a UDT instance.
|
|
68
|
+
*
|
|
69
|
+
* Populated when ALL return paths of a function are ArrayExpressions of
|
|
70
|
+
* the SAME length and each position resolves to the SAME UDT (or to
|
|
71
|
+
* something non-UDT, which becomes `undefined`).
|
|
72
|
+
*
|
|
73
|
+
* Used by the instance populator so that `[a, b] = makeBars()` registers
|
|
74
|
+
* `a` and `b` as UDT instances at their respective tuple positions.
|
|
75
|
+
*/
|
|
76
|
+
private functionReturnTupleTypes;
|
|
77
|
+
/**
|
|
78
|
+
* Registry of user-defined function names → map of {paramName → UDT type}.
|
|
79
|
+
* Populated from `<funcName>.__pineParamTypes__ = {...}` markers emitted
|
|
80
|
+
* by pine2js codegen for parameters that carried a Pine type annotation
|
|
81
|
+
* (e.g. `readField(BAR b)`). Filtered to UDT-known types so non-UDT
|
|
82
|
+
* annotations like `int` / `float` / `string` never enter the map.
|
|
83
|
+
*
|
|
84
|
+
* Consumed by `transformFunctionDeclaration`: when entering a function's
|
|
85
|
+
* body, each typed param is temporarily registered as a UDT instance
|
|
86
|
+
* (`markVariableAsUdtInstance`) so the use-site rewrite for `b.field[N]`
|
|
87
|
+
* fires inside the body. The registration is removed when leaving the
|
|
88
|
+
* function scope, keeping the global registry clean.
|
|
89
|
+
*/
|
|
90
|
+
private functionParamUdtTypes;
|
|
25
91
|
get nextParamIdArg(): any;
|
|
26
92
|
get nextCacheIdArg(): any;
|
|
27
93
|
getNextTACallId(): any;
|
|
@@ -33,10 +99,53 @@ export declare class ScopeManager {
|
|
|
33
99
|
pushScope(type: string): void;
|
|
34
100
|
popScope(): void;
|
|
35
101
|
getCurrentScopeType(): string;
|
|
102
|
+
/**
|
|
103
|
+
* True when any active scope on the stack is a function scope.
|
|
104
|
+
* Different from `getCurrentScopeType() === 'fn'`, which only matches
|
|
105
|
+
* the immediate scope — code inside a nested `if`/`for`/`while` inside
|
|
106
|
+
* a function body still needs the function-scope context (e.g. for
|
|
107
|
+
* call-path-keyed param/ta-callsite ids).
|
|
108
|
+
*/
|
|
109
|
+
isInsideFunctionScope(): boolean;
|
|
36
110
|
getCurrentScopeCount(): number;
|
|
37
111
|
addLocalSeriesVar(name: string): void;
|
|
38
112
|
removeLocalSeriesVar(name: string): void;
|
|
39
113
|
isLocalSeriesVar(name: string): boolean;
|
|
114
|
+
addUdtTypeName(typeName: string, fields?: Record<string, string>): void;
|
|
115
|
+
isUdtTypeName(name: string): boolean;
|
|
116
|
+
getUdtTypeFields(typeName: string): Record<string, string> | undefined;
|
|
117
|
+
markVariableAsUdtInstance(varName: string, typeName: string): void;
|
|
118
|
+
getVariableUdtType(varName: string): string | undefined;
|
|
119
|
+
isUdtInstance(varName: string): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Record a user-defined function as returning a specific UDT type.
|
|
122
|
+
* Idempotent — re-registering with the same type is a no-op; conflicting
|
|
123
|
+
* registrations (different type) drop back to "unknown" by removing the
|
|
124
|
+
* entry, so an ambiguous function never falsely promotes a caller.
|
|
125
|
+
*/
|
|
126
|
+
setFunctionReturnType(funcName: string, typeName: string): void;
|
|
127
|
+
getFunctionReturnType(funcName: string): string | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* Record a user-defined function as returning a tuple whose positions
|
|
130
|
+
* carry specific UDT types (or `undefined` for non-UDT positions).
|
|
131
|
+
* Idempotent — re-registering with the same shape is a no-op; conflicting
|
|
132
|
+
* registrations (different length OR different type at any position) drop
|
|
133
|
+
* the entry, so an ambiguous function never falsely promotes a caller.
|
|
134
|
+
*/
|
|
135
|
+
setFunctionReturnTupleType(funcName: string, tupleTypes: (string | undefined)[]): void;
|
|
136
|
+
getFunctionReturnTupleType(funcName: string): (string | undefined)[] | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* Record a user-defined function's UDT-typed parameters. The argument
|
|
139
|
+
* is a `paramName → UDT type` map filtered down to UDT-known types only.
|
|
140
|
+
*/
|
|
141
|
+
setFunctionParamUdtTypes(funcName: string, paramTypes: Record<string, string>): void;
|
|
142
|
+
getFunctionParamUdtTypes(funcName: string): Record<string, string> | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* Remove a previously-registered UDT instance entry. Used to roll back
|
|
145
|
+
* scope-local registrations (e.g. UDT-typed function parameters) when
|
|
146
|
+
* leaving the function body, so the global registry stays clean.
|
|
147
|
+
*/
|
|
148
|
+
unmarkVariableAsUdtInstance(varName: string): void;
|
|
40
149
|
addContextBoundVar(name: string, isRootParam?: boolean): void;
|
|
41
150
|
removeContextBoundVar(name: any): void;
|
|
42
151
|
addArrayPatternElement(name: string): void;
|
|
@@ -52,6 +161,8 @@ export declare class ScopeManager {
|
|
|
52
161
|
isUserFunction(name: string): boolean;
|
|
53
162
|
addUserMethod(name: string): void;
|
|
54
163
|
isUserMethod(name: string): boolean;
|
|
164
|
+
addRegularUserFunction(name: string): void;
|
|
165
|
+
isRegularUserFunction(name: string): boolean;
|
|
55
166
|
addVariable(name: string, kind: string): string;
|
|
56
167
|
getVariable(name: string): [string, string];
|
|
57
168
|
/**
|
|
@@ -16,27 +16,45 @@ export declare class CodeGenerator {
|
|
|
16
16
|
generate(ast: any): string;
|
|
17
17
|
private preProcessAST;
|
|
18
18
|
/**
|
|
19
|
-
* Scan the program body for
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* the namespace destructured from `$.pine`.
|
|
19
|
+
* Scan the program body for declarations whose names would collide with
|
|
20
|
+
* either Pine namespaces or JavaScript reserved keywords. Rename them
|
|
21
|
+
* with a `_$N` suffix.
|
|
23
22
|
*
|
|
24
|
-
*
|
|
25
|
-
* separately in generateFunctionDeclaration().
|
|
23
|
+
* Two collision classes, one rename pass:
|
|
26
24
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
25
|
+
* 1. Pine namespace collisions (NAMESPACE_COLLISION_NAMES — e.g. `fill`,
|
|
26
|
+
* `size`, `color`, `line`): user variable would shadow the namespace
|
|
27
|
+
* destructured from `$.pine`. The CALL SITE `fill(...)` is the
|
|
28
|
+
* namespace, NOT the renamed variable, so callees are NOT renamed.
|
|
29
|
+
*
|
|
30
|
+
* 2. JS reserved keyword collisions (JS_RESERVED_WORDS — e.g. `delete`,
|
|
31
|
+
* `super`, `static`): the generated JS would fail to parse
|
|
32
|
+
* (`function delete()` → "Unexpected keyword 'delete'"). The CALL SITE
|
|
33
|
+
* `delete(arg)` IS the user function, so callees MUST be renamed.
|
|
34
|
+
*
|
|
35
|
+
* The walker checks the original name's source list at each call site to
|
|
36
|
+
* pick the right behavior.
|
|
37
|
+
*
|
|
38
|
+
* Renaming rules (common):
|
|
39
|
+
* - Variable declaration target (let fill = ...) → renamed
|
|
40
|
+
* - Function declaration name (function delete()) → renamed (class 2 only)
|
|
41
|
+
* - Assignment target (fill := ...) → renamed
|
|
42
|
+
* - Bare identifier read (return fill) → renamed
|
|
43
|
+
* - MemberExpression object (size.tiny) → NOT renamed
|
|
44
|
+
* - MemberExpression property (obj.delete) → NOT renamed
|
|
45
|
+
* - Object property key ({size: ...}) → NOT renamed
|
|
35
46
|
*/
|
|
36
47
|
private renameConflictingVariables;
|
|
37
48
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
49
|
+
* True if `name` requires renaming — either a Pine namespace collision
|
|
50
|
+
* or a JS reserved keyword (which would make the generated JS invalid).
|
|
51
|
+
*/
|
|
52
|
+
private isReservedName;
|
|
53
|
+
/**
|
|
54
|
+
* Walk the AST and collect declarations whose names conflict with either
|
|
55
|
+
* Pine namespaces (NAMESPACE_COLLISION_NAMES) or JS reserved keywords
|
|
56
|
+
* (JS_RESERVED_WORDS). Both collision classes are renamed with the same
|
|
57
|
+
* `_$N` suffix scheme.
|
|
40
58
|
*/
|
|
41
59
|
private collectConflictingVarNames;
|
|
42
60
|
/**
|
|
@@ -58,6 +76,7 @@ export declare class CodeGenerator {
|
|
|
58
76
|
generateStatement(node: any): void;
|
|
59
77
|
generateTypeDefinition(node: any): void;
|
|
60
78
|
private renameIdentifiersInAST;
|
|
79
|
+
private renameParamRefsInBody;
|
|
61
80
|
generateFunctionDeclaration(node: any): void;
|
|
62
81
|
generateVariableDeclaration(node: any): void;
|
|
63
82
|
generateExpressionStatement(node: any): void;
|
|
@@ -14,6 +14,14 @@ export declare class Lexer {
|
|
|
14
14
|
tokenize(): Token[];
|
|
15
15
|
handleNewline(): void;
|
|
16
16
|
handleIndentation(): void;
|
|
17
|
+
/**
|
|
18
|
+
* True when the most recently emitted token (skipping NEWLINE / COMMENT
|
|
19
|
+
* — those are layout, not content) is a token that requires a right-
|
|
20
|
+
* hand-side and therefore implies the next non-blank line is a
|
|
21
|
+
* continuation, not a new block. Mirrors the set the parser's
|
|
22
|
+
* `peekOperatorEx` already crosses NEWLINE for.
|
|
23
|
+
*/
|
|
24
|
+
private isContinuationFromPrevToken;
|
|
17
25
|
readComment(): void;
|
|
18
26
|
readString(): void;
|
|
19
27
|
readColorLiteral(): void;
|
|
@@ -4,12 +4,21 @@ export declare class Parser {
|
|
|
4
4
|
private tokens;
|
|
5
5
|
private pos;
|
|
6
6
|
private functionNames;
|
|
7
|
+
private paramScopes;
|
|
7
8
|
private noLineContinuation;
|
|
8
9
|
constructor(tokens: Token[]);
|
|
9
10
|
peek(offset?: number): Token;
|
|
11
|
+
private isCurrentFunctionParam;
|
|
10
12
|
advance(): Token;
|
|
11
13
|
match(type: any, value?: any): boolean;
|
|
12
14
|
expect(type: any, value?: any): Token;
|
|
15
|
+
private static readonly CONTEXTUAL_KEYWORDS;
|
|
16
|
+
/**
|
|
17
|
+
* Consume an identifier OR a contextual keyword used as an identifier.
|
|
18
|
+
* Used in positions where Pine permits soft keywords as names — most notably
|
|
19
|
+
* UDT field names like `int type = 0`.
|
|
20
|
+
*/
|
|
21
|
+
expectIdentifierOrContextual(): Token;
|
|
13
22
|
matchEx(type: any, value?: any, allowLineContinuation?: boolean): boolean;
|
|
14
23
|
peekOperatorEx(validOps: string[]): any;
|
|
15
24
|
skipNewlines(allowIndent?: boolean): void;
|
|
@@ -3,6 +3,7 @@ export declare const NAMESPACES_LIKE: string[];
|
|
|
3
3
|
export declare const ASYNC_METHODS: string[];
|
|
4
4
|
export declare const FACTORY_METHODS: string[];
|
|
5
5
|
export declare const NAMESPACE_COLLISION_NAMES: Set<string>;
|
|
6
|
+
export declare const JS_RESERVED_WORDS: Set<string>;
|
|
6
7
|
export declare const CONTEXT_DATA_VARS: string[];
|
|
7
8
|
export declare const CONTEXT_PINE_VARS: string[];
|
|
8
9
|
export declare const CONTEXT_CORE_VARS: string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinets",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.15",
|
|
4
4
|
"description": "Run Pine Script anywhere. PineTS is an open-source transpiler and runtime that brings Pine Script logic to Node.js and the browser with 1:1 syntax compatibility. Reliably write, port, and run indicators or strategies on your own infrastructure.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Pine Script",
|