@sdeverywhere/compile 0.7.18 → 0.7.20
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 -2
- package/src/model/model.js +80 -25
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdeverywhere/compile",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.20",
|
|
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
|
-
"@sdeverywhere/parse": "^0.1.
|
|
8
|
+
"@sdeverywhere/parse": "^0.1.1",
|
|
9
9
|
"bufx": "^1.0.5",
|
|
10
10
|
"byline": "^5.0.0",
|
|
11
11
|
"csv-parse": "^5.3.3",
|
package/src/model/model.js
CHANGED
|
@@ -25,6 +25,7 @@ import Variable from './variable.js'
|
|
|
25
25
|
let variables = []
|
|
26
26
|
let inputVars = []
|
|
27
27
|
let constantExprs = new Map()
|
|
28
|
+
let cachedSortedVarsByType = new Map()
|
|
28
29
|
let cachedVarIndexInfo
|
|
29
30
|
let cachedJsonList
|
|
30
31
|
|
|
@@ -46,6 +47,7 @@ function resetModelState() {
|
|
|
46
47
|
variablesByName.clear()
|
|
47
48
|
constantExprs.clear()
|
|
48
49
|
nonAtoANames = Object.create(null)
|
|
50
|
+
cachedSortedVarsByType.clear()
|
|
49
51
|
cachedVarIndexInfo = undefined
|
|
50
52
|
cachedJsonList = undefined
|
|
51
53
|
}
|
|
@@ -439,8 +441,8 @@ function resolveDuplicateDeclarations() {
|
|
|
439
441
|
// Least and greatest safe double values in C rounded to convenient consts
|
|
440
442
|
const MIN_SAFE_DBL = -1e308
|
|
441
443
|
const MAX_SAFE_DBL = 1e308
|
|
442
|
-
let data =
|
|
443
|
-
for (let constVar of
|
|
444
|
+
let data = varsOfType('data')
|
|
445
|
+
for (let constVar of varsOfType('const')) {
|
|
444
446
|
if (data.find(d => d.varName === constVar.varName)) {
|
|
445
447
|
// Change the var type from const to data and add lookup data points.
|
|
446
448
|
// For a constant, the equivalent lookup has the same value over the entire x axis.
|
|
@@ -524,26 +526,53 @@ function allVars() {
|
|
|
524
526
|
}
|
|
525
527
|
return R.filter(isNotPlaceholderVar, variables)
|
|
526
528
|
}
|
|
529
|
+
function cachedSortedVars(varType, generate) {
|
|
530
|
+
// Return the cached array of sorted variables for the given type if
|
|
531
|
+
// available, otherwise call the `generate` function to generate the
|
|
532
|
+
// array and cache it in the map.
|
|
533
|
+
let vars = cachedSortedVarsByType.get(varType)
|
|
534
|
+
if (!vars) {
|
|
535
|
+
vars = generate()
|
|
536
|
+
cachedSortedVarsByType.set(varType, vars)
|
|
537
|
+
}
|
|
538
|
+
return vars
|
|
539
|
+
}
|
|
527
540
|
function constVars() {
|
|
528
|
-
|
|
541
|
+
// Return an array of vars of type `const`, sorted by LHS variable name.
|
|
542
|
+
// Note that this caches the result, so should only be called after the
|
|
543
|
+
// model has been fully read and analyzed.
|
|
544
|
+
return cachedSortedVars('const', () => vsort(varsOfType('const')))
|
|
529
545
|
}
|
|
530
546
|
function lookupVars() {
|
|
531
|
-
|
|
547
|
+
// Return an array of vars of type `lookup`, sorted by LHS variable name.
|
|
548
|
+
// Note that this caches the result, so should only be called after the
|
|
549
|
+
// model has been fully read and analyzed.
|
|
550
|
+
return cachedSortedVars('lookup', () => vsort(varsOfType('lookup')))
|
|
532
551
|
}
|
|
533
552
|
function dataVars() {
|
|
534
|
-
|
|
553
|
+
// Return an array of vars of type `data`, sorted by LHS variable name.
|
|
554
|
+
// Note that this caches the result, so should only be called after the
|
|
555
|
+
// model has been fully read and analyzed.
|
|
556
|
+
return cachedSortedVars('data', () => vsort(varsOfType('data')))
|
|
535
557
|
}
|
|
536
558
|
function auxVars() {
|
|
537
|
-
//
|
|
538
|
-
|
|
559
|
+
// Return an array of vars of type `aux`, sorted according to the dependency graph.
|
|
560
|
+
// Note that this caches the result, so should only be called after the
|
|
561
|
+
// model has been fully read and analyzed.
|
|
562
|
+
return cachedSortedVars('aux', () => sortVarsOfType('aux'))
|
|
539
563
|
}
|
|
540
564
|
function levelVars() {
|
|
541
|
-
//
|
|
542
|
-
|
|
565
|
+
// Return an array of vars of type `level`, sorted according to the dependency graph.
|
|
566
|
+
// Note that this caches the result, so should only be called after the
|
|
567
|
+
// model has been fully read and analyzed.
|
|
568
|
+
return cachedSortedVars('level', () => sortVarsOfType('level'))
|
|
543
569
|
}
|
|
544
570
|
function initVars() {
|
|
545
|
-
//
|
|
546
|
-
|
|
571
|
+
// Return an array of all vars that have the `hasInitValue` flag set to true,
|
|
572
|
+
// sorted according to the dependency graph.
|
|
573
|
+
// Note that this caches the result, so should only be called after the
|
|
574
|
+
// model has been fully read and analyzed.
|
|
575
|
+
return cachedSortedVars('init', () => sortInitVars())
|
|
547
576
|
}
|
|
548
577
|
function varWithRefId(refId) {
|
|
549
578
|
const findVarWithRefId = rid => {
|
|
@@ -1055,26 +1084,52 @@ function printDepsGraph(graph, varType) {
|
|
|
1055
1084
|
|
|
1056
1085
|
function allListedVars() {
|
|
1057
1086
|
// Put variables into the order that they are evaluated by SDE in the generated model
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
vars
|
|
1061
|
-
|
|
1087
|
+
const listedVars = []
|
|
1088
|
+
const visitedRefIds = new Set()
|
|
1089
|
+
function addUnique(vars) {
|
|
1090
|
+
for (const v of vars) {
|
|
1091
|
+
// Skip variables that have already been visited
|
|
1092
|
+
if (visitedRefIds.has(v.refId)) {
|
|
1093
|
+
continue
|
|
1094
|
+
}
|
|
1095
|
+
visitedRefIds.add(v.refId)
|
|
1096
|
+
|
|
1097
|
+
// Filter out variables that are generated/used internally
|
|
1098
|
+
if (v.includeInOutput === false) {
|
|
1099
|
+
continue
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
// Include the variable
|
|
1103
|
+
listedVars.push(v)
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
// 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)
|
|
1114
|
+
// So to make the ordering in the listing better match the order of evaluation,
|
|
1115
|
+
// we emit variables in the above order, but filter to avoid having duplicates.
|
|
1116
|
+
addUnique(constVars())
|
|
1117
|
+
addUnique(lookupVars())
|
|
1118
|
+
addUnique(dataVars())
|
|
1062
1119
|
// The special exogenous `Time` variable may have already been removed by
|
|
1063
1120
|
// `removeUnusedVariables` if it is not referenced explicitly in the model,
|
|
1064
|
-
// so we will only include it in the listing if it is defined here
|
|
1121
|
+
// so we will only include it in the listing if it is defined here. Note
|
|
1122
|
+
// that `_time` is set to `_initial_time` as the first step in the
|
|
1123
|
+
// `initLevels` function, which is why it is included here.
|
|
1065
1124
|
const timeVar = varWithName('_time')
|
|
1066
1125
|
if (timeVar) {
|
|
1067
|
-
|
|
1068
|
-
}
|
|
1069
|
-
vars.push(...auxVars())
|
|
1070
|
-
vars.push(...levelVars())
|
|
1071
|
-
|
|
1072
|
-
// Filter out variables that are generated/used internally
|
|
1073
|
-
const isInternal = v => {
|
|
1074
|
-
return v.includeInOutput === false
|
|
1126
|
+
addUnique([timeVar])
|
|
1075
1127
|
}
|
|
1128
|
+
addUnique(initVars())
|
|
1129
|
+
addUnique(auxVars())
|
|
1130
|
+
addUnique(levelVars())
|
|
1076
1131
|
|
|
1077
|
-
return
|
|
1132
|
+
return listedVars
|
|
1078
1133
|
}
|
|
1079
1134
|
|
|
1080
1135
|
function filteredListedVars() {
|