@sdeverywhere/compile 0.7.17 → 0.7.18
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 +1 -3
- package/src/generate/expand-var-names.js +0 -10
- package/src/generate/{code-gen.js → gen-code-c.js} +188 -89
- package/src/generate/gen-code-js.js +616 -0
- package/src/generate/gen-code.js +36 -0
- package/src/generate/gen-equation.js +16 -6
- package/src/generate/gen-expr.js +205 -48
- package/src/generate/gen-lookup-from-direct.js +14 -6
- package/src/generate/gen-lookup-from-external.js +20 -5
- package/src/generate/gen-lookup-from-points.js +28 -6
- package/src/index.js +38 -3
- package/src/model/model.js +92 -148
- package/src/model/read-equation-fn-game.js +50 -0
- package/src/model/read-equations.js +9 -10
- package/src/model/read-variables.js +2 -2
- package/src/model/variable.js +6 -21
- package/src/parse-and-generate.js +22 -19
- package/src/preprocess/preprocessor.js +2 -2
- package/src/generate/equation-gen.js +0 -1268
- package/src/generate/model-lhs-reader.js +0 -88
- package/src/model/equation-reader.js +0 -723
- package/src/model/expr-reader.js +0 -202
- package/src/model/subscript-range-reader.js +0 -143
- package/src/model/var-name-reader.js +0 -40
- package/src/model/variable-reader.js +0 -172
- package/src/parse/model-reader.js +0 -141
- package/src/parse/parser.js +0 -36
package/src/model/variable.js
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
export default class Variable {
|
|
2
|
-
constructor(
|
|
3
|
-
// The equation rule context allows us to generate code by visiting the parse tree.
|
|
4
|
-
this.eqnCtx = eqnCtx
|
|
2
|
+
constructor() {
|
|
5
3
|
// Save both sides of the equation text in the model for documentation purposes.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
this.modelFormula = this.formula(eqnCtx)
|
|
9
|
-
} else {
|
|
10
|
-
this.modelLHS = ''
|
|
11
|
-
this.modelFormula = ''
|
|
12
|
-
}
|
|
4
|
+
this.modelLHS = ''
|
|
5
|
+
this.modelFormula = ''
|
|
13
6
|
// An equation defines a variable with a var name, saved in canonical form here.
|
|
14
7
|
this.varName = ''
|
|
15
8
|
// Subscripts are canonical dimension or index names on the LHS in normal order.
|
|
@@ -48,6 +41,8 @@ export default class Variable {
|
|
|
48
41
|
// DELAY3* calls are expanded into new level vars and substituted during code generation.
|
|
49
42
|
this.delayVarRefId = ''
|
|
50
43
|
this.delayTimeVarName = ''
|
|
44
|
+
// GAME calls generate a Lookup support var.
|
|
45
|
+
this.gameLookupVarName = ''
|
|
51
46
|
// DELAY FIXED calls generate a FixedDelay support var.
|
|
52
47
|
this.fixedDelayVarName = ''
|
|
53
48
|
// DEPRECIATE STRAIGHTLINE calls generate a Depreciation support var.
|
|
@@ -57,7 +52,6 @@ export default class Variable {
|
|
|
57
52
|
}
|
|
58
53
|
copy() {
|
|
59
54
|
let c = new Variable()
|
|
60
|
-
c.eqnCtx = this.eqnCtx
|
|
61
55
|
c.modelLHS = this.modelLHS
|
|
62
56
|
c.modelFormula = this.modelFormula
|
|
63
57
|
c.varName = this.varName
|
|
@@ -75,19 +69,10 @@ export default class Variable {
|
|
|
75
69
|
c.trendVarName = this.trendVarName
|
|
76
70
|
c.delayVarRefId = this.delayVarRefId
|
|
77
71
|
c.delayTimeVarName = this.delayTimeVarName
|
|
72
|
+
c.gameLookupVarName = this.gameLookupVarName
|
|
78
73
|
c.includeInOutput = this.includeInOutput
|
|
79
74
|
return c
|
|
80
75
|
}
|
|
81
|
-
formula(eqnCtx) {
|
|
82
|
-
if (eqnCtx) {
|
|
83
|
-
if (eqnCtx.expr()) {
|
|
84
|
-
return eqnCtx.expr().getText()
|
|
85
|
-
} else if (eqnCtx.constList()) {
|
|
86
|
-
return eqnCtx.constList().getText()
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return ''
|
|
90
|
-
}
|
|
91
76
|
hasSubscripts() {
|
|
92
77
|
return this.subscripts.length > 0
|
|
93
78
|
}
|
|
@@ -8,10 +8,9 @@ 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 { parseModel as legacyParseVensimModel } from './parse/parser.js'
|
|
12
11
|
import Model from './model/model.js'
|
|
13
12
|
import { getDirectSubscripts } from './model/read-subscripts.js'
|
|
14
|
-
import { generateCode } from './generate/code
|
|
13
|
+
import { generateCode } from './generate/gen-code.js'
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* Parse a Vensim model and generate C code.
|
|
@@ -19,17 +18,18 @@ import { generateCode } from './generate/code-gen.js'
|
|
|
19
18
|
* This is the primary entrypoint for the `sde generate` command.
|
|
20
19
|
*
|
|
21
20
|
* - If `operations` has 'generateC', the generated C code will be written to `buildDir`.
|
|
21
|
+
* - If `operations` has 'generateJS', the generated JS code will be written to `buildDir`.
|
|
22
22
|
* - If `operations` has 'printVarList', variables and subscripts will be written to
|
|
23
23
|
* txt, yaml, and json files under `buildDir`.
|
|
24
|
-
* - If `
|
|
25
|
-
* - If `
|
|
24
|
+
* - If `operations` has 'printRefIdTest', reference identifiers will be printed to the console.
|
|
25
|
+
* - If `operations` has 'convertNames', no output will be generated, but the results of model
|
|
26
26
|
* analysis will be available.
|
|
27
27
|
*
|
|
28
28
|
* @param input The preprocessed Vensim model text.
|
|
29
29
|
* @param spec The model spec (from the JSON file).
|
|
30
|
-
* @param operations The set of operations to perform; can include 'generateC', '
|
|
31
|
-
* 'printRefIdTest', 'convertNames'. If the array is empty, the model will be
|
|
32
|
-
* operation will be performed.
|
|
30
|
+
* @param operations The set of operations to perform; can include 'generateC', 'generateJS',
|
|
31
|
+
* 'printVarList', 'printRefIdTest', 'convertNames'. If the array is empty, the model will be
|
|
32
|
+
* read but no operation will be performed.
|
|
33
33
|
* @param modelDirname The absolute path to the directory containing the mdl file.
|
|
34
34
|
* The dat and xlsx files referenced by the spec will be relative to this directory.
|
|
35
35
|
* @param modelName The model name (without the mdl extension).
|
|
@@ -66,7 +66,7 @@ export async function parseAndGenerate(input, spec, operations, modelDirname, mo
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
// Parse the model and generate code
|
|
69
|
+
// Parse the model and generate code
|
|
70
70
|
let parsedModel = parseModel(input, modelDirname)
|
|
71
71
|
let code = generateCode(parsedModel, { spec, operations, extData, directData, modelDirname })
|
|
72
72
|
|
|
@@ -80,6 +80,11 @@ export async function parseAndGenerate(input, spec, operations, modelDirname, mo
|
|
|
80
80
|
writeOutput(`${modelName}.c`, code)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
if (operations.includes('generateJS')) {
|
|
84
|
+
// Write the generated JS to a file
|
|
85
|
+
writeOutput(`${modelName}.js`, code)
|
|
86
|
+
}
|
|
87
|
+
|
|
83
88
|
if (operations.includes('printVarList')) {
|
|
84
89
|
// Write variables to a text file.
|
|
85
90
|
writeOutput(`${modelName}_vars.txt`, Model.printVarList())
|
|
@@ -90,7 +95,11 @@ export async function parseAndGenerate(input, spec, operations, modelDirname, mo
|
|
|
90
95
|
// Write subscripts to a YAML file.
|
|
91
96
|
writeOutput(`${modelName}_subs.yaml`, yamlSubsList())
|
|
92
97
|
// Write variables and subscripts to a JSON file.
|
|
93
|
-
|
|
98
|
+
const jsonList = Model.jsonList()
|
|
99
|
+
writeOutput(`${modelName}.json`, JSON.stringify(jsonList.full, null, 2))
|
|
100
|
+
// Write minimal variable index and dimension specs to a JSON file used
|
|
101
|
+
// by the runtime package to initialize a `ModelListing` instance).
|
|
102
|
+
writeOutput(`${modelName}_min.json`, JSON.stringify(jsonList.minimal, null, 2))
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
return code
|
|
@@ -127,18 +136,11 @@ export function printNames(namesPathname, operation) {
|
|
|
127
136
|
* @param {string} input The string containing the model text.
|
|
128
137
|
* @param {string} modelDir The absolute path to the directory containing the mdl file.
|
|
129
138
|
* The dat, xlsx, and csv files referenced by the model will be relative to this directory.
|
|
130
|
-
* @param {
|
|
139
|
+
* @param {Object} options The options that control parsing.
|
|
140
|
+
* @param {boolean} options.sort Whether to sort definitions alphabetically in the preprocess step.
|
|
131
141
|
* @return {*} A parsed tree representation of the model.
|
|
132
142
|
*/
|
|
133
|
-
export function parseModel(input, modelDir,
|
|
134
|
-
if (process.env.SDE_NONPUBLIC_USE_NEW_PARSE === '0') {
|
|
135
|
-
// Use the legacy parser
|
|
136
|
-
return {
|
|
137
|
-
kind: 'vensim-legacy',
|
|
138
|
-
parseTree: legacyParseVensimModel(input)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
143
|
+
export function parseModel(input, modelDir, options) {
|
|
142
144
|
// Prepare the parse context that provides access to external data files
|
|
143
145
|
let parseContext /*: VensimParseContext*/
|
|
144
146
|
if (modelDir) {
|
|
@@ -160,6 +162,7 @@ export function parseModel(input, modelDir, sort = false) {
|
|
|
160
162
|
// TODO: We currently sort the preprocessed definitions alphabetically for
|
|
161
163
|
// compatibility with the legacy preprocessor. Once we drop the legacy code
|
|
162
164
|
// we could remove this step and update the tests to use the original order.
|
|
165
|
+
const sort = options?.sort === true
|
|
163
166
|
const root = parseVensimModel(input, parseContext, sort)
|
|
164
167
|
|
|
165
168
|
return {
|
|
@@ -3,14 +3,14 @@ import B from 'bufx'
|
|
|
3
3
|
import * as R from 'ramda'
|
|
4
4
|
import { splitEquations, replaceDelimitedStrings } from '../_shared/helpers.js'
|
|
5
5
|
|
|
6
|
-
export let preprocessModel = (mdlFilename, spec, profile = '
|
|
6
|
+
export let preprocessModel = (mdlFilename, spec, profile = 'runnable', writeFiles = false, outDecls = []) => {
|
|
7
7
|
const MACROS_FILENAME = 'macros.txt'
|
|
8
8
|
const REMOVALS_FILENAME = 'removals.txt'
|
|
9
9
|
const INSERTIONS_FILENAME = 'mdl-edits.txt'
|
|
10
10
|
const ENCODING = '{UTF-8}'
|
|
11
11
|
let profiles = {
|
|
12
12
|
// simplified but still runnable model
|
|
13
|
-
|
|
13
|
+
runnable: {
|
|
14
14
|
emitEncoding: true,
|
|
15
15
|
emitCommentMarkers: true,
|
|
16
16
|
joinFormulaLines: false
|