openpinescript 0.0.0-stage → 0.1.1

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.
Files changed (103) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +332 -2
  3. package/dist/cli.mjs +108691 -0
  4. package/dist/index.cjs +108670 -0
  5. package/dist/index.mjs +108624 -0
  6. package/dist/types/index.d.ts +31 -0
  7. package/dist/types/parser/v1/generated/PineV1Lexer.d.ts +66 -0
  8. package/dist/types/parser/v1/generated/PineV1Parser.d.ts +555 -0
  9. package/dist/types/parser/v1/generated/PineV1ParserVisitor.d.ts +318 -0
  10. package/dist/types/parser/v1/index.d.ts +39 -0
  11. package/dist/types/parser/v2/generated/PineV2Lexer.d.ts +67 -0
  12. package/dist/types/parser/v2/generated/PineV2Parser.d.ts +568 -0
  13. package/dist/types/parser/v2/generated/PineV2ParserVisitor.d.ts +325 -0
  14. package/dist/types/parser/v2/index.d.ts +2 -0
  15. package/dist/types/parser/v3/generated/PineV3Lexer.d.ts +67 -0
  16. package/dist/types/parser/v3/generated/PineV3Parser.d.ts +568 -0
  17. package/dist/types/parser/v3/generated/PineV3ParserVisitor.d.ts +325 -0
  18. package/dist/types/parser/v3/index.d.ts +2 -0
  19. package/dist/types/parser/v4/generated/PineV4Lexer.d.ts +86 -0
  20. package/dist/types/parser/v4/generated/PineV4Parser.d.ts +673 -0
  21. package/dist/types/parser/v4/generated/PineV4ParserVisitor.d.ts +367 -0
  22. package/dist/types/parser/v4/index.d.ts +2 -0
  23. package/dist/types/parser/v5/generated/PineV5Lexer.d.ts +95 -0
  24. package/dist/types/parser/v5/generated/PineV5Parser.d.ts +964 -0
  25. package/dist/types/parser/v5/generated/PineV5ParserVisitor.d.ts +521 -0
  26. package/dist/types/parser/v5/index.d.ts +2 -0
  27. package/dist/types/parser/v6/generated/PineV6Lexer.d.ts +98 -0
  28. package/dist/types/parser/v6/generated/PineV6Parser.d.ts +984 -0
  29. package/dist/types/parser/v6/generated/PineV6ParserVisitor.d.ts +528 -0
  30. package/dist/types/parser/v6/index.d.ts +2 -0
  31. package/dist/types/runtime/v1/Series.d.ts +61 -0
  32. package/dist/types/runtime/v1/broker/Broker.d.ts +325 -0
  33. package/dist/types/runtime/v1/broker/index.d.ts +158 -0
  34. package/dist/types/runtime/v1/broker/val.d.ts +28 -0
  35. package/dist/types/runtime/v1/constDefault.d.ts +11 -0
  36. package/dist/types/runtime/v1/context.d.ts +1705 -0
  37. package/dist/types/runtime/v1/footprint.d.ts +32 -0
  38. package/dist/types/runtime/v1/index.d.ts +7 -0
  39. package/dist/types/runtime/v1/language-spec.d.ts +12 -0
  40. package/dist/types/runtime/v1/openTrades.d.ts +12 -0
  41. package/dist/types/runtime/v1/palette.d.ts +18 -0
  42. package/dist/types/runtime/v1/session.d.ts +482 -0
  43. package/dist/types/runtime/v1/sessions.d.ts +31 -0
  44. package/dist/types/runtime/v1/stateClone.d.ts +19 -0
  45. package/dist/types/runtime/v1/stdlib/alerts.d.ts +31 -0
  46. package/dist/types/runtime/v1/stdlib/arrays.d.ts +133 -0
  47. package/dist/types/runtime/v1/stdlib/barmerge.d.ts +27 -0
  48. package/dist/types/runtime/v1/stdlib/barstate.d.ts +79 -0
  49. package/dist/types/runtime/v1/stdlib/cast.d.ts +81 -0
  50. package/dist/types/runtime/v1/stdlib/chart.d.ts +283 -0
  51. package/dist/types/runtime/v1/stdlib/color.d.ts +51 -0
  52. package/dist/types/runtime/v1/stdlib/core.d.ts +162 -0
  53. package/dist/types/runtime/v1/stdlib/dataset.d.ts +36 -0
  54. package/dist/types/runtime/v1/stdlib/display.d.ts +50 -0
  55. package/dist/types/runtime/v1/stdlib/drawings.d.ts +407 -0
  56. package/dist/types/runtime/v1/stdlib/errors.d.ts +21 -0
  57. package/dist/types/runtime/v1/stdlib/font.d.ts +20 -0
  58. package/dist/types/runtime/v1/stdlib/footprint.d.ts +76 -0
  59. package/dist/types/runtime/v1/stdlib/format.d.ts +57 -0
  60. package/dist/types/runtime/v1/stdlib/index.d.ts +71 -0
  61. package/dist/types/runtime/v1/stdlib/input.d.ts +14 -0
  62. package/dist/types/runtime/v1/stdlib/inputs.d.ts +60 -0
  63. package/dist/types/runtime/v1/stdlib/late_members.d.ts +97 -0
  64. package/dist/types/runtime/v1/stdlib/logging.d.ts +31 -0
  65. package/dist/types/runtime/v1/stdlib/maps.d.ts +55 -0
  66. package/dist/types/runtime/v1/stdlib/math.d.ts +71 -0
  67. package/dist/types/runtime/v1/stdlib/matrix.d.ts +201 -0
  68. package/dist/types/runtime/v1/stdlib/metadata.d.ts +14 -0
  69. package/dist/types/runtime/v1/stdlib/mtf.d.ts +15 -0
  70. package/dist/types/runtime/v1/stdlib/renames.d.ts +117 -0
  71. package/dist/types/runtime/v1/stdlib/renames5.d.ts +113 -0
  72. package/dist/types/runtime/v1/stdlib/renames6.d.ts +81 -0
  73. package/dist/types/runtime/v1/stdlib/request.d.ts +207 -0
  74. package/dist/types/runtime/v1/stdlib/scale.d.ts +19 -0
  75. package/dist/types/runtime/v1/stdlib/session.d.ts +113 -0
  76. package/dist/types/runtime/v1/stdlib/sort_field.d.ts +12 -0
  77. package/dist/types/runtime/v1/stdlib/sources.d.ts +24 -0
  78. package/dist/types/runtime/v1/stdlib/str.d.ts +117 -0
  79. package/dist/types/runtime/v1/stdlib/strategy.d.ts +314 -0
  80. package/dist/types/runtime/v1/stdlib/syminfo.d.ts +209 -0
  81. package/dist/types/runtime/v1/stdlib/ta.d.ts +409 -0
  82. package/dist/types/runtime/v1/stdlib/time.d.ts +158 -0
  83. package/dist/types/runtime/v1/stdlib/trades.d.ts +108 -0
  84. package/dist/types/runtime/v1/stdlib/ui.d.ts +196 -0
  85. package/dist/types/runtime/v1/stdlib/v6_members.d.ts +68 -0
  86. package/dist/types/runtime/v1/timeframes.d.ts +139 -0
  87. package/dist/types/runtime/v1/zones.d.ts +30 -0
  88. package/dist/types/transpiler/common/index.d.ts +51 -0
  89. package/dist/types/transpiler/common/libraries.d.ts +29 -0
  90. package/dist/types/transpiler/common/parseErrors.d.ts +38 -0
  91. package/dist/types/transpiler/common/passes/ScopeAnalysis.d.ts +158 -0
  92. package/dist/types/transpiler/common/passes/TypeRules.d.ts +26 -0
  93. package/dist/types/transpiler/common/profiles/index.d.ts +96 -0
  94. package/dist/types/transpiler/common/version.d.ts +40 -0
  95. package/dist/types/transpiler/v1/ToJsVisitor.d.ts +720 -0
  96. package/dist/types/transpiler/v2/ToJsVisitor.d.ts +72 -0
  97. package/dist/types/transpiler/v3/ToJsVisitor.d.ts +87 -0
  98. package/dist/types/transpiler/v4/ToJsVisitor.d.ts +263 -0
  99. package/dist/types/transpiler/v5/ToJsVisitor.d.ts +1101 -0
  100. package/dist/types/transpiler/v6/ToJsVisitor.d.ts +237 -0
  101. package/dist/types/transpiler/v6/rules.d.ts +94 -0
  102. package/dist/types/utils/v2/common.d.ts +4 -0
  103. package/package.json +92 -4
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Pre-emit analysis pass.
3
+ *
4
+ * Collects facts about the whole script that a single-pass emitter cannot see,
5
+ * because they depend on code that appears LATER in the file:
6
+ *
7
+ * - which identifiers are declared, and where (forward-reference detection)
8
+ * - which identifiers are ever mutated with ':=' (v3 forbids passing those to
9
+ * security(), because the HTF sub-evaluation would see the wrong value)
10
+ * - which identifiers hold a boolean (v3 forbids implicit bool→number
11
+ * arithmetic, and the operand is usually a variable rather than a literal)
12
+ *
13
+ * Runs before ToJsVisitor and hands it a read-only ScopeInfo.
14
+ */
15
+ import type { ParseTree, ParserRuleContext } from "antlr4ng";
16
+ export interface Declaration {
17
+ line: number;
18
+ column: number;
19
+ }
20
+ export interface ScopeInfo {
21
+ /** name → position of its first '=' binding, script scope only. */
22
+ declared: ReadonlyMap<string, Declaration>;
23
+ /**
24
+ * Names assigned with ':=' AT SCRIPT SCOPE.
25
+ *
26
+ * Scope-aware for the same reason `declared` is. These were collected
27
+ * script-wide, so a function local shadowing a global made the global look
28
+ * mutable, and v3's security() guard rejected valid code:
29
+ *
30
+ * f(z) =>
31
+ * src = z
32
+ * src := src * 2 // function-local
33
+ * src
34
+ * src = close // never mutated
35
+ * a = security(tickerid, "D", src) → "cannot use mutable variable 'src'"
36
+ */
37
+ mutated: ReadonlySet<string>;
38
+ /**
39
+ * Names whose declared value is statically a boolean, AT SCRIPT SCOPE.
40
+ *
41
+ * Same fix, same reason — a function-local `up = close > open` made a global
42
+ * numeric `up` look boolean and v3's arithmetic guard rejected `up + 1`.
43
+ *
44
+ * The trade-off is a false NEGATIVE inside function bodies: bool arithmetic on
45
+ * a function-local is no longer caught statically. That is the safe direction —
46
+ * the runtime backstop in the arithmetic helpers still sees it, whereas a false
47
+ * positive rejects a script outright.
48
+ */
49
+ booleans: ReadonlySet<string>;
50
+ /** user-defined function names. */
51
+ functions: ReadonlySet<string>;
52
+ /** all identifiers bound anywhere, including function parameters and loop vars. */
53
+ bound: ReadonlySet<string>;
54
+ /**
55
+ * Names bound INSIDE a function body — parameters and locals.
56
+ *
57
+ * A function body runs at CALL time, so a name that is local to a function
58
+ * says nothing about the lexical position of a same-named global. Without
59
+ * this, a function whose body declares `src` was reported as forward-
60
+ * referencing a global `src` declared further down the file, which rejected
61
+ * valid published code (v3/cci_commodity_channel_index.pine).
62
+ */
63
+ functionScoped: ReadonlySet<string>;
64
+ /**
65
+ * name → the LOCAL SCOPE of each of its bindings, `null` for a binding at
66
+ * script scope.
67
+ *
68
+ * From the manual's programming FAQ: "The global scope is all of the script
69
+ * that is not inside a function, if statement, or other conditional
70
+ * structure", and "only code that is in the same local scope can access a
71
+ * local variable."
72
+ *
73
+ * `bound` and `declared` are flat sets, so a name bound only inside an `if`
74
+ * block looked declared everywhere. TradingView's own "Scope demo" —
75
+ *
76
+ * if barstate.isconfirmed
77
+ * int localValue = close > open ? 1 : -1
78
+ * plot(localValue, ...)
79
+ *
80
+ * — exists to show that this is an error, and the page names it: "gives an
81
+ * 'Undeclared identifier' error when we try to access a local variable from
82
+ * the global scope". Here it emitted `opsv2_localValue`, which `with(sandbox)`
83
+ * turned into a ReferenceError on the first bar. It was the last such crash
84
+ * in the whole documentation corpus.
85
+ *
86
+ * A SPAN rather than a depth, because visibility is a question about two
87
+ * positions and not about nesting: a name bound in one block is invisible in
88
+ * its SIBLING, which is at the same depth.
89
+ */
90
+ scopesOf: ReadonlyMap<string, ReadonlyArray<Span | null>>;
91
+ /**
92
+ * user function name → how many values its tuple body returns.
93
+ *
94
+ * "Programmers can write functions that return multiple values or references
95
+ * by using a tuple as the FINAL STATEMENT in the function's body" — so the
96
+ * arity is a property of the definition and nothing else can supply it. The
97
+ * destructuring site needs it to check `[a, b] = f()` against `f`, and Pine
98
+ * permits forward references, so it cannot be read off the emitter's own
99
+ * left-to-right walk.
100
+ *
101
+ * Absent for a function whose last statement is not a `[ ... ]` list, which
102
+ * is how the destructuring site tells "returns a tuple of the wrong size"
103
+ * from "does not return a tuple at all".
104
+ */
105
+ tupleArity: ReadonlyMap<string, number>;
106
+ /**
107
+ * Functions whose body COULD end in a tuple without stating its width —
108
+ * a call, a switch — so a `[a, b] = f()` against them cannot be refused.
109
+ */
110
+ mayReturnTuple: ReadonlySet<string>;
111
+ /**
112
+ * name → its Pine TYPE, where that is knowable without evaluating anything.
113
+ *
114
+ * v5 dispatches an overloaded method on its receiver: "The underlying type of
115
+ * each variable determines which overload of `getType()` the compiler will
116
+ * use." So the compiler needs a type for a bare name, and this is the least
117
+ * machinery that supplies one.
118
+ *
119
+ * Deliberately conservative — it answers "provably this type", not "probably
120
+ * this type", and is absent for anything it cannot prove. The consumer turns
121
+ * an absence into a diagnostic that names the overloads it could not choose
122
+ * between, so a wrong guess is never silently dispatched on.
123
+ *
124
+ * Script scope only, for the same reason `booleans` is: a function-local
125
+ * shadowing a global would otherwise retype the global.
126
+ */
127
+ staticTypes: ReadonlyMap<string, string>;
128
+ /**
129
+ * name → the initialiser of a bare script-scope `name = expr` binding.
130
+ *
131
+ * Only the plain form — no `var`/`varip`, no qualifier, no type — because
132
+ * that is the one whose constness follows from its initialiser alone.
133
+ * Consulted by `isConstNumber`, which also requires the name to be bound
134
+ * once and never reassigned.
135
+ */
136
+ inits: ReadonlyMap<string, any>;
137
+ }
138
+ /** Half-open in neither direction: both token indices are inside the scope. */
139
+ export interface Span {
140
+ start: number;
141
+ stop: number;
142
+ }
143
+ /**
144
+ * The width of each way out of an `if` or `switch` that initialises a tuple:
145
+ * the length of a `[ … ]` it ends in, 1 for a plain expression with no call
146
+ * in it, and null where the width is not visible here (a call, a loop, a
147
+ * statement). Nested conditionals contribute their own branches.
148
+ */
149
+ export declare function branchTupleWidths(node: any): Array<number | null>;
150
+ /**
151
+ * Is this expression statically known to be a boolean?
152
+ *
153
+ * Deliberately conservative — it answers "provably bool", not "possibly bool".
154
+ * A false negative is caught by the runtime backstop in the arithmetic
155
+ * helpers; a false positive would reject valid code.
156
+ */
157
+ export declare function isStaticallyBool(node: any, booleans: ReadonlySet<string>): boolean;
158
+ export declare function analyseScopes(tree: ParseTree | ParserRuleContext): ScopeInfo;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * What the emitter can PROVE about the type of an expression, for the type
3
+ * errors TradingView raises at compile time (v4+): a float stored in an `int`,
4
+ * a float passed where an `int` length is required.
5
+ *
6
+ * Every answer here is "provably", never "probably". A false positive rejects
7
+ * a script TradingView accepts; a miss leaves the status quo. So anything not
8
+ * listed below is "unknown", and unknown never produces an error. Narrower than
9
+ * `isStaticallyNumeric` in ../../v6/rules.ts on purpose: that one answers
10
+ * "int or float", this one answers "float".
11
+ */
12
+ import type { ScopeInfo } from "./ScopeAnalysis.js";
13
+ /** Is `node` provably a float? */
14
+ export declare function isProvablyFloat(node: any, scopes: ScopeInfo): boolean;
15
+ /** Is `node` the bare identifier `na`? */
16
+ export declare function isPlainNa(node: any): boolean;
17
+ /**
18
+ * Is `node` provably a CONSTANT number — a literal, `math.pi`, or `+ - * / %`
19
+ * over constants, directly or through a script-scope name bound once to one
20
+ * and never reassigned? TradingView prints a constant float differently from a
21
+ * series one in v4/v5 `str.tostring` (see runtime/v1/stdlib/str.ts).
22
+ *
23
+ * Provably, as everywhere here: anything else — inputs, `syminfo.*`, calls,
24
+ * ternaries, a name in a function or block — is not constant.
25
+ */
26
+ export declare function isConstNumber(node: any, scopes: ScopeInfo, seen?: Set<string>): boolean;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Language profiles — per-version RUNTIME configuration.
3
+ *
4
+ * ── SCOPE, AND WHAT USED TO BE HERE ─────────────────────────────────────────
5
+ *
6
+ * This file once carried a `restrictions: Set<RestrictionId>` that the emitter
7
+ * consulted on every guard (`if (!this.restricts("no_reassignment")) return`).
8
+ * That is gone. Language rules now live in the version that owns them:
9
+ *
10
+ * - SYNTAX differences are grammar files (grammar/v{N}/PineV{N}Lexer|Parser.g4)
11
+ * - EMIT differences are visitor subclasses (transpiler/v{N}/ToJsVisitor.ts)
12
+ *
13
+ * A flag table cannot express "v1 has never heard of ':='" — it can only express
14
+ * "v1 parses ':=' and then complains", which is not what TradingView does.
15
+ * Inheritance can.
16
+ *
17
+ * What remains is configuration the RUNTIME reads at execution time, which has
18
+ * no parse tree to hang off: banned identifiers and behavioural defaults.
19
+ *
20
+ * Sources for every entry: docs/common/VERSIONS.md, which cites
21
+ * TradingView's official migration guides.
22
+ */
23
+ import { PineVersion } from "../version.js";
24
+ export interface LanguageProfile {
25
+ readonly version: PineVersion;
26
+ /**
27
+ * Identifiers that must throw when read, mapped to their message.
28
+ * v1–v3 ban `bar_index` (the v2-era name is `n`); v4+ invert this and ban `n`.
29
+ */
30
+ readonly banned: ReadonlyMap<string, string>;
31
+ readonly defaults: {
32
+ /** The indicator-declaration directive. v5 renames study() to indicator(). */
33
+ readonly scriptDirective: "study" | "indicator";
34
+ /**
35
+ * security()'s `lookahead` default. Read by runtime/v1/stdlib/mtf.ts.
36
+ * v1/v2 default to lookahead_on; the v2→v3 migration flipped it to off.
37
+ *
38
+ * Only fields with a real consumer belong here — a default nothing reads
39
+ * lets a test assert the constant against itself and call it coverage.
40
+ */
41
+ readonly securityLookahead: "on" | "off";
42
+ /**
43
+ * ── v6 behavioural flags ──────────────────────────────────────────────
44
+ *
45
+ * Optional, and ABSENT on v1–v5 rather than set to a v5 value. Absence is
46
+ * what "this version predates the question" looks like, and it keeps the
47
+ * five earlier profile literals byte-identical — so no v5 script can pick
48
+ * up a v6 default by way of an edit to a shared helper.
49
+ *
50
+ * Each is read in exactly one place, named on the field.
51
+ */
52
+ /**
53
+ * Colour constants whose VALUE changed, keyed by their dotted name.
54
+ * MG §"Color changes". Read by createStdlib in runtime/v1/stdlib/index.ts.
55
+ */
56
+ readonly palette?: Readonly<Record<string, string>>;
57
+ /**
58
+ * `time(timeframe)` returns the start of that timeframe's bar, not the
59
+ * chart bar's own time. Verified for v5 against TradingView's log
60
+ * (conformance/common/v5_gaps_golden.test.ts). Read by `time()` in
61
+ * runtime/v1/stdlib/time.ts.
62
+ */
63
+ readonly alignsTimeframe?: boolean;
64
+ /**
65
+ * `timeframe.period` always carries a multiplier: "D" -> "1D".
66
+ * MG §"Timeframes must include a multiplier". Read by `period()` in
67
+ * runtime/v1/stdlib/chart.ts.
68
+ */
69
+ readonly timeframeAlwaysMultiplied?: boolean;
70
+ /**
71
+ * Array accessors read -1 as the last element. MG §"Negative indices in
72
+ * arrays". Read by the index check in runtime/v1/stdlib/arrays.ts.
73
+ */
74
+ readonly negativeArrayIndices?: boolean;
75
+ /**
76
+ * A bool can never be `na`, so history past the start of a bool series is
77
+ * `false`. MG §"Boolean values cannot be na". Read by Context.get.
78
+ */
79
+ readonly boolsCanBeNa?: boolean;
80
+ /**
81
+ * How many of the most recent closed trades stay inspectable. Older ones
82
+ * are "trimmed": `strategy.closedtrades.*()` returns na for them and
83
+ * `strategy.closedtrades.first_index` names the oldest kept. MG §"Excess
84
+ * orders are trimmed", detailed on the Strategies page's trade-limit
85
+ * section. Read by `closed()` in runtime/v1/stdlib/trades.ts.
86
+ */
87
+ readonly retainedClosedTrades?: number;
88
+ };
89
+ }
90
+ export declare const LANGUAGE_PROFILES: Readonly<Record<PineVersion, LanguageProfile>>;
91
+ export declare function profileFor(version: PineVersion): LanguageProfile;
92
+ export declare const DEFAULT_PROFILE: LanguageProfile;
93
+ export declare class UnimplementedVersionError extends Error {
94
+ readonly version: PineVersion;
95
+ constructor(version: PineVersion);
96
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Pine Script version detection.
3
+ *
4
+ * The `//@version=N` annotation is a comment, and the ANTLR lexer skips
5
+ * comments — so detection happens here, in a pre-parse scan of the raw source,
6
+ * rather than in the grammar.
7
+ *
8
+ * TradingView treats a script with no annotation as v1.
9
+ */
10
+ export type PineVersion = 1 | 2 | 3 | 4 | 5 | 6;
11
+ /**
12
+ * Versions this engine can PARSE an annotation for. Not the same as the
13
+ * versions it can run — see LANGUAGE_PROFILES[v].implemented for that.
14
+ */
15
+ export declare const KNOWN_VERSIONS: readonly PineVersion[];
16
+ /** A script with no //@version annotation is Pine Script v1. */
17
+ export declare const DEFAULT_VERSION: PineVersion;
18
+ export declare function registerImplementedVersions(versions: readonly PineVersion[]): void;
19
+ /**
20
+ * Exported so the profiles module can name what really runs without importing
21
+ * transpiler/common/index.ts, which imports profiles — the same cycle
22
+ * `registerImplementedVersions` exists to avoid.
23
+ */
24
+ export declare function implementedVersions(): readonly PineVersion[];
25
+ export declare class UnsupportedVersionError extends Error {
26
+ readonly requested: number;
27
+ constructor(requested: number, implemented?: readonly PineVersion[]);
28
+ }
29
+ /**
30
+ * True when the source has a `//@version` line of any form, valid or not. A
31
+ * script with none is read as v1, which is worth telling its author when the
32
+ * body is newer.
33
+ */
34
+ export declare function hasVersionLine(source: string): boolean;
35
+ /**
36
+ * Reads the `//@version=N` annotation. Returns 1 when absent.
37
+ * @throws UnsupportedVersionError for a well-formed annotation naming a version
38
+ * we do not implement.
39
+ */
40
+ export declare function detectVersion(source: string): PineVersion;