@sdeverywhere/compile 0.7.11 → 0.7.13
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 -1
- package/src/_shared/helpers.js +0 -4
- package/src/_shared/read-dat.js +11 -2
- package/src/generate/code-gen.js +21 -25
- package/src/model/model.js +21 -28
- package/src/model/toposort.js +1 -1
package/package.json
CHANGED
package/src/_shared/helpers.js
CHANGED
package/src/_shared/read-dat.js
CHANGED
|
@@ -35,8 +35,16 @@ export async function readDat(pathname, prefix = '') {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
return new Promise(resolve => {
|
|
39
|
-
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
// Errors from the read stream aren't propagated by the byline package
|
|
40
|
+
// so we attach the error handler to `readStream` rather than to `stream`
|
|
41
|
+
let readStream = fs.createReadStream(pathname, 'utf8')
|
|
42
|
+
let stream = byline(readStream)
|
|
43
|
+
readStream.on('error', e => {
|
|
44
|
+
stream.destroy()
|
|
45
|
+
reject(new Error(`Failed to read dat file: ${e.message}`))
|
|
46
|
+
})
|
|
47
|
+
|
|
40
48
|
stream.on('data', line => {
|
|
41
49
|
let values = splitDatLine(line)
|
|
42
50
|
if (values.length === 1) {
|
|
@@ -63,6 +71,7 @@ export async function readDat(pathname, prefix = '') {
|
|
|
63
71
|
lineNum++
|
|
64
72
|
// if (lineNum % 1e5 === 0) console.log(num(lineNum).format('0,0'))
|
|
65
73
|
})
|
|
74
|
+
|
|
66
75
|
stream.on('end', () => {
|
|
67
76
|
addValues()
|
|
68
77
|
resolve(log)
|
package/src/generate/code-gen.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as R from 'ramda'
|
|
2
2
|
|
|
3
|
-
import { asort, lines, strlist,
|
|
3
|
+
import { asort, lines, strlist, mapIndexed } from '../_shared/helpers.js'
|
|
4
4
|
import { sub, allDimensions, allMappings, subscriptFamilies } from '../_shared/subscript.js'
|
|
5
5
|
import Model from '../model/model.js'
|
|
6
6
|
|
|
@@ -37,30 +37,26 @@ let codeGenerator = (parsedModel, opts) => {
|
|
|
37
37
|
function generate() {
|
|
38
38
|
// Read variables and subscript ranges from the model parse tree.
|
|
39
39
|
// This is the main entry point for code generation and is called just once.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return code
|
|
61
|
-
}
|
|
62
|
-
} catch (e) {
|
|
63
|
-
abend(e)
|
|
40
|
+
Model.read(parsedModel, spec, extData, directData, modelDirname)
|
|
41
|
+
// In list mode, print variables to the console instead of generating code.
|
|
42
|
+
if (operations.includes('printRefIdTest')) {
|
|
43
|
+
Model.printRefIdTest()
|
|
44
|
+
}
|
|
45
|
+
if (operations.includes('printRefGraph')) {
|
|
46
|
+
Model.printRefGraph(opts.varname)
|
|
47
|
+
}
|
|
48
|
+
if (operations.includes('convertNames')) {
|
|
49
|
+
// Do not generate output, but leave the results of model analysis.
|
|
50
|
+
}
|
|
51
|
+
if (operations.includes('generateC')) {
|
|
52
|
+
// Generate code for each variable in the proper order.
|
|
53
|
+
let code = emitDeclCode()
|
|
54
|
+
code += emitInitLookupsCode()
|
|
55
|
+
code += emitInitConstantsCode()
|
|
56
|
+
code += emitInitLevelsCode()
|
|
57
|
+
code += emitEvalCode()
|
|
58
|
+
code += emitIOCode()
|
|
59
|
+
return code
|
|
64
60
|
}
|
|
65
61
|
}
|
|
66
62
|
|
package/src/model/model.js
CHANGED
|
@@ -395,14 +395,12 @@ function removeUnusedVariables(spec) {
|
|
|
395
395
|
// ensures that we include all subscripts for a variable, which might mean we
|
|
396
396
|
// include some subscripts that aren't needed, but it is safer than trying to
|
|
397
397
|
// eliminate those and possibly omit something that is needed.
|
|
398
|
-
const referencedVarNames =
|
|
398
|
+
const referencedVarNames = new Set()
|
|
399
399
|
|
|
400
400
|
// Add the given variable name to the list of referenced variables, if it's not
|
|
401
401
|
// already there.
|
|
402
402
|
const recordUsedVarName = varName => {
|
|
403
|
-
|
|
404
|
-
referencedVarNames.push(varName)
|
|
405
|
-
}
|
|
403
|
+
referencedVarNames.add(varName)
|
|
406
404
|
}
|
|
407
405
|
|
|
408
406
|
// Add the given variable to the list of referenced variables, and do the same for
|
|
@@ -443,20 +441,23 @@ function removeUnusedVariables(spec) {
|
|
|
443
441
|
// that are referenced by this variable, either directly (`v.references`) or
|
|
444
442
|
// in an "INITIAL" expression (`v.initReferences`). It's OK if we end up with
|
|
445
443
|
// duplicates in this list, because we will examine each reference only once.
|
|
446
|
-
let
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
444
|
+
let refStack = []
|
|
445
|
+
function pushRefs(v) {
|
|
446
|
+
refStack.push(...refIdsWithName(v.varName))
|
|
447
|
+
refStack.push(...v.references)
|
|
448
|
+
refStack.push(...v.initReferences)
|
|
449
|
+
}
|
|
450
|
+
pushRefs(v)
|
|
451
|
+
while (refStack.length > 0) {
|
|
452
|
+
const refId = refStack.pop()
|
|
450
453
|
if (!referencedRefIds.has(refId)) {
|
|
451
454
|
referencedRefIds.add(refId)
|
|
452
455
|
const refVar = varWithRefId(refId)
|
|
453
456
|
if (refVar) {
|
|
454
457
|
recordUsedVariable(refVar)
|
|
455
|
-
|
|
458
|
+
pushRefs(refVar)
|
|
456
459
|
} else {
|
|
457
|
-
|
|
458
|
-
console.error(v)
|
|
459
|
-
process.exit(1)
|
|
460
|
+
throw new Error(`No var found for ${refId} when recording references for ${v.varName}`)
|
|
460
461
|
}
|
|
461
462
|
}
|
|
462
463
|
}
|
|
@@ -470,7 +471,11 @@ function removeUnusedVariables(spec) {
|
|
|
470
471
|
|
|
471
472
|
// Keep all input variables
|
|
472
473
|
for (const inputVarName of spec.inputVars) {
|
|
473
|
-
|
|
474
|
+
// The inputVars can include a raw index, e.g. `_input_var[0]`,
|
|
475
|
+
// which isn't an actual "ref id", so we'll just derive the
|
|
476
|
+
// var name by chopping off the index part.
|
|
477
|
+
const inputVarBaseName = inputVarName.split('[')[0]
|
|
478
|
+
for (const v of varsWithName(inputVarBaseName)) {
|
|
474
479
|
recordUsedVariable(v)
|
|
475
480
|
}
|
|
476
481
|
}
|
|
@@ -488,7 +493,7 @@ function removeUnusedVariables(spec) {
|
|
|
488
493
|
}
|
|
489
494
|
|
|
490
495
|
// Filter out unneeded variables so we're left with the minimal set of variables to emit
|
|
491
|
-
variables = R.filter(v => referencedVarNames.
|
|
496
|
+
variables = R.filter(v => referencedVarNames.has(v.varName), variables)
|
|
492
497
|
|
|
493
498
|
// Rebuild the variables-by-name map
|
|
494
499
|
variablesByName.clear()
|
|
@@ -877,13 +882,7 @@ function sortVarsOfType(varType) {
|
|
|
877
882
|
// Sort into an lhs dependency list.
|
|
878
883
|
if (PRINT_AUX_GRAPH) printDepsGraph(graph, 'AUX')
|
|
879
884
|
if (PRINT_LEVEL_GRAPH) printDepsGraph(graph, 'LEVEL')
|
|
880
|
-
let deps
|
|
881
|
-
try {
|
|
882
|
-
deps = toposort(graph).reverse()
|
|
883
|
-
} catch (e) {
|
|
884
|
-
console.error(e.message)
|
|
885
|
-
process.exit(1)
|
|
886
|
-
}
|
|
885
|
+
let deps = toposort(graph).reverse()
|
|
887
886
|
|
|
888
887
|
// Turn the dependency-sorted var name list into a var list.
|
|
889
888
|
let sortedVars = varsOfType(
|
|
@@ -978,13 +977,7 @@ function sortInitVars() {
|
|
|
978
977
|
if (PRINT_INIT_GRAPH) printDepsGraph(graph, 'INIT')
|
|
979
978
|
|
|
980
979
|
// Sort into a reference id dependency list.
|
|
981
|
-
let deps
|
|
982
|
-
try {
|
|
983
|
-
deps = toposort(graph).reverse()
|
|
984
|
-
} catch (e) {
|
|
985
|
-
console.error(e.message)
|
|
986
|
-
process.exit(1)
|
|
987
|
-
}
|
|
980
|
+
let deps = toposort(graph).reverse()
|
|
988
981
|
|
|
989
982
|
// Turn the reference id list into a var list.
|
|
990
983
|
let sortedVars = R.map(refId => varWithRefId(refId), deps)
|
package/src/model/toposort.js
CHANGED
|
@@ -42,7 +42,7 @@ function toposort(nodes, edges) {
|
|
|
42
42
|
} catch (e) {
|
|
43
43
|
nodeRep = ''
|
|
44
44
|
}
|
|
45
|
-
throw new Error('
|
|
45
|
+
throw new Error('Found cyclic dependency during toposort:\n' + [...predecessors].join(' →\n') + nodeRep)
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
if (!nodesHash.has(node)) {
|