fix(codegen): scope-unique block var members + collection lvalue aliasing#33
Merged
Merged
Conversation
…sing
Two independent Pine reference/scope correctness bugs, each proven by hand-edit
and validated by the full gate + an 87-strategy behavioral sweep (0 regressions).
BUG 1 — block-scoped `var` name collision. Block-scoped `var`/`varip`
declarations were keyed by raw name and deduped by name, so two same-named
`var`s in SIBLING non-global scopes shared ONE C++ member. analyzer/base.py
_visit_VarDecl now assigns a scope-unique member `{name}__blk{seq}` when a
block-scoped var's raw name already belongs to a different enclosing block,
records the rename in AnalyzerContext.block_var_renames (keyed by block node via
a new _block_node_stack in the If/For/ForIn/While visitors), and codegen
activates it through the existing _active_var_remap plumbing so every read/write
inside the block resolves to the unique member.
egoigor1976-1-trendline (two `var bool valid`, upper vs lower trendline):
44.2% -> 100.0% match vs TradingView (price-exact).
BUG 2 — collection (array/map/matrix) lvalue aliasing value-copied. Pine
arrays/maps/matrices are REFERENCE types, but a local bound to an existing
collection lvalue (incl. a ternary/switch of collection lvalues) was
value-COPIED, so subsequent mutations never reached the member. Extend the
existing UDT-lvalue-alias mechanism to collections: types.py
_collection_lvalue_selection_spec + _collection_local_must_alias (mutated via a
COLLECTION_MUTATING_METHODS call and not rebound); visit_stmt.py _visit_var_decl
emits a non-rebinding reference `T& x = rhs;` for a qualifying mutated local.
jevondijefferson-big-breakout (orderBlocks aliased to internal/swing member via
ternary then unshift/remove): 36.1% -> 76.6% (price-exact 99.4%).
Full gate PINEFORGE_ENGINE_INCLUDE=... pytest: 1390 passed, 1 skipped, 0 failed
(1386 baseline + 4 new teeth tests; 254-strategy corpus compile green). Broad
sweep: exactly 2 movers (the targets), 0 regressions, 14 unrelated multi-helper
strategies byte-identical. Both fixes are no-ops unless their construct is
present, so corpus regeneration stays safe.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two independent Pine reference/scope correctness bugs, each proven by hand-edit and validated by the full gate + an 87-strategy behavioral sweep (0 regressions).
BUG 1 — block-scoped
varname collisionBlock-scoped
var/varipdeclarations were keyed by raw name and deduped by name, so two same-namedvars in sibling non-global scopes shared one C++ member.analyzer/base.py::_visit_VarDeclnow assigns a scope-unique member{name}__blk{seq}when a block-scoped var's raw name already belongs to a different enclosing block, records the rename inAnalyzerContext.block_var_renames(keyed by block node via a new_block_node_stack), and codegen activates it through the existing_active_var_remapplumbing.→ egoigor1976-1-trendline (two
var bool valid, upper vs lower trendline): 44.2% → 100.0% (price-exact).BUG 2 — collection lvalue aliasing value-copied
Pine arrays/maps/matrices are reference types, but a local bound to an existing collection lvalue (incl. a ternary/switch of collection lvalues) was value-copied, so mutations never reached the member. Extended the existing UDT-lvalue-alias mechanism to collections (
types.pyhelpers +visit_stmt.pyemitsT& x = rhs;for a qualifying mutated local).→ jevondijefferson-big-breakout (
orderBlocksaliased to internal/swing member via ternary thenunshift/remove): 36.1% → 76.6% (price-exact 99.4%).Validation
PINEFORGE_ENGINE_INCLUDE=... pytestBoth fixes are no-ops unless their construct is present → corpus regeneration stays safe.
🤖 Generated with Claude Code