Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 30, 2025

Implements essential PineScript v6 language constructs required by standard indicators. The existing transpiler only supported basic expressions, variable declarations, and simple function calls.

New Parser Constructs

  • := reassignment operator - Separate from = assignment
  • if/else if/else blocks - Indentation-based block parsing
  • for loops - Standard for i = 0 to N by step and for item in array with destructuring
  • while loops - Condition-based loops
  • switch expressions - PineScript v6 value-returning switch with => cases
  • History operator [n] - Series historical access (e.g., close[1])
  • Tuple destructuring - Multi-value returns ([a, b, c] = func())
  • break/continue statements
  • Ternary ?: - Properly separated from binary operator parsing

Code Generation

Transpiles to idiomatic TypeScript:

// PineScript
var sum = 0
for i = 0 to length - 1
    sum := sum + close[i]

ma = switch maType
    "SMA" => ta.sma(close, length)
    "EMA" => ta.ema(close, length)
    => ta.sma(close, length)
// Generated TypeScript
let sum = 0;
for (let i = 0; i <= length - 1; i += 1) {
  sum = sum + close.get(i);
}

const ma = (() => {
  switch (maType) {
    case "SMA": return ta.sma(close, length);
    case "EMA": return ta.ema(close, length);
    default: return ta.sma(close, length);
  }
})();

Testing

33 new test cases covering parsing and transpilation for all constructs.

Original prompt

Transpiler Phase 1: Core Language Features

Objective

Enhance the oakscript-engine transpiler (packages/oakscript-engine/src/transpiler/) to support essential PineScript v6 language constructs that are required by most standard indicators.

Current State

The transpiler currently supports:

  • Basic expressions & operators
  • Variable declarations (var)
  • Function calls
  • Member expressions (ta.sma())
  • indicator() declaration
  • plot() function
  • Comments

Features to Implement

1. := Reassignment Operator (Critical)

PineScript uses := for reassigning existing variables.

// PineScript
var counter = 0
counter := counter + 1

var float myValue = na
if condition
    myValue := close

TypeScript output:

let counter = 0;
counter = counter + 1;

let myValue: number = NaN;
if (condition) {
    myValue = close.get(0);
}

2. if/else Blocks (Critical)

Support both single-line and multi-line if statements.

// Single line
color := close > open ? color.green : color.red

// Block form
if close > open
    color := color.green
else if close < open
    color := color.red
else
    color := color.gray

// With else if
if condition1
    value1
else if condition2
    value2
else
    value3

Parser requirements:

  • Detect if keyword
  • Parse condition expression
  • Handle indentation-based blocks (PineScript uses indentation)
  • Support else if chains
  • Support else clause

3. for Loops (Critical)

// Standard for loop
for i = 0 to length - 1
    sum := sum + array.get(arr, i)

// For loop with step
for i = 0 to 10 by 2
    // ...

// For-in loop (iterate arrays)
for item in myArray
    total := total + item

// For loop with index
for [index, item] in myArray
    // ...

TypeScript output:

for (let i = 0; i <= length - 1; i++) {
    sum = sum + arr[i];
}

for (let i = 0; i <= 10; i += 2) {
    // ...
}

for (const item of myArray) {
    total = total + item;
}

for (const [index, item] of myArray.entries()) {
    // ...
}

4. while Loops (Critical)

while condition
    // body
    if exitCondition
        break

TypeScript output:

while (condition) {
    // body
    if (exitCondition) {
        break;
    }
}

5. switch Expressions (Critical)

PineScript v6 switch returns a value.

// Switch expression
maType = switch maTypeInput
    "SMA" => ta.sma(src, length)
    "EMA" => ta.ema(src, length)
    "WMA" => ta.wma(src, length)
    => ta.sma(src, length)  // default

// Switch with expressions
direction = switch
    close > open => 1
    close < open => -1
    => 0

TypeScript output:

const maType = (() => {
    switch (maTypeInput) {
        case "SMA": return ta.sma(src, length);
        case "EMA": return ta.ema(src, length);
        case "WMA": return ta.wma(src, length);
        default: return ta.sma(src, length);
    }
})();

// Or using ternary for simple cases
const direction = close > open ? 1 : close < open ? -1 : 0;

6. Ternary Operator ?: (Critical)

color = close > open ? color.green : color.red
value = condition ? trueValue : falseValue

Already partially supported, but ensure it works with Series operations.

7. History Operator [n] (Critical)

Access historical values of series.

prevClose = close[1]
highFiveBarsAgo = high[5]
change = close - close[1]

// Dynamic index
idx = 3
value = close[idx]

TypeScript output:

const prevClose = close.get(1);
const highFiveBarsAgo = high.get(5);
const change = close.sub(close.get(1));

const idx = 3;
const value = close.get(idx);

8. Multi-Value Return / Tuple Destructuring (High Priority)

[macdLine, signalLine, histogram] = ta.macd(close, 12, 26, 9)
[middle, upper, lower] = ta.bb(close, 20, 2)

TypeScript output:

const [macdLine, signalLine, histogram] = ta.macd(close, 12, 26, 9);
const [middle, upper, lower] = ta.bb(close, 20, 2);

9. break and continue Statements

for i = 0 to 100
    if condition
        break
    if skipCondition
        continue
    // process

Implementation Details

PineParser.ts Changes

Add these methods to the parser:

// New AST node types needed:
// - IfStatement
// - ForLoop
// - ForInLoop
// - WhileLoop
// - SwitchExpression
// - HistoryAccess
// - TupleDestructuring
// - BreakStatement
// - ContinueStatement

private parseIfStatement(): ASTNode {
    // Parse: if condition
    //            body
    //        else if condition2
    //            body2
    //        else
    //            body3
}

private parseForLoop(): ASTNode {
    // Parse: for i = start to end [by step]
    //            body
}

private parseForInLoop(): ASTNode {
    // Parse: for item in array
    //            body
    // Parse: for [index, item] in array
    //            body
}
...

</details>

*This pull request was created as a result of the following prompt from Copilot chat.*
> # Transpiler Phase 1: Core Language Features
> 
> ## Objective
> Enhance the oakscript-engine transpiler (`packages/oakscript-engine/src/transpiler/`) to support essential PineScript v6 language constructs that are required by most standard indicators.
> 
> ## Current State
> The transpiler currently supports:
> - Basic expressions & operators
> - Variable declarations (`var`)
> - Function calls
> - Member expressions (`ta.sma()`)
> - `indicator()` declaration
> - `plot()` function
> - Comments
> 
> ## Features to Implement
> 
> ### 1. `:=` Reassignment Operator (Critical)
> PineScript uses `:=` for reassigning existing variables.
> 
> ```pinescript
> // PineScript
> var counter = 0
> counter := counter + 1
> 
> var float myValue = na
> if condition
>     myValue := close
> ```
> 
> **TypeScript output:**
> ```typescript
> let counter = 0;
> counter = counter + 1;
> 
> let myValue: number = NaN;
> if (condition) {
>     myValue = close.get(0);
> }
> ```
> 
> ### 2. `if`/`else` Blocks (Critical)
> Support both single-line and multi-line if statements.
> 
> ```pinescript
> // Single line
> color := close > open ? color.green : color.red
> 
> // Block form
> if close > open
>     color := color.green
> else if close < open
>     color := color.red
> else
>     color := color.gray
> 
> // With else if
> if condition1
>     value1
> else if condition2
>     value2
> else
>     value3
> ```
> 
> **Parser requirements:**
> - Detect `if` keyword
> - Parse condition expression
> - Handle indentation-based blocks (PineScript uses indentation)
> - Support `else if` chains
> - Support `else` clause
> 
> ### 3. `for` Loops (Critical)
> ```pinescript
> // Standard for loop
> for i = 0 to length - 1
>     sum := sum + array.get(arr, i)
> 
> // For loop with step
> for i = 0 to 10 by 2
>     // ...
> 
> // For-in loop (iterate arrays)
> for item in myArray
>     total := total + item
> 
> // For loop with index
> for [index, item] in myArray
>     // ...
> ```
> 
> **TypeScript output:**
> ```typescript
> for (let i = 0; i <= length - 1; i++) {
>     sum = sum + arr[i];
> }
> 
> for (let i = 0; i <= 10; i += 2) {
>     // ...
> }
> 
> for (const item of myArray) {
>     total = total + item;
> }
> 
> for (const [index, item] of myArray.entries()) {
>     // ...
> }
> ```
> 
> ### 4. `while` Loops (Critical)
> ```pinescript
> while condition
>     // body
>     if exitCondition
>         break
> ```
> 
> **TypeScript output:**
> ```typescript
> while (condition) {
>     // body
>     if (exitCondition) {
>         break;
>     }
> }
> ```
> 
> ### 5. `switch` Expressions (Critical)
> PineScript v6 switch returns a value.
> 
> ```pinescript
> // Switch expression
> maType = switch maTypeInput
>     "SMA" => ta.sma(src, length)
>     "EMA" => ta.ema(src, length)
>     "WMA" => ta.wma(src, length)
>     => ta.sma(src, length)  // default
> 
> // Switch with expressions
> direction = switch
>     close > open => 1
>     close < open => -1
>     => 0
> ```
> 
> **TypeScript output:**
> ```typescript
> const maType = (() => {
>     switch (maTypeInput) {
>         case "SMA": return ta.sma(src, length);
>         case "EMA": return ta.ema(src, length);
>         case "WMA": return ta.wma(src, length);
>         default: return ta.sma(src, length);
>     }
> })();
> 
> // Or using ternary for simple cases
> const direction = close > open ? 1 : close < open ? -1 : 0;
> ```
> 
> ### 6. Ternary Operator `?:` (Critical)
> ```pinescript
> color = close > open ? color.green : color.red
> value = condition ? trueValue : falseValue
> ```
> 
> Already partially supported, but ensure it works with Series operations.
> 
> ### 7. History Operator `[n]` (Critical)
> Access historical values of series.
> 
> ```pinescript
> prevClose = close[1]
> highFiveBarsAgo = high[5]
> change = close - close[1]
> 
> // Dynamic index
> idx = 3
> value = close[idx]
> ```
> 
> **TypeScript output:**
> ```typescript
> const prevClose = close.get(1);
> const highFiveBarsAgo = high.get(5);
> const change = close.sub(close.get(1));
> 
> const idx = 3;
> const value = close.get(idx);
> ```
> 
> ### 8. Multi-Value Return / Tuple Destructuring (High Priority)
> ```pinescript
> [macdLine, signalLine, histogram] = ta.macd(close, 12, 26, 9)
> [middle, upper, lower] = ta.bb(close, 20, 2)
> ```
> 
> **TypeScript output:**
> ```typescript
> const [macdLine, signalLine, histogram] = ta.macd(close, 12, 26, 9);
> const [middle, upper, lower] = ta.bb(close, 20, 2);
> ```
> 
> ### 9. `break` and `continue` Statements
> ```pinescript
> for i = 0 to 100
>     if condition
>         break
>     if skipCondition
>         continue
>     // process
> ```
> 
> ## Implementation Details
> 
> ### PineParser.ts Changes
> 
> Add these methods to the parser:
> 
> ```typescript
> // New AST node types needed:
> // - IfStatement
> // - ForLoop
> // - ForInLoop
> // - WhileLoop
> // - SwitchExpression
> // - HistoryAccess
> // - TupleDestructuring
> // - BreakStatement
> // - ContinueStatement
> 
> private parseIfStatement(): ASTNode {
>     // Parse: if condition
>     //            body
>     //        else if condition2
>     //            body2
>     //        else
>     //            body3
> }
> 
> private parseForLoop(): ASTNode {
>     // Parse: for i = start to end [by step]
>     //            body
> }
> 
> private parseForInLoop(): ASTNode {
>     // Parse: for item in array
>     //            body
>     // Parse: for [index, item] in array
>     //            body
> }
> 
> private parseWhileLoop(): ASTNode {
>     // Parse: while condition
>     //            body
> }
> 
> private parseSwitchExpression(): ASTNode {
>     // Parse: switch [expression]
>     //            value1 => result1
>     //            value2 => result2
>     //            => defaultResult
> }
> 
> private parseHistoryAccess(base: ASTNode): ASTNode {
>     // Parse: series[offset]
> }
> 
> private parseTupleDestructuring(): ASTNode {
>     // Parse: [a, b, c] = expression
> }
> ```
> 
> ### PineToTS.ts Changes
> 
> Add corresponding code generation:
> 
> ```typescript
> private generateIfStatement(node: ASTNode): string { ... }
> private generateForLoop(node: ASTNode): string { ... }
> private generateWhileLoop(node: ASTNode): string { ... }
> private generateSwitchExpression(node: ASTNode): string { ... }
> private generateHistoryAccess(node: ASTNode): string { ... }
> private generateTupleDestructuring(node: ASTNode): string { ... }
> ```
> 
> ### Indentation Handling
> 
> PineScript uses significant indentation (like Python). The parser needs to:
> 1. Track current indentation level
> 2. Detect block start (increased indentation after `:` or newline)
> 3. Detect block end (decreased indentation)
> 
> ```typescript
> private parseBlock(): ASTNode[] {
>     const statements: ASTNode[] = [];
>     const blockIndent = this.currentIndentLevel();
>     
>     while (this.currentIndentLevel() >= blockIndent) {
>         const stmt = this.parseStatement();
>         if (stmt) statements.push(stmt);
>     }
>     
>     return statements;
> }
> ```
> 
> ## Test Cases
> 
> Create test files in `packages/oakscript-engine/tests/`:
> 
> ### test-if-else.pine
> ```pinescript
> //@version=6
> indicator("If/Else Test")
> 
> var color barColor = color.gray
> 
> if close > open
>     barColor := color.green
> else if close < open
>     barColor := color.red
> else
>     barColor := color.gray
> 
> plot(close, color=barColor)
> ```
> 
> ### test-for-loop.pine
> ```pinescript
> //@version=6
> indicator("For Loop Test")
> 
> length = 14
> sum = 0.0
> 
> for i = 0 to length - 1
>     sum := sum + close[i]
> 
> customSMA = sum / length
> plot(customSMA)
> ```
> 
> ### test-switch.pine
> ```pinescript
> //@version=6
> indicator("Switch Test")
> 
> maType = "EMA"
> length = 14
> 
> ma = switch maType
>     "SMA" => ta.sma(close, length)
>     "EMA" => ta.ema(close, length)
>     "WMA" => ta.wma(close, length)
>     => ta.sma(close, length)
> 
> plot(ma)
> ```
> 
> ### test-history.pine
> ```pinescript
> //@version=6
> indicator("History Test")
> 
> change = close - close[1]
> momentum = close - close[10]
> prevHigh = high[1]
> 
> plot(change)
> plot(momentum)
> ```
> 
> ### test-tuple.pine
> ```pinescript
> //@version=6
> indicator("Tuple Test")
> 
> [macdLine, signalLine, hist] = ta.macd(close, 12, 26, 9)
> [middle, upper, lower] = ta.bb(close, 20, 2)
> 
> plot(macdLine)
> plot(signalLine)
> plot(middle)
> ```
> 
> ## Success Criteria
> 
> 1. All test cases transpile without errors
> 2. Generated TypeScript compiles without errors
> 3. Generated code produces correct output when executed
> 4. Parser handles edge cases:
>    - Nested if/else
>    - Nested loops
>    - Mixed constructs (if inside for, etc.)
>    - Empty blocks
>    - Single-line vs multi-line forms
> 
> ## Files to Modify
> 
> 1. `packages/oakscript-engine/src/transpiler/PineParser.ts` - Add parsing for new constructs
> 2. `packages/oakscript-engine/src/transpiler/PineToTS.ts` - Add code generation
> 3. `packages/oakscript-engine/src/transpiler/types.ts` - Add new AST node types if needed
> 4. `packages/oakscript-engine/tests/` - Add test cases
> 
> ## References
> 
> - PineScript v6 Language Reference: `docs/official/language-reference/`
> - Example indicators: `docs/official/indicators_standard/`
> - Current parser: `packages/oakscript-engine/src/transpiler/PineParser.ts`
> - Current generator: `packages/oakscript-engine/src/transpiler/PineToTS.ts`
> 

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot AI and others added 2 commits November 30, 2025 21:03
Co-authored-by: deepentropy <8287111+deepentropy@users.noreply.github.com>
Co-authored-by: deepentropy <8287111+deepentropy@users.noreply.github.com>
Copilot AI changed the title [WIP] Add reassignment operator and if/else support Transpiler Phase 1: Core Language Features Nov 30, 2025
Copilot AI requested a review from deepentropy November 30, 2025 21:10
@deepentropy deepentropy marked this pull request as ready for review November 30, 2025 21:29
Copilot AI review requested due to automatic review settings November 30, 2025 21:29
@deepentropy deepentropy merged commit 5fa3132 into main Nov 30, 2025
4 checks passed
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@deepentropy deepentropy deleted the copilot/enhance-reassignment-and-conditionals branch November 30, 2025 21:29
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements Phase 1 of the PineScript v6 transpiler, adding support for essential language constructs including control flow (if/else, for, while, switch), the reassignment operator (:=), history access ([n]), tuple destructuring, and ternary expressions. The implementation parses these PineScript constructs into an AST and generates idiomatic TypeScript code.

Key Changes

  • Added parsing and code generation for 9 new language constructs (if/else, for loops, while loops, switch expressions, ternary operator, history access, tuple destructuring, break/continue)
  • Implemented indentation-based block parsing for PineScript's Python-like syntax
  • Extended AST node interface with name, operator, and step properties

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 16 comments.

File Description
packages/oakscript-engine/tests/transpiler-phase1.test.ts Comprehensive test suite with 33 tests covering all new language features
packages/oakscript-engine/src/transpiler/PineParser.ts Parser implementation for new constructs with indentation handling and backtracking support
packages/oakscript-engine/src/transpiler/PineToTS.ts Code generator for TypeScript output including IIFE-wrapped switch expressions
Comments suppressed due to low confidence (3)

packages/oakscript-engine/src/transpiler/PineParser.ts:1

  • [nitpick] Ternary expressions are unnecessarily wrapped in parentheses. While not incorrect, this adds visual noise to the generated code. Consider removing the outer parentheses unless the ternary is part of a larger expression that requires them for precedence.
/**

packages/oakscript-engine/src/transpiler/PineParser.ts:1

  • Break and continue statements don't consume the rest of the line or advance past newlines. This could cause the parser to incorrectly interpret subsequent tokens on the same line. Add this.skipToEndOfLine(); after creating these statements to ensure clean line handling.
/**

packages/oakscript-engine/src/transpiler/PineParser.ts:798

  • Unused variable startPos.
      const startPos = this.position;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Comment on lines +495 to +499
if (this.peek() !== '=') {
this.position = savedPosition;
return null;
}
this.advance(); // skip '='
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tuple destructuring only accepts = but should also support := for reassignment. PineScript allows [a, b] := func() for reassigning existing variables. Check for both = and := operators. After the check, if it's :=, advance twice (for : and =).

Copilot uses AI. Check for mistakes.
this.skipWhitespace();

// Must have '=' after tuple
if (this.peek() !== '=') {
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to check if next character is = to avoid false positives. The current check could succeed when encountering == (equality operator). Use this.peek() !== '=' || this.peekNext() === '=' to ensure it's a single = and not ==.

Suggested change
if (this.peek() !== '=') {
if (this.peek() !== '=' || this.peekNext() === '=') {

Copilot uses AI. Check for mistakes.
Comment on lines +461 to +462
const vars = varName.split(',');
this.emit(`for (const [${vars.join(', ')}] of ${iterableExpr}.entries()) {`);
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The destructured variables are joined with ', ' (comma-space) which is inconsistent with tuple destructuring at line 506 that uses no spaces. Additionally, the parser stores comma-separated names without spaces, but split(',') on such a string followed by join(', ') adds spaces. This creates inconsistent spacing in generated code. Use varName directly: for (const [${varName}] of ....

Suggested change
const vars = varName.split(',');
this.emit(`for (const [${vars.join(', ')}] of ${iterableExpr}.entries()) {`);
this.emit(`for (const [${varName}] of ${iterableExpr}.entries()) {`);

Copilot uses AI. Check for mistakes.
Comment on lines +296 to +297
// else if - inline the else if
this.emit('} else ' + this.generateIfStatementInline(alternate));
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The else if generation uses string concatenation which produces inline code that may not respect current indentation. This creates inconsistent formatting compared to other control structures. Consider emitting the } else part separately and then generating the if statement normally to maintain proper indentation.

Suggested change
// else if - inline the else if
this.emit('} else ' + this.generateIfStatementInline(alternate));
// else if - emit closing brace, else, then generate the next if statement
this.emit('}');
this.emit('else ');
this.generateIfStatement(alternate);

Copilot uses AI. Check for mistakes.
lines.push('}');
}

return lines.join('\n' + indent.repeat(this.indent));
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generateIfStatementInline method joins lines with indentation repeated this.indent times, but the lines themselves already include indent (which is a single indent string). This will produce incorrect indentation where each line gets progressively more indented. The join should use \n followed by the current indent level calculated once.

Suggested change
return lines.join('\n' + indent.repeat(this.indent));
return lines.join('\n');

Copilot uses AI. Check for mistakes.

const condExpr = this.generateExpression(condition);
const lines: string[] = [];
const indent = this.getIndentString();
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The variable indent represents a single indentation unit (e.g., ' '), not the current indentation level. This is confusing when later used in indent.repeat(this.indent). Rename to indentUnit or singleIndent for clarity.

Copilot uses AI. Check for mistakes.
Comment on lines +797 to +804
// Save position for potential keyword lookahead
const startPos = this.position;
const name = this.parseIdentifier();

// Check if this is the 'switch' keyword
if (name === 'switch') {
return this.parseSwitchExpression();
}
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The startPos variable is saved but never used. Either remove this unused variable or add a comment explaining why it's preserved (perhaps for future error reporting).

Copilot uses AI. Check for mistakes.
describe('Ternary Operator `?:`', () => {
it('should parse ternary expression', () => {
const parser = new PineParser();
const { ast, errors } = parser.parse('x = condition ? 1 : 2');
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable ast.

Suggested change
const { ast, errors } = parser.parse('x = condition ? 1 : 2');
const { errors } = parser.parse('x = condition ? 1 : 2');

Copilot uses AI. Check for mistakes.
describe('Break and Continue Statements', () => {
it('should parse break statement', () => {
const parser = new PineParser();
const { ast, errors } = parser.parse(`for i = 0 to 10
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable ast.

Suggested change
const { ast, errors } = parser.parse(`for i = 0 to 10
const { errors } = parser.parse(`for i = 0 to 10

Copilot uses AI. Check for mistakes.

it('should parse continue statement', () => {
const parser = new PineParser();
const { ast, errors } = parser.parse(`for i = 0 to 10
Copy link

Copilot AI Nov 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable ast.

Suggested change
const { ast, errors } = parser.parse(`for i = 0 to 10
const { errors } = parser.parse(`for i = 0 to 10

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants