pineforge-codegen 0.8.1__tar.gz → 0.10.0__tar.gz

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 (403) hide show
  1. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/CLAUDE.md +34 -24
  2. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/PKG-INFO +1 -1
  3. pineforge_codegen-0.10.0/VERSION +1 -0
  4. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/analyzer/base.py +350 -36
  5. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/analyzer/call_handlers.py +244 -133
  6. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/analyzer/contracts.py +29 -0
  7. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/analyzer/diagnostics.py +18 -4
  8. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/analyzer/tables.py +20 -2
  9. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/base.py +1348 -113
  10. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/drawing.py +1 -1
  11. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/emit_top.py +258 -21
  12. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/input.py +17 -0
  13. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/security.py +559 -36
  14. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/ta.py +87 -1
  15. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/tables.py +56 -7
  16. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/types.py +165 -30
  17. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/visit_call.py +184 -53
  18. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/visit_expr.py +149 -15
  19. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/visit_stmt.py +85 -38
  20. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/parser.py +73 -6
  21. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/signatures.py +2 -2
  22. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/support_checker.py +39 -2
  23. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/golden/matrix_eigen_pca.cpp +102 -51
  24. pineforge_codegen-0.10.0/tests/test_calc_on_order_fills_codegen.py +435 -0
  25. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_audit_fixes.py +26 -13
  26. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_determinism.py +37 -2
  27. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_drawing_data.py +8 -8
  28. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_new.py +257 -24
  29. pineforge_codegen-0.10.0/tests/test_codegen_ta_derived_length.py +767 -0
  30. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_validation_fixes.py +309 -1
  31. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_compile_smoke.py +167 -5
  32. pineforge_codegen-0.10.0/tests/test_na_reassign_retype.py +183 -0
  33. pineforge_codegen-0.10.0/tests/test_na_relational_lowering.py +219 -0
  34. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_parser.py +15 -0
  35. pineforge_codegen-0.10.0/tests/test_security_math_reducer.py +53 -0
  36. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_security_ohlc_hist_is_complete.py +49 -0
  37. pineforge_codegen-0.10.0/tests/test_security_tf_input_derived.py +175 -0
  38. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker.py +26 -2
  39. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_udt_lvalue_alias.py +92 -0
  40. pineforge_codegen-0.8.1/VERSION +0 -1
  41. pineforge_codegen-0.8.1/tests/test_codegen_ta_derived_length.py +0 -183
  42. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/.github/dependabot.yml +0 -0
  43. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/.github/workflows/gate.yml +0 -0
  44. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/.github/workflows/publish-pyodide.yml +0 -0
  45. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/.github/workflows/release.yml +0 -0
  46. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/.github/workflows/test.yml +0 -0
  47. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/.gitignore +0 -0
  48. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/LEGAL.md +0 -0
  49. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/LICENSE +0 -0
  50. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/PYODIDE_TARGET +0 -0
  51. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/README.md +0 -0
  52. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/docs/codegen-coverage-gaps.md +0 -0
  53. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/gate/compare.mjs +0 -0
  54. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/gate/glue.py +0 -0
  55. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/gate/oracle.py +0 -0
  56. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/gate/run-gate.mjs +0 -0
  57. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/gate/selftest.mjs +0 -0
  58. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/npm/README.md +0 -0
  59. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/npm/index.mjs +0 -0
  60. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/npm/package.json +0 -0
  61. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/package-lock.json +0 -0
  62. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/package.json +0 -0
  63. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/__init__.py +0 -0
  64. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/analyzer/__init__.py +0 -0
  65. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/analyzer/types.py +0 -0
  66. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/ast_nodes.py +0 -0
  67. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/__init__.py +0 -0
  68. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/helpers.py +0 -0
  69. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/codegen/helpers_syminfo.py +0 -0
  70. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/errors.py +0 -0
  71. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/lexer.py +0 -0
  72. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/pragmas.py +0 -0
  73. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/symbols.py +0 -0
  74. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/tokens.py +0 -0
  75. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pineforge_codegen/tv_input_choices.py +0 -0
  76. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/pyproject.toml +0 -0
  77. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/scripts/build-npm-package.mjs +0 -0
  78. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/scripts/dump-tables.py +0 -0
  79. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/scripts/worker-template.mjs +0 -0
  80. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/__init__.py +0 -0
  81. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/_compile.py +0 -0
  82. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/const_ns_plot_style_free.pine +0 -0
  83. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/const_ns_shape_free.pine +0 -0
  84. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/divergent_last_bar_index.pine +0 -0
  85. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/export_func.pine +0 -0
  86. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/footprint_new.pine +0 -0
  87. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/hard_reject_dividends.pine +0 -0
  88. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/matrix_unknown_elem.pine +0 -0
  89. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/multi_error_one_line.pine +0 -0
  90. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/sec_tf_invalid.pine +0 -0
  91. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/unknown_color.pine +0 -0
  92. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/unknown_math.pine +0 -0
  93. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/unknown_str.pine +0 -0
  94. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/unknown_strategy_fn.pine +0 -0
  95. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/unknown_syminfo.pine +0 -0
  96. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/err/unknown_ta.pine +0 -0
  97. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/AAPL__session-ismarket-nyse-rth-01.pine +0 -0
  98. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/AAPL__time-tradingday-daily-reset-counter-01.pine +0 -0
  99. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/QQQ__session-ispremarket-nasdaq-01.pine +0 -0
  100. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/SPY__session-firstbar-vwap-anchor-01.pine +0 -0
  101. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/SPY__session-lastbar-flatten-01.pine +0 -0
  102. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/chart_bg_color.pine +0 -0
  103. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/crypto-htf__mtf-htf-monthly-ema-cross-01.pine +0 -0
  104. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/crypto-leverage__leverage-margin-call-perp-5x-01.pine +0 -0
  105. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/forex__symbol-fx-5dp-eurusd-01.pine +0 -0
  106. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/futures__symbol-futures-pointvalue-es-01.pine +0 -0
  107. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/tutorial__macd__strategy.pine +0 -0
  108. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/tutorial__mtf__strategy_htf.pine +0 -0
  109. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/tutorial__mtf__strategy_ltf.pine +0 -0
  110. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/us-equity__symbol-equity-rth-gaps-aapl-01.pine +0 -0
  111. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/us-equity__us-equity-exchange-tz-intraday-cap-01.pine +0 -0
  112. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__analyzer-parity-choch-bos-isolator-01.pine +0 -0
  113. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__analyzer-parity-edge-margin-50-pct-01.pine +0 -0
  114. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__analyzer-parity-percent-of-equity-sizing-01.pine +0 -0
  115. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__analyzer-parity-small-equity-fraction-01.pine +0 -0
  116. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__analyzer-parity-stop-limit-timing-01.pine +0 -0
  117. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__analyzer-self-test-multi-mode-01.pine +0 -0
  118. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__anomaly-equity-mirror-strategy-equity-01.pine +0 -0
  119. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__barstate-isconfirmed-magnifier-off-01b.pine +0 -0
  120. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__barstate-isconfirmed-magnifier-on-01a.pine +0 -0
  121. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-atr-trail-series-int-points-01.pine +0 -0
  122. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-atr-trailing-stop-state-01.pine +0 -0
  123. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-entry-exit-same-pass-attach-01.pine +0 -0
  124. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-exit-stop-limit-trail-same-bar-01.pine +0 -0
  125. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-exit-three-way-set-once-entry-01.pine +0 -0
  126. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-exit-tp-sl-fixed-01.pine +0 -0
  127. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-narrow-stop-limit-with-trail8-01.pine +0 -0
  128. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-partial-exit-qty-percent-01.pine +0 -0
  129. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-same-id-exit-replace-01.pine +0 -0
  130. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-tp-sl-oca-reduce-isolate-01.pine +0 -0
  131. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-trail-points-no-offset-explicit-01.pine +0 -0
  132. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-trail-points-with-offset-only-01.pine +0 -0
  133. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__bracket-trailing-activation-offset-path-01.pine +0 -0
  134. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__cap-max-intraday-filled-orders-isolate-01.pine +0 -0
  135. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__cap-risk-gates-allow-max-intraday-01.pine +0 -0
  136. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-4emarsi-integration-01.pine +0 -0
  137. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-4emarsi-quad-ema-stack-01.pine +0 -0
  138. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-4emarsi-rsi-pullback-latch-01.pine +0 -0
  139. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-4emarsi-session-window-nbar-exit-01.pine +0 -0
  140. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-boscurv-integration-01.pine +0 -0
  141. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-boscurv-linreg-slope-channel-01.pine +0 -0
  142. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-boscurv-pivot-bos-trigger-01.pine +0 -0
  143. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-bracket-cap-range-pending-stop-01.pine +0 -0
  144. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-adx-regime-classify-01.pine +0 -0
  145. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-bb-kc-squeeze-release-01.pine +0 -0
  146. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-cooldown-daily-cap-01.pine +0 -0
  147. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-equity-feedback-sizing-01.pine +0 -0
  148. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-integration-01.pine +0 -0
  149. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-pivot-liquidity-sweep-01.pine +0 -0
  150. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-pressure-gauge-01.pine +0 -0
  151. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-rsi-macd-momentum-01.pine +0 -0
  152. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-ies-three-ema-bias-score-01.pine +0 -0
  153. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kanuck-calc-on-every-tick-01.pine +0 -0
  154. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kanuck-integration-01.pine +0 -0
  155. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kanuck-kama-state-recurrence-01.pine +0 -0
  156. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kanuck-max-bars-back-500-01.pine +0 -0
  157. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kkb-ema-atr-breakout-band-01.pine +0 -0
  158. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kkb-integration-01.pine +0 -0
  159. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kkb-kalman-filter-1d-01.pine +0 -0
  160. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-kkb-margin-100-pct-01.pine +0 -0
  161. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-liqsweep-integration-01.pine +0 -0
  162. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-liqsweep-pivot-hh-ll-01.pine +0 -0
  163. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-liqsweep-wait-one-continuation-01.pine +0 -0
  164. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-liqsweep-wick-pierce-close-back-01.pine +0 -0
  165. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-marketshift-integration-01.pine +0 -0
  166. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-marketshift-pivot-state-machine-01.pine +0 -0
  167. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-marketshift-rolling-highest-lowest-01.pine +0 -0
  168. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-marketshift-state-edge-detector-01.pine +0 -0
  169. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-scalping-fast-ma-cross-trigger-01.pine +0 -0
  170. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-scalping-integration-01.pine +0 -0
  171. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-scalping-tight-tp-sl-points-01.pine +0 -0
  172. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-trendmaster-integration-01.pine +0 -0
  173. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-trendmaster-line-new-projection-01.pine +0 -0
  174. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-trendmaster-pivot-anchored-bracket-01.pine +0 -0
  175. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-trendmaster-three-tier-ema-state-01.pine +0 -0
  176. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-trendmaster-trend-momentum-structure-gate-01.pine +0 -0
  177. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-cumulative-volume-delta-01.pine +0 -0
  178. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-fvg-active-zones-01.pine +0 -0
  179. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-integration-01.pine +0 -0
  180. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-manual-adx-regime-01.pine +0 -0
  181. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-pivot-strength-5-01.pine +0 -0
  182. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-rsi-smooth-divergence-01.pine +0 -0
  183. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-session-tz-newyork-01.pine +0 -0
  184. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-vcp-vol-zscore-anomaly-01.pine +0 -0
  185. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-wunderscalper-alert-templates-01.pine +0 -0
  186. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-wunderscalper-explicit-reverse-01.pine +0 -0
  187. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__composite-wunderscalper-integration-01.pine +0 -0
  188. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__input-source-runtime-override-high-01.pine +0 -0
  189. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__input-source-subscript-hl2-01.pine +0 -0
  190. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ltf-bool-array-bull-majority-01.pine +0 -0
  191. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ltf-numeric-float-ratio15-01.pine +0 -0
  192. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__magnifier-tick-dist-endpoints-01.pine +0 -0
  193. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__magnifier-tick-dist-endpoints-rsi-cross-08a.pine +0 -0
  194. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__magnifier-tick-dist-volume-weighted-on-01.pine +0 -0
  195. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__matrix-bool-mask-explicit-utc-tz-01.pine +0 -0
  196. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__matrix-bool-mask-no-transpose-01.pine +0 -0
  197. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__matrix-bool-mask-transpose-roundtrip-01.pine +0 -0
  198. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__matrix-bool-regime-mask-24x7-01.pine +0 -0
  199. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__matrix-covariance-eigen-pca-01.pine +0 -0
  200. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__matrix-eigen-rank-deficient-cov-01.pine +0 -0
  201. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__max-bars-back-function-call-deep-history-01.pine +0 -0
  202. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-daily-array-median-percentrank-01.pine +0 -0
  203. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-daily-ema26-warmup-01.pine +0 -0
  204. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-daily-prev-high-break-01.pine +0 -0
  205. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-dual-tf-60-240-rising-01.pine +0 -0
  206. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-60-close-change-baseline-01.pine +0 -0
  207. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-60-close-roll-01.pine +0 -0
  208. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-60-gaps-on-roll-01.pine +0 -0
  209. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-60-rsi14-inside-security-01.pine +0 -0
  210. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-60-sma20-inside-security-01.pine +0 -0
  211. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-60-volume-spike-01.pine +0 -0
  212. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-confluence-manual-trail-01.pine +0 -0
  213. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-confluence-static-bracket-01.pine +0 -0
  214. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-htf-weekly-sma-cross-01.pine +0 -0
  215. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-roll-state-60-240-d-minimal-01.pine +0 -0
  216. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-triple-tf-close-confluence-01.pine +0 -0
  217. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__mtf-triple-tf-macd-hist-confluence-01.pine +0 -0
  218. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__na-deep-history-int-na-01.pine +0 -0
  219. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__na-nz-fixnan-history-chain-01.pine +0 -0
  220. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__oca-exit-bracket-internal-cancel-01.pine +0 -0
  221. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__oca-multi-bracket-isolation-01.pine +0 -0
  222. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__oca-raw-strategy-order-reduce-01.pine +0 -0
  223. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-close-all-cancel-all-01.pine +0 -0
  224. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-close-immediate-vs-next-bar-01.pine +0 -0
  225. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-cross-entry-cancel-same-pass-01.pine +0 -0
  226. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-cross-entry-close-same-pass-01.pine +0 -0
  227. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-cross-exit-close-same-pass-01.pine +0 -0
  228. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-deferred-flip-guaranteed-gap-stops-01.pine +0 -0
  229. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-deferred-flip-pooc-cross-bar-01.pine +0 -0
  230. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-four-bar-stop-no-close-01.pine +0 -0
  231. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-side-same-id-stop-no-cancel-01.pine +0 -0
  232. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-both-touch-priority-01.pine +0 -0
  233. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-cancel-rotation-01.pine +0 -0
  234. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-far-only-01.pine +0 -0
  235. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-near-only-01.pine +0 -0
  236. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-open-high-first-path-01.pine +0 -0
  237. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-open-low-first-path-01.pine +0 -0
  238. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-open-tie-01.pine +0 -0
  239. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-source-order-long-first-01.pine +0 -0
  240. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-dual-stop-source-order-short-first-01.pine +0 -0
  241. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-entry-implicit-reversal-exit-01.pine +0 -0
  242. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-flip-stop-no-paired-close-01.pine +0 -0
  243. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-market-close-fill-basis-01.pine +0 -0
  244. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-one-side-four-bar-far-opposite-01.pine +0 -0
  245. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-opposite-entry-close-same-pass-01.pine +0 -0
  246. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-percent-equity-cash-commission-01.pine +0 -0
  247. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-process-on-close-false-01.pine +0 -0
  248. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-process-on-close-true-01.pine +0 -0
  249. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-range-expansion-pending-stop-01.pine +0 -0
  250. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-entry-close-same-bar-01.pine +0 -0
  251. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-market-entry-repeat-01.pine +0 -0
  252. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-stop-after-flat-01.pine +0 -0
  253. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-stop-cross-before-modify-01.pine +0 -0
  254. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-stop-minute-zero-01.pine +0 -0
  255. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-stop-modification-01.pine +0 -0
  256. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-stop-raise-only-01.pine +0 -0
  257. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-same-id-stop-window-four-bars-01.pine +0 -0
  258. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-stale-stop-after-close-no-cancel-01.pine +0 -0
  259. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-stop-cancel-no-regime-close-01.pine +0 -0
  260. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-stop-entry-cancel-opposite-01.pine +0 -0
  261. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-stop-entry-reversal-grouping-01.pine +0 -0
  262. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__order-stop-entry-touch-boundary-01.pine +0 -0
  263. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__pyramid-cash-fractional-commission-01.pine +0 -0
  264. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__pyramid-close-id-grouping-01.pine +0 -0
  265. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__pyramid-deferred-flip-close-all-01.pine +0 -0
  266. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__pyramid-flip-stop-pyramiding-2-01.pine +0 -0
  267. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__recompute-alma-sar-corr-magnifier-01.pine +0 -0
  268. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__recompute-mtf-rsi-macd-bb-01.pine +0 -0
  269. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__risk-max-contracts-held-gate-pyramid-01.pine +0 -0
  270. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__session-hour-minute-pulse-filter-01.pine +0 -0
  271. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__session-ny-spring-forward-dst-01.pine +0 -0
  272. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__stats-eventrades-zero-pnl-count-01.pine +0 -0
  273. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-accdist-ema-cross-01.pine +0 -0
  274. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-bb-kc-squeeze-breakout-01.pine +0 -0
  275. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-bb-rsi-mean-reversion-01.pine +0 -0
  276. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-cci-threshold-cross-01.pine +0 -0
  277. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-chandelier-exit-direction-01.pine +0 -0
  278. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-closedtrades-risk-introspection-01.pine +0 -0
  279. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-cmo-9-zero-cross-01.pine +0 -0
  280. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-cog-10-signal-cross-01.pine +0 -0
  281. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-dmi-adx-di-cross-01.pine +0 -0
  282. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-donchian-channel-breakout-01.pine +0 -0
  283. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-dual-ma-switch-dispatch-01.pine +0 -0
  284. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-dual-thrust-open-anchored-range-01.pine +0 -0
  285. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-elder-ray-bull-bear-power-01.pine +0 -0
  286. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-ema-ribbon-stack-transition-01.pine +0 -0
  287. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-engulfing-candle-pattern-01.pine +0 -0
  288. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-highestbars-lowestbars-breakout-01.pine +0 -0
  289. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-hma-55-close-cross-01.pine +0 -0
  290. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-hma-fast-slow-cross-01.pine +0 -0
  291. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-inside-bar-engulfing-01.pine +0 -0
  292. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-kama-style-efficiency-ratio-01.pine +0 -0
  293. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-keltner-channel-break-01.pine +0 -0
  294. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-linreg-stdev-channel-revert-01.pine +0 -0
  295. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-macd-12-26-9-line-signal-cross-01.pine +0 -0
  296. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-macd-histogram-reversal-01.pine +0 -0
  297. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-macd-line-gt-signal-continuous-state-01.pine +0 -0
  298. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-map-regime-threshold-lookup-01.pine +0 -0
  299. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-median-vs-ema-cross-01.pine +0 -0
  300. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-mfi-14-bands-20-80-01.pine +0 -0
  301. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-momentum-roc-zero-cross-01.pine +0 -0
  302. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-multi-indicator-score-composite-01.pine +0 -0
  303. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-nvi-pvi-cross-01.pine +0 -0
  304. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-obv-ema-cross-01.pine +0 -0
  305. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-percentrank-mean-reversion-01.pine +0 -0
  306. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-pivot-array-unshift-pop-01.pine +0 -0
  307. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-pivot-atr-stop-target-01.pine +0 -0
  308. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-pivot-confirmed-break-01.pine +0 -0
  309. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-pivot-point-levels-break-01.pine +0 -0
  310. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-pvt-ema-cross-01.pine +0 -0
  311. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-range-filter-var-band-01.pine +0 -0
  312. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rci-14-zero-cross-01.pine +0 -0
  313. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rsi-bb-self-bands-01.pine +0 -0
  314. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rsi-ema-signal-cross-01.pine +0 -0
  315. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rsi-macd-and-continuous-state-01.pine +0 -0
  316. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rsi14-bands-30-70-01.pine +0 -0
  317. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rsi14-cross-50-01.pine +0 -0
  318. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rsi14-gt-50-continuous-state-01.pine +0 -0
  319. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-rsi14-gt60-lt45-no-matrix-01.pine +0 -0
  320. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-sar-flip-entry-01.pine +0 -0
  321. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-sma-152-close-cross-01.pine +0 -0
  322. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-sma-dual-cross-01.pine +0 -0
  323. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-stdev-sma-expansion-break-01.pine +0 -0
  324. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-stoch-slow-k-d-cross-01.pine +0 -0
  325. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-stochastic-rsi-cross-01.pine +0 -0
  326. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-str-match-regex-filter-01.pine +0 -0
  327. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-supertrend-adx-filter-01.pine +0 -0
  328. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-supertrend-direction-flip-01.pine +0 -0
  329. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-triple-sma-stack-latch-01.pine +0 -0
  330. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-tsi-25-13-signal-cross-01.pine +0 -0
  331. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-volume-spike-atr-breakout-01.pine +0 -0
  332. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-vwma-vs-sma-divergence-01.pine +0 -0
  333. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__ta-wpr-14-bands-01.pine +0 -0
  334. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__timeframe-main-period-self-adaptive-01.pine +0 -0
  335. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-calls-sibling-cumulative-01.pine +0 -0
  336. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-default-param-kwargs-01.pine +0 -0
  337. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-drives-strategy-entry-01.pine +0 -0
  338. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-extra-primitive-args-01.pine +0 -0
  339. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-feeds-strategy-exit-prices-01.pine +0 -0
  340. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-in-for-loop-01.pine +0 -0
  341. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-in-if-else-branch-01.pine +0 -0
  342. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-in-switch-arms-01.pine +0 -0
  343. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-in-while-loop-01.pine +0 -0
  344. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-mutating-self-ref-01.pine +0 -0
  345. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-on-array-element-01.pine +0 -0
  346. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-reads-strategy-state-01.pine +0 -0
  347. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-receives-ta-series-param-01.pine +0 -0
  348. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-scalar-return-01.pine +0 -0
  349. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-tuple-return-destructure-01.pine +0 -0
  350. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-udt-return-from-func-01.pine +0 -0
  351. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-uses-history-globals-01.pine +0 -0
  352. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-uses-math-funcs-01.pine +0 -0
  353. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-uses-na-nz-fixnan-01.pine +0 -0
  354. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-var-instance-streak-01.pine +0 -0
  355. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-method-windowed-method-chain-01.pine +0 -0
  356. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__udt-regime-stack-stress-01.pine +0 -0
  357. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__vwap-bands-breakout-1sigma-01.pine +0 -0
  358. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/gate-corpus/ok/validation__vwap-bands-mean-reversion-2sigma-01.pine +0 -0
  359. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_analyzer.py +0 -0
  360. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_analyzer_matrix_inference.py +0 -0
  361. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_analyzer_ta_return_types.py +0 -0
  362. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_drawing_handles.py +0 -0
  363. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_fallthrough_guards.py +0 -0
  364. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_golden.py +0 -0
  365. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_input_getters.py +0 -0
  366. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_matrix_typed.py +0 -0
  367. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_codegen_string_escape.py +0 -0
  368. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_compile_corpus.py +0 -0
  369. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_errors.py +0 -0
  370. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_extract_inputs.py +0 -0
  371. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_glue_smoke.py +0 -0
  372. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_import_all.py +0 -0
  373. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_input_time_int64.py +0 -0
  374. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_int64_reassign_promotion.py +0 -0
  375. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_int64_time_storage.py +0 -0
  376. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_lexer.py +0 -0
  377. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_official_surface.py +0 -0
  378. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_security_tf_literal.py +0 -0
  379. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_signatures.py +0 -0
  380. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_chart_visible_bar_time.py +0 -0
  381. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_color_cast.py +0 -0
  382. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_const_namespaces.py +0 -0
  383. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_dividends_earnings.py +0 -0
  384. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_footprint.py +0 -0
  385. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_input_color.py +0 -0
  386. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_input_source.py +0 -0
  387. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_matrix.py +0 -0
  388. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_security_adjustment.py +0 -0
  389. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_syminfo_gap_fields.py +0 -0
  390. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_timeframe_from_seconds.py +0 -0
  391. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_varip.py +0 -0
  392. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_support_checker_volume_row.py +0 -0
  393. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_symbols.py +0 -0
  394. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_ta_official_surface.py +0 -0
  395. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_transpile_division.py +0 -0
  396. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_transpile_enum_order.py +0 -0
  397. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_transpile_pf_trace.py +0 -0
  398. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_transpile_tr_handle_na.py +0 -0
  399. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_transpiler_matrix_kwargs.py +0 -0
  400. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_typespec_matrix.py +0 -0
  401. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_udt_drawing_field_cleanup.py +0 -0
  402. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_unsupported_reporting.py +0 -0
  403. {pineforge_codegen-0.8.1 → pineforge_codegen-0.10.0}/tests/test_vwap_tuple_unpack.py +0 -0
@@ -206,14 +206,15 @@ strategy. The taxonomy:
206
206
  | Bucket | What |
207
207
  | -------------------------------- | -------------------------------------------------------------------- |
208
208
  | `HARD_REJECT_FUNC` | Calls with no PineForge semantics at all (e.g. `request.financial`). |
209
- | `HARD_REJECT_NAMESPACE` | Whole namespaces (e.g. `ticker.*`). |
210
- | `DIVERGENT_VARS` (warning) | Built-in variables whose value diverges from TV (e.g. `bar_index`). |
209
+ | `HARD_REJECT_NAMESPACE` | Whole-namespace rejects — currently EMPTY (the old `ticker.*` blanket reject became per-function `HARD_REJECT_FUNC` entries: `ticker.{renko,kagi,linebreak,pointfigure,new,modify}`; `ticker.inherit`/`ticker.standard` pass through, `ticker.heikinashi` allowed for the chart's own symbol). |
210
+ | `DIVERGENT_VARS` (warning) / `DIVERGENT_VARS_ERROR` (reject) | Built-in variables whose value diverges from TV (e.g. `bar_index` warns); the ERROR subset (`last_bar_index` — would silently mis-alias to the CURRENT bar index) is rejected because the backtest would be silently wrong. |
211
211
  | `BARSTATE_APPROX_VARS` (warning) | Barstate flags PineForge approximates in batch mode. |
212
212
  | `STRATEGY_UNSUPPORTED_PARAMS` | Per-strategy.* call kwargs that codegen drops silently. |
213
213
  | `NOT_YET_FUNC` | Implementable but currently no codegen — reject loudly. |
214
214
  | `SUPPORTED_*` frozensets | Per-namespace whitelist of names codegen knows how to emit. |
215
215
  | `varip` VarDecl check | `varip` declarations rejected outright — batch backtests have no realtime tick state. |
216
216
  | TF literal validation | `request.security` / `request.security_lower_tf` `timeframe` string literals validated against Pine v6 format at parse time. |
217
+ | syminfo na-gap warning | `SUPPORTED_SYMINFO` = every `SYMINFO_MEMBER_MAP` key, but members whose emission is `na<T>()` or a `get_syminfo_metadata(...)` lookup (root/pricescale/minmove/mincontract/current_contract/expiration_date/isin/sector/industry + fundamentals/recommendations/target_price_*) form `_SYMINFO_SILENT_GAP_FIELDS` (derived from the emission table, so new na-accept fields can't drift out): every read WARNS that the value is na until a data feed injects it. |
217
218
 
218
219
 
219
220
  When extending codegen with a new Pine builtin: add to the corresponding
@@ -230,22 +231,23 @@ These bit us once and are now pinned by `test_compile_smoke.py`'s
230
231
  you delete or weaken the special case, the test will tell you.
231
232
 
232
233
  1. **`year(time)` / `month(time)` / `dayofmonth` / `dayofweek` /
233
- `hour(time, tz)` / `minute` / `second` / `weekofyear` function-call
234
- form** lowers to an inline lambda that mirrors the engine's
235
- `BacktestEngine::_decompose_bar_time()`. The variable form uses
236
- `_bar_year()` etc. via `BAR_BUILTINS` (still UTC-only — `_bar_*`
237
- accessors call `gmtime_r` unconditionally; chart-tz wiring on the
238
- variable side is a separate engine change). The function-call form
239
- honors a tz argument: the two-arg form `hour(time, tz)` uses the
240
- explicit tz; the one-arg form `hour(time)` defaults to
241
- `syminfo_.timezone` (the engine's `SymInfo::timezone` field, "UTC"
242
- by default). When the resolved tz is empty / "UTC" / "Etc/UTC" the
243
- lambda takes the cheap `gmtime_r` fast path; otherwise it enters a
244
- mutex-guarded `setenv("TZ", ...)` + `localtime_r` block that
245
- mirrors `pine_tz::ScopedTimezone` (`src/timezone.cpp`, not exposed
246
- via any public `<pineforge/...>` header). Harnesses validating
247
- against TV exports for non-UTC symbols MUST set chart_tz to match
248
- the chart's TZ at export time.
234
+ `hour(time, tz)` / `minute` / `second` / `weekofyear`** — BOTH the
235
+ function-call form and the bare variable form lower to the engine's
236
+ cached, timezone-aware `pine_<field>(ts_ms, tz)` helpers
237
+ (`session_time.hpp`): the variable form via `BAR_BUILTINS`
238
+ (`pine_year(current_bar_.timestamp, syminfo_.timezone)` …), the
239
+ function form via `visit_call.py` (`pine_hour((int64_t)(ts), tz)`),
240
+ so the two forms agree. The two-arg form uses the explicit tz; the
241
+ one-arg form defaults to `syminfo_.timezone` (engine
242
+ `SymInfo::timezone`, "UTC" by default). The old inline
243
+ `setenv("TZ")+localtime_r` lambda (`tz_time_field_lambda`,
244
+ codegen/tables.py) is no longer emitted per-call tzset churn
245
+ caused a macOS notifyd IPC storm (KI-35) and has zero call sites.
246
+ Chart display TZ is a separate engine slot (`chart_timezone_`,
247
+ `strategy_set_chart_timezone`) intentionally NOT consulted by these
248
+ builtins; harnesses validating metrics against TV exports for
249
+ non-UTC charts must still set chart_tz to match the chart's TZ at
250
+ export time.
249
251
  2. **Matrix-returning methods** (`inv` / `pinv` / `transpose` / `copy` /
250
252
  `submatrix` / `concat` / `diff` / `mult` / `pow` / `eigenvectors` /
251
253
  `kron`) live in `MATRIX_RETURNING_METHODS` (`codegen/tables.py`).
@@ -276,13 +278,21 @@ you delete or weaken the special case, the test will tell you.
276
278
  PREVIOUS bar's HLC (`_s_high[1]`, `_s_low[1]`, `_s_close[1]`) per
277
279
  Pine v6 semantics with `developing=false`.
278
280
  6. **`request.security` is strict.** Only `symbol`, `timeframe`,
279
- `expression`, `gaps`, and `lookahead` are allowed. Symbol must resolve
280
- to the current chart symbol (`syminfo.tickerid` or `syminfo.ticker`).
281
- `gaps` and `lookahead` must be the literal `barmerge.gaps_*` /
281
+ `expression`, `gaps`, `lookahead`, and `ignore_invalid_symbol` are
282
+ allowed (`ignore_invalid_symbol` is accepted but inert the symbol is
283
+ always the chart symbol, so no symbol can be invalid). Symbol must
284
+ resolve to the current chart symbol (`syminfo.tickerid` or
285
+ `syminfo.ticker`, incl. first-binding aliases and
286
+ `ticker.inherit/standard/heikinashi(<chart sym>)`). `gaps` and
287
+ `lookahead` must be the literal `barmerge.gaps_*` /
282
288
  `barmerge.lookahead_*` member access (codegen does not parse other
283
- shapes). `barmerge.lookahead_on` is hard-rejected for backtest-honesty
284
- reasons. The `timeframe` argument, when a string literal, is validated
285
- against the Pine v6 TF format at parse time (PR #3).
289
+ shapes). `barmerge.lookahead_on` is ACCEPTED with a repaint WARNING —
290
+ engine-supported (first-intrabar publication; script-tf publish gating
291
+ for finer-than-chart targets): see `_check_request_security`'s lookahead
292
+ branch and `test_request_security_lookahead_on_kwarg_warns`. The old
293
+ "hard-rejected" wording here was verified stale against the code on
294
+ 2026-07-07 — do not restore it. The `timeframe` argument, when a string
295
+ literal, is validated against the Pine v6 TF format at parse time (PR #3).
286
296
  7. `**SUPPORTED_LOG`** gates `log.{info,warning,error}`. Without it,
287
297
  typos like `log.foo("x")` previously emitted a dead empty-string
288
298
  statement. Don't remove the gate.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pineforge-codegen
3
- Version: 0.8.1
3
+ Version: 0.10.0
4
4
  Summary: PineScript v6 to C++ transpiler that targets the pineforge-engine runtime.
5
5
  Project-URL: Homepage, https://github.com/pineforge-4pass/pineforge-codegen-oss
6
6
  Project-URL: Issues, https://github.com/pineforge-4pass/pineforge-codegen-oss/issues
@@ -0,0 +1 @@
1
+ 0.10.0
@@ -143,6 +143,13 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
143
143
  self._block_var_seq = 0
144
144
  self._ta_counter = 0
145
145
  self._fixnan_counter = 0
146
+ # All fixnan member names minted so far (base + clones), for O(1)
147
+ # collision detection when minting a per-call-site fixnan clone.
148
+ self._fixnan_member_names: set[str] = set()
149
+ # Authoritative fixnan clone-name map for collisions: (func, cs_idx)
150
+ # -> {orig_member: cloned_member}. Consumed verbatim by the codegen
151
+ # when the default ``{base}_cs{cs_idx}`` formula would collide.
152
+ self._func_cs_fixnan_clone_names: dict[tuple[str, int], dict[str, str]] = {}
146
153
  # Track user-defined function nodes for deferred analysis
147
154
  self._func_defs: dict[str, FuncDef] = {}
148
155
  # Track user-defined function return types
@@ -156,6 +163,7 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
156
163
  # Probe: data/validation/udt-method-probe-20-udt-return-from-func.
157
164
  self._func_udt_return_types: dict[str, str] = {}
158
165
  self._func_return_type_specs: dict[str, "TypeSpec"] = {}
166
+ self._func_param_type_specs: dict[str, list] = {}
159
167
  # Per-function var_members and series_vars (for call-site cloning)
160
168
  self._func_var_members: dict[str, list] = {} # func_name -> [(name, PineType, init_str)]
161
169
  self._func_series_vars: dict[str, set] = {} # func_name -> set[str]
@@ -163,9 +171,23 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
163
171
  self._func_ta_ranges: dict[str, tuple[int, int]] = {} # func_name -> (start, end) indices
164
172
  self._func_call_site_count: dict[str, int] = {} # func_name -> count
165
173
  self._func_call_cs_map: dict[int, tuple[str, int]] = {} # call_node_id -> (func_name, cs_idx)
166
- # Functions whose ONLY reason for needing per-call-site body cloning
167
- # is a security-tf-monomorphized request.security (no TA/series state
168
- # of their own see _check_mixed_callsite_security_tf).
174
+ # Textual nested calls whose identity is inherited from the active
175
+ # parent clone rather than assigned a fixed source-level cs index.
176
+ # Kept separately so a second propagation pass (security TF cloning)
177
+ # does not accidentally backfill them as a new cs{N} call site.
178
+ self._func_inherited_call_nodes: set[int] = set()
179
+ # Per-function fixnan site ownership: func_name -> list of fixnan site
180
+ # indices in self._fixnan_sites owned by that function. Mirrors the
181
+ # TA-range slicing but for fixnan state, so per-call-site cloning can
182
+ # mint fresh fixnan members per variant and the codegen dead-code pass
183
+ # can skip fixnan state owned by dead functions.
184
+ self._func_fixnan_indices: dict[str, list[int]] = {}
185
+ # Functions that need per-call-site BODY cloning despite owning no
186
+ # TA/series/var state. The set originated for security-tf
187
+ # monomorphization; it is also the existing emitter contract used by
188
+ # pure wrappers around stateful callees and fixnan-only functions.
189
+ # Security evaluator identity remains independently tracked by each
190
+ # SecurityCallInfo.callsite_idx.
169
191
  self._func_security_clone_only: set[str] = set()
170
192
  # Authoritative clone-name map: (func_name, cs_idx) -> {orig_member_name:
171
193
  # cloned_member_name}. The codegen rebuilds its TA remap from the
@@ -200,6 +222,13 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
200
222
  # a TA ctor length with one of the OUTER function's params, so the outer
201
223
  # call site can re-substitute (e.g. f_bbwp(_bbwLen) -> f_basisMa(_len)).
202
224
  self._enclosing_func_params: list[set[str]] = []
225
+ # Parallel stack of the function NAMES whose param-sets are in
226
+ # ``_enclosing_func_params``. The top of stack (or None at global
227
+ # scope) is the owner of any ORIGINAL ``ta.*`` site minted right now
228
+ # -- recorded on ``TACallSite.owner_func`` so the codegen dead-code
229
+ # pass can tell borrowed clones apart from a dead function's own
230
+ # sites (see contracts.TACallSite.owner_func).
231
+ self._enclosing_func_names: list[str] = []
203
232
  # Set of TA-site indices a nested user-func call rewrote in terms of the
204
233
  # current enclosing function's params (None when not inside a FuncDef body).
205
234
  self._nested_ta_touched: set | None = None
@@ -302,6 +331,8 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
302
331
  var_members=self._var_members,
303
332
  func_infos=self._func_infos,
304
333
  fixnan_sites=self._fixnan_sites,
334
+ func_fixnan_indices=self._func_fixnan_indices,
335
+ func_cs_fixnan_clone_names=self._func_cs_fixnan_clone_names,
305
336
  strategy_params=self._strategy_params,
306
337
  diagnostics=self._diagnostics,
307
338
  filename=self._filename,
@@ -440,40 +471,274 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
440
471
  return out
441
472
 
442
473
  def _propagate_call_site_counts(self) -> None:
443
- """Propagate call-site counts from parent functions to sub-functions.
444
-
445
- If function F has N call sites and calls sub-function G internally,
446
- G also needs N variants so that F_csK can call G_csK with isolated state.
447
- This ensures every stateful sub-function gets per-call-site isolation
448
- inherited from its parent.
474
+ """Propagate stateful UDF identity through complete call paths.
475
+
476
+ A UDF is stateful when it owns series/``var`` state, TA state, or
477
+ ``fixnan`` state, and every pure wrapper that reaches such a UDF is
478
+ stateful transitively. Give each wrapper's textual calls stable cs
479
+ identities, then inherit a multi-call-site parent's count down to its
480
+ stateful callees. Any inherited TA/fixnan variants are materialized
481
+ immediately; exporting a count without the corresponding members would
482
+ make codegen reference undeclared or shared state.
449
483
  """
450
484
  from pineforge_codegen.ast_nodes import FuncCall, FuncDef, Identifier
451
485
 
452
- # Collect all user function definitions from AST
453
486
  func_defs: dict[str, FuncDef] = {}
454
487
  for stmt in self._ast.body:
455
488
  if isinstance(stmt, FuncDef):
456
489
  func_defs[stmt.name] = stmt
457
490
 
458
- # Find which functions call which sub-functions (direct calls only)
459
- def _find_calls(node, known_funcs: set[str]) -> set[str]:
460
- calls: set[str] = set()
461
- if isinstance(node, FuncCall) and isinstance(node.callee, Identifier):
462
- if node.callee.name in known_funcs:
463
- calls.add(node.callee.name)
491
+ # UDT methods participate in the same stateful call graph as plain
492
+ # UDFs. Their analyzer identity is ``Type.method`` while FuncInfo.node
493
+ # carries the synthetic FuncDef used by codegen.
494
+ func_info_by_name = {fi.name: fi for fi in self._func_infos}
495
+ for fi in self._func_infos:
496
+ if getattr(fi, "is_udt_method", False) and fi.node is not None:
497
+ func_defs.setdefault(fi.name, fi.node)
498
+
499
+ # Preserve call-node identity as well as the callee name: late clone
500
+ # materialization needs the textual call's argument mapping to resolve
501
+ # parameterized TA constructor lengths.
502
+ def _resolved_user_call_name(call: FuncCall, owner: str | None) -> str | None:
503
+ if isinstance(call.callee, Identifier):
504
+ return call.callee.name if call.callee.name in func_defs else None
505
+ if not isinstance(call.callee, MemberAccess):
506
+ return None
507
+
508
+ recv = call.callee.object
509
+ method = call.callee.member
510
+ udt_name: str | None = None
511
+ if isinstance(recv, Identifier):
512
+ udt_name = self._udt_var_types.get(recv.name)
513
+ owner_info = func_info_by_name.get(owner or "")
514
+ if udt_name is None and owner_info is not None \
515
+ and owner_info.node is not None:
516
+ if (getattr(owner_info, "is_udt_method", False)
517
+ and owner_info.node.params
518
+ and recv.name == owner_info.node.params[0]):
519
+ udt_name = owner_info.udt_type_name
520
+ elif recv.name in owner_info.node.params:
521
+ param_idx = owner_info.node.params.index(recv.name)
522
+ specs = getattr(owner_info, "param_type_specs", []) or []
523
+ spec = specs[param_idx] if param_idx < len(specs) else None
524
+ if spec is not None and spec.kind == "udt":
525
+ udt_name = spec.name
526
+ if udt_name is None:
527
+ spec = self._type_spec_from_expr(recv)
528
+ if spec is not None and spec.kind == "udt":
529
+ udt_name = spec.name
530
+ key = f"{udt_name}.{method}" if udt_name else ""
531
+ return key if key in func_defs else None
532
+
533
+ def _find_calls(node, known_funcs: set[str],
534
+ owner: str | None = None,
535
+ seen: set[int] | None = None) -> list[tuple[str, FuncCall]]:
536
+ calls: list[tuple[str, FuncCall]] = []
537
+ if node is None:
538
+ return calls
539
+ if seen is None:
540
+ seen = set()
541
+ if isinstance(node, (list, tuple, dict)) or hasattr(node, "__dict__"):
542
+ node_id = id(node)
543
+ if node_id in seen:
544
+ return calls
545
+ seen.add(node_id)
546
+ if isinstance(node, (list, tuple)):
547
+ for item in node:
548
+ calls.extend(_find_calls(item, known_funcs, owner, seen))
549
+ return calls
550
+ if isinstance(node, dict):
551
+ for item in node.values():
552
+ calls.extend(_find_calls(item, known_funcs, owner, seen))
553
+ return calls
554
+ if not hasattr(node, "__dict__"):
555
+ return calls
556
+ if isinstance(node, FuncCall):
557
+ resolved = _resolved_user_call_name(node, owner)
558
+ if resolved in known_funcs:
559
+ calls.append((resolved, node))
464
560
  for attr_val in vars(node).values():
465
- if isinstance(attr_val, list):
466
- for item in attr_val:
467
- if hasattr(item, '__dict__'):
468
- calls |= _find_calls(item, known_funcs)
469
- elif hasattr(attr_val, '__dict__'):
470
- calls |= _find_calls(attr_val, known_funcs)
561
+ calls.extend(_find_calls(attr_val, known_funcs, owner, seen))
471
562
  return calls
472
563
 
473
564
  known_func_names = set(func_defs.keys())
565
+ calls_by_parent = {
566
+ name: _find_calls(func_def, known_func_names, name)
567
+ for name, func_def in func_defs.items()
568
+ }
569
+ calls_by_callee: dict[str, list[FuncCall]] = {
570
+ name: [] for name in known_func_names
571
+ }
572
+ # Preserve source order across definitions and top-level statements.
573
+ # Method bodies use their ``Type.method`` owner so ``self.sibling()``
574
+ # resolves without relying on a now-exited symbol-table scope.
575
+ for stmt in self._ast.body:
576
+ if isinstance(stmt, FuncDef):
577
+ owner = stmt.name
578
+ elif isinstance(stmt, MethodDef):
579
+ owner = f"{stmt.type_name}.{stmt.name}"
580
+ else:
581
+ owner = None
582
+ for callee, call in _find_calls(stmt, known_func_names, owner):
583
+ calls_by_callee.setdefault(callee, []).append(call)
584
+
585
+ # Codegen synthesizes a Series buffer for two expression shapes that
586
+ # do not appear in ``_func_series_vars`` themselves:
587
+ #
588
+ # * a call result read through history, e.g. ``f()[1]``;
589
+ # * a scalar expression bridged into a UDF series parameter, e.g.
590
+ # ``history(close + open)`` where ``history(src) => src[1]``.
591
+ #
592
+ # A buffer is mutable per-call-site state just like TA/fixnan. Mark
593
+ # its lexical owner stateful before the normal call-path closure so a
594
+ # function invoked from two source sites receives two emitted bodies
595
+ # (and therefore two independent generated buffer members). Without
596
+ # this, moving the old function-local static into a class member would
597
+ # accidentally merge both Pine call sites into one history stream.
598
+ def _actual_arg(call: FuncCall, param_name: str, param_idx: int):
599
+ if param_idx < len(call.args):
600
+ return call.args[param_idx]
601
+ return call.kwargs.get(param_name)
602
+
603
+ def _needs_scalar_series_bridge(call: FuncCall) -> bool:
604
+ if not isinstance(call.callee, Identifier):
605
+ return False
606
+ callee = call.callee.name
607
+ fi = func_info_by_name.get(callee)
608
+ if fi is None or fi.node is None:
609
+ return False
610
+ series_params = self._func_series_vars.get(callee, set())
611
+ if not series_params:
612
+ return False
613
+ direct_bar_series = {
614
+ "open", "high", "low", "close", "volume",
615
+ "hl2", "hlc3", "ohlc4",
616
+ }
617
+ for idx, param_name in enumerate(fi.node.params):
618
+ if param_name not in series_params:
619
+ continue
620
+ arg = _actual_arg(call, param_name, idx)
621
+ if arg is None:
622
+ continue
623
+ if isinstance(arg, Identifier) and (
624
+ arg.name in direct_bar_series or arg.name in self._series_vars
625
+ ):
626
+ continue
627
+ return True
628
+ return False
629
+
630
+ def _has_synthetic_history_state(
631
+ node, seen: set[int] | None = None) -> bool:
632
+ if node is None:
633
+ return False
634
+ if seen is None:
635
+ seen = set()
636
+ if isinstance(node, (list, tuple, dict)) or hasattr(node, "__dict__"):
637
+ node_id = id(node)
638
+ if node_id in seen:
639
+ return False
640
+ seen.add(node_id)
641
+ if isinstance(node, (list, tuple)):
642
+ return any(
643
+ _has_synthetic_history_state(item, seen) for item in node
644
+ )
645
+ if isinstance(node, dict):
646
+ return any(
647
+ _has_synthetic_history_state(item, seen)
648
+ for item in node.values()
649
+ )
650
+ if not hasattr(node, "__dict__"):
651
+ return False
652
+ if (isinstance(node, Subscript)
653
+ and isinstance(node.object, FuncCall)):
654
+ return True
655
+ if isinstance(node, FuncCall) and _needs_scalar_series_bridge(node):
656
+ return True
657
+ return any(
658
+ _has_synthetic_history_state(value, seen)
659
+ for value in vars(node).values()
660
+ )
474
661
 
475
- # For each multi-call-site function, propagate count to sub-functions
476
- # that have stateful locals (series vars or var members)
662
+ synthetic_history_stateful = {
663
+ name for name, func_def in func_defs.items()
664
+ if _has_synthetic_history_state(func_def)
665
+ }
666
+
667
+ # request.security owns a separate evaluator context and already
668
+ # materializes/remaps its embedded TA state per SecurityCallInfo. Do
669
+ # not thread ordinary UDF clone indices through a function used as a
670
+ # security expression (or through the containing wrapper); doing so
671
+ # would double-clone evaluator state and disturb expression identity.
672
+ security_boundary_funcs: set[str] = set()
673
+ for sec in getattr(self, "_security_calls", []) or []:
674
+ containing = getattr(sec, "containing_func", "") or ""
675
+ if containing:
676
+ security_boundary_funcs.add(containing)
677
+ expression = getattr(sec, "expression", None)
678
+ if expression is not None:
679
+ security_boundary_funcs.update(
680
+ sub for sub, _ in _find_calls(
681
+ expression, known_func_names, containing or None
682
+ )
683
+ )
684
+
685
+ # Canonical direct-state predicate. TA-only and fixnan-only helpers
686
+ # are just as stateful as functions carrying an explicit series/var.
687
+ stateful = (
688
+ set(self._func_series_vars)
689
+ | set(self._func_var_members)
690
+ | set(self._func_ta_ranges)
691
+ | set(self._func_fixnan_indices)
692
+ | synthetic_history_stateful
693
+ )
694
+
695
+ # Close upward over the call graph so a pure A -> B -> stateful C chain
696
+ # receives variants at every level. The existing clone-only emitter
697
+ # marker is intentionally separate from request.security evaluator
698
+ # identity, so ordinary security calls remain shared unless the
699
+ # dedicated timeframe-monomorphization pass clones them.
700
+ changed = True
701
+ while changed:
702
+ changed = False
703
+ for fname, calls in calls_by_parent.items():
704
+ if fname in stateful:
705
+ continue
706
+ if any(sub in stateful for sub, _ in calls):
707
+ stateful.add(fname)
708
+ changed = True
709
+
710
+ # Direct fixnan-only functions and pure transitive wrappers own no
711
+ # TA/series member that would trip the emitter's ordinary body-clone
712
+ # gate. Reuse its established body-only clone marker; this does not
713
+ # create or renumber any SecurityCallInfo.
714
+ for fname in sorted(stateful):
715
+ if (fname not in self._func_ta_ranges
716
+ and fname not in self._func_series_vars
717
+ and fname not in self._func_var_members):
718
+ self._func_security_clone_only.add(fname)
719
+
720
+ # The initial visitor only numbers directly-stateful callees. Backfill
721
+ # stable identities for newly discovered pure wrappers without
722
+ # disturbing any indices already assigned by the visitor or security
723
+ # monomorphization.
724
+ for fname in sorted(stateful):
725
+ calls = calls_by_callee.get(fname, [])
726
+ current = self._func_call_site_count.get(fname, 0)
727
+ next_idx = current
728
+ for call in calls:
729
+ if id(call) in self._func_inherited_call_nodes:
730
+ continue
731
+ existing = self._func_call_cs_map.get(id(call))
732
+ if existing is not None and existing[0] == fname:
733
+ next_idx = max(next_idx, existing[1] + 1)
734
+ continue
735
+ self._func_call_cs_map[id(call)] = (fname, next_idx)
736
+ next_idx += 1
737
+ if next_idx > current:
738
+ self._func_call_site_count[fname] = next_idx
739
+
740
+ # Inherit each multi-call-site parent's index space down the full path.
741
+ # Re-run to a fixed point for A -> B -> C chains.
477
742
  changed = True
478
743
  while changed:
479
744
  changed = False
@@ -482,14 +747,32 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
482
747
  continue
483
748
  if fname not in func_defs:
484
749
  continue
485
- sub_calls = _find_calls(func_defs[fname], known_func_names)
486
- for sub in sub_calls:
487
- has_state = (sub in self._func_series_vars or
488
- sub in self._func_var_members)
489
- if not has_state:
750
+ if fname in security_boundary_funcs:
751
+ continue
752
+ for sub, call_node in calls_by_parent.get(fname, []):
753
+ if sub not in stateful:
490
754
  continue
491
755
  current = self._func_call_site_count.get(sub, 0)
492
756
  if current < count:
757
+ # One textual nested call is not an independent cs0
758
+ # path: it inherits the active parent clone index.
759
+ # Remove the visitor's provisional cs0 map so codegen's
760
+ # established active-index fallback dispatches
761
+ # F_csK -> G_csK. Keeping the map would make the
762
+ # context-sensitive instance pre-pass pin every parent
763
+ # clone to G_cs0 before that fallback can run.
764
+ if current == 1:
765
+ cs_info = self._func_call_cs_map.get(id(call_node))
766
+ if cs_info == (sub, 0):
767
+ self._func_call_cs_map.pop(id(call_node), None)
768
+ self._func_inherited_call_nodes.add(id(call_node))
769
+ for cs_idx in range(current, count):
770
+ self._materialize_user_func_call_site_state(
771
+ sub,
772
+ cs_idx,
773
+ call_node,
774
+ reuse_existing_owner=fname,
775
+ )
493
776
  self._func_call_site_count[sub] = count
494
777
  changed = True
495
778
 
@@ -1162,6 +1445,7 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
1162
1445
  old_global = self._global_scope
1163
1446
  self._global_scope = False
1164
1447
  self._enclosing_func_params.append(set(node.params))
1448
+ self._enclosing_func_names.append(node.name)
1165
1449
  self._nested_ta_touched = set()
1166
1450
  try:
1167
1451
  for stmt in node.body:
@@ -1169,6 +1453,7 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
1169
1453
  finally:
1170
1454
  self._global_scope = old_global
1171
1455
  self._enclosing_func_params.pop()
1456
+ self._enclosing_func_names.pop()
1172
1457
  nested_touched = self._nested_ta_touched
1173
1458
  self._nested_ta_touched = None
1174
1459
 
@@ -1184,6 +1469,16 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
1184
1469
  if hi > lo:
1185
1470
  self._func_ta_ranges[node.name] = (lo, hi)
1186
1471
 
1472
+ inferred_param_specs = self._param_type_specs_from_def(node)
1473
+ for i, param in enumerate(node.params):
1474
+ if i < len(inferred_param_specs) and inferred_param_specs[i] is not None:
1475
+ continue
1476
+ sym = self._symbols.resolve(param)
1477
+ spec = getattr(sym, "type_spec", None) if sym is not None else None
1478
+ if spec is not None and i < len(inferred_param_specs):
1479
+ inferred_param_specs[i] = spec
1480
+ self._func_param_type_specs[node.name] = inferred_param_specs
1481
+
1187
1482
  self._symbols.exit_scope()
1188
1483
 
1189
1484
  # Detect if function returns a tuple (last stmt is TupleLiteral)
@@ -1511,6 +1806,20 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
1511
1806
 
1512
1807
  # String concatenation: if either side is STRING, result is STRING
1513
1808
  if left_type == PineType.STRING or right_type == PineType.STRING:
1809
+ def _mark_string_param(expr) -> None:
1810
+ if not isinstance(expr, Identifier):
1811
+ return
1812
+ sym = self._symbols.resolve(expr.name)
1813
+ if sym is None or not (sym.scope or "").startswith("func_"):
1814
+ return
1815
+ if sym.pine_type == PineType.UNKNOWN:
1816
+ sym.pine_type = PineType.STRING
1817
+ sym.type_spec = TypeSpec.primitive("string")
1818
+
1819
+ if left_type == PineType.STRING:
1820
+ _mark_string_param(node.right)
1821
+ if right_type == PineType.STRING:
1822
+ _mark_string_param(node.left)
1514
1823
  return PineType.STRING
1515
1824
 
1516
1825
  # Arithmetic: promote to FLOAT if either side is FLOAT
@@ -1583,11 +1892,14 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
1583
1892
  if isinstance(obj, Identifier) and obj.name == "str":
1584
1893
  for arg in node.args:
1585
1894
  self._visit(arg)
1586
- # Most str.* return a string, but a few don't:
1587
- # str.tonumber -> float, str.length -> int
1895
+ # Most str.* return a string, but predicates and index helpers
1896
+ # are scalar. Keep this aligned with signatures.py and the C++
1897
+ # emitter's _infer_type path.
1898
+ if member in ("contains", "startswith", "endswith"):
1899
+ return PineType.BOOL
1588
1900
  if member == "tonumber":
1589
1901
  return PineType.FLOAT
1590
- if member == "length":
1902
+ if member in ("length", "pos"):
1591
1903
  return PineType.INT
1592
1904
  return PineType.STRING
1593
1905
 
@@ -1812,9 +2124,11 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
1812
2124
 
1813
2125
  # syminfo.*
1814
2126
  if ns == "syminfo":
1815
- if node.member == "mintick":
1816
- return PineType.FLOAT
1817
- return PineType.STRING
2127
+ from .. import signatures as _pf_sigs
2128
+ return _pf_sigs.SYMINFO_VARIABLES.get(
2129
+ f"syminfo.{node.member}",
2130
+ PineType.STRING,
2131
+ )
1818
2132
 
1819
2133
  # color.* constants
1820
2134
  if ns == "color":
@@ -1873,7 +2187,7 @@ class Analyzer(CallHandlers, DiagnosticsHelper, TypeHelper):
1873
2187
 
1874
2188
  # text.* constants (align_left, align_right, etc.)
1875
2189
  if ns == "text":
1876
- return PineType.INT
2190
+ return PineType.STRING
1877
2191
 
1878
2192
  # extend.* constants (left, right, both, none)
1879
2193
  if ns == "extend":