@sdeverywhere/compile 0.7.23 → 0.7.25

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdeverywhere/compile",
3
- "version": "0.7.23",
3
+ "version": "0.7.25",
4
4
  "description": "The core Vensim to C compiler for the SDEverywhere tool suite.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -24,6 +24,8 @@ let nextLevelVarSeq = 1
24
24
  let nextAuxVarSeq = 1
25
25
  // parsed csv data cache
26
26
  let csvData = new Map()
27
+ // parsed xlsx data cache
28
+ let xlsxData = new Map()
27
29
 
28
30
  // Newer versions of the xlsx package require manually setting the `fs` instance
29
31
  // before using the `XLSX.readFile` function
@@ -38,6 +40,7 @@ export function resetHelperState() {
38
40
  nextLevelVarSeq = 1
39
41
  nextAuxVarSeq = 1
40
42
  csvData.clear()
43
+ xlsxData.clear()
41
44
  }
42
45
 
43
46
  export let canonicalName = name => {
@@ -200,7 +203,15 @@ export let isIterable = obj => {
200
203
  }
201
204
  // Command helpers
202
205
  export let readXlsx = pathname => {
203
- return XLSX.readFile(pathname, { cellDates: true })
206
+ // Read the XLSX file at the pathname and parse it.
207
+ // Return a `XLSX.WorkBook` object that can be used to access the data.
208
+ // Cache parsed files to support multiple reads from different equations.
209
+ let xlsx = xlsxData.get(pathname)
210
+ if (!xlsx) {
211
+ xlsx = XLSX.readFile(pathname, { cellDates: true })
212
+ xlsxData.set(pathname, xlsx)
213
+ }
214
+ return xlsx
204
215
  }
205
216
  export let readCsv = (pathname, delimiter = ',') => {
206
217
  // Read the CSV file at the pathname and parse it with the given delimiter.
@@ -208,7 +219,7 @@ export let readCsv = (pathname, delimiter = ',') => {
208
219
  // If there is a header row, it is returned as the first row.
209
220
  // Cache parsed files to support multiple reads from different equations.
210
221
  let csv = csvData.get(pathname)
211
- if (csv == null) {
222
+ if (!csv) {
212
223
  const CSV_PARSE_OPTS = {
213
224
  delimiter,
214
225
  columns: false,
@@ -107,7 +107,7 @@ export function sub(name) {
107
107
  let result
108
108
  try {
109
109
  result = subscripts.get(name)
110
- } catch (e) {
110
+ } catch (_) {
111
111
  console.error(`sub name ${name} not found`)
112
112
  }
113
113
  return result
@@ -249,7 +249,7 @@ export function subscriptFamilies(subscripts) {
249
249
  // Return a list of the subscript families for each subscript.
250
250
  try {
251
251
  return R.map(subscriptName => sub(subscriptName).family, subscripts)
252
- } catch (e) {
252
+ } catch (_) {
253
253
  console.error(`ERROR: subscript not found in "${subscripts.join(',')}" in subscriptFamilies`)
254
254
  }
255
255
  }
@@ -0,0 +1,31 @@
1
+ import { canonicalName } from './helpers.js'
2
+ import { isIndex, sub } from './subscript.js'
3
+
4
+ /**
5
+ * Convert a Vensim variable name to a C name.
6
+ *
7
+ * WARNING: This function requires model analysis to be completed first when the variable
8
+ * has subscripts.
9
+ *
10
+ * @param {string} vensimVarName The full Vensim variable name (can contain subscripts).
11
+ * @returns {string} A canonical C representation of the variable name (e.g., '_variable_name').
12
+ */
13
+ export function cName(vensimVarName) {
14
+ // Split the variable name from the subscripts
15
+ let matches = vensimVarName.match(/([^[]+)(?:\[([^\]]+)\])?/)
16
+ if (!matches) {
17
+ throw new Error(`Invalid variable name '${vensimVarName}' found when converting to C representation`)
18
+ }
19
+ let cVarName = canonicalName(matches[1])
20
+ if (matches[2]) {
21
+ // The variable name includes subscripts, so split them into individual IDs
22
+ let cSubIds = matches[2].split(',').map(x => canonicalName(x))
23
+ // If a subscript is an index, convert it to an index number to match Vensim data exports
24
+ let cSubIdParts = cSubIds.map(cSubId => {
25
+ return isIndex(cSubId) ? `[${sub(cSubId).value}]` : `[${cSubId}]`
26
+ })
27
+ // Append the subscript parts to the base variable name to create the full reference
28
+ cVarName += cSubIdParts.join('')
29
+ }
30
+ return cVarName
31
+ }
@@ -1,16 +1,17 @@
1
1
  import * as R from 'ramda'
2
2
 
3
- import { cartesianProductOf, canonicalName } from '../_shared/helpers.js'
4
- import { sub, isDimension } from '../_shared/subscript.js'
3
+ import { cName } from '../_shared/var-names.js'
5
4
 
5
+ import { expandVar } from '../model/expand-var-instances.js'
6
6
  import Model from '../model/model.js'
7
7
 
8
8
  /**
9
- * Return an array of names for all variable in the model, sorted alphabetically and expanded to
9
+ * Return an array of names for all accessible variables, sorted alphabetically and expanded to
10
10
  * include the full set of subscripted variants for variables that include subscripts.
11
11
  *
12
- * @param canonical If true, convert names to canonical representation (variable identifiers), otherwise
13
- * return the original name of each variable as it appears in the model.
12
+ * @param {*} variables The `Variable` objects to process.
13
+ * @param {boolean} canonical If true, convert names to canonical representation (variable identifiers),
14
+ * otherwise return the original name of each variable as it appears in the model.
14
15
  * @returns {string[]} An array of variable names or identifiers.
15
16
  */
16
17
  export function expandVarNames(canonical) {
@@ -19,10 +20,12 @@ export function expandVarNames(canonical) {
19
20
  R.reduce(
20
21
  (a, v) => {
21
22
  if (v.varType !== 'lookup' && v.varType !== 'data' && v.includeInOutput) {
23
+ const varInstances = expandVar(v)
24
+ const varNames = varInstances.map(instance => instance.varName)
22
25
  if (canonical) {
23
- return R.concat(a, R.map(Model.cName, namesForVar(v)))
26
+ return R.concat(a, R.map(cName, varNames))
24
27
  } else {
25
- return R.concat(a, namesForVar(v))
28
+ return R.concat(a, varNames)
26
29
  }
27
30
  } else {
28
31
  return a
@@ -33,73 +36,3 @@ export function expandVarNames(canonical) {
33
36
  )
34
37
  )
35
38
  }
36
-
37
- /**
38
- * Return an array of names for the given variable including all subscript variants.
39
- *
40
- * @param {*} v A `Variable` instance.
41
- * @returns {string[]} An array of expanded names for the given variable.
42
- */
43
- function namesForVar(v) {
44
- if (v.parsedEqn === undefined) {
45
- // XXX: The special `Time` variable does not have a `parsedEqn`, so use the raw LHS
46
- return [v.modelLHS]
47
- }
48
-
49
- // Expand each variable to get the names of all subscripted variants
50
- const lhsVarDef = v.parsedEqn.lhs.varDef
51
- const lhsSubRefs = lhsVarDef.subscriptRefs
52
- if (lhsSubRefs?.length > 0) {
53
- // At each position, expand any dimensions or use a subscript (index) directly
54
- const subOrDimNames = lhsSubRefs.map(subRef => subRef.subName)
55
- return expandDims(lhsVarDef.varName, subOrDimNames)
56
- } else {
57
- // No subscripts, so include a single variable name
58
- return [lhsVarDef.varName]
59
- }
60
- }
61
-
62
- /**
63
- * Return an array of all expanded subscript combinations.
64
- *
65
- * @param {string} baseVarName The base name of the variable.
66
- * @param {string[]} subOrDimNames The array of subscript or dimension names.
67
- * @returns {string[]} An array of string representations of subscripted references,
68
- * e.g., `'x[A1,B1]' ,'x[A1,B2]', ...]`.
69
- */
70
- function expandDims(baseVarName, subOrDimNames) {
71
- // Expand the dimension for each position
72
- const expanded = subOrDimNames.map(name => expandDim(name).flat(Infinity))
73
-
74
- // Expand these into the set of all combinations of subscripts for the variable
75
- const origCombos = cartesianProductOf(expanded)
76
- return origCombos.map(combo => {
77
- const subs = combo.join(',')
78
- return `${baseVarName}[${subs}]`
79
- })
80
- }
81
-
82
- /**
83
- * Return an array containing all subscript (index) names in the given dimension. If
84
- * the given name is a subscript, it will return a single-element array with that
85
- * subscript name.
86
- *
87
- * @param {string} subOrDimName A subscript or dimension name.
88
- * @returns {string[]} A (possibly nested) array of subscript names.
89
- */
90
- function expandDim(subOrDimName) {
91
- // Convert the name to an ID
92
- const subOrDimId = canonicalName(subOrDimName)
93
-
94
- if (isDimension(subOrDimId)) {
95
- // Get the object for the dimension
96
- const dimObj = sub(subOrDimId)
97
-
98
- // The dimension may contain a mix of individual subscripts (indices) and/or subdimensions,
99
- // so recursively expand them
100
- return dimObj.modelValue.map(expandDim)
101
- } else {
102
- // This is an individual subscript (index), so return it directly
103
- return [subOrDimName]
104
- }
105
- }
@@ -0,0 +1,139 @@
1
+ import { cartesianProductOf, canonicalName } from '../_shared/helpers.js'
2
+ import { isDimension, sub } from '../_shared/subscript.js'
3
+
4
+ /**
5
+ * A single instance of a variable.
6
+ * @typedef {Object} VarInstance
7
+ * @property {string} varName The full name of the variable instance, e.g., "Variable Name[SubA, SubB]".
8
+ * @property {number[]} [subscriptIndices] The array of subscript indices; only defined if this variable
9
+ * has subscripts.
10
+ */
11
+
12
+ /**
13
+ * Return an array of names and subscript indices for the given variable, expanded to
14
+ * include all subscript variants.
15
+ *
16
+ * @param {*} v A `Variable` object.
17
+ * @returns {VarInstance[]} An array of `VarInstance` objects corresponding to the expanded variable.
18
+ */
19
+ export function expandVar(v) {
20
+ if (v.parsedEqn === undefined) {
21
+ // XXX: The special `Time` variable does not have a `parsedEqn`, so use the raw LHS
22
+ return [
23
+ {
24
+ varName: v.modelLHS
25
+ }
26
+ ]
27
+ }
28
+
29
+ // Expand each subscript position to get the names of all subscripted variants
30
+ const lhsVarDef = v.parsedEqn.lhs.varDef
31
+ const lhsSubOrDimIds = v.subscripts
32
+ if (lhsSubOrDimIds === undefined || lhsSubOrDimIds.length === 0) {
33
+ // No subscripts, so include a single variable name
34
+ return [
35
+ {
36
+ varName: lhsVarDef.varName
37
+ }
38
+ ]
39
+ }
40
+
41
+ // At each position, expand any dimensions or use a subscript (index) directly
42
+ return expandDims(lhsVarDef.varName, lhsSubOrDimIds)
43
+ }
44
+
45
+ /**
46
+ * Return an array of all expanded subscript combinations.
47
+ *
48
+ * @param {string} baseVarName The base name of the variable.
49
+ * @param {string[]} subOrDimIds The array of subscript or dimension IDs.
50
+ * @returns {VarInstance[]} An array of `VarInstance` objects with string representations of
51
+ * subscripted references, e.g., `'x[A1,B1]', 'x[A1,B2]', ...`.
52
+ */
53
+ function expandDims(baseVarName, subOrDimIds) {
54
+ // Expand the dimension for each position
55
+ const expanded = subOrDimIds.map(id => expandSubSpecs(id).flat(Infinity))
56
+
57
+ // Expand these into the set of all combinations of subscripts for the variable
58
+ const origCombos = cartesianProductOf(expanded)
59
+ return origCombos.map(combo => {
60
+ const subNames = combo.map(spec => spec.name).join(',')
61
+ const subIndices = combo.map(spec => spec.index)
62
+ return {
63
+ varName: `${baseVarName}[${subNames}]`,
64
+ subscriptIndices: subIndices
65
+ }
66
+ })
67
+ }
68
+
69
+ /**
70
+ * Pairs a subscript name with its index.
71
+ * @typedef {Object} SubSpec
72
+ * @property {string} name The name of the subscript, e.g., "A1".
73
+ * @property {number} index The subscript index relative to its parent dimension.
74
+ */
75
+
76
+ /**
77
+ * Return an array containing all subscript specs in the given dimension. If
78
+ * the given ID is a subscript, it will return a single-element array with that
79
+ * subscript name and index.
80
+ *
81
+ * @param {string} subOrDimId A subscript or dimension ID (e.g., '_a1', '_dima').
82
+ * @returns {SubSpec[]} A (possibly nested) array of `SubSpec` objects.
83
+ */
84
+ function expandSubSpecs(subOrDimId) {
85
+ if (isDimension(subOrDimId)) {
86
+ // Get the object for the dimension
87
+ const dimObj = sub(subOrDimId)
88
+
89
+ // The dimension may contain a mix of individual subscripts (indices) and/or subdimensions,
90
+ // so recursively expand them
91
+ return dimObj.value.map(expandSubSpecs)
92
+ } else {
93
+ // This is an individual subscript (index), so return its name and index value
94
+ // XXX: Currently, the object returned by `sub` will not include the `modelName`
95
+ // for subscripts (it's only defined for dimensions?), so if we don't have the
96
+ // `modelName`, find it using the parent dimension object. This could be avoided
97
+ // if subscript objects maintained their original model name.
98
+ const subObj = sub(subOrDimId)
99
+ const dimSubNames = expandSubNamesForDim(subObj.family).flat(Infinity)
100
+ const subName = dimSubNames[subObj.value]
101
+ if (subName === undefined) {
102
+ throw new Error(`Failed to resolve name of subscript ${subOrDimId} in dimension ${subObj.family}`)
103
+ }
104
+ return [
105
+ {
106
+ name: subName,
107
+ index: subObj.value
108
+ }
109
+ ]
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Return an array containing all subscript (index) names in the given dimension,
115
+ * expanding subdimensions as needed. If the given ID is a subscript, it will return
116
+ * single-element array with that subscript name.
117
+ *
118
+ * @param {string} dimId A dimension ID (e.g., '_dima').
119
+ * @returns {string[]} A (possibly nested) array of subscript names (e.g., 'A1').
120
+ */
121
+ function expandSubNamesForDim(dimId) {
122
+ if (!isDimension(dimId)) {
123
+ throw new Error('expandSubNames should only be called with a dimension ID')
124
+ }
125
+
126
+ // Get the object for the dimension
127
+ const dimObj = sub(dimId)
128
+
129
+ // The dimension may contain a mix of individual subscripts (indices) and/or
130
+ // subdimensions, so recursively expand them
131
+ return dimObj.modelValue.map(subOrDimName => {
132
+ const subOrDimId = canonicalName(subOrDimName)
133
+ if (isDimension(subOrDimId)) {
134
+ return expandSubNamesForDim(subOrDimId)
135
+ } else {
136
+ return [subOrDimName]
137
+ }
138
+ })
139
+ }
@@ -2,7 +2,7 @@ import B from 'bufx'
2
2
  import yaml from 'js-yaml'
3
3
  import * as R from 'ramda'
4
4
 
5
- import { canonicalName, decanonicalize, isIterable, /*listConcat,*/ strlist, vlog, vsort } from '../_shared/helpers.js'
5
+ import { canonicalVensimName, decanonicalize, isIterable, strlist, vlog, vsort } from '../_shared/helpers.js'
6
6
  import {
7
7
  addIndex,
8
8
  allAliases,
@@ -13,7 +13,9 @@ import {
13
13
  sub,
14
14
  subscriptFamilies
15
15
  } from '../_shared/subscript.js'
16
+ import { cName } from '../_shared/var-names.js'
16
17
 
18
+ import { expandVar } from './expand-var-instances.js'
17
19
  import { readEquation } from './read-equations.js'
18
20
  import { readDimensionDefs } from './read-subscripts.js'
19
21
  import { readVariables } from './read-variables.js'
@@ -60,12 +62,12 @@ function resetModelState() {
60
62
  * TODO: FIX TYPE
61
63
  * @param {*} parsedModel The parsed model structure.
62
64
  * @param {*} spec The parsed `spec.json` object.
63
- * @param {Map<string, any>} extData The map of datasets from external `.dat` files.
64
- * @param {Map<string, any>} directData The mapping of dataset name used in a `GET DIRECT DATA`
65
+ * @param {Map<string, any>} [extData] The map of datasets from external `.dat` files.
66
+ * @param {Map<string, any>} [directData] The mapping of dataset name used in a `GET DIRECT DATA`
65
67
  * call (e.g., `?data`) to the tabular data contained in the loaded data file.
66
- * @param {string} modelDirname The path to the directory containing the model (used for resolving data
68
+ * @param {string} [modelDirname] The path to the directory containing the model (used for resolving data
67
69
  * files for `GET DIRECT SUBSCRIPT`).
68
- * @param {*} opts An optional object used by tests to stop the read process after a specific phase.
70
+ * @param {*} [opts] An optional object used by tests to stop the read process after a specific phase.
69
71
  */
70
72
  function read(parsedModel, spec, extData, directData, modelDirname, opts) {
71
73
  // Some arrays need to be separated into variables with individual indices to
@@ -425,7 +427,13 @@ function removeUnusedVariables(spec) {
425
427
  }
426
428
 
427
429
  // Filter out unneeded variables so we're left with the minimal set of variables to emit
428
- variables = R.filter(v => referencedVarNames.has(v.varName), variables)
430
+ const filteredVariables = R.filter(v => referencedVarNames.has(v.varName), variables)
431
+ // TODO: Note that we reuse the same `variables` array instance here instead of reassigning
432
+ // to it because some code (like in `code-gen/expand-var-names.js` and in some tests) uses
433
+ // the `variables` array (from module-level storage) directly. We need to fix those uses
434
+ // to use accessors to avoid these subtle issues.
435
+ variables.length = 0
436
+ variables.push(...filteredVariables)
429
437
 
430
438
  // Rebuild the variables-by-name map
431
439
  variablesByName.clear()
@@ -732,28 +740,6 @@ function vensimName(cVarName) {
732
740
  }
733
741
  return result
734
742
  }
735
- function cName(vensimVarName) {
736
- // Convert a Vensim variable name to a C name.
737
- // This function requires model analysis to be completed first when the variable has subscripts.
738
-
739
- // Split the variable name from the subscripts
740
- let matches = vensimVarName.match(/([^[]+)(?:\[([^\]]+)\])?/)
741
- if (!matches) {
742
- throw new Error(`Invalid variable name '${vensimVarName}' found when converting to C representation`)
743
- }
744
- let cVarName = canonicalName(matches[1])
745
- if (matches[2]) {
746
- // The variable name includes subscripts, so split them into individual IDs
747
- let cSubIds = matches[2].split(',').map(x => canonicalName(x))
748
- // If a subscript is an index, convert it to an index number to match Vensim data exports
749
- let cSubIdParts = cSubIds.map(cSubId => {
750
- return isIndex(cSubId) ? `[${sub(cSubId).value}]` : `[${cSubId}]`
751
- })
752
- // Append the subscript parts to the base variable name to create the full reference
753
- cVarName += cSubIdParts.join('')
754
- }
755
- return cVarName
756
- }
757
743
  function isInputVar(varName) {
758
744
  // Return true if the given variable (in canonical form) is included in the list of
759
745
  // input variables in the spec file.
@@ -1105,12 +1091,13 @@ function allListedVars() {
1105
1091
  }
1106
1092
 
1107
1093
  // The order of execution/evaluation in the generated model is:
1108
- // initConstants (vars of type `const` only)
1109
- // initLookups (vars of type `lookup` only)
1110
- // initData (vars of type `data` only)
1111
- // initLevels (vars returned by `initVars`, a mix of initial, aux, and level vars)
1112
- // evalAux (vars of type `aux` only)
1113
- // evalLevels (vars of type `level` only)
1094
+ // initConstants (vars of type `const` only; called for t=0 only)
1095
+ // initLookups (vars of type `lookup` only; called for t=0 only)
1096
+ // initData (vars of type `data` only; called for t=0 only)
1097
+ // initLevels (vars returned by `initVars`, a mix of initial, aux, and level vars;
1098
+ // called for t=0 only)
1099
+ // evalAux (vars of type `aux` only; called for t>=0)
1100
+ // evalLevels (vars of type `level` only; called before `evalAux` for t>0)
1114
1101
  // So to make the ordering in the listing better match the order of evaluation,
1115
1102
  // we emit variables in the above order, but filter to avoid having duplicates.
1116
1103
  addUnique(constVars())
@@ -1151,7 +1138,7 @@ function varIndexInfoMap() {
1151
1138
 
1152
1139
  // Get the set of unique variable names, and assign a 1-based index to each.
1153
1140
  // This matches the index number used in `storeOutput` and `setLookup` in the
1154
- // generated C/JS code
1141
+ // generated C/JS code.
1155
1142
  const infoMap = new Map()
1156
1143
  let varIndex = 1
1157
1144
  for (const v of sortedVars) {
@@ -1209,6 +1196,73 @@ function jsonList() {
1209
1196
  }
1210
1197
  }
1211
1198
 
1199
+ //
1200
+ // We include a `varInstances` object in the generated JSON listing that
1201
+ // includes an array of expanded variable items (one item for every "instance"
1202
+ // of a variable, including subscripted variables) in the same order that they
1203
+ // are evaluated (assigned) in the generated model.
1204
+ //
1205
+ // Each object contains the following minimal set of fields that are needed
1206
+ // for accessing the data for a single variable instance at runtime:
1207
+ // varId (e.g., '_variable_name')
1208
+ // varName (e.g., 'Variable Name')
1209
+ // varType ('const', 'data', 'lookup', 'initial', 'level', 'aux')
1210
+ // varIndex
1211
+ // subscriptIndices
1212
+ //
1213
+ // The order of execution/evaluation in the generated model is:
1214
+ // initConstants (vars of type `const` only, called for t=0 only)
1215
+ // initLookups (vars of type `lookup` only, called for t=0 only)
1216
+ // initData (vars of type `data` only, called for t=0 only)
1217
+ // initLevels (vars returned by `initVars`, a mix of initial, aux, and level vars,
1218
+ // called for t=0 only)
1219
+ // evalAux (vars of type `aux` only; called for t>=0)
1220
+ // evalLevels (vars of type `level` only; called before `evalAux` for t>0)
1221
+ //
1222
+ function expandedVarItems(vars) {
1223
+ const expandedVars = []
1224
+
1225
+ for (const v of vars) {
1226
+ // Filter out variables that are generated/used internally
1227
+ if (v.includeInOutput === false) {
1228
+ continue
1229
+ }
1230
+
1231
+ const varInstances = expandVar(v)
1232
+ for (const { varName, subscriptIndices } of varInstances) {
1233
+ const varId = canonicalVensimName(varName)
1234
+ const varItem = {
1235
+ varId,
1236
+ varName,
1237
+ varType: v.varType
1238
+ }
1239
+ const varInfo = infoMap.get(v.varName)
1240
+ if (varInfo) {
1241
+ varItem.varIndex = varInfo.varIndex
1242
+ if (subscriptIndices?.length > 0) {
1243
+ varItem.subscriptIndices = subscriptIndices
1244
+ }
1245
+ }
1246
+ expandedVars.push(varItem)
1247
+ }
1248
+ }
1249
+
1250
+ return expandedVars
1251
+ }
1252
+ const expandedConstants = expandedVarItems(constVars())
1253
+ const expandedLookupVars = expandedVarItems(lookupVars())
1254
+ const expandedDataVars = expandedVarItems(dataVars())
1255
+ // The special exogenous `Time` variable may have already been removed by
1256
+ // `removeUnusedVariables` if it is not referenced explicitly in the model,
1257
+ // so we will only include it in the listing if it is defined here. Note
1258
+ // that `_time` is set to `_initial_time` as the first step in the
1259
+ // `initLevels` function, which is why it is included in the "init" group.
1260
+ const timeVar = varWithName('_time')
1261
+ const specialInitVars = timeVar ? [timeVar] : []
1262
+ const expandedInitVars = expandedVarItems([...specialInitVars, ...initVars()])
1263
+ const expandedLevelVars = expandedVarItems(levelVars())
1264
+ const expandedAuxVars = expandedVarItems(auxVars())
1265
+
1212
1266
  // Derive minimal versions of the full arrays; these only contain the minimal
1213
1267
  // subset of fields that are needed by the `ModelListing` class from the
1214
1268
  // runtime package. The property names in the minimal objects are slightly
@@ -1245,7 +1299,15 @@ function jsonList() {
1245
1299
  cachedJsonList = {
1246
1300
  full: {
1247
1301
  dimensions: sortedFullDims,
1248
- variables: sortedFullVars
1302
+ variables: sortedFullVars,
1303
+ varInstances: {
1304
+ constants: expandedConstants,
1305
+ lookupVars: expandedLookupVars,
1306
+ dataVars: expandedDataVars,
1307
+ initVars: expandedInitVars,
1308
+ levelVars: expandedLevelVars,
1309
+ auxVars: expandedAuxVars
1310
+ }
1249
1311
  },
1250
1312
  minimal: {
1251
1313
  dimensions: sortedMinimalDims,
@@ -1261,7 +1323,6 @@ export default {
1261
1323
  addVariable,
1262
1324
  allVars,
1263
1325
  auxVars,
1264
- cName,
1265
1326
  constVars,
1266
1327
  dataVars,
1267
1328
  expansionFlags,
@@ -39,7 +39,7 @@ function toposort(nodes, edges) {
39
39
  var nodeRep
40
40
  try {
41
41
  nodeRep = '\n' + node + '\n'
42
- } catch (e) {
42
+ } catch (_) {
43
43
  nodeRep = ''
44
44
  }
45
45
  throw new Error('Found cyclic dependency during toposort:\n' + [...predecessors].join(' →\n') + ' →' + nodeRep)
@@ -8,6 +8,7 @@ import { parseVensimModel } from '@sdeverywhere/parse'
8
8
  import { readXlsx } from './_shared/helpers.js'
9
9
  import { readDat } from './_shared/read-dat.js'
10
10
  import { printSubscripts, yamlSubsList } from './_shared/subscript.js'
11
+ import { cName } from './_shared/var-names.js'
11
12
  import Model from './model/model.js'
12
13
  import { getDirectSubscripts } from './model/read-subscripts.js'
13
14
  import { generateCode } from './generate/gen-code.js'
@@ -120,7 +121,7 @@ export function printNames(namesPathname, operation) {
120
121
  for (let line of lines) {
121
122
  if (line.length > 0) {
122
123
  if (operation === 'to-c') {
123
- B.emitLine(Model.cName(line))
124
+ B.emitLine(cName(line))
124
125
  } else {
125
126
  B.emitLine(Model.vensimName(line))
126
127
  }