@sdeverywhere/cli 0.7.27 → 0.7.28
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/README.md +4 -25
- package/package.json +3 -3
- package/src/sde-build.js +2 -1
- package/src/sde-causes.js +7 -14
- package/src/sde-flatten.js +17 -10
- package/src/sde-generate.js +34 -15
- package/src/sde-names.js +4 -3
- package/src/sde-test.js +2 -1
package/README.md
CHANGED
|
@@ -97,7 +97,10 @@ sde bundle [--config sde.config.js] [--verbose]
|
|
|
97
97
|
sde generate --list {model}
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
#### Preprocess a model to remove macros and tabbed arrays
|
|
100
|
+
#### Preprocess a model to remove macros and tabbed arrays
|
|
101
|
+
|
|
102
|
+
_NOTE:_ For most users it is not necessary to run the preprocessor manually
|
|
103
|
+
because the transpiler runs the preprocessor automatically prior to parsing.
|
|
101
104
|
|
|
102
105
|
```
|
|
103
106
|
sde generate --preprocess {model}
|
|
@@ -204,21 +207,6 @@ There is an example in the `directdata` sample model.
|
|
|
204
207
|
}
|
|
205
208
|
```
|
|
206
209
|
|
|
207
|
-
#### Specify equations to remove from the model
|
|
208
|
-
|
|
209
|
-
When SDEverywhere cannot handle a certain Vensim construct yet, you will need to remove equations that use the construct from the model, convert it by hand into something that SDEverywhere can handle, and then insert it back into the model.
|
|
210
|
-
To have the preprocessor remove equations from the model into a `removals.txt` file, specify substrings to match in the equation in the `removalKeys` section.
|
|
211
|
-
Macros and `TABBED ARRAY` equations are already automatically removed by the preprocessor.
|
|
212
|
-
|
|
213
|
-
For instance, you could key on the variable name in the equation definition.
|
|
214
|
-
|
|
215
|
-
```json
|
|
216
|
-
"removalKeys": [
|
|
217
|
-
"varname1 =",
|
|
218
|
-
"varname2 ="
|
|
219
|
-
]
|
|
220
|
-
```
|
|
221
|
-
|
|
222
210
|
#### Generating, compiling, running, and testing the C code
|
|
223
211
|
|
|
224
212
|
To generate C code using the `--spec` argument, enter the following command:
|
|
@@ -260,15 +248,6 @@ That is, the values are separated by spaces, and each pair has an index number,
|
|
|
260
248
|
The zero-based index maps into a static array of input variable pointers held in the function.
|
|
261
249
|
These are used to set the value directly into the static `double` variable in the generated code.
|
|
262
250
|
|
|
263
|
-
#### Inserting a file into the model
|
|
264
|
-
|
|
265
|
-
Some constructs like macros are not supported by SDEverywhere.
|
|
266
|
-
They are removed from the model by the preprocessor into the `removals.txt` file.
|
|
267
|
-
You can edit these constructs into a form that SDEverywhere supports and insert them back into the model.
|
|
268
|
-
Create a file called `mdl-edits.txt` in the model directory with the constructs to insert.
|
|
269
|
-
For instance, manually expand macros and place them into the `mdl-edits.txt` file.
|
|
270
|
-
The preprocessor will read this file and insert its contents unchanged into the beginning of the model.
|
|
271
|
-
|
|
272
251
|
## License
|
|
273
252
|
|
|
274
253
|
SDEverywhere is distributed under the MIT license. See `LICENSE` for more details.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdeverywhere/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.28",
|
|
4
4
|
"description": "Contains the `sde` command line interface for the SDEverywhere tool suite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"sde": "src/main.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@sdeverywhere/build": "^0.3.
|
|
15
|
-
"@sdeverywhere/compile": "^0.7.
|
|
14
|
+
"@sdeverywhere/build": "^0.3.7",
|
|
15
|
+
"@sdeverywhere/compile": "^0.7.21",
|
|
16
16
|
"bufx": "^1.0.5",
|
|
17
17
|
"byline": "^5.0.0",
|
|
18
18
|
"ramda": "^0.27.0",
|
package/src/sde-build.js
CHANGED
package/src/sde-causes.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from 'fs'
|
|
2
|
+
|
|
3
|
+
import { parseAndGenerate } from '@sdeverywhere/compile'
|
|
2
4
|
|
|
3
5
|
import { modelPathProps, parseSpec } from './utils.js'
|
|
4
6
|
|
|
@@ -14,22 +16,13 @@ let builder = {
|
|
|
14
16
|
let handler = argv => {
|
|
15
17
|
causes(argv.model, argv.c_varname, argv)
|
|
16
18
|
}
|
|
17
|
-
let causes = (model, varname, opts) => {
|
|
19
|
+
let causes = async (model, varname, opts) => {
|
|
18
20
|
// Get the model name and directory from the model argument.
|
|
19
|
-
let { modelDirname, modelPathname } = modelPathProps(model)
|
|
20
|
-
let extData = new Map()
|
|
21
|
-
let directData = new Map()
|
|
21
|
+
let { modelDirname, modelPathname, modelName } = modelPathProps(model)
|
|
22
22
|
let spec = parseSpec(opts.spec)
|
|
23
|
-
// Preprocess model text into parser input.
|
|
24
|
-
// TODO: The legacy `parseModel` function previously required the `preprocessModel`
|
|
25
|
-
// step to be performed first, but the new `parseModel` runs the preprocessor
|
|
26
|
-
// implicitly, so we can remove this step (and can simplify this code to use
|
|
27
|
-
// `parseAndGenerate` instead)
|
|
28
|
-
let input = preprocessModel(modelPathname, spec)
|
|
29
23
|
// Parse the model to get variable and subscript information.
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
generateCode(parsedModel, { spec, operations, extData, directData, modelDirname, varname })
|
|
24
|
+
let input = readFileSync(modelPathname, 'utf8')
|
|
25
|
+
await parseAndGenerate(input, spec, ['printRefGraph'], modelDirname, modelName, '', varname)
|
|
33
26
|
}
|
|
34
27
|
export default {
|
|
35
28
|
command,
|
package/src/sde-flatten.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { readFileSync } from 'fs'
|
|
1
2
|
import path from 'path'
|
|
2
3
|
|
|
3
4
|
import B from 'bufx'
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import { preprocessVensimModel } from '@sdeverywhere/compile'
|
|
6
7
|
|
|
7
8
|
import { buildDir, modelPathProps } from './utils.js'
|
|
8
9
|
|
|
@@ -44,16 +45,23 @@ const flatten = async (outFile, inFiles, opts) => {
|
|
|
44
45
|
// Get the path and short name of the input mdl file
|
|
45
46
|
const inModelProps = modelPathProps(inFile)
|
|
46
47
|
|
|
47
|
-
//
|
|
48
|
-
const
|
|
49
|
-
preprocessModel(inModelProps.modelPathname, undefined, 'runnable', false, decls)
|
|
48
|
+
// Read the mdl file content
|
|
49
|
+
const mdlContent = readFileSync(inModelProps.modelPathname, 'utf8')
|
|
50
50
|
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
// Preprocess the mdl file and extract the equations and subscript range definitions
|
|
52
|
+
const { defs } = preprocessVensimModel(mdlContent)
|
|
53
|
+
|
|
54
|
+
for (const def of defs) {
|
|
55
|
+
// Associate each definition with the name of the model from which it came
|
|
56
|
+
def.sourceModelName = inModelProps.modelName
|
|
57
|
+
|
|
58
|
+
// The object contains the preprocessed definition in a `def` property; copy this
|
|
59
|
+
// to a `processedDecl` property for clarity (since the existing code used that
|
|
60
|
+
// property name).
|
|
61
|
+
def.processedDecl = def.def
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
fileDecls[inModelProps.modelName] =
|
|
64
|
+
fileDecls[inModelProps.modelName] = defs
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
// Collapse so that we have only one equation or declaration per key.
|
|
@@ -176,9 +184,8 @@ const flatten = async (outFile, inFiles, opts) => {
|
|
|
176
184
|
B.open('pp')
|
|
177
185
|
const ENCODING = '{UTF-8}'
|
|
178
186
|
B.emitLine(ENCODING, 'pp')
|
|
179
|
-
B.emitLine('', 'pp')
|
|
180
187
|
for (const decl of sorted) {
|
|
181
|
-
B.emitLine(
|
|
188
|
+
B.emitLine(`\n${decl.processedDecl}`, 'pp')
|
|
182
189
|
}
|
|
183
190
|
|
|
184
191
|
// Write the flattened mdl file to the build directory
|
package/src/sde-generate.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
|
+
import { readFileSync } from 'fs'
|
|
2
3
|
import B from 'bufx'
|
|
3
4
|
|
|
4
|
-
import { parseAndGenerate,
|
|
5
|
+
import { parseAndGenerate, preprocessVensimModel } from '@sdeverywhere/compile'
|
|
5
6
|
|
|
6
7
|
import { buildDir, modelPathProps, parseSpec } from './utils.js'
|
|
7
8
|
|
|
@@ -28,11 +29,6 @@ export let builder = {
|
|
|
28
29
|
type: 'boolean',
|
|
29
30
|
alias: 'p'
|
|
30
31
|
},
|
|
31
|
-
analysis: {
|
|
32
|
-
describe: 'write a nonexecutable preprocessed model for analysis',
|
|
33
|
-
type: 'boolean',
|
|
34
|
-
alias: 'a'
|
|
35
|
-
},
|
|
36
32
|
spec: {
|
|
37
33
|
describe: 'pathname of the I/O specification JSON file',
|
|
38
34
|
type: 'string',
|
|
@@ -64,16 +60,13 @@ export let generate = async (model, opts) => {
|
|
|
64
60
|
let { modelDirname, modelName, modelPathname } = modelPathProps(model)
|
|
65
61
|
// Ensure the build directory exists.
|
|
66
62
|
let buildDirname = buildDir(opts.builddir, modelDirname)
|
|
67
|
-
// Preprocess model text into parser input. Stop now if that's all we're doing.
|
|
68
63
|
let spec = parseSpec(opts.spec)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
let input = preprocessModel(modelPathname, spec, profile, writeFiles)
|
|
74
|
-
if (writeFiles) {
|
|
64
|
+
let mdlContent = readFileSync(modelPathname, 'utf8')
|
|
65
|
+
if (opts.preprocess) {
|
|
66
|
+
// Only run the preprocessor.
|
|
67
|
+
let preprocessed = preprocessModel(mdlContent)
|
|
75
68
|
let outputPathname = path.join(buildDirname, `${modelName}.mdl`)
|
|
76
|
-
B.write(
|
|
69
|
+
B.write(preprocessed, outputPathname)
|
|
77
70
|
process.exit(0)
|
|
78
71
|
}
|
|
79
72
|
// Parse the model and generate code. If no operation is specified, the code generator will
|
|
@@ -94,7 +87,7 @@ export let generate = async (model, opts) => {
|
|
|
94
87
|
if (opts.refidtest) {
|
|
95
88
|
operations.push('printRefIdTest')
|
|
96
89
|
}
|
|
97
|
-
await parseAndGenerate(
|
|
90
|
+
await parseAndGenerate(mdlContent, spec, operations, modelDirname, modelName, buildDirname)
|
|
98
91
|
}
|
|
99
92
|
|
|
100
93
|
export default {
|
|
@@ -104,3 +97,29 @@ export default {
|
|
|
104
97
|
handler,
|
|
105
98
|
generate
|
|
106
99
|
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Read and preprocess the given Vensim model content.
|
|
103
|
+
*
|
|
104
|
+
* @param {string} mdlContent The mdl content.
|
|
105
|
+
* @return {string} The preprocessed mdl text.
|
|
106
|
+
*/
|
|
107
|
+
function preprocessModel(mdlContent) {
|
|
108
|
+
// Run the preprocessor
|
|
109
|
+
const { defs } = preprocessVensimModel(mdlContent)
|
|
110
|
+
|
|
111
|
+
// Sort the definitions alphabetically by key. This mainly exists for compatibility
|
|
112
|
+
// with the legacy `sde generate --preprocess` command, which was changed in #55 to
|
|
113
|
+
// sort definitions alphabetically.
|
|
114
|
+
defs.sort((a, b) => {
|
|
115
|
+
return a.key < b.key ? -1 : a.key > b.key ? 1 : 0
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
// Join the preprocessed definitions into a single string
|
|
119
|
+
let text = '{UTF-8}\n'
|
|
120
|
+
for (const def of defs) {
|
|
121
|
+
text += `\n${def.def}\n`
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return text
|
|
125
|
+
}
|
package/src/sde-names.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from 'fs'
|
|
2
|
+
|
|
3
|
+
import { parseAndGenerate, printNames } from '@sdeverywhere/compile'
|
|
2
4
|
|
|
3
5
|
import { modelPathProps, parseSpec } from './utils.js'
|
|
4
6
|
|
|
@@ -26,9 +28,8 @@ let names = async (model, namesPathname, opts) => {
|
|
|
26
28
|
// Get the model name and directory from the model argument.
|
|
27
29
|
let { modelDirname, modelPathname, modelName } = modelPathProps(model)
|
|
28
30
|
let spec = parseSpec(opts.spec)
|
|
29
|
-
// Preprocess model text into parser input.
|
|
30
|
-
let input = preprocessModel(modelPathname, spec)
|
|
31
31
|
// Parse the model to get variable and subscript information.
|
|
32
|
+
let input = readFileSync(modelPathname, 'utf8')
|
|
32
33
|
await parseAndGenerate(input, spec, ['convertNames'], modelDirname, modelName, '')
|
|
33
34
|
// Read each variable name from the names file and convert it.
|
|
34
35
|
printNames(namesPathname, opts.toc ? 'to-c' : 'to-vensim')
|
package/src/sde-test.js
CHANGED