openpinescript 0.1.0 → 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.
package/README.md CHANGED
@@ -8,14 +8,18 @@
8
8
  No TradingView account. No cloud. No execution quota. No 500 ms loop timeout.
9
9
 
10
10
  [![TradingView parity](https://img.shields.io/badge/TradingView_parity-112_columns_×_2%2C474_bars-7B3FE4?style=for-the-badge)](docs/common/CONFORMANCE.md)
11
- [![Tests](https://img.shields.io/badge/tests-2%2C396_passing-22C55E?style=for-the-badge)](docs/common/CONFORMANCE.md#testing)
11
+ [![Tests](https://img.shields.io/badge/tests-4%2C400%2B_passing-22C55E?style=for-the-badge)](docs/common/CONFORMANCE.md#testing)
12
12
  [![Pine Script](https://img.shields.io/badge/Pine_Script-v1_→_v6-F97316?style=for-the-badge)](#-supported-pine-script-versions)
13
+ [![Docs](https://img.shields.io/badge/docs-be--thomas.github.io%2FOpenPineScript-0EA5E9?style=for-the-badge)](https://be-thomas.github.io/OpenPineScript/)
14
+ [![npm](https://img.shields.io/npm/v/openpinescript?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/openpinescript)
13
15
 
14
16
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg?style=flat-square)](LICENSE)
15
17
  [![Node](https://img.shields.io/badge/node-≥20-339933.svg?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org)
16
18
  [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6.svg?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
17
19
  [![Docs corpus](https://img.shields.io/badge/docs_corpus-741%2F763_compile-0EA5E9.svg?style=flat-square)](docs/common/CONFORMANCE.md#parity-763-real-scripts-from-tradingviews-docs)
18
20
 
21
+ ### [📖 Documentation and an interactive tutorial: **be-thomas.github.io/OpenPineScript**](https://be-thomas.github.io/OpenPineScript/)
22
+
19
23
  ### [▶ Open Beta: try it in your browser at **zealterminal.com**](https://zealterminal.com) — no install, no CSV
20
24
 
21
25
  [Docs](https://be-thomas.github.io/OpenPineScript/) · [Try it online](#-try-it-online) · [Quick start](#-quick-start) · [Why](#-why-openpinescript) · [Parity](#-verified-against-tradingview-itself) · [Guides](#-documentation) · [FAQ](#-faq)
@@ -105,26 +109,6 @@ npm install openpinescript
105
109
  import { Session } from "openpinescript";
106
110
  ```
107
111
 
108
- To work on the engine itself, run it from a clone:
109
-
110
- ```bash
111
- git clone https://github.com/be-thomas/OpenPineScript.git
112
- cd OpenPineScript
113
- npm install
114
- ```
115
-
116
- Then run a bundled example:
117
-
118
- ```bash
119
- npm run opsv2 -- examples/v1/sma_crossover.pine --data mock_data/common/AAPL_mock.csv
120
- ```
121
-
122
- Or explore interactively:
123
-
124
- ```bash
125
- npm run replv2
126
- ```
127
-
128
112
  ![OpenPineScript REPL evaluating Pine Script expressions in a terminal session](https://raw.githubusercontent.com/be-thomas/OpenPineScript/main/images/common/repl-1.png)
129
113
 
130
114
  ---
@@ -138,7 +122,7 @@ npm run replv2
138
122
  | 🗂️ **Six language versions** | v1 → v6, each with its own grammar and emitter, so a v2 script is parsed by a parser that has never heard of `var`. |
139
123
  | 🔁 **Pine → JavaScript** | Emit readable JS and embed it anywhere — a worker, a server, a browser, a CI job. |
140
124
  | 🤖 **Built for automation** | JSON output, exit codes, input overrides, and a comparison mode that diffs your run against a TradingView export. |
141
- | 🧪 **3,389 tests** | Differential testing against an independent oracle, a full version matrix, 763 real scripts from TradingView's docs, and the parity suites above. |
125
+ | 🧪 **4,400+ tests** | Differential testing against an independent oracle, a full version matrix, 763 real scripts from TradingView's docs, and the parity suites above. |
142
126
 
143
127
  ---
144
128
 
@@ -198,7 +182,7 @@ broker emulator, multi-timeframe `security()`, and the real-time tick model.
198
182
  - **Put it behind a chart** — [zealterminal.com](https://zealterminal.com) is this engine in a browser tab, in open beta, if you want to see that shape working before you build it
199
183
 
200
184
  ```bash
201
- npm run opsv2 -- strategy.pine --data data.csv --out-dir ./results --json
185
+ npx openpinescript strategy.pine --data data.csv --out-dir ./results
202
186
  ```
203
187
 
204
188
  > 📖 **[Full CLI reference →](CLI-Usage.md)** — output flags, comparison mode,
@@ -210,6 +194,7 @@ npm run opsv2 -- strategy.pine --data data.csv --out-dir ./results --json
210
194
 
211
195
  | Doc | What it answers |
212
196
  |---|---|
197
+ | **[Docs site](https://be-thomas.github.io/OpenPineScript/)** | The CLI guide, a five-lesson tutorial that runs the real engine in your browser, and a guide written for AI agents |
213
198
  | **[Conformance report](docs/common/CONFORMANCE.md)** | How the numbers are verified, what that caught, what is not covered |
214
199
  | **[CLI usage](CLI-Usage.md)** | Every flag, with worked examples |
215
200
  | **[Architecture](docs/common/ARCHITECTURE.md)** | The compile pipeline and the repository layout |
@@ -307,8 +292,9 @@ bar by bar against a runtime that provides the standard library.
307
292
  <summary><b>How do I convert Pine Script to JavaScript?</b></summary>
308
293
  <br>
309
294
 
310
- `npm run opsv2 -- script.pine --emit-js out.js`, or call `compileScript(src)`
311
- from `transpiler/common` to get the emitted source back as a string.
295
+ `npx openpinescript script.pine --data data.csv --show-transpiled` prints the
296
+ compiled JavaScript before running it, or call `compileScript(src)` from the
297
+ library (`import { compileScript } from "openpinescript"`) to get it as a string.
312
298
  </details>
313
299
 
314
300
  ---
package/dist/cli.mjs CHANGED
@@ -19109,7 +19109,7 @@ function typeFit(declared, value) {
19109
19109
  __name(typeFit, "typeFit");
19110
19110
 
19111
19111
  // parser/v1/index.ts
19112
- import { CharStreams, CommonTokenStream, BaseErrorListener } from "antlr4ng";
19112
+ import { CharStream as CharStream2, CommonTokenStream, BaseErrorListener } from "antlr4ng";
19113
19113
 
19114
19114
  // parser/v1/generated/PineV1Parser.ts
19115
19115
  import * as antlr from "antlr4ng";
@@ -29653,7 +29653,7 @@ function IndentTokenSource(Base, options = {}) {
29653
29653
  this.indentErrors = [];
29654
29654
  this.tokenFactory = {
29655
29655
  create: /* @__PURE__ */ __name((source2, type, text6, channel, start, stop, line4, charPositionInLine) => {
29656
- const t = new CommonToken(source2, type, channel, start, stop);
29656
+ const t = CommonToken.fromSource(source2, type, channel, start, stop);
29657
29657
  t.line = line4;
29658
29658
  t.column = charPositionInLine;
29659
29659
  if (text6 !== void 0 && text6 !== null) t.text = text6;
@@ -29708,7 +29708,7 @@ function IndentTokenSource(Base, options = {}) {
29708
29708
  }
29709
29709
  let text6 = t.text;
29710
29710
  if (!text6 && this.inputStream) {
29711
- text6 = this.inputStream.getText(new Interval(t.start, t.stop));
29711
+ text6 = this.inputStream.getTextFromInterval(new Interval(t.start, t.stop));
29712
29712
  }
29713
29713
  text6 = text6 || "";
29714
29714
  const lastNewLineIndex = text6.lastIndexOf("\n");
@@ -29734,7 +29734,7 @@ function IndentTokenSource(Base, options = {}) {
29734
29734
  }
29735
29735
  /** Is the line that LBEG token `t` introduces flush against column 0? */
29736
29736
  startsAtColumnZero(t) {
29737
- const text6 = t.text ?? this.inputStream?.getText(new Interval(t.start, t.stop)) ?? "";
29737
+ const text6 = t.text ?? this.inputStream?.getTextFromInterval(new Interval(t.start, t.stop)) ?? "";
29738
29738
  const nl = Math.max(text6.lastIndexOf("\n"), text6.lastIndexOf("\r"));
29739
29739
  if (text6.substring(nl + 1).length !== 0) return false;
29740
29740
  const c = this.inputStream?.LA(1);
@@ -29745,7 +29745,7 @@ function IndentTokenSource(Base, options = {}) {
29745
29745
  }
29746
29746
  /** Line number of the last line an LBEG token spans. */
29747
29747
  newlinesIn(t) {
29748
- const text6 = t.text ?? this.inputStream?.getText(new Interval(t.start, t.stop)) ?? "";
29748
+ const text6 = t.text ?? this.inputStream?.getTextFromInterval(new Interval(t.start, t.stop)) ?? "";
29749
29749
  return (text6.match(/\n|\r(?!\n)/g) ?? []).length;
29750
29750
  }
29751
29751
  handleIndentation(indentLength, triggerToken, isEOF = false) {
@@ -29898,7 +29898,7 @@ var ErrorCollector = class extends BaseErrorListener {
29898
29898
  };
29899
29899
  function createParser(TokenSourceCtor, ParserCtor, entry2) {
29900
29900
  return /* @__PURE__ */ __name(function parse7(source2) {
29901
- const inputStream = CharStreams.fromString(source2);
29901
+ const inputStream = CharStream2.fromString(source2);
29902
29902
  const lexer = new TokenSourceCtor(inputStream);
29903
29903
  lexer.removeErrorListeners();
29904
29904
  const lexerListener = new ErrorCollector();
@@ -101538,7 +101538,7 @@ var PineV6TokenSource = class extends IndentTokenSource(PineV6Lexer, { strictCon
101538
101538
  var parse6 = createParser(PineV6TokenSource, PineV6Parser, (p) => p.pine_script());
101539
101539
 
101540
101540
  // transpiler/v1/ToJsVisitor.ts
101541
- import { ParseTreeVisitor } from "antlr4ng";
101541
+ import { AbstractParseTreeVisitor } from "antlr4ng";
101542
101542
 
101543
101543
  // transpiler/common/passes/ScopeAnalysis.ts
101544
101544
  function children(node) {
@@ -101933,7 +101933,7 @@ function isConstIntLiteral(node) {
101933
101933
  }
101934
101934
  }
101935
101935
  __name(isConstIntLiteral, "isConstIntLiteral");
101936
- var V1ToJsVisitor = class extends ParseTreeVisitor {
101936
+ var V1ToJsVisitor = class extends AbstractParseTreeVisitor {
101937
101937
  constructor() {
101938
101938
  super(...arguments);
101939
101939
  /**
@@ -108265,18 +108265,22 @@ function getFlag(args, flag) {
108265
108265
  __name(getFlag, "getFlag");
108266
108266
  function parseArgs(argv) {
108267
108267
  const args = argv.slice(2);
108268
+ if (args.includes("--help") || args.includes("-h")) {
108269
+ printUsage(console.log);
108270
+ process.exit(0);
108271
+ }
108268
108272
  const scriptPath = args.find((a) => a.endsWith(".pine")) ?? null;
108269
108273
  if (!scriptPath) {
108270
108274
  console.error(`${C2.Red}Error:${C2.Reset} No .pine script file specified.
108271
108275
  `);
108272
- printUsage();
108276
+ printUsage(console.error);
108273
108277
  process.exit(1);
108274
108278
  }
108275
108279
  const dataPath = getFlag(args, "--data");
108276
108280
  if (!dataPath) {
108277
108281
  console.error(`${C2.Red}Error:${C2.Reset} --data <csv> is required.
108278
108282
  `);
108279
- printUsage();
108283
+ printUsage(console.error);
108280
108284
  process.exit(1);
108281
108285
  }
108282
108286
  const inputs = {};
@@ -108317,9 +108321,10 @@ function parseArgs(argv) {
108317
108321
  };
108318
108322
  }
108319
108323
  __name(parseArgs, "parseArgs");
108320
- function printUsage() {
108321
- console.log(
108322
- `${C2.Bold}Usage:${C2.Reset} npm run opsv2 -- <script.pine> --data <data.csv> [flags]
108324
+ function printUsage(out) {
108325
+ out(
108326
+ `${C2.Bold}Usage:${C2.Reset} openpinescript <script.pine> --data <data.csv> [flags]
108327
+ npx openpinescript <script.pine> --data <data.csv> [flags]
108323
108328
 
108324
108329
  ${C2.Bold}Output flags:${C2.Reset}
108325
108330
  --out-dir <dir> Write chart.csv, trades.csv, and summary.json to <dir>
package/dist/index.cjs CHANGED
@@ -10595,7 +10595,7 @@ function IndentTokenSource(Base, options = {}) {
10595
10595
  this.indentErrors = [];
10596
10596
  this.tokenFactory = {
10597
10597
  create: /* @__PURE__ */ __name((source2, type, text6, channel, start, stop, line4, charPositionInLine) => {
10598
- const t = new import_antlr4ng.CommonToken(source2, type, channel, start, stop);
10598
+ const t = import_antlr4ng.CommonToken.fromSource(source2, type, channel, start, stop);
10599
10599
  t.line = line4;
10600
10600
  t.column = charPositionInLine;
10601
10601
  if (text6 !== void 0 && text6 !== null) t.text = text6;
@@ -10650,7 +10650,7 @@ function IndentTokenSource(Base, options = {}) {
10650
10650
  }
10651
10651
  let text6 = t.text;
10652
10652
  if (!text6 && this.inputStream) {
10653
- text6 = this.inputStream.getText(new import_antlr4ng.Interval(t.start, t.stop));
10653
+ text6 = this.inputStream.getTextFromInterval(new import_antlr4ng.Interval(t.start, t.stop));
10654
10654
  }
10655
10655
  text6 = text6 || "";
10656
10656
  const lastNewLineIndex = text6.lastIndexOf("\n");
@@ -10676,7 +10676,7 @@ function IndentTokenSource(Base, options = {}) {
10676
10676
  }
10677
10677
  /** Is the line that LBEG token `t` introduces flush against column 0? */
10678
10678
  startsAtColumnZero(t) {
10679
- const text6 = t.text ?? this.inputStream?.getText(new import_antlr4ng.Interval(t.start, t.stop)) ?? "";
10679
+ const text6 = t.text ?? this.inputStream?.getTextFromInterval(new import_antlr4ng.Interval(t.start, t.stop)) ?? "";
10680
10680
  const nl = Math.max(text6.lastIndexOf("\n"), text6.lastIndexOf("\r"));
10681
10681
  if (text6.substring(nl + 1).length !== 0) return false;
10682
10682
  const c = this.inputStream?.LA(1);
@@ -10687,7 +10687,7 @@ function IndentTokenSource(Base, options = {}) {
10687
10687
  }
10688
10688
  /** Line number of the last line an LBEG token spans. */
10689
10689
  newlinesIn(t) {
10690
- const text6 = t.text ?? this.inputStream?.getText(new import_antlr4ng.Interval(t.start, t.stop)) ?? "";
10690
+ const text6 = t.text ?? this.inputStream?.getTextFromInterval(new import_antlr4ng.Interval(t.start, t.stop)) ?? "";
10691
10691
  return (text6.match(/\n|\r(?!\n)/g) ?? []).length;
10692
10692
  }
10693
10693
  handleIndentation(indentLength, triggerToken, isEOF = false) {
@@ -10840,7 +10840,7 @@ var ErrorCollector = class extends import_antlr4ng2.BaseErrorListener {
10840
10840
  };
10841
10841
  function createParser(TokenSourceCtor, ParserCtor, entry2) {
10842
10842
  return /* @__PURE__ */ __name(function parse7(source2) {
10843
- const inputStream = import_antlr4ng2.CharStreams.fromString(source2);
10843
+ const inputStream = import_antlr4ng2.CharStream.fromString(source2);
10844
10844
  const lexer = new TokenSourceCtor(inputStream);
10845
10845
  lexer.removeErrorListeners();
10846
10846
  const lexerListener = new ErrorCollector();
@@ -98788,7 +98788,7 @@ function isConstIntLiteral(node) {
98788
98788
  }
98789
98789
  }
98790
98790
  __name(isConstIntLiteral, "isConstIntLiteral");
98791
- var V1ToJsVisitor = class extends import_antlr4ng3.ParseTreeVisitor {
98791
+ var V1ToJsVisitor = class extends import_antlr4ng3.AbstractParseTreeVisitor {
98792
98792
  constructor() {
98793
98793
  super(...arguments);
98794
98794
  /**
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ var __export = (target, all) => {
6
6
  };
7
7
 
8
8
  // parser/v1/index.ts
9
- import { CharStreams, CommonTokenStream, BaseErrorListener } from "antlr4ng";
9
+ import { CharStream as CharStream2, CommonTokenStream, BaseErrorListener } from "antlr4ng";
10
10
 
11
11
  // parser/v1/generated/PineV1Parser.ts
12
12
  import * as antlr from "antlr4ng";
@@ -10550,7 +10550,7 @@ function IndentTokenSource(Base, options = {}) {
10550
10550
  this.indentErrors = [];
10551
10551
  this.tokenFactory = {
10552
10552
  create: /* @__PURE__ */ __name((source2, type, text6, channel, start, stop, line4, charPositionInLine) => {
10553
- const t = new CommonToken(source2, type, channel, start, stop);
10553
+ const t = CommonToken.fromSource(source2, type, channel, start, stop);
10554
10554
  t.line = line4;
10555
10555
  t.column = charPositionInLine;
10556
10556
  if (text6 !== void 0 && text6 !== null) t.text = text6;
@@ -10605,7 +10605,7 @@ function IndentTokenSource(Base, options = {}) {
10605
10605
  }
10606
10606
  let text6 = t.text;
10607
10607
  if (!text6 && this.inputStream) {
10608
- text6 = this.inputStream.getText(new Interval(t.start, t.stop));
10608
+ text6 = this.inputStream.getTextFromInterval(new Interval(t.start, t.stop));
10609
10609
  }
10610
10610
  text6 = text6 || "";
10611
10611
  const lastNewLineIndex = text6.lastIndexOf("\n");
@@ -10631,7 +10631,7 @@ function IndentTokenSource(Base, options = {}) {
10631
10631
  }
10632
10632
  /** Is the line that LBEG token `t` introduces flush against column 0? */
10633
10633
  startsAtColumnZero(t) {
10634
- const text6 = t.text ?? this.inputStream?.getText(new Interval(t.start, t.stop)) ?? "";
10634
+ const text6 = t.text ?? this.inputStream?.getTextFromInterval(new Interval(t.start, t.stop)) ?? "";
10635
10635
  const nl = Math.max(text6.lastIndexOf("\n"), text6.lastIndexOf("\r"));
10636
10636
  if (text6.substring(nl + 1).length !== 0) return false;
10637
10637
  const c = this.inputStream?.LA(1);
@@ -10642,7 +10642,7 @@ function IndentTokenSource(Base, options = {}) {
10642
10642
  }
10643
10643
  /** Line number of the last line an LBEG token spans. */
10644
10644
  newlinesIn(t) {
10645
- const text6 = t.text ?? this.inputStream?.getText(new Interval(t.start, t.stop)) ?? "";
10645
+ const text6 = t.text ?? this.inputStream?.getTextFromInterval(new Interval(t.start, t.stop)) ?? "";
10646
10646
  return (text6.match(/\n|\r(?!\n)/g) ?? []).length;
10647
10647
  }
10648
10648
  handleIndentation(indentLength, triggerToken, isEOF = false) {
@@ -10795,7 +10795,7 @@ var ErrorCollector = class extends BaseErrorListener {
10795
10795
  };
10796
10796
  function createParser(TokenSourceCtor, ParserCtor, entry2) {
10797
10797
  return /* @__PURE__ */ __name(function parse7(source2) {
10798
- const inputStream = CharStreams.fromString(source2);
10798
+ const inputStream = CharStream2.fromString(source2);
10799
10799
  const lexer = new TokenSourceCtor(inputStream);
10800
10800
  lexer.removeErrorListeners();
10801
10801
  const lexerListener = new ErrorCollector();
@@ -82435,7 +82435,7 @@ var PineV6TokenSource = class extends IndentTokenSource(PineV6Lexer, { strictCon
82435
82435
  var parse6 = createParser(PineV6TokenSource, PineV6Parser, (p) => p.pine_script());
82436
82436
 
82437
82437
  // transpiler/v1/ToJsVisitor.ts
82438
- import { ParseTreeVisitor } from "antlr4ng";
82438
+ import { AbstractParseTreeVisitor } from "antlr4ng";
82439
82439
 
82440
82440
  // utils/v2/common.ts
82441
82441
  var PREFIX = "opsv2_";
@@ -98743,7 +98743,7 @@ function isConstIntLiteral(node) {
98743
98743
  }
98744
98744
  }
98745
98745
  __name(isConstIntLiteral, "isConstIntLiteral");
98746
- var V1ToJsVisitor = class extends ParseTreeVisitor {
98746
+ var V1ToJsVisitor = class extends AbstractParseTreeVisitor {
98747
98747
  constructor() {
98748
98748
  super(...arguments);
98749
98749
  /**
@@ -1,4 +1,4 @@
1
- import { ParseTreeVisitor } from "antlr4ng";
1
+ import { AbstractParseTreeVisitor } from "antlr4ng";
2
2
  import { Pine_scriptContext } from "./PineV1Parser.js";
3
3
  import { StmtContext } from "./PineV1Parser.js";
4
4
  import { Global_stmtContext } from "./PineV1Parser.js";
@@ -50,7 +50,7 @@ import { IdContext } from "./PineV1Parser.js";
50
50
  * @param <Result> The return type of the visit operation. Use `void` for
51
51
  * operations with no return type.
52
52
  */
53
- export declare class PineV1ParserVisitor<Result> extends ParseTreeVisitor<Result> {
53
+ export declare class PineV1ParserVisitor<Result> extends AbstractParseTreeVisitor<Result> {
54
54
  /**
55
55
  * Visit a parse tree produced by `PineV1Parser.pine_script`.
56
56
  * @param ctx the parse tree
@@ -22,7 +22,7 @@ export interface ParserError {
22
22
  * cannot satisfy both signatures nominally, and only `line`/`column`/`msg` are
23
23
  * read here.
24
24
  */
25
- export declare class ErrorCollector extends BaseErrorListener<any> {
25
+ export declare class ErrorCollector extends BaseErrorListener {
26
26
  errors: ParserError[];
27
27
  syntaxError(recognizer: any, offendingSymbol: any, line: number, charPositionInLine: number, msg: string, e: any): void;
28
28
  }
@@ -1,4 +1,4 @@
1
- import { ParseTreeVisitor } from "antlr4ng";
1
+ import { AbstractParseTreeVisitor } from "antlr4ng";
2
2
  import { Var_assignContext } from "./PineV2Parser.js";
3
3
  import { Global_stmt_contentContext } from "./PineV2Parser.js";
4
4
  import { Local_stmt_contentContext } from "./PineV2Parser.js";
@@ -51,7 +51,7 @@ import { IdContext } from "./PineV2Parser.js";
51
51
  * @param <Result> The return type of the visit operation. Use `void` for
52
52
  * operations with no return type.
53
53
  */
54
- export declare class PineV2ParserVisitor<Result> extends ParseTreeVisitor<Result> {
54
+ export declare class PineV2ParserVisitor<Result> extends AbstractParseTreeVisitor<Result> {
55
55
  /**
56
56
  * Visit a parse tree produced by `PineV2Parser.var_assign`.
57
57
  * @param ctx the parse tree
@@ -1,4 +1,4 @@
1
- import { ParseTreeVisitor } from "antlr4ng";
1
+ import { AbstractParseTreeVisitor } from "antlr4ng";
2
2
  import { Var_assignContext } from "./PineV3Parser.js";
3
3
  import { Global_stmt_contentContext } from "./PineV3Parser.js";
4
4
  import { Local_stmt_contentContext } from "./PineV3Parser.js";
@@ -51,7 +51,7 @@ import { IdContext } from "./PineV3Parser.js";
51
51
  * @param <Result> The return type of the visit operation. Use `void` for
52
52
  * operations with no return type.
53
53
  */
54
- export declare class PineV3ParserVisitor<Result> extends ParseTreeVisitor<Result> {
54
+ export declare class PineV3ParserVisitor<Result> extends AbstractParseTreeVisitor<Result> {
55
55
  /**
56
56
  * Visit a parse tree produced by `PineV3Parser.var_assign`.
57
57
  * @param ctx the parse tree
@@ -1,4 +1,4 @@
1
- import { ParseTreeVisitor } from "antlr4ng";
1
+ import { AbstractParseTreeVisitor } from "antlr4ng";
2
2
  import { Decl_modContext } from "./PineV4Parser.js";
3
3
  import { Type_qualContext } from "./PineV4Parser.js";
4
4
  import { Type_nameContext } from "./PineV4Parser.js";
@@ -57,7 +57,7 @@ import { Other_literalContext } from "./PineV4Parser.js";
57
57
  * @param <Result> The return type of the visit operation. Use `void` for
58
58
  * operations with no return type.
59
59
  */
60
- export declare class PineV4ParserVisitor<Result> extends ParseTreeVisitor<Result> {
60
+ export declare class PineV4ParserVisitor<Result> extends AbstractParseTreeVisitor<Result> {
61
61
  /**
62
62
  * Visit a parse tree produced by `PineV4Parser.decl_mod`.
63
63
  * @param ctx the parse tree
@@ -1,4 +1,4 @@
1
- import { ParseTreeVisitor } from "antlr4ng";
1
+ import { AbstractParseTreeVisitor } from "antlr4ng";
2
2
  import { While_exprContext } from "./PineV5Parser.js";
3
3
  import { Switch_exprContext } from "./PineV5Parser.js";
4
4
  import { Switch_bodyContext } from "./PineV5Parser.js";
@@ -79,7 +79,7 @@ import { Other_literalContext } from "./PineV5Parser.js";
79
79
  * @param <Result> The return type of the visit operation. Use `void` for
80
80
  * operations with no return type.
81
81
  */
82
- export declare class PineV5ParserVisitor<Result> extends ParseTreeVisitor<Result> {
82
+ export declare class PineV5ParserVisitor<Result> extends AbstractParseTreeVisitor<Result> {
83
83
  /**
84
84
  * Visit a parse tree produced by `PineV5Parser.while_expr`.
85
85
  * @param ctx the parse tree
@@ -1,4 +1,4 @@
1
- import { ParseTreeVisitor } from "antlr4ng";
1
+ import { AbstractParseTreeVisitor } from "antlr4ng";
2
2
  import { Once_exprContext } from "./PineV6Parser.js";
3
3
  import { Other_literalContext } from "./PineV6Parser.js";
4
4
  import { Global_stmt_contentContext } from "./PineV6Parser.js";
@@ -80,7 +80,7 @@ import { Num_literalContext } from "./PineV6Parser.js";
80
80
  * @param <Result> The return type of the visit operation. Use `void` for
81
81
  * operations with no return type.
82
82
  */
83
- export declare class PineV6ParserVisitor<Result> extends ParseTreeVisitor<Result> {
83
+ export declare class PineV6ParserVisitor<Result> extends AbstractParseTreeVisitor<Result> {
84
84
  /**
85
85
  * Visit a parse tree produced by `PineV6Parser.once_expr`.
86
86
  * @param ctx the parse tree
@@ -24,7 +24,7 @@
24
24
  * See transpiler/v3/ToJsVisitor.ts for a worked example, and
25
25
  * docs/common/ARCHITECTURE.md ("Design rules") for the rationale.
26
26
  */
27
- import { ParseTreeVisitor } from "antlr4ng";
27
+ import { AbstractParseTreeVisitor } from "antlr4ng";
28
28
  import type { TerminalNode, ParserRuleContext, ParseTree } from "antlr4ng";
29
29
  import type { PineVersion } from "../common/version.js";
30
30
  import { Pine_scriptContext, StmtContext, Global_stmtContext, Global_stmt_contentContext, Fun_def_stmtContext, Fun_def_singlelineContext, Fun_def_multilineContext, Fun_headContext, Fun_body_singlelineContext, Local_stmt_singlelineContext, Local_stmt_contentContext, Loop_breakContext, Loop_continueContext, Fun_body_multilineContext, Local_stmts_multilineContext, Local_stmts_listContext, Local_stmt_multilineContext, Var_defContext, Var_defsContext, Ids_arrayContext, Arith_exprsContext, Arith_exprContext, If_exprContext, For_exprContext, Stmts_blockContext, Ternary_exprContext, Or_exprContext, And_exprContext, Eq_exprContext, Cmp_exprContext, Add_exprContext, Mult_exprContext, Unary_exprContext, Sqbr_exprContext, AtomContext, Fun_callContext, Fun_actual_argsContext, Pos_argsContext, Kw_argsContext, Kw_argContext, LiteralContext, Num_literalContext, Other_literalContext, IdContext } from "../../parser/v1/generated/PineV1Parser.js";
@@ -95,7 +95,7 @@ export declare function isRule(node: unknown, ruleContextName: string): boolean;
95
95
  * produce JavaScript that does not parse.
96
96
  */
97
97
  export declare function unwrapString(text: string): string;
98
- export declare class V1ToJsVisitor extends ParseTreeVisitor<string> {
98
+ export declare class V1ToJsVisitor extends AbstractParseTreeVisitor<string> {
99
99
  /**
100
100
  * Depth of user-function bodies currently being emitted.
101
101
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openpinescript",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Run TradingView Pine Script locally and offline. Compiles Pine Script v1-v6 to JavaScript and executes it against your own OHLCV data, with indicator, plotting and strategy backtesting output verified against TradingView itself.",
5
5
  "keywords": [
6
6
  "pine-script",
@@ -53,7 +53,7 @@
53
53
  ],
54
54
  "sideEffects": false,
55
55
  "scripts": {
56
- "generate:parser": "node scripts/common/build-grammars.mjs && node scripts/common/patch-visitor.cjs",
56
+ "generate:parser": "node scripts/common/build-grammars.mjs",
57
57
  "generate:parser:v1": "node scripts/common/build-grammars.mjs v1",
58
58
  "generate:parser:v2": "node scripts/common/build-grammars.mjs v2",
59
59
  "generate:parser:v3": "node scripts/common/build-grammars.mjs v3",
@@ -73,11 +73,11 @@
73
73
  "prepublishOnly": "npm run build && npm test"
74
74
  },
75
75
  "dependencies": {
76
- "antlr4ng": "^1.0.0"
76
+ "antlr4ng": "^3.0.16"
77
77
  },
78
78
  "devDependencies": {
79
79
  "@types/node": "^22.10.2",
80
- "antlr-ng": "^1.0.0",
80
+ "antlr-ng": "^1.0.10",
81
81
  "esbuild": "^0.27.0",
82
82
  "ts-morph": "^27.0.2",
83
83
  "ts-node": "^10.9.2",