openpinescript 0.0.0-stage → 0.1.0
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/LICENSE +674 -0
- package/README.md +346 -2
- package/dist/cli.mjs +108686 -0
- package/dist/index.cjs +108670 -0
- package/dist/index.mjs +108624 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/parser/v1/generated/PineV1Lexer.d.ts +66 -0
- package/dist/types/parser/v1/generated/PineV1Parser.d.ts +555 -0
- package/dist/types/parser/v1/generated/PineV1ParserVisitor.d.ts +318 -0
- package/dist/types/parser/v1/index.d.ts +39 -0
- package/dist/types/parser/v2/generated/PineV2Lexer.d.ts +67 -0
- package/dist/types/parser/v2/generated/PineV2Parser.d.ts +568 -0
- package/dist/types/parser/v2/generated/PineV2ParserVisitor.d.ts +325 -0
- package/dist/types/parser/v2/index.d.ts +2 -0
- package/dist/types/parser/v3/generated/PineV3Lexer.d.ts +67 -0
- package/dist/types/parser/v3/generated/PineV3Parser.d.ts +568 -0
- package/dist/types/parser/v3/generated/PineV3ParserVisitor.d.ts +325 -0
- package/dist/types/parser/v3/index.d.ts +2 -0
- package/dist/types/parser/v4/generated/PineV4Lexer.d.ts +86 -0
- package/dist/types/parser/v4/generated/PineV4Parser.d.ts +673 -0
- package/dist/types/parser/v4/generated/PineV4ParserVisitor.d.ts +367 -0
- package/dist/types/parser/v4/index.d.ts +2 -0
- package/dist/types/parser/v5/generated/PineV5Lexer.d.ts +95 -0
- package/dist/types/parser/v5/generated/PineV5Parser.d.ts +964 -0
- package/dist/types/parser/v5/generated/PineV5ParserVisitor.d.ts +521 -0
- package/dist/types/parser/v5/index.d.ts +2 -0
- package/dist/types/parser/v6/generated/PineV6Lexer.d.ts +98 -0
- package/dist/types/parser/v6/generated/PineV6Parser.d.ts +984 -0
- package/dist/types/parser/v6/generated/PineV6ParserVisitor.d.ts +528 -0
- package/dist/types/parser/v6/index.d.ts +2 -0
- package/dist/types/runtime/v1/Series.d.ts +61 -0
- package/dist/types/runtime/v1/broker/Broker.d.ts +325 -0
- package/dist/types/runtime/v1/broker/index.d.ts +158 -0
- package/dist/types/runtime/v1/broker/val.d.ts +28 -0
- package/dist/types/runtime/v1/constDefault.d.ts +11 -0
- package/dist/types/runtime/v1/context.d.ts +1705 -0
- package/dist/types/runtime/v1/footprint.d.ts +32 -0
- package/dist/types/runtime/v1/index.d.ts +7 -0
- package/dist/types/runtime/v1/language-spec.d.ts +12 -0
- package/dist/types/runtime/v1/openTrades.d.ts +12 -0
- package/dist/types/runtime/v1/palette.d.ts +18 -0
- package/dist/types/runtime/v1/session.d.ts +482 -0
- package/dist/types/runtime/v1/sessions.d.ts +31 -0
- package/dist/types/runtime/v1/stateClone.d.ts +19 -0
- package/dist/types/runtime/v1/stdlib/alerts.d.ts +31 -0
- package/dist/types/runtime/v1/stdlib/arrays.d.ts +133 -0
- package/dist/types/runtime/v1/stdlib/barmerge.d.ts +27 -0
- package/dist/types/runtime/v1/stdlib/barstate.d.ts +79 -0
- package/dist/types/runtime/v1/stdlib/cast.d.ts +81 -0
- package/dist/types/runtime/v1/stdlib/chart.d.ts +283 -0
- package/dist/types/runtime/v1/stdlib/color.d.ts +51 -0
- package/dist/types/runtime/v1/stdlib/core.d.ts +162 -0
- package/dist/types/runtime/v1/stdlib/dataset.d.ts +36 -0
- package/dist/types/runtime/v1/stdlib/display.d.ts +50 -0
- package/dist/types/runtime/v1/stdlib/drawings.d.ts +407 -0
- package/dist/types/runtime/v1/stdlib/errors.d.ts +21 -0
- package/dist/types/runtime/v1/stdlib/font.d.ts +20 -0
- package/dist/types/runtime/v1/stdlib/footprint.d.ts +76 -0
- package/dist/types/runtime/v1/stdlib/format.d.ts +57 -0
- package/dist/types/runtime/v1/stdlib/index.d.ts +71 -0
- package/dist/types/runtime/v1/stdlib/input.d.ts +14 -0
- package/dist/types/runtime/v1/stdlib/inputs.d.ts +60 -0
- package/dist/types/runtime/v1/stdlib/late_members.d.ts +97 -0
- package/dist/types/runtime/v1/stdlib/logging.d.ts +31 -0
- package/dist/types/runtime/v1/stdlib/maps.d.ts +55 -0
- package/dist/types/runtime/v1/stdlib/math.d.ts +71 -0
- package/dist/types/runtime/v1/stdlib/matrix.d.ts +201 -0
- package/dist/types/runtime/v1/stdlib/metadata.d.ts +14 -0
- package/dist/types/runtime/v1/stdlib/mtf.d.ts +15 -0
- package/dist/types/runtime/v1/stdlib/renames.d.ts +117 -0
- package/dist/types/runtime/v1/stdlib/renames5.d.ts +113 -0
- package/dist/types/runtime/v1/stdlib/renames6.d.ts +81 -0
- package/dist/types/runtime/v1/stdlib/request.d.ts +207 -0
- package/dist/types/runtime/v1/stdlib/scale.d.ts +19 -0
- package/dist/types/runtime/v1/stdlib/session.d.ts +113 -0
- package/dist/types/runtime/v1/stdlib/sort_field.d.ts +12 -0
- package/dist/types/runtime/v1/stdlib/sources.d.ts +24 -0
- package/dist/types/runtime/v1/stdlib/str.d.ts +117 -0
- package/dist/types/runtime/v1/stdlib/strategy.d.ts +314 -0
- package/dist/types/runtime/v1/stdlib/syminfo.d.ts +209 -0
- package/dist/types/runtime/v1/stdlib/ta.d.ts +409 -0
- package/dist/types/runtime/v1/stdlib/time.d.ts +158 -0
- package/dist/types/runtime/v1/stdlib/trades.d.ts +108 -0
- package/dist/types/runtime/v1/stdlib/ui.d.ts +196 -0
- package/dist/types/runtime/v1/stdlib/v6_members.d.ts +68 -0
- package/dist/types/runtime/v1/timeframes.d.ts +139 -0
- package/dist/types/runtime/v1/zones.d.ts +30 -0
- package/dist/types/transpiler/common/index.d.ts +51 -0
- package/dist/types/transpiler/common/libraries.d.ts +29 -0
- package/dist/types/transpiler/common/parseErrors.d.ts +38 -0
- package/dist/types/transpiler/common/passes/ScopeAnalysis.d.ts +158 -0
- package/dist/types/transpiler/common/passes/TypeRules.d.ts +26 -0
- package/dist/types/transpiler/common/profiles/index.d.ts +96 -0
- package/dist/types/transpiler/common/version.d.ts +40 -0
- package/dist/types/transpiler/v1/ToJsVisitor.d.ts +720 -0
- package/dist/types/transpiler/v2/ToJsVisitor.d.ts +72 -0
- package/dist/types/transpiler/v3/ToJsVisitor.d.ts +87 -0
- package/dist/types/transpiler/v4/ToJsVisitor.d.ts +263 -0
- package/dist/types/transpiler/v5/ToJsVisitor.d.ts +1101 -0
- package/dist/types/transpiler/v6/ToJsVisitor.d.ts +237 -0
- package/dist/types/transpiler/v6/rules.d.ts +94 -0
- package/dist/types/utils/v2/common.d.ts +4 -0
- package/package.json +92 -4
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pine Script v2 → JavaScript emitter.
|
|
3
|
+
*
|
|
4
|
+
* v2 inherits every line of emit logic from v1 and adds exactly one thing:
|
|
5
|
+
* reassignment with ':='.
|
|
6
|
+
*
|
|
7
|
+
* The operator is a v2 GRAMMAR addition (PineV2Lexer.g4 declares the token,
|
|
8
|
+
* PineV2Parser.g4 the rule), so v1 rejects `x := 1` as a syntax error — its
|
|
9
|
+
* grammar has never heard of the token. There is no "reassignment is not
|
|
10
|
+
* allowed in v1" guard anywhere, because v1 cannot reach one.
|
|
11
|
+
*
|
|
12
|
+
* SCOPE is the part a grammar cannot express, and the documented rule is a
|
|
13
|
+
* DECLARATION rule, not a scope one:
|
|
14
|
+
*
|
|
15
|
+
* "Pine now supports mutable variables! Use the ':=' operator to assign a new
|
|
16
|
+
* value to a variable that has already been defined."
|
|
17
|
+
* — TradingView release notes, Pine v2
|
|
18
|
+
* "A variable must be declared before you can set a value for it."
|
|
19
|
+
* — Expressions, declarations and statements (v3 manual, which documents
|
|
20
|
+
* ':=' as requiring only //@version=2)
|
|
21
|
+
*
|
|
22
|
+
* Neither source restricts ':=' by scope, and the corpus agrees: two published
|
|
23
|
+
* //@version=2 scripts reassign at script scope —
|
|
24
|
+
*
|
|
25
|
+
* longStopPrice = 0.0 gap_down_reversal_strategy
|
|
26
|
+
* longStopPrice := if (strategy.position_size > 0)
|
|
27
|
+
*
|
|
28
|
+
* if crossunder(corVix, -.1) or ... VIX_bonds_strategy
|
|
29
|
+
* signal1 := -100
|
|
30
|
+
*
|
|
31
|
+
* An earlier version of this file restricted ':=' to for-loop accumulators and
|
|
32
|
+
* rejected both. That restriction was inferred, not sourced, and it was wrong:
|
|
33
|
+
* TradingView compiled and published these scripts. What is enforced now is the
|
|
34
|
+
* rule the documentation actually states — assign only to a name that was
|
|
35
|
+
* declared.
|
|
36
|
+
*
|
|
37
|
+
* v3 inherits this guard unchanged. ':=' scope was never a v1→v2→v3 delta.
|
|
38
|
+
*
|
|
39
|
+
* ⚠ See the sourcing note in grammar/v2/PineV2Lexer.g4 on why ':=' is placed at v2
|
|
40
|
+
* rather than v1. If that turns out to be wrong, this class moves to v1 wholesale.
|
|
41
|
+
*/
|
|
42
|
+
import type { PineVersion } from "../common/version.js";
|
|
43
|
+
import { V1ToJsVisitor } from "../v1/ToJsVisitor.js";
|
|
44
|
+
import { Var_assignContext, Global_stmt_contentContext, Local_stmt_contentContext } from "../../parser/v2/generated/PineV2Parser.js";
|
|
45
|
+
export type { Local_stmt_contentContext };
|
|
46
|
+
export declare class V2ToJsVisitor extends V1ToJsVisitor {
|
|
47
|
+
protected readonly version: PineVersion;
|
|
48
|
+
/**
|
|
49
|
+
* ':=' assigns to a variable "that has already been defined". Assigning to a
|
|
50
|
+
* name that is never declared is the `Undeclared identifier` error, which is
|
|
51
|
+
* how `if x==1 / y := 2` fails on TradingView.
|
|
52
|
+
*
|
|
53
|
+
* Scope is deliberately NOT checked — see the sourcing note at the top of this
|
|
54
|
+
* file. POSITION is not checked here either: forward references are legal in
|
|
55
|
+
* v2, and v3 rejects them through `enforceNoForwardReference`, which already
|
|
56
|
+
* sees this id because `visitVar_assign` visits it.
|
|
57
|
+
*/
|
|
58
|
+
protected enforceDeclaredBeforeReassignment(ctx: Var_assignContext): void;
|
|
59
|
+
/** Handle: x := 1 */
|
|
60
|
+
visitVar_assign(ctx: Var_assignContext): string;
|
|
61
|
+
/**
|
|
62
|
+
* v2's global_stmt_content / local_stmt_content gained a `var_assign`
|
|
63
|
+
* alternative, so the statement dispatcher has to route it. Everything else
|
|
64
|
+
* falls through to the inherited implementation.
|
|
65
|
+
*/
|
|
66
|
+
protected visitContent(ctx: Global_stmt_contentContext | Local_stmt_contentContext): string;
|
|
67
|
+
/**
|
|
68
|
+
* ':=' is a binding form too, so a function body ending in one returns the
|
|
69
|
+
* reassigned variable. v1 only knows about '='.
|
|
70
|
+
*/
|
|
71
|
+
protected trailingValueName(content: Local_stmt_contentContext): string | null;
|
|
72
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pine Script v3 → JavaScript emitter.
|
|
3
|
+
*
|
|
4
|
+
* ── THE WORKED EXAMPLE OF A VERSION DELTA ───────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* v3 inherits every line of emit logic from v2 (and thus v1). This file
|
|
7
|
+
* contains ONLY what the v2→v3 migration guide documents:
|
|
8
|
+
*
|
|
9
|
+
* 1. A variable may not reference itself in its own '=' declaration.
|
|
10
|
+
* 2. An identifier may not be used before it is declared.
|
|
11
|
+
* 3. Bools no longer coerce to numbers in arithmetic.
|
|
12
|
+
* 4. A ':='-mutated variable may not be passed to security().
|
|
13
|
+
*
|
|
14
|
+
* Each is one `enforce*` method plus a two-line override that calls it and
|
|
15
|
+
* delegates to `super`. Nothing in v1 or v2 was touched to add any of them.
|
|
16
|
+
*
|
|
17
|
+
* Every one is a TIGHTENING. v3 relaxes nothing: an earlier draft listed
|
|
18
|
+
* "':=' becomes available at every scope" as a fifth delta, but v2 never had a
|
|
19
|
+
* scope restriction to lift — see the sourcing note in ../v2/ToJsVisitor.ts.
|
|
20
|
+
*
|
|
21
|
+
* The security() lookahead default also flips in v3, but that is a RUNTIME
|
|
22
|
+
* behaviour rather than an emit one — it lives in the v3 language profile and is
|
|
23
|
+
* read by runtime/v1/stdlib/mtf.ts.
|
|
24
|
+
*
|
|
25
|
+
* NOTE ON `:=` — inherited from v2 wholesale, operator and guard alike. v1
|
|
26
|
+
* rejects it as a syntax error because PineV1Lexer.g4 has no such token.
|
|
27
|
+
*/
|
|
28
|
+
import type { ParseTree } from "antlr4ng";
|
|
29
|
+
import type { PineVersion } from "../common/version.js";
|
|
30
|
+
import { V2ToJsVisitor } from "../v2/ToJsVisitor.js";
|
|
31
|
+
import { Var_defContext, Add_exprContext, Mult_exprContext, Fun_callContext, IdContext } from "../../parser/v3/generated/PineV3Parser.js";
|
|
32
|
+
/** Anything carrying a source position (see the v1 base for why it is structural). */
|
|
33
|
+
interface SourceLocated {
|
|
34
|
+
start?: {
|
|
35
|
+
line: number;
|
|
36
|
+
column: number;
|
|
37
|
+
} | null;
|
|
38
|
+
}
|
|
39
|
+
export declare class V3ToJsVisitor extends V2ToJsVisitor {
|
|
40
|
+
protected readonly version: PineVersion;
|
|
41
|
+
/**
|
|
42
|
+
* `s = nz(s[1]) + close` was the v1/v2 state idiom. v3 requires declaring
|
|
43
|
+
* first (`s = 0.0`) and then assigning with ':='.
|
|
44
|
+
*/
|
|
45
|
+
protected enforceNoSelfReference(name: string, value: ParseTree, ctx: SourceLocated): void;
|
|
46
|
+
visitVar_def(ctx: Var_defContext): string;
|
|
47
|
+
/** An identifier may not be used before its declaration. Checked lexically. */
|
|
48
|
+
protected enforceNoForwardReference(name: string, ctx: SourceLocated): void;
|
|
49
|
+
visitId(ctx: IdContext): string;
|
|
50
|
+
/**
|
|
51
|
+
* v1/v2 coerced true→1 and false→0; v3 requires an explicit `b ? 1 : 0`.
|
|
52
|
+
*
|
|
53
|
+
* Static detection only, and deliberately conservative — `isStaticallyBool`
|
|
54
|
+
* answers "provably bool", not "possibly bool". A false negative is caught by
|
|
55
|
+
* the runtime backstop in the arithmetic helpers; a false positive would
|
|
56
|
+
* reject valid code.
|
|
57
|
+
*/
|
|
58
|
+
protected enforceNoBoolArithmetic(operand: ParseTree, ctx: SourceLocated, op: string): void;
|
|
59
|
+
/**
|
|
60
|
+
* The operator ADJACENT to operand `i`, in a flat `a + b - c` chain.
|
|
61
|
+
*
|
|
62
|
+
* Children alternate operand, operator, operand, …, so operand `i` is
|
|
63
|
+
* preceded by the operator at `i * 2 - 1`. Reading `getChild(1)`
|
|
64
|
+
* unconditionally named the FIRST operator every time, so `z = 1 + 2 - b`
|
|
65
|
+
* with a bool `b` reported "cannot use a bool as an operand of '+'" when the
|
|
66
|
+
* offending operator is '-'. Cosmetic, but a diagnostic that points at the
|
|
67
|
+
* wrong token sends the reader to the wrong place.
|
|
68
|
+
*/
|
|
69
|
+
private operatorFor;
|
|
70
|
+
visitAdd_expr(ctx: Add_exprContext): string;
|
|
71
|
+
visitMult_expr(ctx: Mult_exprContext): string;
|
|
72
|
+
/**
|
|
73
|
+
* Its value at HTF evaluation time is not the value the chart context holds,
|
|
74
|
+
* so the result would be silently wrong. Wrap the calculation in a function.
|
|
75
|
+
*/
|
|
76
|
+
protected enforceNoMutableSecurityArg(args: ParseTree | null, ctx: SourceLocated): void;
|
|
77
|
+
/**
|
|
78
|
+
* Does this security-family call carry the mutable-argument restriction?
|
|
79
|
+
*
|
|
80
|
+
* A seam, because v5 splits the family: `request.security_lower_tf` keeps the
|
|
81
|
+
* rule and `request.security` loses it. Answering here rather than in
|
|
82
|
+
* `emitSecurity` keeps the walk in one place.
|
|
83
|
+
*/
|
|
84
|
+
protected securityRestrictsMutableArgs(_ctx: Fun_callContext): boolean;
|
|
85
|
+
protected emitSecurity(ctx: Fun_callContext): string;
|
|
86
|
+
}
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pine Script v4 → JavaScript emitter.
|
|
3
|
+
*
|
|
4
|
+
* v4 inherits every guard v3 added — self-reference, forward reference, bool
|
|
5
|
+
* arithmetic, mutable `security()` argument — and every line of emit logic from
|
|
6
|
+
* v1. The migration guide relaxes none of them.
|
|
7
|
+
*
|
|
8
|
+
* What v4 adds is in two halves:
|
|
9
|
+
*
|
|
10
|
+
* SYNTAX (this file)
|
|
11
|
+
* `var` / `varip` declaration modifiers, and an optional type prefix.
|
|
12
|
+
* `var` is the only one with emit consequences; the type prefix is checked
|
|
13
|
+
* and discarded, and the qualifiers are discarded outright.
|
|
14
|
+
*
|
|
15
|
+
* The five compound assignment operators, `+= -= *= /= %=` (March 2021).
|
|
16
|
+
* Sourced from the v4 release notes; see PineV4Lexer.g4 for the quote.
|
|
17
|
+
*
|
|
18
|
+
* `else if` (May 2020). Grammar in PineV4Parser.g4, emit below.
|
|
19
|
+
*
|
|
20
|
+
* NAMES (transpiler/common/profiles/index.ts + runtime)
|
|
21
|
+
* The 3a rename table — `n` → `bar_index`, `red` → `color.red`,
|
|
22
|
+
* `period` → `timeframe.period`, and the rest. Those are lookups, not emit
|
|
23
|
+
* rules, so they do not belong here.
|
|
24
|
+
*
|
|
25
|
+
* NOT in v4, despite an earlier draft of the delta spec saying so: `while` and
|
|
26
|
+
* `switch`. Both are v5. v4 adds no statement keyword at all, which is why this
|
|
27
|
+
* file overrides declarations and nothing else.
|
|
28
|
+
*/
|
|
29
|
+
import type { PineVersion } from "../common/version.js";
|
|
30
|
+
import { V3ToJsVisitor } from "../v3/ToJsVisitor.js";
|
|
31
|
+
import type { StdlibEntry } from "../../runtime/v1/stdlib/metadata.js";
|
|
32
|
+
import { Var_defContext, Var_defsContext, Var_assignContext, If_exprContext, IdContext, Pos_argsContext, Pos_argContext, Fun_callContext } from "../../parser/v4/generated/PineV4Parser.js";
|
|
33
|
+
/** Anything carrying a source position (see the v1 base for why it is structural). */
|
|
34
|
+
interface SourceLocated {
|
|
35
|
+
start?: {
|
|
36
|
+
line: number;
|
|
37
|
+
column: number;
|
|
38
|
+
} | null;
|
|
39
|
+
}
|
|
40
|
+
/** A declaration's `var` / `varip` modifier, or null when it has neither. */
|
|
41
|
+
type Persistence = "var" | "varip" | null;
|
|
42
|
+
export declare class V4ToJsVisitor extends V3ToJsVisitor {
|
|
43
|
+
protected readonly version: PineVersion;
|
|
44
|
+
/**
|
|
45
|
+
* v4's view of the stdlib: the base, minus the spellings v4 removed, plus the
|
|
46
|
+
* namespaced ones it introduced.
|
|
47
|
+
*
|
|
48
|
+
* Subtracting matters as much as adding. Leaving `red` in alongside
|
|
49
|
+
* `color.red` would accept both dialects, and a script written half in each
|
|
50
|
+
* would compile here and fail on TradingView — the exact class of divergence
|
|
51
|
+
* this engine exists to avoid.
|
|
52
|
+
*/
|
|
53
|
+
protected get registry(): Record<string, StdlibEntry>;
|
|
54
|
+
/**
|
|
55
|
+
* From v4, a user-defined function MAY return a tuple.
|
|
56
|
+
*
|
|
57
|
+
* SOURCING. From the manual's user-defined functions page: "Programmers can
|
|
58
|
+
* write functions that return multiple values or references by using a tuple
|
|
59
|
+
* as the final statement in the function's body", with
|
|
60
|
+
*
|
|
61
|
+
* sumDiff(float val1, float val2) =>
|
|
62
|
+
* [val1 + val2, val1 - val2]
|
|
63
|
+
*
|
|
64
|
+
* [sum, diff] = sumDiff(math.random(), math.random())
|
|
65
|
+
*
|
|
66
|
+
* and the rule for reading one back: "the script must use a tuple declaration
|
|
67
|
+
* containing one NEW variable for each returned item. It is not possible to
|
|
68
|
+
* reassign existing tuples or to use previously declared variables within
|
|
69
|
+
* them."
|
|
70
|
+
*
|
|
71
|
+
* v1–v3 keep the refusal — `conformance/common/guards_by_version.test.ts` has
|
|
72
|
+
* always declared the guard for those three and left v4 and v5 unstated, and
|
|
73
|
+
* this is the override that was missing. Eight of TradingView's own published
|
|
74
|
+
* scripts were rejected by it, including the one on its own error-messages
|
|
75
|
+
* page about tuples.
|
|
76
|
+
*
|
|
77
|
+
* Lifting the guard is the WHOLE change: `[a, b]` already emits a JavaScript
|
|
78
|
+
* array through `visitArith_exprs`, a body's last statement is already what a
|
|
79
|
+
* function returns, and `ctx.new_vars` already unpacks a built-in's tuple.
|
|
80
|
+
*/
|
|
81
|
+
protected enforceNoTupleReturn(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Rejects a v1–v3 spelling with the name that replaced it.
|
|
84
|
+
*
|
|
85
|
+
* Hooked on `visitId` rather than driven off the registry, because a missing
|
|
86
|
+
* registry entry is not by itself an error — `visitId` emits any identifier
|
|
87
|
+
* it does not recognise, since most identifiers are the script's own
|
|
88
|
+
* variables. So `red` at v4 would just emit `opsv2_red` and read as
|
|
89
|
+
* `undefined`: a colour that is silently `na`, on a chart that still draws.
|
|
90
|
+
*/
|
|
91
|
+
protected enforceRenamedInV4(name: string, ctx: SourceLocated): void;
|
|
92
|
+
/**
|
|
93
|
+
* Is this identifier the CALLEE of a function call, rather than a read?
|
|
94
|
+
*
|
|
95
|
+
* Structural rather than `instanceof` — every version generates its own
|
|
96
|
+
* context classes, so `instanceof` is false across the hierarchy (see the
|
|
97
|
+
* note on `isRule` in the v1 base).
|
|
98
|
+
*/
|
|
99
|
+
protected isCalleeOf(ctx: SourceLocated): boolean;
|
|
100
|
+
visitId(ctx: IdContext): string;
|
|
101
|
+
/** Reads the modifier off a declaration. Absent on every v1–v3 declaration. */
|
|
102
|
+
protected persistenceOf(ctx: Var_defContext | Var_defsContext): Persistence;
|
|
103
|
+
/**
|
|
104
|
+
* `var x = expr` initialises once and then holds its value across bars.
|
|
105
|
+
*
|
|
106
|
+
* The initialiser is emitted as a THUNK. `ctx.var_def` runs it on the first
|
|
107
|
+
* bar only, so `expr` is not re-evaluated afterwards — which matters both for
|
|
108
|
+
* cost and for correctness: `var t = timenow` must keep the first bar's
|
|
109
|
+
* timestamp, and passing an already-evaluated value would silently make it
|
|
110
|
+
* the current one every bar while still looking like it worked.
|
|
111
|
+
*
|
|
112
|
+
* The @L:C key is the DECLARATION SITE, not the name. Two `var`s of the same
|
|
113
|
+
* name in different scopes are different variables and must not share an
|
|
114
|
+
* initialised flag.
|
|
115
|
+
*/
|
|
116
|
+
visitVar_def(ctx: Var_defContext): string;
|
|
117
|
+
/**
|
|
118
|
+
* `var [a, b] = f()` — the tuple form.
|
|
119
|
+
*
|
|
120
|
+
* Rejected rather than emitted wrongly. `ctx.new_vars` destructures a fresh
|
|
121
|
+
* call result into several series, and there is no once-only form of it: the
|
|
122
|
+
* honest options are to build one, or to say so. A wrong `var` here would
|
|
123
|
+
* re-run `f()` every bar while the script says it must not, and nothing
|
|
124
|
+
* downstream could detect that.
|
|
125
|
+
*/
|
|
126
|
+
visitVar_defs(ctx: Var_defsContext): string;
|
|
127
|
+
/** Script-scope names declared with an explicit `int`, bound once. */
|
|
128
|
+
private readonly declaredInts;
|
|
129
|
+
/**
|
|
130
|
+
* "Value with NA type cannot be assigned to a variable that was defined
|
|
131
|
+
* without type keyword" — `x = na`, and the `b = na` of `var float a = na, b = na`,
|
|
132
|
+
* where the keyword covers `a` only. v1–v3 accept it, so this lives in v4.
|
|
133
|
+
*
|
|
134
|
+
* `int q = close` — a float stored in a declared int. Only when the
|
|
135
|
+
* initialiser is PROVABLY a float (see TypeRules.ts).
|
|
136
|
+
*/
|
|
137
|
+
protected enforceDeclarationTypes(ctx: Var_defContext): void;
|
|
138
|
+
/** TradingView's wording, which differs by version. */
|
|
139
|
+
protected declaredIntMessage(name: string): string;
|
|
140
|
+
/**
|
|
141
|
+
* A float argument where a `series int` length is required. The first
|
|
142
|
+
* positional slot of these functions is the source, so only the second is
|
|
143
|
+
* read — `ta.highest(10)` has its length first and is left alone.
|
|
144
|
+
*/
|
|
145
|
+
protected enforceIntLengthArgument(ctx: Fun_callContext): void;
|
|
146
|
+
/**
|
|
147
|
+
* A float where a drawing constructor's x coordinate (a `series int`) is
|
|
148
|
+
* required: `label.new(bar_index - 10.7, ...)` is a compile error on v4, v5
|
|
149
|
+
* and v6. `w / 2` between ints is no proof (see isProvablyFloat), so it still
|
|
150
|
+
* compiles. The `chart.point` overloads (v5/v6) take points, not coordinates,
|
|
151
|
+
* so only the 4-coordinate form (4+ positional args, or the x1/x2 keywords)
|
|
152
|
+
* is read.
|
|
153
|
+
*/
|
|
154
|
+
protected enforceIntCoordinateArguments(ctx: Fun_callContext): void;
|
|
155
|
+
/** TradingView names a binary expression `call 'operator -' (series float)`; anything else is shown as written. */
|
|
156
|
+
private describeFloatOperand;
|
|
157
|
+
visitFun_call(ctx: any): string;
|
|
158
|
+
/**
|
|
159
|
+
* `tostring(x)` / `str.tostring(x)` of a constant number prints differently
|
|
160
|
+
* from the same call on a series (runtime/v1/stdlib/str.ts `numberToString`),
|
|
161
|
+
* and only the source can tell them apart. A call with no format whose
|
|
162
|
+
* argument is provably constant gets the runtime's CONST_DEFAULT marker in
|
|
163
|
+
* the format position.
|
|
164
|
+
*/
|
|
165
|
+
private markConstTostring;
|
|
166
|
+
/**
|
|
167
|
+
* The arithmetic half of a compound assignment — `"+"` for `+=` — or null
|
|
168
|
+
* when the statement is a plain `:=`.
|
|
169
|
+
*/
|
|
170
|
+
protected compoundOperatorOf(ctx: Var_assignContext): string | null;
|
|
171
|
+
/**
|
|
172
|
+
* `current <op> value`, emitted EXACTLY as the binary operator would be.
|
|
173
|
+
*
|
|
174
|
+
* TradingView defines `x += y` as "an arithmetic operator combined with the
|
|
175
|
+
* reassignment operator", so it has to mean precisely `x := x + y` — which
|
|
176
|
+
* for `+` and `-` is not the JavaScript operator. `opsv2_safe_add` is what
|
|
177
|
+
* `visitAdd_expr` emits, and it is what makes `na + 1` come out `na` and
|
|
178
|
+
* `"a" + "b"` concatenate. Emitting a raw `+` here would have made compound
|
|
179
|
+
* assignment the one place in the language where `na` behaved differently.
|
|
180
|
+
*
|
|
181
|
+
* `value` is parenthesised because not every emitted expression is
|
|
182
|
+
* self-contained: a comparison comes out as bare `a > b`, so `x *= a > b`
|
|
183
|
+
* would otherwise bind as `(x * a) > b`. (`and` and `or` used to be the
|
|
184
|
+
* example here, back when they emitted `a && b`; they are now a call to
|
|
185
|
+
* `ctx.allOf`, which brackets itself — see visitAnd_expr.)
|
|
186
|
+
*/
|
|
187
|
+
protected compoundValue(op: string, current: string, value: string): string;
|
|
188
|
+
/**
|
|
189
|
+
* `x += expr`.
|
|
190
|
+
*
|
|
191
|
+
* Routed through the same guard as `:=` — the target must already be
|
|
192
|
+
* declared, which for a compound assignment is not a formality: there is no
|
|
193
|
+
* previous value to add to otherwise.
|
|
194
|
+
*/
|
|
195
|
+
visitVar_assign(ctx: Var_assignContext): string;
|
|
196
|
+
/**
|
|
197
|
+
* `else if cond` — the else branch is another `if` rather than a block.
|
|
198
|
+
*
|
|
199
|
+
* Emitted INLINE, as one more `else if` on the JavaScript side, instead of
|
|
200
|
+
* by visiting the nested `if` normally. That distinction is the whole of the
|
|
201
|
+
* work here, and it is not a matter of taste:
|
|
202
|
+
*
|
|
203
|
+
* x = if a
|
|
204
|
+
* 1
|
|
205
|
+
* else if b
|
|
206
|
+
* 2
|
|
207
|
+
* else
|
|
208
|
+
* 3
|
|
209
|
+
*
|
|
210
|
+
* A normal visit would give the nested `if` its own IIFE, producing
|
|
211
|
+
* `(() => { if (a) { return 1; } else (() => { … })(); })()` — the inner
|
|
212
|
+
* function computes 2 or 3 and the outer one throws the result away, so `x`
|
|
213
|
+
* is `undefined` on every bar that takes the `else`. No error; just an `na`
|
|
214
|
+
* where a number belongs.
|
|
215
|
+
*
|
|
216
|
+
* Recursing HERE keeps the whole chain inside the single wrapper
|
|
217
|
+
* `visitIf_expr` already opened, and inside the one `suppressBlockReturn`
|
|
218
|
+
* level it already set — so every arm of the chain returns, or does not,
|
|
219
|
+
* together.
|
|
220
|
+
*/
|
|
221
|
+
protected emitElseBranch(ctx: If_exprContext): string | null;
|
|
222
|
+
/**
|
|
223
|
+
* v4's `pos_args` is a list of `pos_arg`, not of `arith_expr`. Overriding the
|
|
224
|
+
* SEAM rather than `visitPos_args` means `emitSecurity` — which walks the
|
|
225
|
+
* same list to defer its third argument into a thunk — picks the change up
|
|
226
|
+
* without knowing about it.
|
|
227
|
+
*/
|
|
228
|
+
protected positionalArgs(ctx: Pos_argsContext): any[];
|
|
229
|
+
/** `arith_expr | arith_exprs` — a transparent wrapper either way. */
|
|
230
|
+
visitPos_arg(ctx: Pos_argContext): string;
|
|
231
|
+
/**
|
|
232
|
+
* `[o, h, l, c] = security(sym, "D", [open, high, low, close])`.
|
|
233
|
+
*
|
|
234
|
+
* The tuple is the ARGUMENT's, so its width is read off the bracketed list
|
|
235
|
+
* rather than out of the registry — `security` returns one value or four
|
|
236
|
+
* depending on what it was handed, and no single registry entry can say that.
|
|
237
|
+
*
|
|
238
|
+
* Both spellings are read, positional and keyword, because both appear in
|
|
239
|
+
* TradingView's own examples.
|
|
240
|
+
*/
|
|
241
|
+
protected tupleArityFromArgument(call: Fun_callContext): number | null;
|
|
242
|
+
/**
|
|
243
|
+
* How many values this `expression` argument yields, when that is knowable.
|
|
244
|
+
*
|
|
245
|
+
* Two shapes, and the second is why this is not just `.arith_exprs()`:
|
|
246
|
+
*
|
|
247
|
+
* [o, h, l, c] = request.security(sym, "D", [open, high, low, close])
|
|
248
|
+
* [bop, avg] = request.security(sym, "1D", dataFunction())
|
|
249
|
+
*
|
|
250
|
+
* The manual's own error-messages page uses the second — a call to a
|
|
251
|
+
* user-defined function whose body ends in a tuple. Its width is a fact about
|
|
252
|
+
* that DEFINITION, which `ScopeInfo.tupleArity` collected for exactly this.
|
|
253
|
+
*/
|
|
254
|
+
protected expressionArity(node: any): number | null;
|
|
255
|
+
/**
|
|
256
|
+
* The call this expression consists of ENTIRELY, or null.
|
|
257
|
+
*
|
|
258
|
+
* Only a single-child spine is followed, so `f() + 1` is not `f()`: the
|
|
259
|
+
* arithmetic makes it one value however many `f` returns.
|
|
260
|
+
*/
|
|
261
|
+
protected soleCall(node: any): any | null;
|
|
262
|
+
}
|
|
263
|
+
export {};
|