Skip to content

fix(codegen): scope-unique block var members + collection lvalue aliasing#33

Merged
luisleo526 merged 1 commit into
mainfrom
fix/block-var-scope-and-collection-aliasing
Jun 30, 2026
Merged

fix(codegen): scope-unique block var members + collection lvalue aliasing#33
luisleo526 merged 1 commit into
mainfrom
fix/block-var-scope-and-collection-aliasing

Conversation

@luisleo526

Copy link
Copy Markdown
Contributor

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 vars 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), and codegen activates it through the existing _active_var_remap plumbing.

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.py helpers + visit_stmt.py emits 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%).

Validation

result
full gate PINEFORGE_ENGINE_INCLUDE=... pytest 1390 passed, 1 skipped, 0 failed (1386 + 4 teeth tests; 254-corpus compile green)
broad 87-strategy sweep exactly 2 movers (the targets), 0 regressions; 14 unrelated multi-helper strategies byte-identical
teeth both regression tests fail on the unpatched tree; 2 no-op guards pin "no-op unless triggered"

Both fixes are no-ops unless their construct is present → corpus regeneration stays safe.

🤖 Generated with Claude Code

…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>
@luisleo526 luisleo526 merged commit 5afc544 into main Jun 30, 2026
9 checks passed
@luisleo526 luisleo526 deleted the fix/block-var-scope-and-collection-aliasing branch June 30, 2026 17:41
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.

1 participant