theprogrammablemind 7.6.0 → 7.7.0-beta.1
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 +170 -80
- package/package.json +2 -1
- package/runtime.js +1 -0
- package/src/config.js +29 -17
- package/src/flatten.js +3 -0
- package/src/generators.js +112 -123
- package/src/helpers.js +41 -1
- package/src/project.js +3 -1
package/client.js
CHANGED
@@ -173,22 +173,44 @@ const setupArgs = (args, config, logs, hierarchy) => {
|
|
173
173
|
args.theDebugger = {
|
174
174
|
breakOnSemantics: (value) => args.breakOnSemantics = value
|
175
175
|
}
|
176
|
-
args.s = (c) => config.getSemantics(logs).apply(args, c)
|
177
|
-
args.g = (c) => config.getGenerators(logs).apply(args, c)
|
178
|
-
args.gp = (c) => config.getGenerators(logs).apply(args, { ...c, paraphrase: true, isResponse: false, response: false})
|
179
|
-
args.gr = (c) => config.getGenerators(logs).apply(args, { ...c, paraphrase: false, isResponse: true })
|
180
176
|
if (!logs) {
|
181
177
|
debugger
|
182
178
|
}
|
183
|
-
args.e = (c) => config.getEvaluator(args.s, args.calls, logs, c)
|
184
179
|
args.log = (message) => logs.push(message)
|
185
|
-
|
186
|
-
args.
|
187
|
-
|
180
|
+
|
181
|
+
args.addAssumedScoped = (args, assumed) => {
|
182
|
+
const addAssumed = (args, ...moreAssumed) => {
|
183
|
+
return { ...args, assumed: Object.assign({}, (args.assumed || {}), ...moreAssumed) }
|
184
|
+
}
|
185
|
+
|
186
|
+
args.s = (c) => config.getSemantics(logs).apply(args, c)
|
187
|
+
args.g = (c, a = {}) => {
|
188
|
+
return config.getGenerators(logs).apply(addAssumed(args, a), c, a)
|
189
|
+
}
|
190
|
+
args.gp = (c, a = {}) => {
|
191
|
+
return config.getGenerators(logs).apply(addAssumed(args, a, {paraphrase: true, isResponse: false, response: false}), c, {paraphrase: true, isResponse: false, response: false})
|
192
|
+
}
|
193
|
+
args.gr = (c, a = {}) => {
|
194
|
+
return config.getGenerators(logs).apply(addAssumed(args, a, {paraphrase: false, isResponse: true}), { ...c, paraphrase: false, isResponse: true })
|
195
|
+
}
|
196
|
+
args.e = (c) => {
|
197
|
+
return config.getEvaluator(args.s, args.calls, logs, c)
|
198
|
+
}
|
199
|
+
args.gs = gs(args.g)
|
200
|
+
args.gsp = gs(args.gp)
|
201
|
+
args.gsr = gs(args.gr)
|
202
|
+
}
|
203
|
+
// for semantics
|
204
|
+
args.addAssumedScoped(args, {})
|
188
205
|
config.getAddedArgs(args)
|
189
206
|
}
|
190
207
|
|
191
208
|
const gs = (g) => (contexts, separator, lastSeparator) => {
|
209
|
+
if (!Array.isArray(contexts)) {
|
210
|
+
debugger
|
211
|
+
throw new Error("Expected a list")
|
212
|
+
}
|
213
|
+
|
192
214
|
let s = ''
|
193
215
|
if (!separator) {
|
194
216
|
separator = ' '
|
@@ -276,8 +298,9 @@ const processContext = (context, { objects = {}, config, logs = [] }) => {
|
|
276
298
|
setupArgs(args, config, logs, hierarchy)
|
277
299
|
|
278
300
|
context = semantics.apply(args, context)
|
279
|
-
const generated = generators.apply(args, context)
|
280
|
-
const
|
301
|
+
const generated = generators.apply(args, context)
|
302
|
+
const assumed = { paraphrase: true, response: false, isResponse: false }
|
303
|
+
const paraphrases = generators.apply({...args, assumed}, context, { paraphrase: true, response: false, isResponse: false })
|
281
304
|
let responses = []
|
282
305
|
if (context.isResponse) {
|
283
306
|
responses = generated
|
@@ -447,37 +470,25 @@ const processContextsB = ({ config, hierarchy, semantics, generators, json, isTe
|
|
447
470
|
continue
|
448
471
|
}
|
449
472
|
let assumed = { isResponse: true };
|
450
|
-
const generated = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)
|
473
|
+
const generated = contextPrime.isResponse ? config.getGenerators(json.logs).apply({...args, assumed}, contextPrime, assumed) : ''
|
451
474
|
let generatedParenthesized = []
|
452
475
|
if (generateParenthesized) {
|
453
476
|
config.parenthesized = true
|
454
|
-
generatedParenthesized = contextPrime.isResponse ? config.getGenerators(json.logs).apply(args, contextPrime, assumed)
|
477
|
+
generatedParenthesized = contextPrime.isResponse ? config.getGenerators(json.logs).apply({...args, assumed}, contextPrime, assumed) : ''
|
455
478
|
config.parenthesized = false
|
456
479
|
}
|
457
480
|
// assumed = { paraphrase: true, response: false };
|
458
|
-
assumed = { paraphrase: true };
|
459
|
-
args.g = (c) => config.getGenerators(json.logs).apply(args, c, assumed)
|
460
|
-
args.gp = (c) => config.getGenerators(json.logs).apply(args, {...c, paraphrase: true, isResponse: false, response: false }, assumed)
|
461
|
-
args.gr = (c) => config.getGenerators(json.logs).apply(args, {...c, paraphrase: false }, assumed)
|
462
|
-
args.gs = gs(args.g)
|
463
|
-
args.gsp = gs(args.gsp)
|
464
|
-
args.gsr = gs(args.gr)
|
481
|
+
assumed = { paraphrase: true, isResponse: false, response: false };
|
465
482
|
if (generateParenthesized) {
|
466
483
|
config.parenthesized = false
|
467
484
|
}
|
468
|
-
const paraphrases = config.getGenerators(json.logs).apply(args, contextPrime, assumed)
|
485
|
+
const paraphrases = config.getGenerators(json.logs).apply({...args, assumed}, contextPrime, assumed)
|
469
486
|
let paraphrasesParenthesized = []
|
470
487
|
if (generateParenthesized) {
|
471
488
|
config.parenthesized = true
|
472
|
-
paraphrasesParenthesized = config.getGenerators(json.logs).apply(args, contextPrime, assumed)
|
489
|
+
paraphrasesParenthesized = config.getGenerators(json.logs).apply({...args, assumed}, contextPrime, assumed)
|
473
490
|
config.parenthesized = false
|
474
491
|
}
|
475
|
-
args.g = (c) => config.getGenerators(json.logs).apply(args, c)
|
476
|
-
args.gp = (c) => config.getGenerators(json.logs).apply(args, {...c, paraphrase: true, isResponse: false, response: false })
|
477
|
-
args.gr = (c) => config.getGenerators(json.logs).apply(args, {...c, paraphrase: false })
|
478
|
-
args.gs = gs(args.g)
|
479
|
-
args.gsp = gs(args.gp)
|
480
|
-
args.gsr = gs(args.gr)
|
481
492
|
contextsPrime.push(contextPrime)
|
482
493
|
generatedPrime.push(generated)
|
483
494
|
paraphrasesPrime.push(paraphrases)
|
@@ -614,7 +625,12 @@ const loadInstance = (config, instance) => {
|
|
614
625
|
if (results.skipSemantics) {
|
615
626
|
config.config.skipSemantics = results.skipSemantics
|
616
627
|
}
|
617
|
-
|
628
|
+
const args = { config, hierarchy, json: results, commandLineArgs: {} }
|
629
|
+
if (instance.queries) {
|
630
|
+
args.isInstance = `instance${i}`
|
631
|
+
args.instance = instance.queries[i]
|
632
|
+
}
|
633
|
+
processContextsB(args)
|
618
634
|
if (results.skipSemantics) {
|
619
635
|
config.config.skipSemantics = null
|
620
636
|
}
|
@@ -660,6 +676,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
|
|
660
676
|
opChoices: []
|
661
677
|
},
|
662
678
|
times: 0.0,
|
679
|
+
clientSideTimes: 0.0,
|
663
680
|
trace: '',
|
664
681
|
contexts: [],
|
665
682
|
generated: [],
|
@@ -701,8 +718,16 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
|
|
701
718
|
if (json.status !== 200) {
|
702
719
|
throw json
|
703
720
|
} else {
|
721
|
+
let clientSideTime
|
722
|
+
if (isTest) {
|
723
|
+
start = runtime.performance.performance.now()
|
724
|
+
}
|
704
725
|
const { contextsPrime, generatedPrime, paraphrasesPrime, paraphrasesParenthesizedPrime, generatedParenthesizedPrime, responsesPrime } =
|
705
726
|
processContextsB({ isTest, config, hierarchy, json, commandLineArgs /*, generators, semantics */ })
|
727
|
+
if (isTest) {
|
728
|
+
end = runtime.performance.performance.now()
|
729
|
+
clientSideTime = end - start
|
730
|
+
}
|
706
731
|
response.associations = json.associations
|
707
732
|
response.learned_contextual_priorities = json.learned_contextual_priorities
|
708
733
|
response.hierarchy = json.hierarchy
|
@@ -713,6 +738,7 @@ const _process = async (config, query, { initializer, commandLineArgs, credentia
|
|
713
738
|
// appendNoDups(response.metadata.priorities, json.metadata.priorities)
|
714
739
|
appendNoDups(response.metadata.opChoices, json.metadata.opChoices)
|
715
740
|
response.times += json.times
|
741
|
+
response.clientSideTimes += clientSideTime
|
716
742
|
response.trace = response.trace.concat(json.trace)
|
717
743
|
response.version = json.version
|
718
744
|
response.explain_priorities = json.explain_priorities
|
@@ -778,10 +804,6 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug }) =
|
|
778
804
|
const test = expected.query
|
779
805
|
// initialize in between test so state is not preserved since the test was adding without state
|
780
806
|
config.rebuild()
|
781
|
-
if (!args.dontAddAssociations) {
|
782
|
-
config.addAssociationsFromTests(config.tests)
|
783
|
-
}
|
784
|
-
// config.addAssocationsFromTests(
|
785
807
|
const errorHandler = (error) => {
|
786
808
|
if (error.metadata) {
|
787
809
|
const priorities = analyzeMetaData(expected.metadata, error.metadata)
|
@@ -806,10 +828,10 @@ const runTest = async (config, expected, { args, verbose, testConfig, debug }) =
|
|
806
828
|
defaultInnerProcess(config, errorHandler, result)
|
807
829
|
}
|
808
830
|
if (verbose) {
|
809
|
-
const widths = [100,
|
831
|
+
const widths = [100, 60]
|
810
832
|
const lines = new Lines(widths)
|
811
833
|
lines.setElement(0, 0, test)
|
812
|
-
lines.setElement(0, 1, `time on server ${result.times.toFixed(2)}`)
|
834
|
+
lines.setElement(0, 1, `time on server: ${result.times.toFixed(2)} client: ${(result.clientSideTimes/1000).toFixed(2)}`)
|
813
835
|
lines.log()
|
814
836
|
}
|
815
837
|
const expected_objects = sortJson(convertToStable(expected.objects), { depth: 25 })
|
@@ -1173,7 +1195,7 @@ const defaultInnerProcess = (config, errorHandler, responses) => {
|
|
1173
1195
|
}
|
1174
1196
|
|
1175
1197
|
if (responses.explain_priorities) {
|
1176
|
-
console.log("Explain Priorities")
|
1198
|
+
console.log("Explain Priorities (listed from lower priority to higher priority)")
|
1177
1199
|
for ([inputss, outpus, reason] of responses.explain_priorities) {
|
1178
1200
|
console.log(` ${JSON.stringify(inputss)} reason: ${reason}`)
|
1179
1201
|
}
|
@@ -1232,7 +1254,7 @@ const defaultProcess = ({ config, errorHandler }) => async (promise) => {
|
|
1232
1254
|
}
|
1233
1255
|
|
1234
1256
|
// builtTemplate saveInstance
|
1235
|
-
const rebuildTemplate = async ({ config, target, template, errorHandler = defaultErrorHandler }) => {
|
1257
|
+
const rebuildTemplate = async ({ config, target, previousResultss, startOfChanges, template, errorHandler = defaultErrorHandler }) => {
|
1236
1258
|
const accumulators = {
|
1237
1259
|
resultss: [],
|
1238
1260
|
fragments: [],
|
@@ -1245,7 +1267,7 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
|
|
1245
1267
|
finish()
|
1246
1268
|
return
|
1247
1269
|
}
|
1248
|
-
const { property, hierarchy, query: queryOrExtraConfig, initializer, skipSemantics } = queries.shift()
|
1270
|
+
const { property, hierarchy, query: queryOrExtraConfig, previousResults, initializer, skipSemantics } = queries.shift()
|
1249
1271
|
// queries are strings or { query: "blah", development: true/false }
|
1250
1272
|
if (typeof queryOrExtraConfig === 'string' || queryOrExtraConfig.query) {
|
1251
1273
|
let query = queryOrExtraConfig;
|
@@ -1267,17 +1289,26 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
|
|
1267
1289
|
}
|
1268
1290
|
}
|
1269
1291
|
try {
|
1270
|
-
|
1292
|
+
let results
|
1293
|
+
let prMessage = ''
|
1294
|
+
if (previousResults && previousResults.query == query.query) {
|
1295
|
+
results = previousResults
|
1296
|
+
prMessage = ' Using previous results. use -rtf for a hard rebuild of everything on the server side.'
|
1297
|
+
loadInstance(config, { resultss: [results] })
|
1298
|
+
} else {
|
1299
|
+
results = await _process(config, query.query, {initializer, rebuildingTemplate: true})
|
1300
|
+
}
|
1271
1301
|
if (config.config.debug) {
|
1272
1302
|
// TODO pass in the error handler like the other ones
|
1273
1303
|
defaultInnerProcess(config, defaultErrorHandler, results)
|
1274
1304
|
}
|
1275
1305
|
if (results.contexts.length > 1) {
|
1276
1306
|
console.log(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
|
1307
|
+
throw new Error(`query "${query.query}". There is ${results.contexts.length} contexts in the results. Make sure its producing the results that you expect.`)
|
1277
1308
|
} else if (results.paraphrases[0] != query.query) {
|
1278
|
-
console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}"
|
1309
|
+
console.log(`query "${query.query}". The paraphrase is different from the query "${results.paraphrases[0]}".${prMessage}`)
|
1279
1310
|
} else {
|
1280
|
-
console.log(`query ${query.query}`)
|
1311
|
+
console.log(`query "${query.query}".${prMessage}`)
|
1281
1312
|
}
|
1282
1313
|
global.transitoryMode = transitoryMode
|
1283
1314
|
config.config.skipSemantics = null
|
@@ -1299,14 +1330,18 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
|
|
1299
1330
|
// it will just get added to the config
|
1300
1331
|
const extraConfig = queryOrExtraConfig
|
1301
1332
|
console.log('config', extraConfig)
|
1302
|
-
|
1303
|
-
|
1304
|
-
}
|
1305
|
-
|
1306
|
-
|
1333
|
+
if (extraConfig.stop) {
|
1334
|
+
await looper([])
|
1335
|
+
} else {
|
1336
|
+
try {
|
1337
|
+
config.addInternal(_.cloneDeep(extraConfig), { handleCalculatedProps: true } )
|
1338
|
+
} catch ( e ) {
|
1339
|
+
const where = extraConfig.where ? ` ${extraConfig.where}` : ''
|
1340
|
+
throw new Error(`Error processing extra config${where}: ${e.stack}}`)
|
1341
|
+
}
|
1342
|
+
accumulators[property].push({ extraConfig: true, ...extraConfig })
|
1343
|
+
await looper(queries)
|
1307
1344
|
}
|
1308
|
-
accumulators[property].push({ extraConfig: true, ...extraConfig })
|
1309
|
-
await looper(queries)
|
1310
1345
|
}
|
1311
1346
|
}
|
1312
1347
|
|
@@ -1327,6 +1362,7 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
|
|
1327
1362
|
} else {
|
1328
1363
|
delete result.load_cache_time
|
1329
1364
|
delete result.times
|
1365
|
+
delete result.clientSideTimes
|
1330
1366
|
delete result.memory_free_percent
|
1331
1367
|
delete result.logs
|
1332
1368
|
delete result.version
|
@@ -1360,13 +1396,41 @@ const rebuildTemplate = async ({ config, target, template, errorHandler = defaul
|
|
1360
1396
|
}
|
1361
1397
|
let todo = []
|
1362
1398
|
todo = todo.concat((template.initializers || []).map((query) => { return { initializer: true, property: 'resultss', query, skipSemantics: false || query.skipSemantics } }))
|
1363
|
-
todo = todo.concat((template.queries || []).map((query) => {
|
1399
|
+
todo = todo.concat((template.queries || []).map((query, index) => {
|
1400
|
+
let pr
|
1401
|
+
if (index < startOfChanges) {
|
1402
|
+
pr = previousResultss[index]
|
1403
|
+
}
|
1404
|
+
return { property: 'resultss', query, previousResults: pr, skipSemantics: false || query.skipSemantics}
|
1405
|
+
}))
|
1364
1406
|
todo = todo.concat((template.fragments || []).map((query) => { return Object.assign({}, toProperties(query), { property: 'fragments', skipSemantics: false }) }))
|
1365
1407
|
todo = todo.concat((template.semantics || []).map((definition) => { return { property: 'semantics', query: `${definition.from}\n${definition.to}`, skipSemantics: true } }))
|
1366
1408
|
await looper(Object.assign([], todo))
|
1367
1409
|
}
|
1368
1410
|
|
1369
|
-
const
|
1411
|
+
const checkTemplate = (template) => {
|
1412
|
+
return
|
1413
|
+
if (!template) {
|
1414
|
+
return
|
1415
|
+
}
|
1416
|
+
if (template.checks) {
|
1417
|
+
throw new Error("The 'checks' property should be in the 'test' property not the 'template' property")
|
1418
|
+
}
|
1419
|
+
}
|
1420
|
+
|
1421
|
+
const checkTest = (testConfig) => {
|
1422
|
+
if (!testConfig) {
|
1423
|
+
return
|
1424
|
+
}
|
1425
|
+
if (!testConfig.name) {
|
1426
|
+
throw new Error("The 'test' property is missing the 'name' property that contains the name of the '<km>.test.json' file")
|
1427
|
+
}
|
1428
|
+
if (!testConfig.contents) {
|
1429
|
+
throw new Error("The 'test' property is missing the 'contents' property that contains contents of the '<km>.test.json' file")
|
1430
|
+
}
|
1431
|
+
}
|
1432
|
+
|
1433
|
+
const knowledgeModuleImpl = async ({
|
1370
1434
|
module: moduleFromJSFile,
|
1371
1435
|
description,
|
1372
1436
|
section,
|
@@ -1399,9 +1463,10 @@ const knowledgeModule = async ({
|
|
1399
1463
|
if (!description) {
|
1400
1464
|
throw new Error("'description' is a required parameter. The value should the description of the knowledge module.")
|
1401
1465
|
}
|
1402
|
-
if (!
|
1466
|
+
if (!testConfig) {
|
1403
1467
|
throw new Error("'test' is a required parameter. The value should the path to the file used to store the tests of the knowledge module and the contents of the file in the form { name: <filePath>, contexts: <json> }.")
|
1404
1468
|
}
|
1469
|
+
checkTest(testConfig)
|
1405
1470
|
|
1406
1471
|
const isProcess = require.main === moduleFromJSFile
|
1407
1472
|
|
@@ -1452,13 +1517,14 @@ const knowledgeModule = async ({
|
|
1452
1517
|
parser.add_argument('-tnp', '--testNoParenthesized', { action: 'store_true', help: 'Don\' check parenthesized differences for the tests' })
|
1453
1518
|
parser.add_argument('-n', '--count', { help: 'Number of times to run the tests. Default is one. Use this to check for flakey test. If possible the system will print out a message with the word "hint" suggesting how to fix the problem' })
|
1454
1519
|
// parser.add_argument('-b', '--build', { help: 'Specify the template file name of the form <kmName>. There should be a file called <baseKmName>.<kmName>.template.json with the queries to run. For example { queries: [...] }. The template file will be run and generate an instantiation called <baseKmName>.<kmName>.instance.json and a file called <kmName>.js that will load the template file (this is file generated only if not already existing) and a test file called <KmName>.tests.json. This can then be loaded into an instance of the current knowledge module to setup initial conditions.' })
|
1455
|
-
parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild' })
|
1520
|
+
parser.add_argument('-rt', '--rebuildTemplate', { action: 'store_true', help: 'Force a template rebuild. Using optimization where if the query/config has not changed it will use the previous value. One there is a change all subsequence query/configs will be run.' })
|
1521
|
+
parser.add_argument('-rtf', '--rebuildTemplateFull', { action: 'store_true', help: 'Force a template rebuild. Skip the optimization' })
|
1456
1522
|
parser.add_argument('-l', '--loop', { action: 'store_true', help: 'Run a loop so that multiply queries may be run' })
|
1457
1523
|
parser.add_argument('-i', '--info', { action: 'store_true', help: 'Print meta-data for the module' })
|
1458
1524
|
parser.add_argument('-v', '--vimdiff', { action: 'store_true', help: 'For failures run vimdiff' })
|
1459
1525
|
parser.add_argument('-g', '--greg', { action: 'store_true', help: 'Set the server to be localhost so I can debug stuff' })
|
1460
1526
|
parser.add_argument('-cl', '--checkForLoop', { nargs: "?", help: 'Check for loops in the priorities, Optional argument is list of operator keys to consider. For example [["banana", 0], ["food", 1]]' })
|
1461
|
-
parser.add_argument('-r', '--
|
1527
|
+
parser.add_argument('-r', '--reset', { action: 'store_true', help: 'Get the server to bypass the cache and rebuild everything' })
|
1462
1528
|
parser.add_argument('-q', '--query', { help: 'Run the specified query' })
|
1463
1529
|
parser.add_argument('-ip ', '--server', { help: 'Server to run against' })
|
1464
1530
|
parser.add_argument('-qp ', '--queryParams', { help: 'Query params for the server call' })
|
@@ -1466,7 +1532,6 @@ const knowledgeModule = async ({
|
|
1466
1532
|
parser.add_argument('--parenthesized', { action: 'store_true', help: 'Show the generated phrases with parenthesis.' })
|
1467
1533
|
parser.add_argument('-c', '--clean', { help: 'Remove data from the test files. a === association' })
|
1468
1534
|
parser.add_argument('-od', '--objectDiff', { action: 'store_true', help: 'When showing the objects use a colour diff' })
|
1469
|
-
parser.add_argument('-daa', '--dontAddAssociations', { action: 'store_true', help: 'Do not add associations from the tests.' })
|
1470
1535
|
parser.add_argument('-p', '--print', { help: 'Print the specified elements c === config, w === words, b === bridges, o === operators d === objects (d for data), h === hierarchy, g === generators, s === semantics, l === load t=tests ordering p === priorities a == associations j == JSON sent to server. for example --print wb' })
|
1471
1536
|
parser.add_argument('-s', '--save', { action: 'store_true', help: 'When running with the --query flag this will save the current run to the test file. When running without the --query flag all tests will be run and resaved.' })
|
1472
1537
|
parser.add_argument('-sd', '--saveDeveloper', { action: 'store_true', help: 'Same as -s but the query will not show up in the info command.' })
|
@@ -1484,6 +1549,10 @@ const knowledgeModule = async ({
|
|
1484
1549
|
const args = parser.parse_args()
|
1485
1550
|
args.count = args.count || 1
|
1486
1551
|
|
1552
|
+
if (args.rebuildTemplateFull) {
|
1553
|
+
args.rebuildTemplate = true
|
1554
|
+
}
|
1555
|
+
|
1487
1556
|
if (args.parenthesized) {
|
1488
1557
|
config.parenthesized = true
|
1489
1558
|
}
|
@@ -1671,24 +1740,40 @@ const knowledgeModule = async ({
|
|
1671
1740
|
}
|
1672
1741
|
}
|
1673
1742
|
|
1743
|
+
checkTemplate(template)
|
1744
|
+
|
1674
1745
|
if (template) {
|
1675
|
-
|
1676
|
-
if (
|
1746
|
+
let needsRebuild
|
1747
|
+
if (args.rebuildTemplate && !args.rebuildTemplateFull) {
|
1748
|
+
// get the startOfChanges for the partial rebuild
|
1749
|
+
needsRebuild = config.needsRebuild(template.template, template.instance, { ...options, rebuild: false })
|
1750
|
+
} else {
|
1751
|
+
// do a check or full rebuild
|
1752
|
+
needsRebuild = config.needsRebuild(template.template, template.instance, options)
|
1753
|
+
}
|
1754
|
+
|
1755
|
+
if (needsRebuild.needsRebuild) {
|
1756
|
+
if (needsRebuild.previousResultss) {
|
1757
|
+
console.log("Rebuild using the optimization to use previous results until a change is hit. For a full rebuild use -rtf")
|
1758
|
+
}
|
1677
1759
|
console.log(`This module "${config.name}" needs rebuilding all other arguments will be ignored. Try again after the template is rebuilt.`)
|
1678
1760
|
options.rebuild = true
|
1679
1761
|
config.config.rebuild = true
|
1680
1762
|
}
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1763
|
+
try {
|
1764
|
+
config.load(template.template, template.instance, { rebuild: needsRebuild.needsRebuild || options.rebuild, previousResultss: needsRebuild.previousResultss, startOfChanges: needsRebuild.startOfChanges })
|
1765
|
+
} catch( e ) {
|
1766
|
+
console.error(`Error loading template for ${config.name}. ${e.error ? e.error : e}`)
|
1767
|
+
runtime.process.exit(-1)
|
1768
|
+
}
|
1769
|
+
if (!args.query) {
|
1770
|
+
printConfig()
|
1771
|
+
}
|
1772
|
+
if (needsRebuild.needsRebuild) {
|
1684
1773
|
return
|
1685
1774
|
}
|
1686
1775
|
}
|
1687
1776
|
|
1688
|
-
if (!args.save && !args.rebuildTemplate && !args.dontAddAssociations) {
|
1689
|
-
config.addAssociationsFromTests(config.tests);
|
1690
|
-
}
|
1691
|
-
|
1692
1777
|
if (args.retrain) {
|
1693
1778
|
config.config.retrain = true
|
1694
1779
|
}
|
@@ -1696,7 +1781,6 @@ const knowledgeModule = async ({
|
|
1696
1781
|
if (args.test || args.testVerbose || args.testAllVerbose || args.save) {
|
1697
1782
|
global.transitoryMode = true
|
1698
1783
|
}
|
1699
|
-
|
1700
1784
|
if (!args.query && !args.test && !args.info && (args.save || args.saveDeveloper)) {
|
1701
1785
|
global.transitoryMode = true
|
1702
1786
|
saveTests(config, test, testConfig, args.saveDeveloper)
|
@@ -1718,7 +1802,6 @@ const knowledgeModule = async ({
|
|
1718
1802
|
useTestConfig = config.getConfigs()[args.testModuleName].getTestConfig()
|
1719
1803
|
useTestConfig.testModuleName = args.testModuleName
|
1720
1804
|
test = useTestConfig.name
|
1721
|
-
|
1722
1805
|
}
|
1723
1806
|
runTests(config, test, { args, debug: args.debug, testConfig: useTestConfig, verbose: args.testVerbose || args.testAllVerbose, stopAtFirstError: !args.testAllVerbose }).then((results) => {
|
1724
1807
|
let newError = false
|
@@ -1762,17 +1845,21 @@ const knowledgeModule = async ({
|
|
1762
1845
|
console.log(` actual ${label} `, actual)
|
1763
1846
|
newError = true
|
1764
1847
|
headerShown = true
|
1848
|
+
if (args.vimdiff) {
|
1849
|
+
vimdiff(result.actual.paraphrasesParenthesized, result.expected.paraphrasesParenthesized)
|
1850
|
+
}
|
1765
1851
|
}
|
1766
1852
|
}
|
1767
1853
|
show('paraphrases', result.expected.paraphrases, result.actual.paraphrases)
|
1768
1854
|
if (!args.testNoParenthesized) {
|
1769
1855
|
show('paraphrases parenthesized', result.expected.paraphrasesParenthesized, result.actual.paraphrasesParenthesized)
|
1770
1856
|
}
|
1857
|
+
/*
|
1858
|
+
}
|
1771
1859
|
show('responses', result.expected.responses, result.actual.responses)
|
1772
1860
|
if (!args.testNoParenthesized) {
|
1773
1861
|
show('responses parenthesized', result.expected.generatedParenthesized, result.actual.generatedParenthesized)
|
1774
1862
|
}
|
1775
|
-
/*
|
1776
1863
|
if (JSON.stringify(result.expected.paraphrases) !== JSON.stringify(result.actual.paraphrases)) {
|
1777
1864
|
if (!headerShown) {
|
1778
1865
|
console.log(' Failure')
|
@@ -1798,10 +1885,10 @@ const knowledgeModule = async ({
|
|
1798
1885
|
}
|
1799
1886
|
const widths = [4, 18, 72]
|
1800
1887
|
const lines = new Lines(widths)
|
1801
|
-
lines.setElement(1, 1, 'expected checked')
|
1888
|
+
lines.setElement(1, 1, 'expected checked objects')
|
1802
1889
|
lines.setElement(2, 2, JSON.stringify(result.expected.checked, null, 2))
|
1803
1890
|
lines.log()
|
1804
|
-
lines.setElement(1, 1, 'actual checked')
|
1891
|
+
lines.setElement(1, 1, 'actual checked objects')
|
1805
1892
|
lines.setElement(2, 2, JSON.stringify(result.actual.checked, null, 2))
|
1806
1893
|
lines.log()
|
1807
1894
|
if (args.vimdiff) {
|
@@ -1816,10 +1903,10 @@ const knowledgeModule = async ({
|
|
1816
1903
|
}
|
1817
1904
|
const widths = [4, 18, 72]
|
1818
1905
|
const lines = new Lines(widths)
|
1819
|
-
lines.setElement(1, 1, 'expected
|
1906
|
+
lines.setElement(1, 1, 'expected checked contexts', true)
|
1820
1907
|
lines.setElement(2, 2, JSON.stringify(result.expected.checkedContexts, null, 2))
|
1821
1908
|
lines.log()
|
1822
|
-
lines.setElement(1, 1, 'actual
|
1909
|
+
lines.setElement(1, 1, 'actual checked contexts', true)
|
1823
1910
|
lines.setElement(2, 2, JSON.stringify(result.actual.checkedContexts, null, 2))
|
1824
1911
|
lines.log()
|
1825
1912
|
if (args.vimdiff) {
|
@@ -1836,16 +1923,18 @@ const knowledgeModule = async ({
|
|
1836
1923
|
}
|
1837
1924
|
}
|
1838
1925
|
}
|
1839
|
-
if (
|
1926
|
+
if (hasError) {
|
1927
|
+
if (!headerShown) {
|
1928
|
+
if (!(useTestConfig.check && useTestConfig.check.length > 0)) {
|
1929
|
+
console.log('There are failures due to things other than paraphrases, responses and checked properties being different. They are not shown because you ran -tv or -tva which only shows difference in paraphrase and results. Usually what I do is -s and do a diff to make sure there are no other problems. If the paraphrases or results were different they would have shown here.')
|
1930
|
+
}
|
1931
|
+
}
|
1840
1932
|
if (!(useTestConfig.check && useTestConfig.check.length > 0)) {
|
1841
|
-
console.log('
|
1933
|
+
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.')
|
1934
|
+
// console.log(JSON.stringify(contexts))
|
1935
|
+
console.log('**************************** THERE WERE ERRORS ************************')
|
1842
1936
|
}
|
1843
1937
|
}
|
1844
|
-
if (!(useTestConfig.check && useTestConfig.check.length > 0)) {
|
1845
|
-
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.')
|
1846
|
-
// console.log(JSON.stringify(contexts))
|
1847
|
-
console.log('**************************** ERRORS ************************')
|
1848
|
-
}
|
1849
1938
|
}
|
1850
1939
|
// const contexts = { failures: results }
|
1851
1940
|
l(n - 1, hasError || newError)
|
@@ -1929,7 +2018,7 @@ const knowledgeModule = async ({
|
|
1929
2018
|
}
|
1930
2019
|
|
1931
2020
|
if (template) {
|
1932
|
-
if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess })) {
|
2021
|
+
if (config.needsRebuild(template.template, template.instance, { isModule: !isProcess }).needsRebuild) {
|
1933
2022
|
const error = `This module "${config.name}" cannot be used because the instance file needs rebuilding. Run on the command line with no arguments or the -rt argument to rebuild.`
|
1934
2023
|
throw new Error(error)
|
1935
2024
|
}
|
@@ -1939,8 +2028,6 @@ const knowledgeModule = async ({
|
|
1939
2028
|
errorHandler(e)
|
1940
2029
|
}
|
1941
2030
|
}
|
1942
|
-
|
1943
|
-
config.addAssociationsFromTests(config.tests);
|
1944
2031
|
}
|
1945
2032
|
|
1946
2033
|
createConfigExport = () => {
|
@@ -1951,7 +2038,6 @@ const knowledgeModule = async ({
|
|
1951
2038
|
}
|
1952
2039
|
moduleFromJSFile.exports = createConfigExport
|
1953
2040
|
}
|
1954
|
-
|
1955
2041
|
}
|
1956
2042
|
|
1957
2043
|
/*
|
@@ -1999,6 +2085,10 @@ function w(func) {
|
|
1999
2085
|
return func
|
2000
2086
|
}
|
2001
2087
|
|
2088
|
+
const knowledgeModule = async (...args) => {
|
2089
|
+
await knowledgeModuleImpl(...args).catch((e) => console.error(e))
|
2090
|
+
}
|
2091
|
+
|
2002
2092
|
module.exports = {
|
2003
2093
|
process: _process,
|
2004
2094
|
where,
|
package/package.json
CHANGED
@@ -12,6 +12,7 @@
|
|
12
12
|
"scripts": {
|
13
13
|
"to:debug": "node inspect node_modules/.bin/jest --runInBand -t NEO23",
|
14
14
|
"test:debug": "node inspect node_modules/.bin/jest --runInBand --config ./jest.config.json",
|
15
|
+
"td": "node inspect node_modules/.bin/jest --runInBand --config ./jest.config.json",
|
15
16
|
"tod": "node inspect node_modules/.bin/jest --runInBand -t NEO23",
|
16
17
|
"lint:fix": "eslint \"**/*.js\" --fix",
|
17
18
|
"lint": "eslint \"**/*.js\"",
|
@@ -64,6 +65,6 @@
|
|
64
65
|
"json-stable-stringify": "^1.0.1",
|
65
66
|
"node-fetch": "^2.6.1"
|
66
67
|
},
|
67
|
-
"version": "7.
|
68
|
+
"version": "7.7.0-beta.1",
|
68
69
|
"license": "ISC"
|
69
70
|
}
|
package/runtime.js
CHANGED
package/src/config.js
CHANGED
@@ -27,7 +27,7 @@ const config_toServer = (config) => {
|
|
27
27
|
|
28
28
|
const debugPriority = (priority) => {
|
29
29
|
if (global.entodictonDebugPriority) {
|
30
|
-
if (helpers.
|
30
|
+
if (helpers.subPriority(entodictonDebugPriority, priority)) {
|
31
31
|
debugger; // debug hierarchy hit
|
32
32
|
}
|
33
33
|
}
|
@@ -965,7 +965,7 @@ class Config {
|
|
965
965
|
}
|
966
966
|
|
967
967
|
// { rebuild: false, isModule: false }
|
968
|
-
needsRebuild(template, instance, options) {
|
968
|
+
needsRebuild (template, instance, options) {
|
969
969
|
if (options.rebuild) {
|
970
970
|
return true
|
971
971
|
}
|
@@ -1058,7 +1058,21 @@ class Config {
|
|
1058
1058
|
return elements.map( toCanonicalQuery )
|
1059
1059
|
}
|
1060
1060
|
|
1061
|
-
const
|
1061
|
+
const templateQueries = toCanonicalQueries(template.queries || []).map(helpers.updateQueries)
|
1062
|
+
const instanceQueries = toCanonicalQueries(instance.queries || [])
|
1063
|
+
let sameQueries = true
|
1064
|
+
let startOfChanges;
|
1065
|
+
for (let iq = 0; iq < templateQueries.length; ++iq) {
|
1066
|
+
if (!helpers.safeEquals(templateQueries[iq], instanceQueries[iq])) {
|
1067
|
+
sameQueries = false
|
1068
|
+
startOfChanges = iq
|
1069
|
+
}
|
1070
|
+
}
|
1071
|
+
// things were deleted case
|
1072
|
+
if (templateQueries.length < instanceQueries.length) {
|
1073
|
+
startOfChanges = instanceQueries.length
|
1074
|
+
}
|
1075
|
+
// const sameQueries = helpers.safeEquals(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), toCanonicalQueries(instance.queries || []))
|
1062
1076
|
|
1063
1077
|
const debug = false
|
1064
1078
|
if (debug) {
|
@@ -1067,16 +1081,20 @@ class Config {
|
|
1067
1081
|
debugger
|
1068
1082
|
debugger
|
1069
1083
|
}
|
1070
|
-
console.log("instance", instance)
|
1084
|
+
// console.log("instance", instance)
|
1071
1085
|
console.log("sameQueries", sameQueries)
|
1072
1086
|
console.log("sameFragments", sameFragments)
|
1073
|
-
console.log("templateFragments", templateFragments)
|
1074
|
-
console.log("instanceFragments", instanceFragments)
|
1075
|
-
console.log('template.queries', JSON.stringify(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), null, 2))
|
1076
|
-
console.log("instance.queries", JSON.stringify(toCanonicalQueries(instance.queries || []), null, 2))
|
1087
|
+
// console.log("templateFragments", templateFragments)
|
1088
|
+
// console.log("instanceFragments", instanceFragments)
|
1089
|
+
// console.log('template.queries', JSON.stringify(toCanonicalQueries(template.queries || []).map(helpers.updateQueries), null, 2))
|
1090
|
+
// console.log("instance.queries", JSON.stringify(toCanonicalQueries(instance.queries || []), null, 2))
|
1077
1091
|
}
|
1078
1092
|
}
|
1079
|
-
|
1093
|
+
if (startOfChanges || instance.resultss) {
|
1094
|
+
return { needsRebuild: !(instance && sameQueries && sameFragments), startOfChanges, previousResultss: instance.resultss }
|
1095
|
+
} else {
|
1096
|
+
return { needsRebuild: !(instance && sameQueries && sameFragments) }
|
1097
|
+
}
|
1080
1098
|
}
|
1081
1099
|
|
1082
1100
|
validifyTemplate (template) {
|
@@ -1097,7 +1115,7 @@ class Config {
|
|
1097
1115
|
}
|
1098
1116
|
|
1099
1117
|
// loadTemplate
|
1100
|
-
load (template, instance, options = { rebuild: false } ) {
|
1118
|
+
load (template, instance, options = { rebuild: false, previousResultss: undefined, startOfChanges: undefined } ) {
|
1101
1119
|
this.validifyTemplate(template)
|
1102
1120
|
instance.template = template
|
1103
1121
|
this.logs.push(`loading template for ${this.name}`)
|
@@ -1105,7 +1123,7 @@ class Config {
|
|
1105
1123
|
// TODO fix beforeQuery
|
1106
1124
|
template = { fragments: [], queries: [], ...template }
|
1107
1125
|
template.fragments = template.fragments.concat(this.dynamicFragments)
|
1108
|
-
client.rebuildTemplate({ config: this, target: this.name, beforeQuery: () => {}, template, ...options })
|
1126
|
+
client.rebuildTemplate({ config: this, target: this.name, previousResultss: options.previousResultss, startOfChanges: options.startOfChanges, beforeQuery: () => {}, template, ...options })
|
1109
1127
|
} else {
|
1110
1128
|
// no change
|
1111
1129
|
// this.initInstances.push({ ...instance, name: config.name })
|
@@ -1137,12 +1155,6 @@ class Config {
|
|
1137
1155
|
return this.config.objects.namespaced[this._uuid]
|
1138
1156
|
}
|
1139
1157
|
|
1140
|
-
addAssociationsFromTests(tests = []) {
|
1141
|
-
for (let test of tests) {
|
1142
|
-
this.addAssociations(test.associations || []);
|
1143
|
-
}
|
1144
|
-
}
|
1145
|
-
|
1146
1158
|
addAssociations (associations) {
|
1147
1159
|
for (let association of associations) {
|
1148
1160
|
this.addAssociation(association)
|
package/src/flatten.js
CHANGED
package/src/generators.js
CHANGED
@@ -73,7 +73,8 @@ class Generator {
|
|
73
73
|
return matches
|
74
74
|
}
|
75
75
|
|
76
|
-
apply (baseArgs, objects, g, gs, context, hierarchy, config, response, log, options = {}) {
|
76
|
+
// apply (baseArgs, objects, g, gs, context, hierarchy, config, response, log, options = {}) {
|
77
|
+
apply (baseArgs, objects, context, hierarchy, config, response, log, options = {}) {
|
77
78
|
if (!log) {
|
78
79
|
throw new Error('generators.apply argument log is required')
|
79
80
|
}
|
@@ -103,12 +104,12 @@ class Generator {
|
|
103
104
|
log,
|
104
105
|
global:
|
105
106
|
objects,
|
106
|
-
g,
|
107
|
+
// g,
|
107
108
|
n,
|
108
109
|
hierarchy,
|
109
110
|
context,
|
110
111
|
uuid: this.uuid,
|
111
|
-
gs,
|
112
|
+
// gs,
|
112
113
|
config,
|
113
114
|
response,
|
114
115
|
api: this.getAPI(config),
|
@@ -165,136 +166,124 @@ class Generators {
|
|
165
166
|
this.logs = logs
|
166
167
|
};
|
167
168
|
|
168
|
-
// assumed - properties added to
|
169
|
-
apply (args,
|
169
|
+
// assumed - properties added to context before the generators are called. For setting paraphrase property
|
170
|
+
apply (args, context, assumed = {}, options = {}) {
|
171
|
+
if (Array.isArray(context)) {
|
172
|
+
throw new Error("Expected a context not an array")
|
173
|
+
}
|
174
|
+
if (typeof context !== 'object') {
|
175
|
+
return String(context)
|
176
|
+
}
|
177
|
+
|
170
178
|
const config = args.config
|
171
179
|
const objects = args.objects
|
172
180
|
const hierarchy = args.hierarchy
|
173
181
|
const response = args.response
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
const
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
}
|
200
|
-
}
|
201
|
-
|
202
|
-
// this.logs.push(`Generators: applied ${generator.toString()}\n to\n ${JSON.stringify(context)}`)
|
203
|
-
let errorMessage = 'The apply function did not return a value'
|
204
|
-
try {
|
205
|
-
generated= generator.apply(args, objects, g, args.gs, context, hierarchy, config, response, log)
|
206
|
-
} catch( e ) {
|
207
|
-
// the next if handle this
|
208
|
-
generated = null
|
209
|
-
e.retryCall = () => generator.apply(args, objects, g, args.gs, context, hierarchy, config, response, log)
|
210
|
-
const help = 'The error has a retryCall property that will recall the function that failed.'
|
211
|
-
if (e.stack && e.message) {
|
212
|
-
const info = `${generator.notes ? generator.notes : ''}${generator.where ? generator.where : ''}`
|
213
|
-
errorMessage = `Error applying generator '${info}. Error is ${e.toString()} stack is ${e.stack}. Generator is ${generator.toString()}. ${help}`
|
214
|
-
} else if (e.error) {
|
215
|
-
const info = `${generator.notes ? generator.notes : ''}${generator.where ? generator.where : ''}`
|
216
|
-
errorMessage = `Error applying generator '${info}. Error is ${e.error.join()}. Generator is ${generator.toString()}. ${help}`
|
217
|
-
} else {
|
218
|
-
errorMessage = e.toString()
|
219
|
-
}
|
182
|
+
|
183
|
+
// args = { ...args, ...args.getAssumedScoped(assumed) }
|
184
|
+
args.addAssumedScoped(args, assumed)
|
185
|
+
context = Object.assign({}, context, args.assumed)
|
186
|
+
let generated = ''
|
187
|
+
let applied = false
|
188
|
+
const stack = args.calls.push()
|
189
|
+
for (let igenerator = 0; igenerator < this.generators.length; ++igenerator) {
|
190
|
+
const generator = this.generators[igenerator]
|
191
|
+
if (generator.matches(args, objects, context, hierarchy, config, options)) {
|
192
|
+
const log = (message) => { this.logs.push(message) }
|
193
|
+
// this.logs.push(`Generators: applied ${generator.toString()}\n to\n ${JSON.stringify(context)}`)
|
194
|
+
let errorMessage = 'The apply function did not return a value'
|
195
|
+
try {
|
196
|
+
generated= generator.apply(args, objects, context, hierarchy, config, response, log)
|
197
|
+
} catch( e ) {
|
198
|
+
// the next if handle this
|
199
|
+
generated = null
|
200
|
+
e.retryCall = () => generator.apply(args, objects, context, hierarchy, config, response, log)
|
201
|
+
const help = 'The error has a retryCall property that will recall the function that failed.'
|
202
|
+
if (e.stack && e.message) {
|
203
|
+
const info = `${generator.notes ? generator.notes : ''}${generator.where ? generator.where : ''}`
|
204
|
+
errorMessage = `Error applying generator '${info}. Error is ${e.toString()} stack is ${e.stack}. Generator is ${generator.toString()}. ${help}`
|
205
|
+
} else if (e.error) {
|
206
|
+
const info = `${generator.notes ? generator.notes : ''}${generator.where ? generator.where : ''}`
|
207
|
+
errorMessage = `Error applying generator '${info}. Error is ${e.error.join()}. Generator is ${generator.toString()}. ${help}`
|
208
|
+
} else {
|
209
|
+
errorMessage = e.toString()
|
220
210
|
}
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
}
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
}
|
257
|
-
lines.newRow()
|
258
|
-
lines.setElement(0, 1, 'APPLIED')
|
211
|
+
}
|
212
|
+
if (!generated && generated !== '') {
|
213
|
+
const widths = [10, 10, 90]
|
214
|
+
const lines = new Lines(widths)
|
215
|
+
lines.setElement(0, 0, 'Generator')
|
216
|
+
const source = `${generator.km}/#${generator.index}`
|
217
|
+
lines.setElement(0, 2, `ERROR while applying (${source}) ${generator.toLabel()}`)
|
218
|
+
lines.newRow()
|
219
|
+
lines.setElement(0, 2, generator.toString())
|
220
|
+
lines.newRow()
|
221
|
+
lines.setElement(0, 1, 'TO')
|
222
|
+
lines.setElement(0, 2, `(HASHCODE ${helpers.hashCode(JSON.stringify(helpers.sortJson(context, { depth: 25 })))})`)
|
223
|
+
lines.setElement(1, 2, JSON.stringify(helpers.sortJson(context, { depth: 25 }), null, 2))
|
224
|
+
lines.newRow()
|
225
|
+
lines.setElement(0, 1, 'STACK')
|
226
|
+
lines.setElement(0, 2, stack)
|
227
|
+
lines.newRow()
|
228
|
+
lines.setElement(0, 1, 'DEBUG')
|
229
|
+
lines.setElement(0, 2, `To debug this use args.callId == '${args.calls.current()}'`)
|
230
|
+
lines.newRow()
|
231
|
+
lines.setElement(0, 1, 'ERROR')
|
232
|
+
lines.setElement(0, 2, errorMessage)
|
233
|
+
this.logs.push(lines.toString())
|
234
|
+
const message = `ERROR while applying (${source}) ${generator.toLabel()}\n to\n ${JSON.stringify(context, null, 2)}.\n${errorMessage}'`
|
235
|
+
// this.logs.push(message)
|
236
|
+
// return [message]
|
237
|
+
args.calls.pop()
|
238
|
+
throw { error: [message], logs: this.logs }
|
239
|
+
}
|
240
|
+
if (((config || {}).config || {}).debug) {
|
241
|
+
const widths = [10, 10, 90]
|
242
|
+
const lines = new Lines(widths)
|
243
|
+
lines.setElement(0, 0, 'Generator')
|
244
|
+
if (generator.index > -1 && generator.km) {
|
245
|
+
// lines.setElement(0, 2, `KM '${generator.km}' ordinal: ${generator.index}`)
|
259
246
|
lines.setElement(0, 2, generator.toLabel())
|
260
|
-
lines.newRow()
|
261
|
-
lines.setElement(0, 2, generator.toString())
|
262
|
-
lines.newRow()
|
263
|
-
lines.setElement(0, 1, 'RESULT')
|
264
|
-
lines.setElement(0, 2, generated)
|
265
|
-
lines.newRow()
|
266
|
-
lines.setElement(0, 1, 'STACK')
|
267
|
-
lines.setElement(0, 2, stack)
|
268
|
-
lines.newRow()
|
269
|
-
lines.setElement(0, 1, 'DEBUG')
|
270
|
-
lines.setElement(0, 2, `To debug this use args.callId == '${args.calls.current()}'`)
|
271
|
-
lines.newRow()
|
272
|
-
lines.setElement(0, 1, 'TO')
|
273
|
-
lines.setElement(0, 2, `(HASHCODE ${helpers.hashCode(JSON.stringify(helpers.sortJson(context, { depth: 25 })))})`)
|
274
|
-
lines.setElement(1, 2, JSON.stringify(helpers.sortJson(context, { depth: 25 }), null, 2))
|
275
|
-
this.logs.push(lines.toString())
|
276
247
|
}
|
277
|
-
|
278
|
-
|
248
|
+
lines.newRow()
|
249
|
+
lines.setElement(0, 1, 'APPLIED')
|
250
|
+
lines.setElement(0, 2, generator.toLabel())
|
251
|
+
lines.newRow()
|
252
|
+
lines.setElement(0, 2, generator.toString())
|
253
|
+
lines.newRow()
|
254
|
+
lines.setElement(0, 1, 'RESULT')
|
255
|
+
lines.setElement(0, 2, generated)
|
256
|
+
lines.newRow()
|
257
|
+
lines.setElement(0, 1, 'STACK')
|
258
|
+
lines.setElement(0, 2, stack)
|
259
|
+
lines.newRow()
|
260
|
+
lines.setElement(0, 1, 'DEBUG')
|
261
|
+
lines.setElement(0, 2, `To debug this use args.callId == '${args.calls.current()}'`)
|
262
|
+
lines.newRow()
|
263
|
+
lines.setElement(0, 1, 'TO')
|
264
|
+
lines.setElement(0, 2, `(HASHCODE ${helpers.hashCode(JSON.stringify(helpers.sortJson(context, { depth: 25 })))})`)
|
265
|
+
lines.setElement(1, 2, JSON.stringify(helpers.sortJson(context, { depth: 25 }), null, 2))
|
266
|
+
this.logs.push(lines.toString())
|
279
267
|
}
|
268
|
+
applied = true
|
269
|
+
break
|
280
270
|
}
|
281
|
-
args.calls.pop()
|
282
|
-
if (!applied && ((config || {}).config || {}).debug) {
|
283
|
-
const widths = [10, 10, 90]
|
284
|
-
const lines = new Lines(widths)
|
285
|
-
lines.setElement(0, 0, 'Generator')
|
286
|
-
lines.setElement(0, 2, 'No generator applied')
|
287
|
-
lines.newRow()
|
288
|
-
lines.setElement(0, 1, 'STACK')
|
289
|
-
lines.setElement(0, 2, stack)
|
290
|
-
lines.newRow()
|
291
|
-
lines.setElement(0, 1, 'TO')
|
292
|
-
lines.setElement(0, 2, JSON.stringify(context, null, 2))
|
293
|
-
this.logs.push(lines.toString())
|
294
|
-
}
|
295
|
-
contextsPrime.push((config || {}).parenthesized ? "(" + generated + ")" : generated)
|
296
271
|
}
|
297
|
-
|
272
|
+
args.calls.pop()
|
273
|
+
if (!applied && ((config || {}).config || {}).debug) {
|
274
|
+
const widths = [10, 10, 90]
|
275
|
+
const lines = new Lines(widths)
|
276
|
+
lines.setElement(0, 0, 'Generator')
|
277
|
+
lines.setElement(0, 2, 'No generator applied')
|
278
|
+
lines.newRow()
|
279
|
+
lines.setElement(0, 1, 'STACK')
|
280
|
+
lines.setElement(0, 2, stack)
|
281
|
+
lines.newRow()
|
282
|
+
lines.setElement(0, 1, 'TO')
|
283
|
+
lines.setElement(0, 2, JSON.stringify(context, null, 2))
|
284
|
+
this.logs.push(lines.toString())
|
285
|
+
}
|
286
|
+
return ((config || {}).parenthesized ? "(" + generated + ")" : generated)
|
298
287
|
}
|
299
288
|
}
|
300
289
|
|
package/src/helpers.js
CHANGED
@@ -334,6 +334,45 @@ const ecatch = (where, call) => {
|
|
334
334
|
}
|
335
335
|
}
|
336
336
|
|
337
|
+
const equalKey = (key1, key2) => {
|
338
|
+
return key1[0] == key2[0] && key1[1] == key2[1]
|
339
|
+
}
|
340
|
+
|
341
|
+
// matches for { context: ..., [ordered], choose: ... } exactely OR
|
342
|
+
// [ <id1>, <id2> ] - where id1 is chosen
|
343
|
+
const subPriority = (sub, sup) => {
|
344
|
+
if (Array.isArray(sub)) {
|
345
|
+
const subChoosen = sub[0]
|
346
|
+
const subOther = sub[1]
|
347
|
+
const hasChoosen = sup.choose.find( (index) => equalKey(sup.context[index], subChoosen)) != undefined
|
348
|
+
const hasOtherChosen = sup.choose.find( (index) => equalKey(sup.context[index], subOther)) != undefined
|
349
|
+
const hasOther = sup.context.find( (other) => equalKey(other, subOther) ) !== undefined
|
350
|
+
return !!(hasChoosen && hasOther) && !hasOtherChosen
|
351
|
+
}
|
352
|
+
|
353
|
+
if (!safeEquals([...sub.choose].sort(), [...sup.choose].sort())) {
|
354
|
+
return false
|
355
|
+
}
|
356
|
+
|
357
|
+
const choose = (priority) => {
|
358
|
+
const chosen = []
|
359
|
+
for (const i of priority.choose) {
|
360
|
+
chosen.push(priority.context[i])
|
361
|
+
}
|
362
|
+
return chosen
|
363
|
+
}
|
364
|
+
const chosen1 = choose(sub)
|
365
|
+
const chosen2 = choose(sup)
|
366
|
+
const sameId = (id1, id2) => id1[0] == id2[0] && id1[1] == id2[1]
|
367
|
+
// same length so only need one way
|
368
|
+
const missing1 = chosen1.find( (id1) => !chosen2.find( (id2) => sameId(id1, id2)) )
|
369
|
+
if (missing1) {
|
370
|
+
return false
|
371
|
+
}
|
372
|
+
|
373
|
+
return true
|
374
|
+
}
|
375
|
+
|
337
376
|
module.exports = {
|
338
377
|
ecatch,
|
339
378
|
functionsToStrings,
|
@@ -354,5 +393,6 @@ module.exports = {
|
|
354
393
|
isCompound,
|
355
394
|
InitCalls,
|
356
395
|
hashCode,
|
357
|
-
sortJson
|
396
|
+
sortJson,
|
397
|
+
subPriority,
|
358
398
|
}
|
package/src/project.js
CHANGED
@@ -16,6 +16,9 @@ const project = (object, filter) => {
|
|
16
16
|
return object.map( element => project(element, filter) )
|
17
17
|
} else {
|
18
18
|
for (let properties of filter) {
|
19
|
+
if (typeof properties == 'function') {
|
20
|
+
properties = properties(object)
|
21
|
+
}
|
19
22
|
if (typeof properties == 'object') {
|
20
23
|
if (properties.propertyLists) {
|
21
24
|
for (const propertyList in properties.propertyLists) {
|
@@ -45,7 +48,6 @@ const project = (object, filter) => {
|
|
45
48
|
if (properties.property) {
|
46
49
|
const property = properties.property
|
47
50
|
if (properties.isPropertyList) {
|
48
|
-
debugger
|
49
51
|
if (!Array.isArray(object[property])) {
|
50
52
|
return projection
|
51
53
|
}
|