entodicton 9.7.1-beta.1 → 9.7.1-beta.11
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/client.js +20 -17
- package/index.js +3 -2
- package/package.json +1 -1
- package/src/config.js +16 -2
- package/src/configHelpers.js +14 -1
- package/src/debug.js +17 -2
- package/src/flatten.js +9 -17
- package/src/fragments.js +29 -2
- package/src/generators.js +20 -15
- package/src/helpers.js +26 -0
- package/src/semantics.js +34 -24
package/client.js
CHANGED
|
@@ -12,7 +12,7 @@ const _ = require('lodash')
|
|
|
12
12
|
const stringify = require('json-stable-stringify')
|
|
13
13
|
const Lines = require('./lines')
|
|
14
14
|
const flattens = require('./src/flatten')
|
|
15
|
-
const { sortJson, appendNoDups, InitCalls, updateQueries, safeNoDups, stableId, where, suggestAssociationsFix, suggestAssociationsFixFromSummaries, validProps } = require('./src/helpers')
|
|
15
|
+
const { helpDebugHierarchy, sortJson, appendNoDups, InitCalls, updateQueries, safeNoDups, stableId, where, suggestAssociationsFix, suggestAssociationsFixFromSummaries, validProps, OverrideCheck, } = require('./src/helpers')
|
|
16
16
|
const runtime = require('./runtime')
|
|
17
17
|
const db = require('./src/debug')
|
|
18
18
|
|
|
@@ -479,7 +479,7 @@ const getConfigForTest = (config, testConfig) => {
|
|
|
479
479
|
return configForTest
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
-
const runTest = async (config, expected, { args, verbose, testConfig, debug, timings = { server: 0, client: 0 } }) => {
|
|
482
|
+
const runTest = async (config, expected, { args, verbose, testConfig, debug, timings = { server: 0, client: 0 }, index = 0 }) => {
|
|
483
483
|
const test = expected.query
|
|
484
484
|
if (args.query && args.query != test) {
|
|
485
485
|
// no run this
|
|
@@ -512,10 +512,11 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug, tim
|
|
|
512
512
|
defaultInnerProcess(config, errorHandler, result)
|
|
513
513
|
}
|
|
514
514
|
if (verbose) {
|
|
515
|
-
const widths = [100, 60]
|
|
515
|
+
const widths = [4, 100, 60]
|
|
516
516
|
const lines = new Lines(widths)
|
|
517
|
-
lines.setElement(0, 0,
|
|
518
|
-
lines.setElement(0, 1,
|
|
517
|
+
lines.setElement(0, 0, index)
|
|
518
|
+
lines.setElement(0, 1, test)
|
|
519
|
+
lines.setElement(0, 2, `time on server: ${result.times.toFixed(2)} client: ${(result.clientSideTimes / 1000).toFixed(2)}`)
|
|
519
520
|
timings.server += result.times
|
|
520
521
|
timings.client += result.clientSideTimes / 1000
|
|
521
522
|
lines.log()
|
|
@@ -618,18 +619,22 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug, tim
|
|
|
618
619
|
|
|
619
620
|
const runTestsHelper = async (config, tests, failed, juicyBits) => {
|
|
620
621
|
const { stopAtFirstError } = juicyBits
|
|
622
|
+
let index = 0
|
|
621
623
|
while (true) {
|
|
622
624
|
if (tests.length === 0) {
|
|
623
625
|
return Promise.resolve(failed)
|
|
624
626
|
}
|
|
625
627
|
const test = tests.shift()
|
|
628
|
+
juicyBits.index = index
|
|
626
629
|
const result = await runTest(config, test, juicyBits)
|
|
627
630
|
if (result != null) {
|
|
631
|
+
result.index = index
|
|
628
632
|
failed.push(result)
|
|
629
633
|
if (stopAtFirstError) {
|
|
630
634
|
return failed
|
|
631
635
|
}
|
|
632
636
|
}
|
|
637
|
+
index += 1
|
|
633
638
|
}
|
|
634
639
|
}
|
|
635
640
|
|
|
@@ -678,13 +683,6 @@ const saveTests = (config, testFile, testConfig) => {
|
|
|
678
683
|
return saveTestsHelper(testFile, config, tests, tests.map((test) => test.query), testConfig)
|
|
679
684
|
}
|
|
680
685
|
|
|
681
|
-
/*
|
|
682
|
-
const showExamples = (testFile) => {
|
|
683
|
-
const tests = JSON.parse(fs.readFileSync(testFile))
|
|
684
|
-
Object.keys(tests).forEach((test) => console.log(test))
|
|
685
|
-
}
|
|
686
|
-
*/
|
|
687
|
-
|
|
688
686
|
const showInfo = (description, section, config) => {
|
|
689
687
|
console.log(JSON.stringify(config.getInfo(), null, 2))
|
|
690
688
|
}
|
|
@@ -1314,7 +1312,6 @@ const knowledgeModuleImpl = async ({
|
|
|
1314
1312
|
|
|
1315
1313
|
const helpDebugWord = 'In order to get a debug break when a specific word is created set the DEBUG_WORD environment variable to the JSON of the association to break on. For example DEBUG_WORD=\'"the"\''
|
|
1316
1314
|
const helpDebugAssociation = 'In order to get a debug break when a specific association is created set the DEBUG_ASSOCIATION environment variable to the JSON of the association to break on. For example DEBUG_ASSOCIATION=\'[["the", 0], ["mammal", 1]]\''
|
|
1317
|
-
const helpDebugHierarchy = 'In order to get a debug break when a specific hierarchy is created set the DEBUG_HIERARCHY environment variable to the JSON of the child-parent pair to break on. For example DEBUG_HIERARCHY=\'[["cat", 1], ["mammel", 1]]\''
|
|
1318
1315
|
const helpDebugPriority = 'In order to get a debug break when a specific set of priorities is created set set DEBUG_PRIORITY environment variable to the JSON of the priorities that you want to break on. For example DEBUG_PRIORITY=\'[["verb", 0], ["article", 0]]\''
|
|
1319
1316
|
const helpDebugContextualPriority = 'In order to get a debug break when a specific set of contextual priorities is created set set DEBUG_CONTEXTUAL_PRIORITY environment variable to the JSON of the priorities that you want to break on. For example DEBUG_CONTEXTUAL_PRIORITY=\'{ context: [["verb", 0], ["article", 0], select: 1}\''
|
|
1320
1317
|
const helpDebugBridge = 'In order to get a debug break when a specific bridge is created set the DEBUG_BRIDGE environment variable to id to break on. For example DEBUG_BRIDGE=\'car\''
|
|
@@ -1528,7 +1525,7 @@ const knowledgeModuleImpl = async ({
|
|
|
1528
1525
|
console.log('Test queries')
|
|
1529
1526
|
let counter = 0
|
|
1530
1527
|
for (const test of config.tests) {
|
|
1531
|
-
console.log(
|
|
1528
|
+
console.log(`#${counter} - ${test.query}`)
|
|
1532
1529
|
counter += 1
|
|
1533
1530
|
}
|
|
1534
1531
|
}
|
|
@@ -1757,7 +1754,7 @@ const knowledgeModuleImpl = async ({
|
|
|
1757
1754
|
if (hasError) {
|
|
1758
1755
|
console.log('**************************** ERRORS ************************')
|
|
1759
1756
|
for (const result of results) {
|
|
1760
|
-
console.log(
|
|
1757
|
+
console.log(`Utterance: #${result.index} ${result.utterance}`)
|
|
1761
1758
|
if (!result.hasError) {
|
|
1762
1759
|
continue
|
|
1763
1760
|
}
|
|
@@ -1773,7 +1770,7 @@ const knowledgeModuleImpl = async ({
|
|
|
1773
1770
|
newError = true
|
|
1774
1771
|
headerShown = true
|
|
1775
1772
|
if (args.vimdiff) {
|
|
1776
|
-
vimdiff(actual, expected, `"${label} - ${result.utterance}"`)
|
|
1773
|
+
vimdiff(actual, expected, `"${label} - #${result.index} ${result.utterance}"`)
|
|
1777
1774
|
}
|
|
1778
1775
|
result.hasError = true
|
|
1779
1776
|
}
|
|
@@ -1916,12 +1913,17 @@ const knowledgeModuleImpl = async ({
|
|
|
1916
1913
|
console.log('use -v arg to write files expected.json and actual.json in the current directory for detailed comparison. Or do -s and then git diff the changes.')
|
|
1917
1914
|
// console.log(JSON.stringify(contexts))
|
|
1918
1915
|
let errorCount = 0
|
|
1916
|
+
const failedTests = []
|
|
1919
1917
|
for (const result of results) {
|
|
1920
1918
|
if (result.hasError) {
|
|
1921
|
-
console.log(`FAILED ${result.utterance}`)
|
|
1919
|
+
console.log(`FAILED #${result.index} ${result.utterance}`)
|
|
1920
|
+
failedTests.push({ index: result.index, utterance: result.utterance })
|
|
1922
1921
|
errorCount += 1
|
|
1923
1922
|
}
|
|
1924
1923
|
}
|
|
1924
|
+
const failedFile = './FAILED.json'
|
|
1925
|
+
console.log(`Failed tests are written to ${failedFile}`)
|
|
1926
|
+
runtime.fs.writeFileSync(failedFile, JSON.stringify(failedTests, 0, 2))
|
|
1925
1927
|
console.log(`**************************** THERE WERE ${errorCount} TEST FAILURES ************************`)
|
|
1926
1928
|
}
|
|
1927
1929
|
}
|
|
@@ -2104,4 +2106,5 @@ module.exports = {
|
|
|
2104
2106
|
writeTest,
|
|
2105
2107
|
getConfigForTest,
|
|
2106
2108
|
debug: db,
|
|
2109
|
+
OverrideCheck,
|
|
2107
2110
|
}
|
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Semantics, Semantic } = require('./src/semantics')
|
|
2
2
|
const { Generators, Generator } = require('./src/generators')
|
|
3
3
|
const { Config } = require('./src/config')
|
|
4
|
-
const { w, where } = require('./src/helpers')
|
|
4
|
+
const { w, where, OverrideCheck } = require('./src/helpers')
|
|
5
5
|
const Digraph = require('./src/digraph')
|
|
6
6
|
const client = require('./client')
|
|
7
7
|
const flattens = require('./src/flatten')
|
|
@@ -28,5 +28,6 @@ module.exports = {
|
|
|
28
28
|
flattens: flattens.flattens,
|
|
29
29
|
flatten: flattens.flatten,
|
|
30
30
|
unflatten: unflatten.unflatten,
|
|
31
|
-
debug
|
|
31
|
+
debug,
|
|
32
|
+
OverrideCheck,
|
|
32
33
|
}
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -454,7 +454,7 @@ const handleBridgeProps = (config, bridge, { addFirst, uuid } = {}) => {
|
|
|
454
454
|
// match: async (args) => bridge.id === args.context.marker && args.context.level === level && !args.context.paraphrase && (args.context.response || args.context.isResponse) && await match(args),
|
|
455
455
|
match: async (args) => {
|
|
456
456
|
if (bridge.callId == args.callId) {
|
|
457
|
-
debugger
|
|
457
|
+
debugger // eslint-disable-line no-debugger
|
|
458
458
|
}
|
|
459
459
|
return args.isA(args.context.marker, bridge.id) && args.context.level === level && !args.context.paraphrase && (args.context.response != null || args.context.isResponse) && await match(args)
|
|
460
460
|
},
|
|
@@ -572,6 +572,7 @@ const handleCalculatedProps = (baseConfig, moreConfig, { addFirst, uuid } = {})
|
|
|
572
572
|
'operator',
|
|
573
573
|
'optional',
|
|
574
574
|
'parents',
|
|
575
|
+
'preferOver',
|
|
575
576
|
'return_type_selector',
|
|
576
577
|
'scope',
|
|
577
578
|
'selector',
|
|
@@ -601,7 +602,12 @@ const handleCalculatedProps = (baseConfig, moreConfig, { addFirst, uuid } = {})
|
|
|
601
602
|
}
|
|
602
603
|
|
|
603
604
|
if (runtime.process.env.DEBUG_HIERARCHY) {
|
|
604
|
-
|
|
605
|
+
try {
|
|
606
|
+
global.entodictonDebugHierarchy = JSON.parse(runtime.process.env.DEBUG_HIERARCHY)
|
|
607
|
+
} catch( e ) {
|
|
608
|
+
console.error("Invalid valid for DEBUG_HIERARCHY")
|
|
609
|
+
console.error(helpers.helpDebugHierarchy)
|
|
610
|
+
}
|
|
605
611
|
}
|
|
606
612
|
|
|
607
613
|
// i keep randomly doing one of the other so I will just make both work the same way
|
|
@@ -1655,6 +1661,7 @@ class Config {
|
|
|
1655
1661
|
}
|
|
1656
1662
|
}
|
|
1657
1663
|
|
|
1664
|
+
// handler/listener
|
|
1658
1665
|
updateBridge(id, updater) {
|
|
1659
1666
|
const bridge = this.config.bridges.find((b) => b.id === id)
|
|
1660
1667
|
updater({ config: this, bridge })
|
|
@@ -2313,6 +2320,7 @@ class Config {
|
|
|
2313
2320
|
}
|
|
2314
2321
|
}
|
|
2315
2322
|
|
|
2323
|
+
// TODO Api or API -> pick one and do that
|
|
2316
2324
|
async setMultiApi (initializer) {
|
|
2317
2325
|
await this.setApi(() => multiApiImpl(initializer))
|
|
2318
2326
|
}
|
|
@@ -2420,11 +2428,17 @@ class Config {
|
|
|
2420
2428
|
if (!api.initialize) {
|
|
2421
2429
|
throw new Error(`Expected the API for ${this.name} to have an initialize function.`)
|
|
2422
2430
|
}
|
|
2431
|
+
if (api.baseAPI) {
|
|
2432
|
+
new helpers.OverrideCheck(api.baseAPI).check(api)
|
|
2433
|
+
}
|
|
2423
2434
|
}
|
|
2424
2435
|
} else {
|
|
2425
2436
|
if (!value.initialize) {
|
|
2426
2437
|
throw new Error(`Expected the API to have an initialize function for ${this.name}. If you are trying to pass in multiple API configs at once use setApiKMs to set the names of the configs that you want set.`)
|
|
2427
2438
|
}
|
|
2439
|
+
if (value.baseAPI) {
|
|
2440
|
+
new helpers.OverrideCheck(value.baseAPI).check(value)
|
|
2441
|
+
}
|
|
2428
2442
|
}
|
|
2429
2443
|
|
|
2430
2444
|
if (this._api && this._api.multiApi) {
|
package/src/configHelpers.js
CHANGED
|
@@ -145,6 +145,7 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
|
|
|
145
145
|
args.objects = config.get('objects')
|
|
146
146
|
args.getObjects = getObjects(args.objects)
|
|
147
147
|
}
|
|
148
|
+
args.debug = debug
|
|
148
149
|
args.enable = (key) => {
|
|
149
150
|
config.addEnable(key)
|
|
150
151
|
}
|
|
@@ -163,7 +164,19 @@ const setupArgs = (args, config, logs, hierarchy, uuidForScoping) => {
|
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
args.contextHierarchy = new ContextHierarchy()
|
|
166
|
-
args.
|
|
167
|
+
args.namespaced = {
|
|
168
|
+
get: (km, context, property) => {
|
|
169
|
+
context.namespaced ??= {}
|
|
170
|
+
context.namespaced[km] ??= {}
|
|
171
|
+
return context.namespaced[km][property]
|
|
172
|
+
},
|
|
173
|
+
set: (km, context, property, value) => {
|
|
174
|
+
context.namespaced ??= {}
|
|
175
|
+
context.namespaced[km] ??= {}
|
|
176
|
+
return context.namespaced[km][property] = value
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
args.stack = new HandlerStack()
|
|
167
180
|
args.cleanAssign = cleanAssign
|
|
168
181
|
args.km = (name) => config.getConfig(name)
|
|
169
182
|
args.api = (name) => config.getConfig(name).api
|
package/src/debug.js
CHANGED
|
@@ -27,6 +27,18 @@ const unhit = (name) => {
|
|
|
27
27
|
hits[name] = false
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
const hitScoped = async (name, call) => {
|
|
31
|
+
hit(name)
|
|
32
|
+
try {
|
|
33
|
+
const result = await call()
|
|
34
|
+
unhit(name)
|
|
35
|
+
return result
|
|
36
|
+
} catch( e ) {
|
|
37
|
+
unhit(name)
|
|
38
|
+
throw e
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
30
42
|
const wasHit = (name) => {
|
|
31
43
|
return hits[name]
|
|
32
44
|
}
|
|
@@ -64,16 +76,19 @@ const _break = (name) => {
|
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
78
|
|
|
79
|
+
const breakAt = _break;
|
|
80
|
+
|
|
67
81
|
module.exports = {
|
|
68
82
|
counter,
|
|
69
83
|
get,
|
|
70
84
|
_break, // break is a keyword
|
|
71
|
-
|
|
85
|
+
breakAt,
|
|
72
86
|
// used for tests
|
|
73
87
|
reset,
|
|
74
88
|
hit,
|
|
75
89
|
unhit,
|
|
76
90
|
wasHit,
|
|
77
91
|
getDb,
|
|
78
|
-
setDb
|
|
92
|
+
setDb,
|
|
93
|
+
hitScoped,
|
|
79
94
|
}
|
package/src/flatten.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
const { isArray, isObject, isCompound } = require('./helpers')
|
|
1
|
+
const { isArray, isObject, isCompound, } = require('./helpers')
|
|
2
|
+
const debug = require('./debug')
|
|
2
3
|
const _ = require('lodash')
|
|
3
4
|
|
|
4
|
-
const DEBUG = (
|
|
5
|
+
const DEBUG = (label, details) => {
|
|
5
6
|
// DEBUG(...args)
|
|
6
7
|
}
|
|
7
8
|
|
|
@@ -46,33 +47,24 @@ const zip = (a1, a2) => {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
const flattenListHelper = (markers, values) => {
|
|
49
|
-
const flats = []
|
|
50
50
|
let wasFlattened = false
|
|
51
|
-
|
|
51
|
+
const all = []
|
|
52
52
|
for (const value of values) {
|
|
53
53
|
if (!isCompound(value)) {
|
|
54
|
-
|
|
54
|
+
all.push([value])
|
|
55
55
|
} else {
|
|
56
56
|
const [more, wf] = flatten(markers, value)
|
|
57
57
|
if (wf) {
|
|
58
58
|
wasFlattened = wasFlattened || wf
|
|
59
|
-
|
|
59
|
+
all.push(more)
|
|
60
60
|
} else {
|
|
61
|
-
|
|
61
|
+
all.push(...more.map((m) => [m]))
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return [[singles], wasFlattened]
|
|
69
|
-
} else {
|
|
70
|
-
const results = []
|
|
71
|
-
for (const flat of cartesian(...flats)) {
|
|
72
|
-
results.push(singles.concat(flat))
|
|
73
|
-
}
|
|
74
|
-
return [results, wasFlattened]
|
|
75
|
-
}
|
|
66
|
+
const result = cartesian(...all)
|
|
67
|
+
return [result, wasFlattened]
|
|
76
68
|
}
|
|
77
69
|
|
|
78
70
|
// returns (list, wasFlattened)
|
package/src/fragments.js
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
const _ = require('lodash')
|
|
2
2
|
const helpers = require('./helpers')
|
|
3
3
|
|
|
4
|
+
function createChangeTracker(obj) {
|
|
5
|
+
const changes = new Set();
|
|
6
|
+
|
|
7
|
+
const handler = {
|
|
8
|
+
set(target, prop, value) {
|
|
9
|
+
changes.add(prop);
|
|
10
|
+
target[prop] = value;
|
|
11
|
+
return true;
|
|
12
|
+
},
|
|
13
|
+
deleteProperty(target, prop) {
|
|
14
|
+
changes.add(prop);
|
|
15
|
+
delete target[prop];
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
proxy: new Proxy(obj, handler),
|
|
22
|
+
getChanges: () => Array.from(changes)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
4
27
|
function fragmentInstantiator (args, contexts) {
|
|
5
28
|
return new Object({
|
|
6
29
|
contexts: () => {
|
|
@@ -13,13 +36,15 @@ function fragmentInstantiator (args, contexts) {
|
|
|
13
36
|
args.pathEquals = helpers.pathEquals
|
|
14
37
|
while (todo.length > 0) {
|
|
15
38
|
const { context, path } = todo.pop()
|
|
16
|
-
|
|
39
|
+
const { proxy, getChanges } = createChangeTracker(context);
|
|
40
|
+
args.context = proxy
|
|
17
41
|
args.path = path
|
|
18
42
|
for (const mapping of mappings) {
|
|
19
43
|
if (await mapping.match(args)) {
|
|
20
44
|
await mapping.apply(args)
|
|
21
45
|
}
|
|
22
46
|
}
|
|
47
|
+
const ignore = getChanges()
|
|
23
48
|
for (const key of Object.keys(context)) {
|
|
24
49
|
// if (['number', 'string', 'boolean'].includes(typeof (context[key]))) {
|
|
25
50
|
if (!helpers.isCompound(context[key])) {
|
|
@@ -28,7 +53,9 @@ function fragmentInstantiator (args, contexts) {
|
|
|
28
53
|
if (context[key].instantiated) {
|
|
29
54
|
continue
|
|
30
55
|
}
|
|
31
|
-
|
|
56
|
+
if (!ignore.includes(key)) {
|
|
57
|
+
todo.push({ context: context[key], path: [...path, key] })
|
|
58
|
+
}
|
|
32
59
|
}
|
|
33
60
|
}
|
|
34
61
|
if (contexts.length == 1 && instantiated.length == 1) {
|
package/src/generators.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { args: contextArgs, normalizeGenerator } = require('./helpers')
|
|
2
2
|
const Lines = require('../lines')
|
|
3
3
|
const helpers = require('./helpers')
|
|
4
|
+
const debug = require('./debug')
|
|
4
5
|
|
|
5
6
|
class Generator {
|
|
6
7
|
// constructor ({ match, apply, uuid, index, km, priority, notes }) {
|
|
@@ -65,14 +66,16 @@ class Generator {
|
|
|
65
66
|
}
|
|
66
67
|
const args = Object.assign({}, baseArgs, moreArgs, (baseArgs.getUUIDScoped || (() => { return {} }))(this.uuid))
|
|
67
68
|
// return this.match(args)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
return await debug.hitScoped(args.callId, async () => {
|
|
70
|
+
const matches = await this.match(args)
|
|
71
|
+
if ((matches && (options.debug || {}).match) ||
|
|
72
|
+
callId === this.callId) {
|
|
73
|
+
// next line is the matcher
|
|
74
|
+
debugger // eslint-disable-line no-debugger
|
|
75
|
+
await this.match(args)
|
|
76
|
+
}
|
|
77
|
+
return matches
|
|
78
|
+
})
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
// apply (baseArgs, objects, g, gs, context, hierarchy, config, response, log, options = {}) {
|
|
@@ -121,11 +124,13 @@ class Generator {
|
|
|
121
124
|
if (this.property === 'generatorp') {
|
|
122
125
|
args.g = args.gp
|
|
123
126
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
return await debug.hitScoped(args.callId, async () => {
|
|
128
|
+
if ((options.debug || {}).apply ||
|
|
129
|
+
callId === this.callId) {
|
|
130
|
+
debugger // eslint-disable-line no-debugger
|
|
131
|
+
}
|
|
132
|
+
return await this._apply(args)
|
|
133
|
+
})
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
136
|
|
|
@@ -220,7 +225,7 @@ class Generators {
|
|
|
220
225
|
lines.setElement(0, 2, stack)
|
|
221
226
|
lines.newRow()
|
|
222
227
|
lines.setElement(0, 1, 'DEBUG')
|
|
223
|
-
lines.setElement(0, 2, `To debug this use
|
|
228
|
+
lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}')`)
|
|
224
229
|
lines.newRow()
|
|
225
230
|
lines.setElement(0, 1, 'ERROR')
|
|
226
231
|
lines.setElement(0, 2, errorMessage)
|
|
@@ -252,7 +257,7 @@ class Generators {
|
|
|
252
257
|
lines.setElement(0, 2, stack)
|
|
253
258
|
lines.newRow()
|
|
254
259
|
lines.setElement(0, 1, 'DEBUG')
|
|
255
|
-
lines.setElement(0, 2, `To debug this use
|
|
260
|
+
lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}')`)
|
|
256
261
|
lines.newRow()
|
|
257
262
|
lines.setElement(0, 1, 'TO')
|
|
258
263
|
lines.setElement(0, 2, `context_id: ${context.context_id}`)
|
package/src/helpers.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
const deepEqual = require('deep-equal')
|
|
2
2
|
const stringify = require('json-stable-stringify')
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
// check if member function of a class have been overriden by an subclass
|
|
6
|
+
class OverrideCheck {
|
|
7
|
+
constructor(base, suffix='API') {
|
|
8
|
+
this.base = base
|
|
9
|
+
this.checks = Object.getOwnPropertyNames(base.prototype).filter(key => typeof base.prototype[key] === 'function' && key.endsWith(suffix));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
check(obj) {
|
|
13
|
+
const overriden = obj.constructor !== obj.baseAPI
|
|
14
|
+
if (!overriden) {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
for (const check of this.checks) {
|
|
18
|
+
if (obj[check] == this.base.prototype[check]) {
|
|
19
|
+
throw new Error(`For ${obj.constructor.name} you need to override ${check}`)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
4
25
|
function pathEquals (p1, p2) {
|
|
5
26
|
if (p1.length !== p2.length) {
|
|
6
27
|
return false
|
|
@@ -579,7 +600,11 @@ function setByPath(obj, path, value) {
|
|
|
579
600
|
return value;
|
|
580
601
|
}
|
|
581
602
|
|
|
603
|
+
const helpDebugHierarchy = 'In order to get a debug break when a specific hierarchy is created set the DEBUG_HIERARCHY environment variable to the JSON of the child-parent pair to break on. For example DEBUG_HIERARCHY=\'["cat", "mammel"]\''
|
|
604
|
+
|
|
582
605
|
module.exports = {
|
|
606
|
+
helpDebugHierarchy,
|
|
607
|
+
|
|
583
608
|
stableId,
|
|
584
609
|
ecatch,
|
|
585
610
|
functionsToStrings,
|
|
@@ -611,4 +636,5 @@ module.exports = {
|
|
|
611
636
|
assignAssumed,
|
|
612
637
|
watchProperty,
|
|
613
638
|
pathEquals,
|
|
639
|
+
OverrideCheck,
|
|
614
640
|
}
|
package/src/semantics.js
CHANGED
|
@@ -75,13 +75,15 @@ class Semantic {
|
|
|
75
75
|
async matches (args, context, options = {}) {
|
|
76
76
|
args = {...args}
|
|
77
77
|
this.fixUpArgs(args, context)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
return await debug.hitScoped(args.callId, async () => {
|
|
79
|
+
const matches = await this.matcher(args)
|
|
80
|
+
if (matches && (options.debug || {}).match || args.callId === this.callId) {
|
|
81
|
+
// next line is the matcher
|
|
82
|
+
debugger // eslint-disable-line no-debugger
|
|
83
|
+
await this.matcher(args)
|
|
84
|
+
}
|
|
85
|
+
return matches
|
|
86
|
+
})
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
async apply (args, context, s, options = {}) {
|
|
@@ -97,21 +99,24 @@ class Semantic {
|
|
|
97
99
|
const contextPrime = Object.assign({}, context)
|
|
98
100
|
this.fixUpArgs(args, contextPrime)
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
102
|
+
return await debug.hitScoped(args.callId, async () => {
|
|
103
|
+
if ((options.debug || {}).apply || args.callId === this.callId) {
|
|
104
|
+
debugger // eslint-disable-line no-debugger
|
|
105
|
+
}
|
|
106
|
+
if (args.breakOnSemantics) {
|
|
107
|
+
debugger // eslint-disable-line no-debugger
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
args.stack.push(this)
|
|
112
|
+
await this._apply(args)
|
|
113
|
+
args.stack.pop()
|
|
114
|
+
} catch( e ) {
|
|
115
|
+
args.stack.pop()
|
|
116
|
+
throw e
|
|
117
|
+
}
|
|
118
|
+
return contextPrime
|
|
119
|
+
})
|
|
115
120
|
}
|
|
116
121
|
}
|
|
117
122
|
|
|
@@ -187,6 +192,8 @@ class Semantics {
|
|
|
187
192
|
let seenQuestion = false
|
|
188
193
|
const deferred = []
|
|
189
194
|
args.log = (message) => { this.logs.push(message) }
|
|
195
|
+
const finallyList = []; // called after the semantic is processed
|
|
196
|
+
args._finally = (call) => finallyList.unshift(call)
|
|
190
197
|
for (const isemantic in this.semantics) {
|
|
191
198
|
const semantic = this.semantics[isemantic]
|
|
192
199
|
// only one question at a time
|
|
@@ -253,7 +260,7 @@ class Semantics {
|
|
|
253
260
|
lines.setElement(0, 2, semantic.toString())
|
|
254
261
|
lines.newRow()
|
|
255
262
|
lines.setElement(0, 1, 'DEBUG')
|
|
256
|
-
lines.setElement(0, 2, `To debug this use
|
|
263
|
+
lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}')`)
|
|
257
264
|
lines.newRow()
|
|
258
265
|
lines.setElement(0, 1, 'TO')
|
|
259
266
|
lines.setElement(0, 2, `context_id: ${context.context_id}`)
|
|
@@ -288,7 +295,7 @@ class Semantics {
|
|
|
288
295
|
lines.setElement(0, 2, semantic.toString())
|
|
289
296
|
lines.newRow()
|
|
290
297
|
lines.setElement(0, 1, 'DEBUG')
|
|
291
|
-
lines.setElement(0, 2, `To debug this use
|
|
298
|
+
lines.setElement(0, 2, `To debug this use debug.breakAt('${args.calls.current()}')`)
|
|
292
299
|
lines.newRow()
|
|
293
300
|
lines.setElement(0, 1, 'TO')
|
|
294
301
|
lines.setElement(0, 2, `context_id: ${context.context_id}`)
|
|
@@ -319,6 +326,9 @@ class Semantics {
|
|
|
319
326
|
}
|
|
320
327
|
counter += 1
|
|
321
328
|
}
|
|
329
|
+
for (const f of finallyList) {
|
|
330
|
+
await f()
|
|
331
|
+
}
|
|
322
332
|
args.calls.pop()
|
|
323
333
|
if (!applied && debug) {
|
|
324
334
|
const widths = Lines.addRemainder([10, 10])
|