@pineforge/codegen-pyodide 1.0.0-rc.1 → 1.0.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.
@@ -18,6 +18,7 @@ from .lexer import Token, TokenType
18
18
  from .errors import CompileError, Diagnostic, Level, Phase, SourceLocation
19
19
  from .limits import MAX_NESTING_DEPTH, TimeBudget, limit_error, syntax_children
20
20
  from .ast_nodes import (
21
+ HISTORY_MEMBER_ANNOTATION,
21
22
  ASTNode, ArgOrder,
22
23
  Program, StrategyDecl, ImportStmt,
23
24
  VarDecl, Assignment, TupleAssign,
@@ -1482,6 +1483,11 @@ class Parser:
1482
1483
  def _parse_postfix(self):
1483
1484
  chain_tok = self._current()
1484
1485
  expr = self._parse_primary()
1486
+ # Whether ``expr`` is a history reference this chain wrote, not one in
1487
+ # parentheses: TradingView refuses a member straight after it
1488
+ # (``c[1].v``, CE10011; ``b[1].get_top()``, CE10010), which the
1489
+ # support checker reports (HISTORY_MEMBER_ANNOTATION).
1490
+ after_subscript = False
1485
1491
  while True:
1486
1492
  # Subscript: expr[index]
1487
1493
  if self._check(TokenType.LBRACKET):
@@ -1491,6 +1497,9 @@ class Parser:
1491
1497
  self._consume(TokenType.RBRACKET)
1492
1498
  expr = Subscript(object=expr, index=index)
1493
1499
  self._set_loc(expr, start_tok)
1500
+ after_subscript = True
1501
+ self._check_chain(expr, chain_tok)
1502
+ continue
1494
1503
 
1495
1504
  # Member access: expr.member or expr.member(args)
1496
1505
  elif self._check(TokenType.DOT):
@@ -1501,24 +1510,30 @@ class Parser:
1501
1510
  if self._looks_like_call_template_args():
1502
1511
  template_args = self._parse_template_args()
1503
1512
 
1513
+ annotations = {}
1514
+ if template_args:
1515
+ annotations["template_args"] = template_args
1516
+ if after_subscript:
1517
+ annotations[HISTORY_MEMBER_ANNOTATION] = True
1504
1518
  if self._check(TokenType.LPAREN):
1505
1519
  # Build callee as MemberAccess, then parse call
1506
1520
  callee = MemberAccess(object=expr, member=member_tok.value)
1507
1521
  self._set_loc(callee, member_tok)
1508
- if template_args:
1509
- callee.annotations = {"template_args": template_args}
1522
+ if annotations:
1523
+ callee.annotations = annotations
1510
1524
  expr = self._parse_call_with_callee(callee)
1511
1525
  else:
1512
1526
  expr = MemberAccess(object=expr, member=member_tok.value)
1513
1527
  self._set_loc(expr, member_tok)
1514
- if template_args:
1515
- expr.annotations = {"template_args": template_args}
1528
+ if annotations:
1529
+ expr.annotations = annotations
1516
1530
 
1517
1531
  # Direct call: expr(args) — needed for identifiers followed by (
1518
1532
  elif self._check(TokenType.LPAREN) and self._is_call_position(expr):
1519
1533
  expr = self._parse_call_with_callee(expr)
1520
1534
  else:
1521
1535
  break
1536
+ after_subscript = False
1522
1537
  self._check_chain(expr, chain_tok)
1523
1538
  return expr
1524
1539
 
@@ -36,6 +36,7 @@ import re
36
36
  from typing import Callable
37
37
 
38
38
  from .ast_nodes import (
39
+ HISTORY_MEMBER_ANNOTATION,
39
40
  ASTNode,
40
41
  Program, StrategyDecl, ImportStmt, TypeField,
41
42
  VarDecl, Assignment, TupleAssign,
@@ -1482,6 +1483,40 @@ class SupportChecker:
1482
1483
  )
1483
1484
  self._visit_children(node)
1484
1485
 
1486
+ def _refuse_history_member(self, node: MemberAccess) -> None:
1487
+ """A field read or a method call written straight after the
1488
+ history-referencing operator: TradingView refuses ``c[1].v``
1489
+ ("User variable identifiers should not contain '.'", CE10011) and
1490
+ ``b[1].get_top()`` (CE10010), and takes the history reference in
1491
+ parentheses, ``(c[1]).v``, which reads the field of the object the
1492
+ variable held (fixtures/udt_history_tv)."""
1493
+ history = node.object
1494
+ receiver = "x[k]"
1495
+ if (isinstance(history, Subscript)
1496
+ and isinstance(history.object, Identifier)
1497
+ and isinstance(history.index, (NumberLiteral, Identifier))):
1498
+ index = (history.index.name if isinstance(history.index, Identifier)
1499
+ else history.index.value)
1500
+ receiver = f"{history.object.name}[{index}]"
1501
+ if id(node) in self._callee_node_ids:
1502
+ self._err(
1503
+ node,
1504
+ f"{receiver}.{node.member}(): TradingView refuses a method "
1505
+ "call straight after the history-referencing operator "
1506
+ "(CE10010; CE10011 after an array's or a matrix's history).",
1507
+ hint=f"Call the method on the history reference in "
1508
+ f"parentheses: ({receiver}).{node.member}().",
1509
+ )
1510
+ return
1511
+ self._err(
1512
+ node,
1513
+ f"{receiver}.{node.member}: TradingView refuses a field read "
1514
+ "straight after the history-referencing operator (CE10011: "
1515
+ "\"User variable identifiers should not contain '.'\").",
1516
+ hint=f"Read the field of the history reference in parentheses: "
1517
+ f"({receiver}).{node.member}.",
1518
+ )
1519
+
1485
1520
  def _visit_FuncCall(self, node: FuncCall) -> None:
1486
1521
  ns, name = _qualified_name(node.callee)
1487
1522
 
@@ -1976,6 +2011,8 @@ class SupportChecker:
1976
2011
  self._visit(node.false_val)
1977
2012
 
1978
2013
  def _visit_MemberAccess(self, node: MemberAccess) -> None:
2014
+ if (node.annotations or {}).get(HISTORY_MEMBER_ANNOTATION):
2015
+ self._refuse_history_member(node)
1979
2016
  chain = _resolve_member_chain(node)
1980
2017
  if (
1981
2018
  chain is not None
Binary file
package/release.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "codegen": "1.0.0-rc.1",
2
+ "codegen": "1.0.1",
3
3
  "pyodide": "314.0.0",
4
4
  "python": "3.14.0",
5
5
  "emscripten": "emscripten_5_0_3",
6
- "sha256": "b692b0d616595a9b6260481bef7d88a5d63f11d094c7e30ce63bea420619af71"
6
+ "sha256": "2ad9a8595850ce2c485dcddb049fd738097d9149d2136ce83a951a506541a113"
7
7
  }
package/tables.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "CODEGEN_VERSION": "1.0.0-rc.1",
2
+ "CODEGEN_VERSION": "1.0.1",
3
3
  "TA_CLASS_MAP_KEYS": [
4
4
  "sma",
5
5
  "ema",
Binary file