You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
engine: VECTOR ELM MAP with scalar source + arithmetic (expression) offset fails to compile (no diagnostic) -- narrows the Phase 5 vector.xmile gate #578
VECTOR ELM MAP with a scalar source and an arithmetic (expression) offset fails to compile with NotSimulatable: "failed to compile fragments for variables: y" and no model-level diagnostic (it fails silently at the assembly stage rather than emitting a parse/compile error).
The concrete pattern is in test/sdeverywhere/models/vector/vector.mdl:49 (and the equivalent test/sdeverywhere/models/vector/vector.xmile:40):
Here the source x[three] is a single fully-collapsed element (scalar, not an array view), and the offset (DimA - 1) is an arithmetic Op2(Sub, DimA, 1) dimension-position expression (not a static subscript).
Root cause (verified against the pipeline)
VECTOR ELM MAP derives its result-array shape from the offset argument's view via find_expr_array_view in src/simlin-engine/src/compiler/mod.rs:872-879:
find_expr_array_view only yields a view for Expr::StaticSubscript / Expr::TempArray offsets. For y:
the source x[three] is scalar (no array view), and
the offset (DimA - 1) is an arithmetic expression, so find_expr_array_view returns None for it.
With no view derivable, the hoister never builds the AssignTemp per-element fragment for y, and assembly later reports the missing fragment (silent until the assembly stage, db.rs ~4979-4983). Verified by the Phase 5 spike with a minimal 4-variable repro (DimA, DimX, x[DimX]=1..5, y[DimA] = VECTOR ELM MAP(x[three], (DimA - 1))).
How this differs from already-tracked ELM MAP issues
This is distinct from and larger than the closed cross-dimension ELM MAP work and the Phase 5 VM base+stride correction:
engine: VECTOR ELM MAP with cross-dimension sources fails in compiler #357 (CLOSED, "VECTOR ELM MAP with cross-dimension sources fails in compiler") is about an array-valued source on a different dimension (b[B1] from DimB used in a DimA context) and a dimension-mismatch resolution problem. This issue is the opposite shape: a scalar source plus an arithmetic-expression offset where find_expr_array_view yields no view at all. Different failure, different fix.
The Phase 5 VM base+stride numeric correction (Phase 5 Tasks 2-6, branch clearn-hero-model) fixes the flattened-sliced-view / missing-per-element-base bug for the c/f/g cases (those have an array-valued StaticSubscript offset like a[DimA]/e[DimA,DimB], so they hoist fine). It does not address result-shape inference for an expression offset, per-element expression-offset evaluation, or a scalar-source ELM MAP.
Fixing this requires VECTOR ELM MAP to (a) derive its result shape when the offset is an arbitrary scalar-valued expression evaluated per result element, (b) evaluate the per-element offset (position(DimA) - 1, recomputed for each DimA element) -- the current ELM MAP hoist models only a single whole-array offset view, and (c) support a scalar source broadcast. This touches find_expr_array_view / the expand_arrayed_with_hoisting shape inference in src/simlin-engine/src/compiler/mod.rs (around 872-879 and ~1598-1650), not just the VM view push.
Why it matters / current handling
Phase 5 Task 6 of the element-level cycle resolution work un-excludes test/sdeverywhere/models/vector/vector.xmile as a genuine-Vensim regression gate. Because y does not compile, Phase 5 (following the phase file's own Task 6 guidance -- "prefer full inclusion; only narrow with a tracked issue if a non-ELM-MAP-fixable variable genuinely resists a general fix") will include vector.xmile but narrow the gate to exclude the y variable, with this issue as the tracking reference.
The genuine-Vensim expected output for y (from real-Vensim test/sdeverywhere/models/vector/vector.dat:195-203) is y[A1]=3, y[A2]=4, y[A3]=5. Closing this issue (scalar-source / expression-offset ELM MAP shape inference + per-element offset evaluation) lets y be added back to the gate and the vector.xmile comparison fully un-narrowed.
Components affected
src/simlin-engine/src/compiler/mod.rs -- find_expr_array_view (lines 872-879) and expand_arrayed_with_hoisting shape inference (~1598-1650)
src/simlin-engine/src/compiler/codegen.rs -- ELM MAP source/offset view emission (per-element expression-offset evaluation)
src/simlin-engine/src/vm.rs -- ELM MAP dispatch (if per-element offset evaluation needs a runtime path)
test/sdeverywhere/models/vector/vector.mdl:49 / test/sdeverywhere/models/vector/vector.xmile:40 -- the y definition (fixture)
test/sdeverywhere/models/vector/vector.dat:195-203 -- genuine-Vensim expected y values (y[A1]=3, y[A2]=4, y[A3]=5)
The Phase 5 vector.xmile gate (narrowed to exclude y until this is closed)
Possible approaches
Extend find_expr_array_view (or the surrounding expand_arrayed_with_hoisting shape inference) so an ELM MAP whose offset is a scalar-valued expression derives its result shape from the target iteration dimension (the LHS DimA) rather than only from a StaticSubscript/TempArray offset view.
Add a per-element-evaluated offset path for ELM MAP: evaluate offset once per result element (e.g. position(DimA) - 1 per DimA), instead of modeling only a single whole-array offset view.
Support a scalar source operand for ELM MAP (broadcast / single-element source) so x[three] is a valid source.
Context
Discovered during the Phase 5 Task 1 spike of the element-level cycle resolution work (branch clearn-hero-model; spike commit 00f25d1f). Full analysis and reproduction in docs/implementation-plans/2026-05-18-element-cycle-resolution/phase_05_spike_findings.md (section 6). The spike verified the root cause by reading the compilation pipeline and running a minimal 4-variable repro through the engine with a temporary read-only diagnostic (reverted; no engine code changed by the spike). The now-stale src/simlin-engine/tests/simulate.rs:651-657 exclusion comment flagged this same y pattern but mis-attributed it to the VM incremental path; it actually fails at compile/assembly.
Problem
VECTOR ELM MAPwith a scalar source and an arithmetic (expression) offset fails to compile withNotSimulatable: "failed to compile fragments for variables: y"and no model-level diagnostic (it fails silently at the assembly stage rather than emitting a parse/compile error).The concrete pattern is in
test/sdeverywhere/models/vector/vector.mdl:49(and the equivalenttest/sdeverywhere/models/vector/vector.xmile:40):Here the source
x[three]is a single fully-collapsed element (scalar, not an array view), and the offset(DimA - 1)is an arithmeticOp2(Sub, DimA, 1)dimension-position expression (not a static subscript).Root cause (verified against the pipeline)
VECTOR ELM MAPderives its result-array shape from the offset argument's view viafind_expr_array_viewinsrc/simlin-engine/src/compiler/mod.rs:872-879:find_expr_array_viewonly yields a view forExpr::StaticSubscript/Expr::TempArrayoffsets. Fory:x[three]is scalar (no array view), and(DimA - 1)is an arithmetic expression, sofind_expr_array_viewreturnsNonefor it.With no view derivable, the hoister never builds the
AssignTempper-element fragment fory, and assembly later reports the missing fragment (silent until the assembly stage,db.rs~4979-4983). Verified by the Phase 5 spike with a minimal 4-variable repro (DimA,DimX,x[DimX]=1..5,y[DimA] = VECTOR ELM MAP(x[three], (DimA - 1))).How this differs from already-tracked ELM MAP issues
This is distinct from and larger than the closed cross-dimension ELM MAP work and the Phase 5 VM base+stride correction:
b[B1]from DimB used in a DimA context) and a dimension-mismatch resolution problem. This issue is the opposite shape: a scalar source plus an arithmetic-expression offset wherefind_expr_array_viewyields no view at all. Different failure, different fix.clearn-hero-model) fixes the flattened-sliced-view / missing-per-element-base bug for thec/f/gcases (those have an array-valuedStaticSubscriptoffset likea[DimA]/e[DimA,DimB], so they hoist fine). It does not address result-shape inference for an expression offset, per-element expression-offset evaluation, or a scalar-source ELM MAP.VECTOR SORT ORDERpblock / unverified multi-dim VSO semantics -- a different builtin, variable, and concern. Not related.SUM(VECTOR ELM MAP(...))VM compilation, A2A reduction, builtin nesting, the interpreter->VM port, and 0-vs-1-based indexing -- none cover scalar-source + expression-offset shape inference.Fixing this requires
VECTOR ELM MAPto (a) derive its result shape when the offset is an arbitrary scalar-valued expression evaluated per result element, (b) evaluate the per-element offset (position(DimA) - 1, recomputed for eachDimAelement) -- the current ELM MAP hoist models only a single whole-array offset view, and (c) support a scalar source broadcast. This touchesfind_expr_array_view/ theexpand_arrayed_with_hoistingshape inference insrc/simlin-engine/src/compiler/mod.rs(around 872-879 and ~1598-1650), not just the VM view push.Why it matters / current handling
Phase 5 Task 6 of the element-level cycle resolution work un-excludes
test/sdeverywhere/models/vector/vector.xmileas a genuine-Vensim regression gate. Becauseydoes not compile, Phase 5 (following the phase file's own Task 6 guidance -- "prefer full inclusion; only narrow with a tracked issue if a non-ELM-MAP-fixable variable genuinely resists a general fix") will includevector.xmilebut narrow the gate to exclude theyvariable, with this issue as the tracking reference.The genuine-Vensim expected output for
y(from real-Vensimtest/sdeverywhere/models/vector/vector.dat:195-203) isy[A1]=3, y[A2]=4, y[A3]=5. Closing this issue (scalar-source / expression-offset ELM MAP shape inference + per-element offset evaluation) letsybe added back to the gate and thevector.xmilecomparison fully un-narrowed.Components affected
src/simlin-engine/src/compiler/mod.rs--find_expr_array_view(lines 872-879) andexpand_arrayed_with_hoistingshape inference (~1598-1650)src/simlin-engine/src/compiler/codegen.rs-- ELM MAP source/offset view emission (per-element expression-offset evaluation)src/simlin-engine/src/vm.rs-- ELM MAP dispatch (if per-element offset evaluation needs a runtime path)test/sdeverywhere/models/vector/vector.mdl:49/test/sdeverywhere/models/vector/vector.xmile:40-- theydefinition (fixture)test/sdeverywhere/models/vector/vector.dat:195-203-- genuine-Vensim expectedyvalues (y[A1]=3, y[A2]=4, y[A3]=5)yuntil this is closed)Possible approaches
find_expr_array_view(or the surroundingexpand_arrayed_with_hoistingshape inference) so an ELM MAP whose offset is a scalar-valued expression derives its result shape from the target iteration dimension (the LHSDimA) rather than only from aStaticSubscript/TempArrayoffset view.offsetonce per result element (e.g.position(DimA) - 1perDimA), instead of modeling only a single whole-array offset view.x[three]is a valid source.Context
Discovered during the Phase 5 Task 1 spike of the element-level cycle resolution work (branch
clearn-hero-model; spike commit00f25d1f). Full analysis and reproduction indocs/implementation-plans/2026-05-18-element-cycle-resolution/phase_05_spike_findings.md(section 6). The spike verified the root cause by reading the compilation pipeline and running a minimal 4-variable repro through the engine with a temporary read-only diagnostic (reverted; no engine code changed by the spike). The now-stalesrc/simlin-engine/tests/simulate.rs:651-657exclusion comment flagged this sameypattern but mis-attributed it to the VM incremental path; it actually fails at compile/assembly.