@sdeverywhere/compile 0.7.25 → 0.7.27
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 +2 -3
- package/src/_shared/bufx.js +66 -0
- package/src/_shared/helpers.js +1 -1
- package/src/_shared/read-dat.js +1 -1
- package/src/_shared/subscript.js +1 -17
- package/src/generate/gen-code-c.js +86 -36
- package/src/generate/gen-code-js.js +59 -0
- package/src/model/model.js +2 -12
- package/src/parse-and-generate.js +3 -7
package/package.json
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdeverywhere/compile",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.27",
|
|
4
4
|
"description": "The core Vensim to C compiler for the SDEverywhere tool suite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@sdeverywhere/parse": "^0.1.2",
|
|
9
|
-
"bufx": "^1.0.5",
|
|
10
9
|
"byline": "^5.0.0",
|
|
11
10
|
"csv-parse": "^5.3.3",
|
|
12
|
-
"js-yaml": "^3.13.1",
|
|
13
11
|
"ramda": "^0.27.0",
|
|
12
|
+
"strip-bom": "^5.0.0",
|
|
14
13
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
|
|
15
14
|
},
|
|
16
15
|
"author": "Climate Interactive",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as fs from 'node:fs'
|
|
2
|
+
import stripBom from 'strip-bom'
|
|
3
|
+
|
|
4
|
+
// Numeric value of a string or number
|
|
5
|
+
let num = x => (typeof x === 'number' ? x : Number.parseFloat(x))
|
|
6
|
+
// Split a string into lines that may have Windows, Unix, or old Mac line endings.
|
|
7
|
+
let lines = s => s.split(/\r\n|\n|\r/)
|
|
8
|
+
// Print a string to the console
|
|
9
|
+
let print = s => {
|
|
10
|
+
console.log(s)
|
|
11
|
+
}
|
|
12
|
+
// Read a UTF-8 file into a string. Strip the BOM if present.
|
|
13
|
+
let read = pathname => stripBom(fs.readFileSync(pathname, 'utf8'))
|
|
14
|
+
// Write a string to a UTF-8 file
|
|
15
|
+
let write = (s, pathname) => {
|
|
16
|
+
fs.writeFileSync(pathname, s, { encoding: 'utf8' })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Output buffer
|
|
20
|
+
let bufs = { _: '' }
|
|
21
|
+
// Open a buffer for writing
|
|
22
|
+
let open = channel => (bufs[channel] = '')
|
|
23
|
+
// Emit a string to a buffer
|
|
24
|
+
let emit = (a, channel = null) => {
|
|
25
|
+
channel = channel || '_'
|
|
26
|
+
bufs[channel] += a
|
|
27
|
+
}
|
|
28
|
+
// Emit a string to a buffer terminated by a newline
|
|
29
|
+
let emitLine = (a, channel = null) => {
|
|
30
|
+
channel = channel || '_'
|
|
31
|
+
bufs[channel] += a + '\n'
|
|
32
|
+
}
|
|
33
|
+
// Print a buffer to the console
|
|
34
|
+
let printBuf = (channel = null) => {
|
|
35
|
+
channel = channel || '_'
|
|
36
|
+
print(bufs[channel])
|
|
37
|
+
}
|
|
38
|
+
// Write a buffer to a file
|
|
39
|
+
let writeBuf = (pathname, channel = null) => {
|
|
40
|
+
channel = channel || '_'
|
|
41
|
+
write(bufs[channel], pathname)
|
|
42
|
+
}
|
|
43
|
+
// Get buffer contents as a string
|
|
44
|
+
let getBuf = (channel = null) => {
|
|
45
|
+
channel = channel || '_'
|
|
46
|
+
return bufs[channel]
|
|
47
|
+
}
|
|
48
|
+
// Clear a buffer
|
|
49
|
+
let clearBuf = (channel = null) => {
|
|
50
|
+
channel = channel || '_'
|
|
51
|
+
bufs[channel] = ''
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default {
|
|
55
|
+
clearBuf,
|
|
56
|
+
emit,
|
|
57
|
+
emitLine,
|
|
58
|
+
getBuf,
|
|
59
|
+
lines,
|
|
60
|
+
num,
|
|
61
|
+
open,
|
|
62
|
+
printBuf,
|
|
63
|
+
read,
|
|
64
|
+
write,
|
|
65
|
+
writeBuf
|
|
66
|
+
}
|
package/src/_shared/helpers.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as fs from 'node:fs'
|
|
2
2
|
import util from 'util'
|
|
3
|
-
import B from 'bufx'
|
|
4
3
|
import { parse as parseCsv } from 'csv-parse/sync'
|
|
5
4
|
import * as R from 'ramda'
|
|
6
5
|
import XLSX from 'xlsx'
|
|
6
|
+
import B from './bufx.js'
|
|
7
7
|
|
|
8
8
|
import { canonicalId, canonicalVarId } from '@sdeverywhere/parse'
|
|
9
9
|
|
package/src/_shared/read-dat.js
CHANGED
package/src/_shared/subscript.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import util from 'util'
|
|
2
|
-
import B from 'bufx'
|
|
3
|
-
import yaml from 'js-yaml'
|
|
4
2
|
import * as R from 'ramda'
|
|
3
|
+
import B from './bufx.js'
|
|
5
4
|
import { canonicalName, vlog } from './helpers.js'
|
|
6
5
|
|
|
7
6
|
// A subscript is a dimension or an index.
|
|
@@ -218,21 +217,6 @@ export function printSubscripts() {
|
|
|
218
217
|
}
|
|
219
218
|
return B.getBuf()
|
|
220
219
|
}
|
|
221
|
-
export function yamlSubsList() {
|
|
222
|
-
let subs = {}
|
|
223
|
-
for (let [k, v] of subscripts) {
|
|
224
|
-
subs[k] = v
|
|
225
|
-
}
|
|
226
|
-
return yaml.safeDump(subs)
|
|
227
|
-
}
|
|
228
|
-
export function loadSubscriptsFromYaml(yamlSubs) {
|
|
229
|
-
// Load the subscripts map from subscripts serialized to a YAML file by yamlSubsList.
|
|
230
|
-
// This function should be called instead of adding subscripts through the constructor.
|
|
231
|
-
let subs = yaml.safeLoad(yamlSubs)
|
|
232
|
-
for (const k in subs) {
|
|
233
|
-
subscripts.set(k, subs[k])
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
220
|
export function extractMarkedDims(subscripts) {
|
|
237
221
|
// Extract all marked dimensions and update subscripts.
|
|
238
222
|
let dims = []
|
|
@@ -146,6 +146,24 @@ ${chunkedFunctions('evalLevels', Model.levelVars(), ' // Evaluate levels.')}`
|
|
|
146
146
|
// Input/output section
|
|
147
147
|
//
|
|
148
148
|
function emitIOCode() {
|
|
149
|
+
// Configure the body of the `setConstant` function depending on the value
|
|
150
|
+
// of the `customConstants` property in the spec file
|
|
151
|
+
let setConstantBody
|
|
152
|
+
if (spec.customConstants === true || Array.isArray(spec.customConstants)) {
|
|
153
|
+
setConstantBody = `\
|
|
154
|
+
switch (varIndex) {
|
|
155
|
+
${setConstantImpl(Model.varIndexInfo(), spec.customConstants)}
|
|
156
|
+
default:
|
|
157
|
+
fprintf(stderr, "No constant found for var index %zu in setConstant\\n", varIndex);
|
|
158
|
+
break;
|
|
159
|
+
}`
|
|
160
|
+
} else {
|
|
161
|
+
let msg = 'The setConstant function was not enabled for the generated model. '
|
|
162
|
+
msg += 'Set the customConstants property in the spec/config file to allow for overriding constants at runtime.'
|
|
163
|
+
setConstantBody = `\
|
|
164
|
+
fprintf(stderr, "${msg}\\n");`
|
|
165
|
+
}
|
|
166
|
+
|
|
149
167
|
// Configure the body of the `setLookup` function depending on the value
|
|
150
168
|
// of the `customLookups` property in the spec file
|
|
151
169
|
// TODO: The fprintf calls should be replaced with a mechanism that throws
|
|
@@ -200,12 +218,12 @@ ${customOutputSection(Model.varIndexInfo(), spec.customOutputs)}
|
|
|
200
218
|
|
|
201
219
|
mode = 'io'
|
|
202
220
|
return `\
|
|
203
|
-
void setInputs(
|
|
204
|
-
${
|
|
221
|
+
void setInputs(double* inputValues, int32_t* inputIndices) {
|
|
222
|
+
${setInputsImpl()}
|
|
205
223
|
}
|
|
206
224
|
|
|
207
|
-
void
|
|
208
|
-
${
|
|
225
|
+
void setConstant(size_t varIndex, size_t* subIndices, double value) {
|
|
226
|
+
${setConstantBody}
|
|
209
227
|
}
|
|
210
228
|
|
|
211
229
|
void setLookup(size_t varIndex, size_t* subIndices, double* points, size_t numPoints) {
|
|
@@ -322,13 +340,19 @@ ${section(chunk)}
|
|
|
322
340
|
}
|
|
323
341
|
function internalVarsSection() {
|
|
324
342
|
// Declare internal variables to run the model.
|
|
325
|
-
let
|
|
343
|
+
let numInputsDecl
|
|
344
|
+
if (spec.inputVars && spec.inputVars.length > 0) {
|
|
345
|
+
numInputsDecl = `const int numInputs = ${spec.inputVars.length};`
|
|
346
|
+
} else {
|
|
347
|
+
numInputsDecl = `const int numInputs = 0;`
|
|
348
|
+
}
|
|
349
|
+
let numOutputsDecl
|
|
326
350
|
if (outputAllVars) {
|
|
327
|
-
|
|
351
|
+
numOutputsDecl = `const int numOutputs = ${expandedVarNames().length};`
|
|
328
352
|
} else {
|
|
329
|
-
|
|
353
|
+
numOutputsDecl = `const int numOutputs = ${spec.outputVars.length};`
|
|
330
354
|
}
|
|
331
|
-
return
|
|
355
|
+
return `${numInputsDecl}\n${numOutputsDecl}`
|
|
332
356
|
}
|
|
333
357
|
function arrayDimensionsSection() {
|
|
334
358
|
// Emit a declaration for each array dimension's index numbers.
|
|
@@ -402,38 +426,64 @@ ${section(chunk)}
|
|
|
402
426
|
const section = R.pipe(outputVars, code, lines)
|
|
403
427
|
return section(varIndexInfo)
|
|
404
428
|
}
|
|
405
|
-
function
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
let inputVars = ''
|
|
409
|
-
if (spec.inputVars && spec.inputVars.length > 0) {
|
|
410
|
-
let inputVarPtrs = R.reduce((a, inputVar) => R.concat(a, ` &${inputVar},\n`), '', spec.inputVars)
|
|
411
|
-
inputVars = `\
|
|
412
|
-
static double* inputVarPtrs[] = {\n${inputVarPtrs} };
|
|
413
|
-
char* inputs = (char*)inputData;
|
|
414
|
-
char* token = strtok(inputs, " ");
|
|
415
|
-
while (token) {
|
|
416
|
-
char* p = strchr(token, ':');
|
|
417
|
-
if (p) {
|
|
418
|
-
*p = '\\0';
|
|
419
|
-
int modelVarIndex = atoi(token);
|
|
420
|
-
double value = atof(p+1);
|
|
421
|
-
*inputVarPtrs[modelVarIndex] = value;
|
|
429
|
+
function setInputsImpl() {
|
|
430
|
+
if (!spec.inputVars || spec.inputVars.length === 0) {
|
|
431
|
+
return ''
|
|
422
432
|
}
|
|
423
|
-
|
|
424
|
-
|
|
433
|
+
// Build the pointer table for input variables
|
|
434
|
+
let inputVarPtrs = R.reduce((a, inputVar) => R.concat(a, ` &${inputVar},\n`), '', spec.inputVars)
|
|
435
|
+
return `\
|
|
436
|
+
static double* inputVarPtrs[] = {
|
|
437
|
+
${inputVarPtrs} };
|
|
438
|
+
if (inputIndices == NULL) {
|
|
439
|
+
// When inputIndices is NULL, assume that inputValues contains all input values
|
|
440
|
+
// in the same order that the variables are defined in the model spec
|
|
441
|
+
for (size_t i = 0; i < numInputs; i++) {
|
|
442
|
+
*inputVarPtrs[i] = inputValues[i];
|
|
425
443
|
}
|
|
426
|
-
|
|
444
|
+
} else {
|
|
445
|
+
// When inputIndices is non-NULL, set the input values according to the indices
|
|
446
|
+
// in the inputIndices array, where each index corresponds to the index of the
|
|
447
|
+
// variable in the model spec
|
|
448
|
+
size_t numInputsToSet = (size_t)inputIndices[0];
|
|
449
|
+
for (size_t i = 0; i < numInputsToSet; i++) {
|
|
450
|
+
size_t inputVarIndex = (size_t)inputIndices[i + 1];
|
|
451
|
+
*inputVarPtrs[inputVarIndex] = inputValues[i];
|
|
452
|
+
}
|
|
453
|
+
}`
|
|
427
454
|
}
|
|
428
|
-
function
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
455
|
+
function setConstantImpl(varIndexInfo, customConstants) {
|
|
456
|
+
// Emit case statements for all const variables that can be overridden at runtime
|
|
457
|
+
let includeCase
|
|
458
|
+
if (Array.isArray(customConstants)) {
|
|
459
|
+
// Only include a case statement if the variable was explicitly included
|
|
460
|
+
// in the `customConstants` array in the spec file
|
|
461
|
+
const customConstantVarNames = customConstants.map(varName => {
|
|
462
|
+
// The developer might specify a variable name that includes subscripts,
|
|
463
|
+
// but we will ignore the subscript part and only match on the base name
|
|
464
|
+
return canonicalVensimName(varName.split('[')[0])
|
|
465
|
+
})
|
|
466
|
+
includeCase = varName => customConstantVarNames.includes(varName)
|
|
467
|
+
} else {
|
|
468
|
+
// Include a case statement for all constant variables
|
|
469
|
+
includeCase = () => true
|
|
435
470
|
}
|
|
436
|
-
|
|
471
|
+
const constVars = R.filter(info => {
|
|
472
|
+
return info.varType === 'const' && includeCase(info.varName)
|
|
473
|
+
})
|
|
474
|
+
const code = R.map(info => {
|
|
475
|
+
let constVar = info.varName
|
|
476
|
+
for (let i = 0; i < info.subscriptCount; i++) {
|
|
477
|
+
constVar += `[subIndices[${i}]]`
|
|
478
|
+
}
|
|
479
|
+
let c = ''
|
|
480
|
+
c += ` case ${info.varIndex}:\n`
|
|
481
|
+
c += ` ${constVar} = value;\n`
|
|
482
|
+
c += ` break;`
|
|
483
|
+
return c
|
|
484
|
+
})
|
|
485
|
+
const section = R.pipe(constVars, code, lines)
|
|
486
|
+
return section(varIndexInfo)
|
|
437
487
|
}
|
|
438
488
|
function setLookupImpl(varIndexInfo, customLookups) {
|
|
439
489
|
// Emit case statements for all lookups and data variables that can be overridden
|
|
@@ -241,6 +241,27 @@ ${chunkedFunctions('evalLevels', true, Model.levelVars(), ' // Evaluate levels'
|
|
|
241
241
|
function emitIOCode() {
|
|
242
242
|
mode = 'io'
|
|
243
243
|
|
|
244
|
+
// Configure the body of the `setConstant` function depending on the value
|
|
245
|
+
// of the `customConstants` property in the spec file
|
|
246
|
+
let setConstantBody
|
|
247
|
+
if (spec.customConstants === true || Array.isArray(spec.customConstants)) {
|
|
248
|
+
setConstantBody = `\
|
|
249
|
+
if (!varSpec) {
|
|
250
|
+
throw new Error('Got undefined varSpec in setConstant');
|
|
251
|
+
}
|
|
252
|
+
const varIndex = varSpec.varIndex;
|
|
253
|
+
const subs = varSpec.subscriptIndices;
|
|
254
|
+
switch (varIndex) {
|
|
255
|
+
${setConstantImpl(Model.varIndexInfo(), spec.customConstants)}
|
|
256
|
+
default:
|
|
257
|
+
throw new Error(\`No constant found for var index \${varIndex} in setConstant\`);
|
|
258
|
+
}`
|
|
259
|
+
} else {
|
|
260
|
+
let msg = 'The setConstant function was not enabled for the generated model. '
|
|
261
|
+
msg += 'Set the customConstants property in the spec/config file to allow for overriding constants at runtime.'
|
|
262
|
+
setConstantBody = ` throw new Error('${msg}');`
|
|
263
|
+
}
|
|
264
|
+
|
|
244
265
|
// Configure the body of the `setLookup` function depending on the value
|
|
245
266
|
// of the `customLookups` property in the spec file
|
|
246
267
|
let setLookupBody
|
|
@@ -312,6 +333,10 @@ ${customOutputSection(Model.varIndexInfo(), spec.customOutputs)}
|
|
|
312
333
|
return `\
|
|
313
334
|
/*export*/ function setInputs(valueAtIndex /*: (index: number) => number*/) {${inputsFromBufferImpl()}}
|
|
314
335
|
|
|
336
|
+
/*export*/ function setConstant(varSpec /*: VarSpec*/, value /*: number*/) {
|
|
337
|
+
${setConstantBody}
|
|
338
|
+
}
|
|
339
|
+
|
|
315
340
|
/*export*/ function setLookup(varSpec /*: VarSpec*/, points /*: Float64Array | undefined*/) {
|
|
316
341
|
${setLookupBody}
|
|
317
342
|
}
|
|
@@ -521,6 +546,39 @@ ${section(chunk)}
|
|
|
521
546
|
}
|
|
522
547
|
return inputVars
|
|
523
548
|
}
|
|
549
|
+
function setConstantImpl(varIndexInfo, customConstants) {
|
|
550
|
+
// Emit case statements for all const variables that can be overridden at runtime
|
|
551
|
+
let overrideAllowed
|
|
552
|
+
if (Array.isArray(customConstants)) {
|
|
553
|
+
// Only include a case statement if the variable was explicitly included
|
|
554
|
+
// in the `customConstants` array in the spec file
|
|
555
|
+
const customConstantVarNames = customConstants.map(varName => {
|
|
556
|
+
// The developer might specify a variable name that includes subscripts,
|
|
557
|
+
// but we will ignore the subscript part and only match on the base name
|
|
558
|
+
return canonicalVensimName(varName.split('[')[0])
|
|
559
|
+
})
|
|
560
|
+
overrideAllowed = varName => customConstantVarNames.includes(varName)
|
|
561
|
+
} else {
|
|
562
|
+
// Include a case statement for all constant variables
|
|
563
|
+
overrideAllowed = () => true
|
|
564
|
+
}
|
|
565
|
+
const constVars = R.filter(info => {
|
|
566
|
+
return info.varType === 'const' && overrideAllowed(info.varName)
|
|
567
|
+
})
|
|
568
|
+
const code = R.map(info => {
|
|
569
|
+
let constVar = info.varName
|
|
570
|
+
for (let i = 0; i < info.subscriptCount; i++) {
|
|
571
|
+
constVar += `[subs[${i}]]`
|
|
572
|
+
}
|
|
573
|
+
let c = ''
|
|
574
|
+
c += ` case ${info.varIndex}:\n`
|
|
575
|
+
c += ` ${constVar} = value;\n`
|
|
576
|
+
c += ` break;`
|
|
577
|
+
return c
|
|
578
|
+
})
|
|
579
|
+
const section = R.pipe(constVars, code, lines)
|
|
580
|
+
return section(varIndexInfo)
|
|
581
|
+
}
|
|
524
582
|
function setLookupImpl(varIndexInfo, customLookups) {
|
|
525
583
|
// Emit case statements for all lookups and data variables that can be overridden
|
|
526
584
|
// at runtime
|
|
@@ -605,6 +663,7 @@ export default async function () {
|
|
|
605
663
|
|
|
606
664
|
setTime,
|
|
607
665
|
setInputs,
|
|
666
|
+
setConstant,
|
|
608
667
|
setLookup,
|
|
609
668
|
|
|
610
669
|
storeOutputs,
|
package/src/model/model.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import B from 'bufx'
|
|
2
|
-
import yaml from 'js-yaml'
|
|
3
1
|
import * as R from 'ramda'
|
|
4
2
|
|
|
3
|
+
import B from '../_shared/bufx.js'
|
|
5
4
|
import { canonicalVensimName, decanonicalize, isIterable, strlist, vlog, vsort } from '../_shared/helpers.js'
|
|
6
5
|
import {
|
|
7
6
|
addIndex,
|
|
@@ -946,14 +945,6 @@ function printVarList() {
|
|
|
946
945
|
}
|
|
947
946
|
return B.getBuf()
|
|
948
947
|
}
|
|
949
|
-
function yamlVarList() {
|
|
950
|
-
// Print selected properties of all variable objects to a YAML string.
|
|
951
|
-
let vars = R.sortBy(
|
|
952
|
-
R.prop('refId'),
|
|
953
|
-
R.map(v => filterVar(v), variables)
|
|
954
|
-
)
|
|
955
|
-
return yaml.safeDump(vars)
|
|
956
|
-
}
|
|
957
948
|
function printVar(v) {
|
|
958
949
|
let nonAtoA = isNonAtoAName(v.varName) ? ' (non-apply-to-all)' : ''
|
|
959
950
|
B.emitLine(`${v.modelLHS}: ${v.varType}${nonAtoA}`)
|
|
@@ -1348,6 +1339,5 @@ export default {
|
|
|
1348
1339
|
varsWithName,
|
|
1349
1340
|
varWithName,
|
|
1350
1341
|
varWithRefId,
|
|
1351
|
-
vensimName
|
|
1352
|
-
yamlVarList
|
|
1342
|
+
vensimName
|
|
1353
1343
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Copyright (c) 2022 Climate Interactive / New Venture Fund
|
|
2
2
|
|
|
3
3
|
import path from 'path'
|
|
4
|
-
import B from 'bufx'
|
|
5
4
|
|
|
6
5
|
import { parseVensimModel } from '@sdeverywhere/parse'
|
|
7
6
|
|
|
7
|
+
import B from './_shared/bufx.js'
|
|
8
8
|
import { readXlsx } from './_shared/helpers.js'
|
|
9
9
|
import { readDat } from './_shared/read-dat.js'
|
|
10
|
-
import { printSubscripts
|
|
10
|
+
import { printSubscripts } from './_shared/subscript.js'
|
|
11
11
|
import { cName } from './_shared/var-names.js'
|
|
12
12
|
import Model from './model/model.js'
|
|
13
13
|
import { getDirectSubscripts } from './model/read-subscripts.js'
|
|
@@ -21,7 +21,7 @@ import { generateCode } from './generate/gen-code.js'
|
|
|
21
21
|
* - If `operations` has 'generateC', the generated C code will be written to `buildDir`.
|
|
22
22
|
* - If `operations` has 'generateJS', the generated JS code will be written to `buildDir`.
|
|
23
23
|
* - If `operations` has 'printVarList', variables and subscripts will be written to
|
|
24
|
-
* txt
|
|
24
|
+
* txt and json files under `buildDir`.
|
|
25
25
|
* - If `operations` has 'printRefIdTest', reference identifiers will be printed to the console.
|
|
26
26
|
* - If `operations` has 'convertNames', no output will be generated, but the results of model
|
|
27
27
|
* analysis will be available.
|
|
@@ -92,10 +92,6 @@ export async function parseAndGenerate(input, spec, operations, modelDirname, mo
|
|
|
92
92
|
writeOutput(`${modelName}_vars.txt`, Model.printVarList())
|
|
93
93
|
// Write subscripts to a text file.
|
|
94
94
|
writeOutput(`${modelName}_subs.txt`, printSubscripts())
|
|
95
|
-
// Write variables to a YAML file.
|
|
96
|
-
writeOutput(`${modelName}_vars.yaml`, Model.yamlVarList())
|
|
97
|
-
// Write subscripts to a YAML file.
|
|
98
|
-
writeOutput(`${modelName}_subs.yaml`, yamlSubsList())
|
|
99
95
|
// Write variables and subscripts to a JSON file.
|
|
100
96
|
const jsonList = Model.jsonList()
|
|
101
97
|
writeOutput(`${modelName}.json`, JSON.stringify(jsonList.full, null, 2))
|