diff --git a/packages/compile/src/generate/gen-code-c.spec.ts b/packages/compile/src/generate/gen-code-c.spec.ts index 88c330e9..594d7043 100644 --- a/packages/compile/src/generate/gen-code-c.spec.ts +++ b/packages/compile/src/generate/gen-code-c.spec.ts @@ -63,7 +63,68 @@ describe('generateCode (Vensim -> C)', () => { y = :NOT: x ~~| ` const code = readInlineModelAndGenerateC(mdl) - expect(code).toMatch('#include "sde.h"') + expect(code).toMatch(`\ +#include "sde.h" + +// Model variables +double _x; +double _y;`) + }) + + it('should work when valid input variable name without subscript is provided in spec file', () => { + const mdl = ` + x = 10 ~~| + y = x + 1 ~~| + ` + const code = readInlineModelAndGenerateC(mdl, { + inputVarNames: ['x'], + outputVarNames: ['y'] + }) + expect(code).toMatch(`\ +#include "sde.h" + +// Model variables +double _x; +double _y;`) + }) + + it('should work when valid input variable name with subscript (referenced by output variable) is provided in spec file', () => { + const mdl = ` + DimA: A1, A2 ~~| + A[DimA] = 10, 20 ~~| + B[DimA] = A[DimA] + 1 ~~| + ` + const code = readInlineModelAndGenerateC(mdl, { + inputVarNames: ['A[A1]'], + outputVarNames: ['B[A1]', 'B[A2]'] + }) + expect(code).toMatch(`\ +#include "sde.h" + +// Model variables +double _a[2]; +double _b[2];`) + }) + + it('should work when valid input variable name with subscript (not referenced by output variable) is provided in spec file', () => { + // Note that `A` is specified as an input variable, but `A` is not referenced by output + // variable `B`, which is an unusual (but valid) usage scenario, so `A` should not be + // pruned by the `removeUnusedVariables` code (see #438) + const mdl = ` + DimA: A1, A2 ~~| + A[DimA] = 10, 20 ~~| + B[DimA] = 30, 40 ~~| + ` + const code = readInlineModelAndGenerateC(mdl, { + inputVarNames: ['A[A1]'], + outputVarNames: ['B[A1]', 'B[A2]'] + }) + expect(code).toMatch(`\ +#include "sde.h" + +// Model variables +double _a[2]; +double _b[2];`) }) it('should throw error when unknown input variable name is provided in spec file', () => { diff --git a/packages/compile/src/generate/gen-equation-c.spec.ts b/packages/compile/src/generate/gen-equation-c.spec.ts index 9ce59fd2..eee09a87 100644 --- a/packages/compile/src/generate/gen-equation-c.spec.ts +++ b/packages/compile/src/generate/gen-equation-c.spec.ts @@ -743,6 +743,24 @@ describe('generateEquation (Vensim -> C)', () => { expect(genC(vars.get('_b'), 'init-constants')).toEqual(['_b = 30.0;']) }) + it('should work when valid input variable name with subscript is provided in spec file', () => { + const vars = readInlineModel( + ` + DimA: A1, A2 ~~| + A[DimA] = 10, 20 ~~| + B[DimA] = A[DimA] + 1 ~~| + `, + { + inputVarNames: ['A[A1]'], + outputVarNames: ['B[A1]', 'B[A2]'] + } + ) + expect(vars.size).toBe(3) + expect(genC(vars.get('_a[_a1]'), 'init-constants')).toEqual(['_a[0] = 10.0;']) + expect(genC(vars.get('_a[_a2]'), 'init-constants')).toEqual(['_a[1] = 20.0;']) + expect(genC(vars.get('_b'), 'eval')).toEqual(['for (size_t i = 0; i < 2; i++) {', '_b[i] = _a[i] + 1.0;', '}']) + }) + it('should throw error when unknown input variable name is provided in spec file', () => { expect(() => readInlineModel( diff --git a/packages/compile/src/model/model.js b/packages/compile/src/model/model.js index 55acb4ba..9d161fd1 100644 --- a/packages/compile/src/model/model.js +++ b/packages/compile/src/model/model.js @@ -471,7 +471,11 @@ function removeUnusedVariables(spec) { // Keep all input variables for (const inputVarName of spec.inputVars) { - for (const v of varsWithName(inputVarName)) { + // The inputVars can include a raw index, e.g. `_input_var[0]`, + // which isn't an actual "ref id", so we'll just derive the + // var name by chopping off the index part. + const inputVarBaseName = inputVarName.split('[')[0] + for (const v of varsWithName(inputVarBaseName)) { recordUsedVariable(v) } }