@sdeverywhere/compile 0.7.20 → 0.7.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -4
- package/src/_shared/helpers.js +8 -39
- package/src/_shared/subscript.js +1 -23
- package/src/generate/gen-const-list.js +9 -19
- package/src/generate/gen-equation.js +109 -73
- package/src/generate/gen-expr.js +67 -24
- package/src/generate/loop-index-vars.js +12 -0
- package/src/index.js +5 -1
- package/src/model/model.js +2 -6
- package/src/model/read-equation-fn-delay.js +55 -29
- package/src/model/read-equation-fn-game.js +2 -2
- package/src/model/read-equation-fn-npv.js +10 -3
- package/src/model/read-equation-fn-smooth.js +15 -8
- package/src/model/read-equation-fn-trend.js +6 -2
- package/src/model/read-equation-fn-with-lookup.js +1 -1
- package/src/model/read-equations.js +273 -119
- package/src/model/read-variables.js +13 -21
- package/src/parse-and-generate.js +10 -15
- package/src/preprocess/preprocessor.js +0 -247
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { isDimension } from '../_shared/subscript.js'
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Mapping of dimension IDs to loop index variables. The `indexVars` is an array
|
|
5
|
+
* of C/JS loop index variable names that will be generated. For example, suppose
|
|
6
|
+
* `indexVars` is ['i', 'j', 'k'] and we have an equation:
|
|
7
|
+
* x[DimA, DimB, DimC] = y[DimB, DimC, DimA] ~~|
|
|
8
|
+
* This class will map the index variables according to the order in which the
|
|
9
|
+
* `index` method is called:
|
|
10
|
+
* const vars = new LoopIndexVars(['i', 'j', 'k'])
|
|
11
|
+
* vars.index('_dima') // returns 'i'
|
|
12
|
+
* vars.index('_dimb') // returns 'j'
|
|
13
|
+
* vars.index('_dimc') // returns 'k'
|
|
14
|
+
*/
|
|
3
15
|
export default class LoopIndexVars {
|
|
4
16
|
constructor(indexVars) {
|
|
5
17
|
this.loopIndexVars = this.loopIndexVarGen(indexVars)
|
package/src/index.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// Copyright (c) 2022 Climate Interactive / New Venture Fund
|
|
2
2
|
|
|
3
|
+
// XXX: For now we re-export the preprocess function from the parse package
|
|
4
|
+
// mainly for use by the cli package (so that we don't need to have the cli
|
|
5
|
+
// package directly depend on the parse package)
|
|
6
|
+
export { preprocessVensimModel } from '@sdeverywhere/parse'
|
|
7
|
+
|
|
3
8
|
export { canonicalName } from './_shared/helpers.js'
|
|
4
9
|
export { readDat } from './_shared/read-dat.js'
|
|
5
|
-
export { preprocessModel } from './preprocess/preprocessor.js'
|
|
6
10
|
export { generateCode } from './generate/gen-code.js'
|
|
7
11
|
export { parseAndGenerate, parseModel, printNames } from './parse-and-generate.js'
|
|
8
12
|
|
package/src/model/model.js
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
indexNamesForSubscript,
|
|
11
11
|
isDimension,
|
|
12
12
|
isIndex,
|
|
13
|
-
normalizeSubscripts,
|
|
14
13
|
sub,
|
|
15
14
|
subscriptFamilies
|
|
16
15
|
} from '../_shared/subscript.js'
|
|
@@ -465,7 +464,7 @@ function findNonAtoAVars() {
|
|
|
465
464
|
// Find variables with multiple instances with the same var name, which makes them
|
|
466
465
|
// elements in a non-apply-to-all array. This function constructs the nonAtoANames list.
|
|
467
466
|
function areSubsEqual(vars, i) {
|
|
468
|
-
// Scan the subscripts for each var at position i in
|
|
467
|
+
// Scan the subscripts for each var at position i in the original order.
|
|
469
468
|
// Return true if the subscript is the same for all vars with that name.
|
|
470
469
|
let subscript = vars[0].subscripts[i]
|
|
471
470
|
for (let v of vars) {
|
|
@@ -478,7 +477,7 @@ function findNonAtoAVars() {
|
|
|
478
477
|
R.forEach(name => {
|
|
479
478
|
let vars = varsWithName(name)
|
|
480
479
|
if (vars.length > 1) {
|
|
481
|
-
// This is a non-apply-to-all array. Construct the
|
|
480
|
+
// This is a non-apply-to-all array. Construct the expansion dims array for it.
|
|
482
481
|
// The expansion dim is true at each dim position where the subscript varies.
|
|
483
482
|
let numDims = vars[0].subscripts.length
|
|
484
483
|
let expansionDims = []
|
|
@@ -665,8 +664,6 @@ function splitRefId(refId) {
|
|
|
665
664
|
varName = m[0]
|
|
666
665
|
}
|
|
667
666
|
}
|
|
668
|
-
// Put subscripts in normal order.
|
|
669
|
-
subscripts = normalizeSubscripts(subscripts)
|
|
670
667
|
return { varName, subscripts }
|
|
671
668
|
}
|
|
672
669
|
function varWithName(varName) {
|
|
@@ -744,7 +741,6 @@ function cName(vensimVarName) {
|
|
|
744
741
|
if (matches[2]) {
|
|
745
742
|
// The variable name includes subscripts, so split them into individual IDs
|
|
746
743
|
let cSubIds = matches[2].split(',').map(x => canonicalName(x))
|
|
747
|
-
cSubIds = normalizeSubscripts(cSubIds)
|
|
748
744
|
// If a subscript is an index, convert it to an index number to match Vensim data exports
|
|
749
745
|
let cSubIdParts = cSubIds.map(cSubId => {
|
|
750
746
|
return isIndex(cSubId) ? `[${sub(cSubId).value}]` : `[${cSubId}]`
|
|
@@ -81,12 +81,13 @@ export function generateDelayVariables(v, callExpr, context) {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Generate a single level variable that is used to implement a `DELAY`
|
|
84
|
+
* Generate equation text for a single level variable that is used to implement a `DELAY`
|
|
85
|
+
* function call, and add a reference to `levelRefId`.
|
|
85
86
|
*/
|
|
86
87
|
function generateDelayLevel(context, levelLHS, levelRefId, input, aux, init) {
|
|
87
88
|
const levelEqn = `${levelLHS} = INTEG(${input} - ${aux}, ${init}) ~~|`
|
|
88
|
-
context.defineVariable(levelEqn)
|
|
89
89
|
context.addVarReference(levelRefId)
|
|
90
|
+
return levelEqn
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
//
|
|
@@ -94,7 +95,8 @@ function generateDelayLevel(context, levelLHS, levelRefId, input, aux, init) {
|
|
|
94
95
|
//
|
|
95
96
|
|
|
96
97
|
/**
|
|
97
|
-
*
|
|
98
|
+
* Generate and define variables that are needed to implement a `DELAY1[I]` function call
|
|
99
|
+
* for a non-subscripted or apply-to-all variable.
|
|
98
100
|
*/
|
|
99
101
|
function generateDelay1VarsForNormalVar(v, context, subs, argInput, argDelay, argInit) {
|
|
100
102
|
// Generate a single level variable instance
|
|
@@ -103,17 +105,23 @@ function generateDelay1VarsForNormalVar(v, context, subs, argInput, argDelay, ar
|
|
|
103
105
|
const levelVarRefId = canonicalName(levelVarBaseName)
|
|
104
106
|
const levelLHS = `${levelVarBaseName}${subs}`
|
|
105
107
|
|
|
108
|
+
// Generate the equation text for the delay level variable
|
|
109
|
+
const eqns = []
|
|
106
110
|
// TODO: There should be parens around the factors in this init expression
|
|
107
111
|
const argInitTimesDelay = `${argInit} * ${argDelay}`
|
|
108
|
-
generateDelayLevel(context, levelLHS, levelVarRefId, argInput, varLHS, argInitTimesDelay)
|
|
112
|
+
eqns.push(generateDelayLevel(context, levelLHS, levelVarRefId, argInput, varLHS, argInitTimesDelay))
|
|
109
113
|
v.delayVarRefId = levelVarRefId
|
|
110
114
|
|
|
111
115
|
// Generate an aux variable to hold the delay time expression
|
|
112
|
-
generateDelay1Aux(v, context, subs, argDelay)
|
|
116
|
+
eqns.push(generateDelay1Aux(v, context, subs, argDelay))
|
|
117
|
+
|
|
118
|
+
// Add the generated variables to the model
|
|
119
|
+
context.defineVariables(eqns)
|
|
113
120
|
}
|
|
114
121
|
|
|
115
122
|
/**
|
|
116
|
-
*
|
|
123
|
+
* Generate and define variables that are needed to implement a `DELAY1[I]` function call
|
|
124
|
+
* for a non-apply-to-all variable.
|
|
117
125
|
*/
|
|
118
126
|
function generateDelay1VarsForSeparatedVar(v, context, subs, argInput, argDelay, argInit) {
|
|
119
127
|
// XXX: This code that deals with separated variables is largely copied from the legacy
|
|
@@ -151,17 +159,23 @@ function generateDelay1VarsForSeparatedVar(v, context, subs, argInput, argDelay,
|
|
|
151
159
|
const levelVarRefId = canonicalVensimName(levelLHS)
|
|
152
160
|
Model.addNonAtoAVar(canonicalName(levelVarBaseName), [true])
|
|
153
161
|
|
|
162
|
+
// Generate the equation text for the delay level variable
|
|
163
|
+
const eqns = []
|
|
154
164
|
// TODO: There should be parens around the factors in this init expression
|
|
155
165
|
const argInitTimesDelay = `${argInit} * ${argDelay}`
|
|
156
|
-
generateDelayLevel(context, levelLHS, levelVarRefId, argInput, varLHS, argInitTimesDelay)
|
|
166
|
+
eqns.push(generateDelayLevel(context, levelLHS, levelVarRefId, argInput, varLHS, argInitTimesDelay))
|
|
157
167
|
v.delayVarRefId = levelVarRefId
|
|
158
168
|
|
|
159
169
|
// Generate an aux variable to hold the delay time expression
|
|
160
|
-
generateDelay1Aux(v, context, subs, argDelay)
|
|
170
|
+
eqns.push(generateDelay1Aux(v, context, subs, argDelay))
|
|
171
|
+
|
|
172
|
+
// Add the generated variables to the model
|
|
173
|
+
context.defineVariables(eqns)
|
|
161
174
|
}
|
|
162
175
|
|
|
163
176
|
/**
|
|
164
|
-
*
|
|
177
|
+
* Generate equation text for a single "delay time" aux variable that is used to implement
|
|
178
|
+
* a `DELAY1[I]` function call, and add a reference to the delay time variable.
|
|
165
179
|
*/
|
|
166
180
|
function generateDelay1Aux(v, context, subs, argDelay) {
|
|
167
181
|
const delayTimeVarName = newAuxVarName()
|
|
@@ -176,8 +190,8 @@ function generateDelay1Aux(v, context, subs, argDelay) {
|
|
|
176
190
|
}
|
|
177
191
|
|
|
178
192
|
const delayTimeEqn = `${delayTimeLHS} = ${argDelay} ~~|`
|
|
179
|
-
context.defineVariable(delayTimeEqn)
|
|
180
193
|
context.addVarReference(delayTimeVarRefId)
|
|
194
|
+
return delayTimeEqn
|
|
181
195
|
}
|
|
182
196
|
|
|
183
197
|
//
|
|
@@ -185,7 +199,8 @@ function generateDelay1Aux(v, context, subs, argDelay) {
|
|
|
185
199
|
//
|
|
186
200
|
|
|
187
201
|
/**
|
|
188
|
-
*
|
|
202
|
+
* Generate and define variables that are needed to implement a `DELAY3[I]` function call
|
|
203
|
+
* for a non-subscripted or apply-to-all variable.
|
|
189
204
|
*/
|
|
190
205
|
function generateDelay3VarsForNormalVar(v, context, subs, argInput, argDelay, argInit) {
|
|
191
206
|
// Generate names for the 3 level variables and 4 aux variables
|
|
@@ -208,28 +223,33 @@ function generateDelay3VarsForNormalVar(v, context, subs, argInput, argDelay, ar
|
|
|
208
223
|
const level3RefId = canonicalName(level3)
|
|
209
224
|
|
|
210
225
|
// Generate level variables
|
|
226
|
+
const eqns = []
|
|
211
227
|
const delay3Val = `((${argDelay}) / 3)`
|
|
212
228
|
// TODO: There should be parens around these factors
|
|
213
229
|
const initArg = `${argInit} * ${delay3Val}`
|
|
214
|
-
generateDelayLevel(context, level3LHS, level3RefId, aux2LHS, aux3LHS, initArg)
|
|
215
|
-
generateDelayLevel(context, level2LHS, level2RefId, aux1LHS, aux2LHS, initArg)
|
|
216
|
-
generateDelayLevel(context, level1LHS, level1RefId, argInput, aux1LHS, initArg)
|
|
230
|
+
eqns.push(generateDelayLevel(context, level3LHS, level3RefId, aux2LHS, aux3LHS, initArg))
|
|
231
|
+
eqns.push(generateDelayLevel(context, level2LHS, level2RefId, aux1LHS, aux2LHS, initArg))
|
|
232
|
+
eqns.push(generateDelayLevel(context, level1LHS, level1RefId, argInput, aux1LHS, initArg))
|
|
217
233
|
v.delayVarRefId = canonicalName(level3)
|
|
218
234
|
|
|
219
235
|
// Generate aux variable equations using the subs in the generated level vars
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
236
|
+
eqns.push(`${aux1LHS} = ${level1LHS} / ${delay3Val} ~~|`)
|
|
237
|
+
eqns.push(`${aux2LHS} = ${level2LHS} / ${delay3Val} ~~|`)
|
|
238
|
+
eqns.push(`${aux3LHS} = ${level3LHS} / ${delay3Val} ~~|`)
|
|
223
239
|
|
|
224
240
|
// Generate an aux variable to hold the delay time expression
|
|
225
241
|
v.delayTimeVarName = canonicalName(aux4)
|
|
226
242
|
const delayTimeVarRefId = canonicalVensimName(aux4LHS)
|
|
227
|
-
|
|
243
|
+
eqns.push(`${aux4LHS} = ${delay3Val} ~~|`)
|
|
228
244
|
context.addVarReference(delayTimeVarRefId)
|
|
245
|
+
|
|
246
|
+
// Add the generated variables to the model
|
|
247
|
+
context.defineVariables(eqns)
|
|
229
248
|
}
|
|
230
249
|
|
|
231
250
|
/**
|
|
232
|
-
*
|
|
251
|
+
* Generate and define variables that are needed to implement a `DELAY3[I]` function call
|
|
252
|
+
* for a non-apply-to-all variable.
|
|
233
253
|
*/
|
|
234
254
|
function generateDelay3VarsForSeparatedVar(v, context, subs, argInput, argDelay, argInit) {
|
|
235
255
|
// XXX: This code that deals with separated variables is largely copied from the legacy
|
|
@@ -290,23 +310,29 @@ function generateDelay3VarsForSeparatedVar(v, context, subs, argInput, argDelay,
|
|
|
290
310
|
Model.addNonAtoAVar(canonicalName(level2), [true])
|
|
291
311
|
Model.addNonAtoAVar(canonicalName(level3), [true])
|
|
292
312
|
|
|
313
|
+
Model.addNonAtoAVar(canonicalName(aux1), [true])
|
|
314
|
+
Model.addNonAtoAVar(canonicalName(aux2), [true])
|
|
315
|
+
Model.addNonAtoAVar(canonicalName(aux3), [true])
|
|
316
|
+
|
|
293
317
|
// Generate level variables
|
|
294
|
-
|
|
295
|
-
generateDelayLevel(context,
|
|
296
|
-
generateDelayLevel(context,
|
|
318
|
+
const eqns = []
|
|
319
|
+
eqns.push(generateDelayLevel(context, level3LHS, level3RefId, aux2LHS, aux3LHS, initArg))
|
|
320
|
+
eqns.push(generateDelayLevel(context, level2LHS, level2RefId, aux1LHS, aux2LHS, initArg))
|
|
321
|
+
eqns.push(generateDelayLevel(context, level1LHS, level1RefId, argInput, aux1LHS, initArg))
|
|
297
322
|
v.delayVarRefId = level3RefId
|
|
298
323
|
|
|
299
324
|
// Generate aux variable equations using the subs in the generated level vars
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
325
|
+
eqns.push(`${aux1LHS} = ${level1LHS} / ${delay3Val} ~~|`)
|
|
326
|
+
eqns.push(`${aux2LHS} = ${level2LHS} / ${delay3Val} ~~|`)
|
|
327
|
+
eqns.push(`${aux3LHS} = ${level3LHS} / ${delay3Val} ~~|`)
|
|
303
328
|
|
|
304
329
|
// Generate an aux variable to hold the delay time expression
|
|
305
330
|
v.delayTimeVarName = canonicalName(aux4)
|
|
306
|
-
|
|
307
|
-
Model.addNonAtoAVar(v.delayTimeVarName, [true])
|
|
308
|
-
}
|
|
331
|
+
Model.addNonAtoAVar(v.delayTimeVarName, [true])
|
|
309
332
|
const delayTimeVarRefId = canonicalVensimName(aux4LHS)
|
|
310
|
-
|
|
333
|
+
eqns.push(`${aux4LHS} = ${delay3Val} ~~|`)
|
|
311
334
|
context.addVarReference(delayTimeVarRefId)
|
|
335
|
+
|
|
336
|
+
// Add the generated variables to the model
|
|
337
|
+
context.defineVariables(eqns)
|
|
312
338
|
}
|
|
@@ -33,9 +33,9 @@ export function generateGameVariables(v, callExpr, context) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Define a variable for the synthesized game inputs lookup
|
|
36
|
-
const gameLookupVars = context.
|
|
36
|
+
const gameLookupVars = context.defineVariables([`${gameLookupVarName}${subs} ~~|`])
|
|
37
37
|
|
|
38
|
-
// Normally `
|
|
38
|
+
// Normally `defineVariables` sets `includeInOutput` to false for generated
|
|
39
39
|
// variables, but we want the generated lookup variable to appear in the
|
|
40
40
|
// model listing so that the user can reference it, so set `includeInOutput`
|
|
41
41
|
// to true. Also change the `varType` to 'lookup' instead of 'data'. We
|
|
@@ -26,6 +26,10 @@ export function generateNpvVariables(v, callExpr, context) {
|
|
|
26
26
|
// const subs = this.genSubs(stream, discountRate, initVal, factor)
|
|
27
27
|
const subs = ''
|
|
28
28
|
|
|
29
|
+
// Build an array of equation strings; variables will be defined for these at the
|
|
30
|
+
// end of this step once all equations are known
|
|
31
|
+
const eqns = []
|
|
32
|
+
|
|
29
33
|
// Level 1:
|
|
30
34
|
// df = INTEG((-df * discount rate) / (1 + discount rate * TIME STEP), 1)
|
|
31
35
|
const dfVarName = newLevelVarName()
|
|
@@ -34,7 +38,7 @@ export function generateNpvVariables(v, callExpr, context) {
|
|
|
34
38
|
// TODO: There should be parens around the `discount rate` argument in case it is an expression
|
|
35
39
|
// and not a simple constant
|
|
36
40
|
const dfEqn = `${dfLHS} = INTEG((-${dfLHS} * ${argDiscountRate}) / (1 + ${argDiscountRate} * TIME STEP), 1) ~~|`
|
|
37
|
-
|
|
41
|
+
eqns.push(dfEqn)
|
|
38
42
|
|
|
39
43
|
// Level 2:
|
|
40
44
|
// ncum = INTEG(stream * df, init val)
|
|
@@ -42,7 +46,7 @@ export function generateNpvVariables(v, callExpr, context) {
|
|
|
42
46
|
const ncumVarId = canonicalName(ncumVarName)
|
|
43
47
|
const ncumLHS = `${ncumVarName}${subs}`
|
|
44
48
|
const ncumEqn = `${ncumLHS} = INTEG(${argStream} * ${dfLHS}, ${argInitVal}) ~~|`
|
|
45
|
-
|
|
49
|
+
eqns.push(ncumEqn)
|
|
46
50
|
|
|
47
51
|
// Aux:
|
|
48
52
|
// npv = (ncum + stream * TIME STEP * df) * factor
|
|
@@ -52,7 +56,7 @@ export function generateNpvVariables(v, callExpr, context) {
|
|
|
52
56
|
// TODO: There should be parens around the `stream` argument in case it is an expression
|
|
53
57
|
// and not a simple constant
|
|
54
58
|
const auxEqn = `${auxLHS} = (${ncumVarName} + ${argStream} * TIME STEP * ${dfVarName}) * ${argFactor} ~~|`
|
|
55
|
-
|
|
59
|
+
eqns.push(auxEqn)
|
|
56
60
|
v.npvVarName = auxVarId
|
|
57
61
|
|
|
58
62
|
// Add references to the generated variables
|
|
@@ -62,6 +66,9 @@ export function generateNpvVariables(v, callExpr, context) {
|
|
|
62
66
|
context.addVarReference(dfVarId)
|
|
63
67
|
context.addVarReference(auxVarId)
|
|
64
68
|
|
|
69
|
+
// Add the generated variables to the model
|
|
70
|
+
context.defineVariables(eqns)
|
|
71
|
+
|
|
65
72
|
// TODO: Check on this comment from the legacy reader to see if it's still applicable:
|
|
66
73
|
// If they have subscripts, the refIds are still just the var name, because they are apply-to-all arrays.
|
|
67
74
|
}
|
|
@@ -45,17 +45,21 @@ export function generateSmoothVariables(v, callExpr, context) {
|
|
|
45
45
|
const fnId = callExpr.fnId
|
|
46
46
|
if (fnId === '_SMOOTH' || fnId === '_SMOOTHI') {
|
|
47
47
|
// Generate 1 level variable that will replace the `SMOOTH[I]` function call
|
|
48
|
-
const
|
|
48
|
+
const level = generateSmoothLevel(v, context, argInput, argDelay, argInit, 1)
|
|
49
49
|
// For `SMOOTH[I]`, the smoothVarRefId is the level var's refId
|
|
50
|
-
v.smoothVarRefId =
|
|
50
|
+
v.smoothVarRefId = level.varRefId
|
|
51
|
+
// Add the generated variable to the model
|
|
52
|
+
context.defineVariables([level.eqn])
|
|
51
53
|
} else {
|
|
52
54
|
// Generate 3 level variables that will replace the `SMOOTH3[I]` function call
|
|
53
55
|
const delay3Val = `(${argDelay} / 3)`
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
56
|
+
const level1 = generateSmoothLevel(v, context, argInput, delay3Val, argInit, 1)
|
|
57
|
+
const level2 = generateSmoothLevel(v, context, level1.varFullName, delay3Val, argInit, 2)
|
|
58
|
+
const level3 = generateSmoothLevel(v, context, level2.varFullName, delay3Val, argInit, 3)
|
|
57
59
|
// For `SMOOTH3[I]`, the smoothVarRefId is the final level var's refId
|
|
58
|
-
v.smoothVarRefId =
|
|
60
|
+
v.smoothVarRefId = level3.varRefId
|
|
61
|
+
// Add the generated variables to the model
|
|
62
|
+
context.defineVariables([level1.eqn, level2.eqn, level3.eqn])
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
|
|
@@ -126,11 +130,14 @@ function generateSmoothLevel(v, context, argInput, argDelay, argInit, levelNumbe
|
|
|
126
130
|
if (isSeparatedVar(v)) {
|
|
127
131
|
Model.addNonAtoAVar(canonicalName(levelVarBaseName), [true])
|
|
128
132
|
}
|
|
129
|
-
context.defineVariable(levelEqn)
|
|
130
133
|
context.addVarReference(levelVarRefId)
|
|
131
134
|
|
|
132
135
|
// The name of the level variable returned here includes the original subscript/dimension names
|
|
133
136
|
// (not the separated subscript names) so that the `argInput` is correct for the 2nd and 3rd levels
|
|
134
137
|
const levelVarFullName = `${levelVarBaseName}${origSubs}`
|
|
135
|
-
return
|
|
138
|
+
return {
|
|
139
|
+
varRefId: levelVarRefId,
|
|
140
|
+
varFullName: levelVarFullName,
|
|
141
|
+
eqn: levelEqn
|
|
142
|
+
}
|
|
136
143
|
}
|
|
@@ -24,12 +24,13 @@ export function generateTrendVariables(v, callExpr, context) {
|
|
|
24
24
|
const subs = context.extractSubscriptsFromVarNames(argInput, argAvgTime, argInitVal)
|
|
25
25
|
|
|
26
26
|
// Generate a level variable that will be used in place of the `TREND` call
|
|
27
|
+
const eqns = []
|
|
27
28
|
const levelVarName = newLevelVarName()
|
|
28
29
|
const levelLHS = `${levelVarName}${subs}`
|
|
29
30
|
// TODO: There should be parens around the arguments in this equation in case any of them
|
|
30
31
|
// is an expression and not a simple constant
|
|
31
32
|
const levelEqn = `${levelLHS} = INTEG((${argInput} - ${levelLHS}) / ${argAvgTime}, ${argInput} / (1 + ${argInitVal} * ${argAvgTime})) ~~|`
|
|
32
|
-
|
|
33
|
+
eqns.push(levelEqn)
|
|
33
34
|
context.addVarReference(canonicalName(levelVarName))
|
|
34
35
|
|
|
35
36
|
// Generate a aux variable that will be used in place of the `TREND` call
|
|
@@ -38,7 +39,10 @@ export function generateTrendVariables(v, callExpr, context) {
|
|
|
38
39
|
// TODO: There should be parens around the arguments in this equation in case any of them
|
|
39
40
|
// is an expression and not a simple constant
|
|
40
41
|
const auxEqn = `${auxLHS} = ZIDZ(${argInput} - ${levelLHS}, ${argAvgTime} * ABS(${levelLHS})) ~~|`
|
|
41
|
-
|
|
42
|
+
eqns.push(auxEqn)
|
|
42
43
|
v.trendVarName = canonicalName(auxVarName)
|
|
43
44
|
context.addVarReference(v.trendVarName)
|
|
45
|
+
|
|
46
|
+
// Add the generated variables to the model
|
|
47
|
+
context.defineVariables(eqns)
|
|
44
48
|
}
|
|
@@ -23,7 +23,7 @@ export function generateLookup(v, callExpr, context) {
|
|
|
23
23
|
const lookupVarName = newLookupVarName()
|
|
24
24
|
const lookupDef = toPrettyString(lookupArg, { compact: true })
|
|
25
25
|
const lookupEqn = `${lookupVarName}${lookupDef} ~~|`
|
|
26
|
-
context.
|
|
26
|
+
context.defineVariables([lookupEqn])
|
|
27
27
|
|
|
28
28
|
// Keep track of all lookup variables that are referenced. This will be used later to decide
|
|
29
29
|
// whether a lookup variable needs to be included in generated code.
|