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: DELAY N / SMOOTH N require a compile-time-constant order -- non-constant/parameterized order -> UnknownBuiltin (blocks full simulation of thyroid-2008-d and any dynamic-order delay/smooth) #562
The Simlin engine's DELAY N / SMOOTH N support requires a compile-time-constant order argument. src/simlin-engine/src/builtins_visitor.rs::rewrite_alias_module_call (lines 84-127) selects the concrete stdlib model to instantiate by reading the value of the order argument via parse_module_order_arg (lines 74-82), which only accepts an Expr0::Const:
If the order is any non-constant expression -- a variable, a macro port/parameter, MAX(1, Delay Order), etc. -- parse_module_order_arg returns None, rewrite_alias_module_call cannot resolve the call to a stdlib model, and the call surfaces as UnknownBuiltin. (Even a constant order other than 1 or 3 hits the _ => UnknownBuiltin arm, but the primary gap reported here is the non-constant case.)
Scope: this is a pre-existing, orthogonal engine limitation -- NOT a macro bug
This is not a macro defect and was not introduced by the Vensim macro support epic (docs/implementation-plans/2026-05-13-macros/). The identical failure occurs for a plain main-model equation with no macros involved:
x = DELAY N(in, dt, init, order) // `order` a non-constant variable -> UnknownBuiltin
It only surfaced during the Phase 7 #554-follow-up fix (the delayn macro-collision fix, commit 029cf97f): test/metasd/thyroid-dynamics/thyroid-2008-d.mdl defines :MACRO: DELAYN(Input,DelayTime,Init,Order) ... DELAYN = DELAY N(Input,DelayTime,Init,Order) and invokes it as DELAYN(TSH, tau, TSH, MAX(1, Delay Order)), passing a non-constant order. The macro template body therefore cannot resolve DELAY N to a stdlib model and emits an in-body UnknownBuiltin.
The macro epic's Phase 7 metasd expansion tier correctly tolerates this: the resulting UnknownBuiltin is confined to the macro body and is non-macro-attributable, so thyroid-2008-d PASSES the expansion tier (macros.AC6.4 is satisfied). This limitation gates no macro acceptance criterion. It only blocks full simulation of thyroid (and of any model using DELAY N / SMOOTH N with a dynamic/parameterized order), and no metasd macro model is currently simulation-tier-eligible anyway (that broader gap is tracked separately under #561). This issue records the deferred engine-capability gap so it is not silently lost.
Why it matters
Builtin coverage / correctness: DELAY N / SMOOTH N with a variable or parameterized order is valid Vensim and appears in real-world SD models (and naturally in macros that take the order as a parameter, e.g. thyroid's DELAYN). Such models cannot simulate at all in Simlin today; the call dead-ends at UnknownBuiltin.
Test corpus reach: blocks full simulation of test/metasd/thyroid-dynamics/thyroid-2008-d.mdl (and any similar model), reducing end-to-end numeric validation reach.
Confusing signal: the importer accepts DELAY N / SMOOTH N, but a non-constant order yields a generic UnknownBuiltin on a function the engine otherwise recognizes, rather than a clear "dynamic-order delay unsupported" diagnostic.
Components affected
src/simlin-engine/src/builtins_visitor.rs lines 74-82 (parse_module_order_arg) and lines 84-127 (rewrite_alias_module_call) -- the compile-time constant-order-to-stdlib-model selection
src/simlin-engine/src/compiler/, src/simlin-engine/src/bytecode.rs, src/simlin-engine/src/vm.rs -- if remediated via a runtime ring-buffer / order-parameterized N-th order delay/smooth instead of compile-time delay1/delay3 (smth1/smth3) selection
stdlib (src/simlin-engine/stdlib/*.stmx) -- if remediated via an order-parameterized stdlib model
Recommended remediation (not to perform now)
Support a dynamic / order-parameterized N-th order delay and smooth rather than compile-time selection between delay1/delay3 (smth1/smth3) from a constant order argument. Two candidate approaches:
An order-parameterized stdlib model that accepts the order as an input port and internally generalizes the delay1/delay3 structure.
In either case, also emit a clearer diagnostic than bare UnknownBuiltin when a dynamic-order delay/smooth cannot be lowered.
Where this is documented in-tree (so it is not silently lost)
src/simlin-engine/tests/metasd_macros.rs -- thyroid's SimTier skip reason annotates this blocker
The issue_554_followup_thyroid_shape_* test pins thyroid's shape/expansion behavior with this limitation present
Context
Identified during Phase 7 Task 2 of the Vensim macro support epic (docs/implementation-plans/2026-05-13-macros/), specifically while landing the #554-follow-up delayn macro-collision fix (commit 029cf97f). Out of scope for the macro epic; tracked here as a deferred general-engine capability gap.
Related: #561 (metasd macro simulation-tier enablement umbrella -- this is one of the per-model non-macro blockers it defers to individual tracking; cross-reference, do not duplicate), #554 (the delayn/INIT recursion false-positive follow-up that surfaced this), #560 (a sibling unrelated builtin-coverage gap: stochastic builtins), #346 (DELAY FIXED ring-buffer -- a different builtin and a different defect: fixed-pipeline-delay approximation, not dynamic order; distinct, cross-referenced only to disambiguate).
Problem
The Simlin engine's
DELAY N/SMOOTH Nsupport requires a compile-time-constant order argument.src/simlin-engine/src/builtins_visitor.rs::rewrite_alias_module_call(lines 84-127) selects the concrete stdlib model to instantiate by reading the value of the order argument viaparse_module_order_arg(lines 74-82), which only accepts anExpr0::Const:rewrite_alias_module_callthen maps the constant order to a fixed stdlib model:If the order is any non-constant expression -- a variable, a macro port/parameter,
MAX(1, Delay Order), etc. --parse_module_order_argreturnsNone,rewrite_alias_module_callcannot resolve the call to a stdlib model, and the call surfaces asUnknownBuiltin. (Even a constant order other than 1 or 3 hits the_ => UnknownBuiltinarm, but the primary gap reported here is the non-constant case.)Scope: this is a pre-existing, orthogonal engine limitation -- NOT a macro bug
This is not a macro defect and was not introduced by the Vensim macro support epic (
docs/implementation-plans/2026-05-13-macros/). The identical failure occurs for a plainmain-model equation with no macros involved:It only surfaced during the Phase 7 #554-follow-up fix (the
delaynmacro-collision fix, commit029cf97f):test/metasd/thyroid-dynamics/thyroid-2008-d.mdldefines:MACRO: DELAYN(Input,DelayTime,Init,Order) ... DELAYN = DELAY N(Input,DelayTime,Init,Order)and invokes it asDELAYN(TSH, tau, TSH, MAX(1, Delay Order)), passing a non-constant order. The macro template body therefore cannot resolveDELAY Nto a stdlib model and emits an in-bodyUnknownBuiltin.The macro epic's Phase 7 metasd expansion tier correctly tolerates this: the resulting
UnknownBuiltinis confined to the macro body and is non-macro-attributable, sothyroid-2008-dPASSES the expansion tier (macros.AC6.4 is satisfied). This limitation gates no macro acceptance criterion. It only blocks full simulation of thyroid (and of any model usingDELAY N/SMOOTH Nwith a dynamic/parameterized order), and no metasd macro model is currently simulation-tier-eligible anyway (that broader gap is tracked separately under #561). This issue records the deferred engine-capability gap so it is not silently lost.Why it matters
DELAY N/SMOOTH Nwith a variable or parameterized order is valid Vensim and appears in real-world SD models (and naturally in macros that take the order as a parameter, e.g. thyroid'sDELAYN). Such models cannot simulate at all in Simlin today; the call dead-ends atUnknownBuiltin.test/metasd/thyroid-dynamics/thyroid-2008-d.mdl(and any similar model), reducing end-to-end numeric validation reach.DELAY N/SMOOTH N, but a non-constant order yields a genericUnknownBuiltinon a function the engine otherwise recognizes, rather than a clear "dynamic-order delay unsupported" diagnostic.Components affected
src/simlin-engine/src/builtins_visitor.rslines 74-82 (parse_module_order_arg) and lines 84-127 (rewrite_alias_module_call) -- the compile-time constant-order-to-stdlib-model selectionsrc/simlin-engine/src/compiler/,src/simlin-engine/src/bytecode.rs,src/simlin-engine/src/vm.rs-- if remediated via a runtime ring-buffer / order-parameterized N-th order delay/smooth instead of compile-timedelay1/delay3(smth1/smth3) selectionsrc/simlin-engine/stdlib/*.stmx) -- if remediated via an order-parameterized stdlib modelRecommended remediation (not to perform now)
Support a dynamic / order-parameterized N-th order delay and smooth rather than compile-time selection between
delay1/delay3(smth1/smth3) from a constant order argument. Two candidate approaches:delay1/delay3structure.In either case, also emit a clearer diagnostic than bare
UnknownBuiltinwhen a dynamic-order delay/smooth cannot be lowered.Where this is documented in-tree (so it is not silently lost)
src/simlin-engine/tests/metasd_macros.rs-- thyroid'sSimTierskip reason annotates this blockerissue_554_followup_thyroid_shape_*test pins thyroid's shape/expansion behavior with this limitation presentContext
Identified during Phase 7 Task 2 of the Vensim macro support epic (
docs/implementation-plans/2026-05-13-macros/), specifically while landing the #554-follow-updelaynmacro-collision fix (commit029cf97f). Out of scope for the macro epic; tracked here as a deferred general-engine capability gap.Related: #561 (metasd macro simulation-tier enablement umbrella -- this is one of the per-model non-macro blockers it defers to individual tracking; cross-reference, do not duplicate), #554 (the
delayn/INIT recursion false-positive follow-up that surfaced this), #560 (a sibling unrelated builtin-coverage gap: stochastic builtins), #346 (DELAY FIXED ring-buffer -- a different builtin and a different defect: fixed-pipeline-delay approximation, not dynamic order; distinct, cross-referenced only to disambiguate).