Skip to content

fix(codegen): declare loop-local drawing-object handles (line/label/box) - #24

Merged
luisleo526 merged 1 commit into
mainfrom
fix/skip-expr-local-vardecl-drop
Jun 28, 2026
Merged

luisleo526 merged 1 commit into
mainfrom
fix/skip-expr-local-vardecl-drop

Conversation

@luisleo526

Copy link
Copy Markdown
Contributor

Problem

A variable assigned from a skipped visual call (line.new / label.new / box.new / …) was declared only when the namespace was table (SKIP_VAR_TYPES). For the other drawing namespaces the declaration was dropped. In script/if scope the var is a class member (declared anyway), but as a for-loop local it became undeclared:

var aoLines = array.new<line>()
for k = 1 to aoCount
    ln = line.new(...)        // dropped
    array.push(aoLines, ln)   // -> aoLines.push_back(ln);  // no `ln`
error: use of undeclared identifier 'ln'

Found running real-world strategies through the engine — common in webhook/DCA bots that draw AO level lines in a loop (11 strategies in the test set hit this).

Fix

Always emit a default-valued local declaration for skip-expr assignments. The value is inert (drawing ops have no backtest effect) but references must compile. Removes the now-unused SKIP_VAR_TYPES import.

Tests / regression

  • New tests/test_codegen_drawing_handles.py (line + label handles in a loop).
  • No corpus regression: all 258 corpus probes transpile byte-identically with vs without this change (no corpus probe uses this pattern).
  • End-to-end: a real strategy with this pattern compiles with 0 errors when combined with fix(codegen): escape C++ string literals (quotes/backslash/newline) #23 (string escaping).

🤖 Generated with Claude Code

A variable assigned from a skipped visual call (line.new / label.new / box.new
/ ...) was only declared when the namespace was `table` (SKIP_VAR_TYPES); for
other drawing namespaces the declaration was dropped. In script/if scope the var
is a class member (declared anyway), but as a *for-loop local* it became
undeclared, so e.g.

    ln = line.new(...)
    array.push(aoLines, ln)

emitted `aoLines.push_back(ln);` with no `ln` -> "use of undeclared identifier
'ln'". Common in webhook/DCA strategies that draw AO level lines in a loop.

Always emit a default-valued local declaration for skip-expr assignments — the
value is inert (drawing ops have no backtest effect) but references must compile.
Removes the now-unused SKIP_VAR_TYPES import.

Adds regression tests. No corpus regression: all 258 corpus probes transpile
byte-identically with vs without this change.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@luisleo526
luisleo526 merged commit 5d253bf into main Jun 28, 2026
9 checks passed
@luisleo526
luisleo526 deleted the fix/skip-expr-local-vardecl-drop branch June 28, 2026 08:17
luisleo526 added a commit that referenced this pull request Oct 4, 2026
releases[1.1.0] now names pineforge-parity-baseline-20261004-engine-7b596622
(engine 7b596622, the merge of engine #325, with this repository at
c5d97ee): 7,951 excellent / 38 strong of 7,989. The README's markers are
re-rendered from that facts file (pineforge-release #24), and the
changelog's documentation bullet names the baseline in place of
20261003-engine-dbd17b38. The README's release sentence says the release
"grades", as the engine README does, since 1.1.0 is the current release.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
luisleo526 added a commit that referenced this pull request Oct 4, 2026
releases[1.1.0] now names pineforge-parity-baseline-20261004-engine-7b596622
(engine 7b596622, the merge of engine #325, with this repository at
c5d97ee): 7,951 excellent / 38 strong of 7,989. The README's markers are
re-rendered from that facts file (pineforge-release #24), and the
changelog's documentation bullet names the baseline in place of
20261003-engine-dbd17b38. The README's release sentence says the release
"grades", as the engine README does, since 1.1.0 is the current release.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
luisleo526 added a commit that referenced this pull request Oct 4, 2026
* docs: changelog and version scoping for 1.1.0

1.1.0 pairs with engine v1.1.0, whose pineforge.h declares the six
checked settings functions (engine #317) that the C++ of codegen 1.1.0
defines (#159). The changelog section covers #159 and #160: the checked
settings functions, the exception handling at the C ABI and the latched
setter failure, the input.enum default that came out as the enum's first
member, the names reserved for the settings code, the pairing and the
migration step. The Python and JSON contract does not change; the
engine's Docker harness adds applied_runtime.syminfo and two failure
messages for syminfo.mincontract (engine #322).

The README, AGENTS.md / CLAUDE.md, CONTRIBUTING.md,
docs/PUBLIC_CONTRACT.md and docs/pine-cap-activation.md name 1.1.0 where
they named 1.0.1 as the current release or pair, and the pairing table
gets a 1.1.0 row. The release scoreboard sentence renders
releases[1.1.0] from the facts file; the active scoreboard moves to
baseline pineforge-parity-baseline-20261003-engine-dbd17b38. The
anomalies sentence no longer starts its line with a facts marker, so
GitHub keeps it out of a raw HTML block.

Measured for 1.1.0: the engine's 325 corpus sources and the 277 gate
fixtures transpile, with the settings code removed, to 1.0.1's C++ byte
for byte (13 refusals, same messages), each in under 0.1 s on CPython
3.14.6 on an Apple M4 Max. The tutorial run of the quick-start C++
against engine e9f78a6f (Linux x86_64, GCC 13) prints 9 trades and
+738.20, and 13 trades with the old sizing declared.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* docs: correct the 1.1.0 notes against the code

A review of every claim against #159's code and tests and the engine at
main found these:

- transpile_full()'s inputs and transpile_json report the folded enum
  member as the default of an input.enum whose default is a variable,
  where 1.0.1 reported null: the contract keeps its shape, one value
  changes;
- the enum fold needs a variable set to a literal member, and the C++
  beyond the settings code changes for the fold and the renamed names;
- the receipt gives min, max and step as numbers or null;
- #322 leaves a gridless report's bytes as they were apart from
  elapsed_seconds, but across 1.0.1 and 1.1.0 the fingerprint records the
  versions and the generated C++'s hash, and engine #315 and #316 can
  change trades; the second mincontract message is for a library without
  strategy_set_syminfo_metadata; the fingerprint field is
  fingerprint.provenance.runtime.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* docs: rewrap a changelog line

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* docs: the harness symbol feeds and #162 in the 1.1.0 notes

The engine's Docker harness gains --symbol-feeds (PINEFORGE_SYMBOL_FEEDS
in the hub image; engine #327, pineforge-release #23), which installs
other symbols' bars for request.security through C ABI calls that exist
since 1.0.0, so the generated C++ does not change. Its report key
applied_runtime.symbol_feeds and its failure output join the report-key
notes. The documentation bullet names #162, merged since.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* docs: render 1.1.0's grades from its re-mapped baseline

releases[1.1.0] now names pineforge-parity-baseline-20261004-engine-7b596622
(engine 7b596622, the merge of engine #325, with this repository at
c5d97ee): 7,951 excellent / 38 strong of 7,989. The README's markers are
re-rendered from that facts file (pineforge-release #24), and the
changelog's documentation bullet names the baseline in place of
20261003-engine-dbd17b38. The README's release sentence says the release
"grades", as the engine README does, since 1.1.0 is the current release.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* docs: fold request discovery (#164) into the 1.1.0 notes

#164 merged with an Unreleased changelog section and "(unreleased)"
wording; it ships in 1.1.0. Its Request discovery section moves into
1.1.0 with the pull request's link, and the lead names #164 and #162.
The compatibility note no longer says the Python and JSON contract keeps
its result keys: it is additive (transpile_full() and the JSON success
envelope gain requests, input.symbol manifest entries gain kind), nothing
is removed or renamed, and #159's changed enum default stays. #164's
own note joins it: its emitted C++ is unchanged over the engine's 325
corpus sources and the 540 test fixtures, each in a fresh process (51
refused with the same message), which this branch re-checked.

README.md and docs/PUBLIC_CONTRACT.md name 1.1.0 where #164 wrote
"(unreleased)" or "Development builds"; the contract's heading is now
"Request discovery", the anchor the changelog links. The contract's
result-key table, success envelope example and manifest paragraph list
requests and kind, which the error envelope does not carry.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
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