@hzhangxyz/ddss 0.0.30 → 0.0.32

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.
Files changed (2) hide show
  1. package/dist/index.js +1 -565
  2. package/package.json +5 -4
package/dist/index.js CHANGED
@@ -1,566 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import * as fs from 'node:fs/promises';
3
- import * as os from 'node:os';
4
- import * as path from 'node:path';
5
- import { Command } from 'commander';
6
- import { Sequelize, DataTypes, Model, Op } from 'sequelize';
7
- import { Search as Search$1, Term, List, Rule } from 'atsds';
8
- import { stdout, stdin } from 'node:process';
9
- import { unparse, parse } from 'atsds-bnf';
10
- import { EGraph } from 'atsds-egg';
11
- import * as readline from 'node:readline/promises';
12
-
13
- class Fact extends Model {
14
- }
15
- class Idea extends Model {
16
- }
17
- async function initializeDatabase(addr) {
18
- const sequelize = new Sequelize(addr, { logging: false });
19
- Fact.init({
20
- id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
21
- data: { type: DataTypes.TEXT, unique: true, allowNull: false },
22
- }, { sequelize, tableName: "facts", timestamps: false });
23
- Idea.init({
24
- id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
25
- data: { type: DataTypes.TEXT, unique: true, allowNull: false },
26
- }, { sequelize, tableName: "ideas", timestamps: false });
27
- await sequelize.sync();
28
- return sequelize;
29
- }
30
- async function insertOrIgnore(model, data) {
31
- await model.bulkCreate([{ data }], {
32
- ignoreDuplicates: true,
33
- });
34
- }
35
-
36
- function strRuleGetStrIdea(data) {
37
- if (!data.startsWith("--")) {
38
- const lines = data.split("\n");
39
- return `----\n${lines[0]}\n`;
40
- }
41
- return null;
42
- }
43
- function patchStdout(rl) {
44
- const originalWrite = stdout.write;
45
- let isReprompting = false;
46
- // @ts-ignore
47
- stdout.write = (chunk, encoding, callback) => {
48
- // (1) Use original write when reprompting to avoid infinite recursion
49
- // since rl.prompt() internally calls stdout.write.
50
- if (isReprompting) {
51
- return originalWrite.call(stdout, chunk, encoding, callback);
52
- }
53
- // (2) Let normal newlines (e.g., from user pressing Enter) pass through
54
- // without triggering the reprompting logic.
55
- if (chunk === "\n" || chunk === "\r\n") {
56
- return originalWrite.call(stdout, chunk, encoding, callback);
57
- }
58
- if (chunk.includes("\n")) {
59
- // Move cursor to the start of the line.
60
- originalWrite.call(stdout, "\r");
61
- const result = originalWrite.call(stdout, chunk, encoding, callback);
62
- isReprompting = true;
63
- rl.prompt();
64
- isReprompting = false;
65
- return result;
66
- }
67
- return originalWrite.call(stdout, chunk, encoding, callback);
68
- };
69
- return () => {
70
- // @ts-ignore
71
- stdout.write = originalWrite;
72
- };
73
- }
74
-
75
- async function main$5(addr, sequelize) {
76
- if (!sequelize) {
77
- sequelize = await initializeDatabase(addr);
78
- }
79
- const search = new Search$1();
80
- let maxFact = -1;
81
- while (true) {
82
- const begin = Date.now();
83
- let count = 0;
84
- const newFacts = await Fact.findAll({
85
- where: { id: { [Op.gt]: maxFact } },
86
- });
87
- for (const fact of newFacts) {
88
- maxFact = Math.max(maxFact, fact.id);
89
- search.add(fact.data);
90
- }
91
- const tasks = [];
92
- const handler = (rule) => {
93
- const dsStr = rule.toString();
94
- tasks.push(insertOrIgnore(Fact, dsStr));
95
- const idea = strRuleGetStrIdea(dsStr);
96
- if (idea) {
97
- tasks.push(insertOrIgnore(Idea, idea));
98
- }
99
- return false;
100
- };
101
- count = search.execute(handler);
102
- await Promise.all(tasks);
103
- const end = Date.now();
104
- const duration = (end - begin) / 1000;
105
- if (count === 0) {
106
- const delay = Math.max(0, 0.1 - duration);
107
- await new Promise((resolve) => setTimeout(resolve, delay * 1000));
108
- }
109
- }
110
- }
111
-
112
- async function main$4(addr, sequelize) {
113
- if (!sequelize) {
114
- sequelize = await initializeDatabase(addr);
115
- }
116
- const ideas = await Idea.findAll();
117
- for (const idea of ideas) {
118
- console.log("idea:", unparse(idea.data));
119
- }
120
- const facts = await Fact.findAll();
121
- for (const fact of facts) {
122
- console.log("fact:", unparse(fact.data));
123
- }
124
- }
125
-
126
- function buildTermToRule(data) {
127
- return new Rule(`----\n${data.toString()}\n`);
128
- }
129
- function extractLhsRhsFromRule(data) {
130
- if (data.length() !== 0) {
131
- return null;
132
- }
133
- const term = data.conclusion();
134
- const inner = term.term();
135
- if (!(inner instanceof List)) {
136
- return null;
137
- }
138
- if (!(inner.length() === 4 && inner.getitem(0).toString() === "binary" && inner.getitem(1).toString() === "==")) {
139
- return null;
140
- }
141
- return [inner.getitem(2), inner.getitem(3)];
142
- }
143
- function buildLhsRhsToTerm(lhs, rhs) {
144
- return new Term(`(binary == ${lhs.toString()} ${rhs.toString()})`);
145
- }
146
- class InternalEGraph {
147
- core;
148
- mapping;
149
- constructor() {
150
- this.core = new EGraph();
151
- this.mapping = new Map();
152
- }
153
- getOrAdd(data) {
154
- const key = data.toString();
155
- if (!this.mapping.has(key)) {
156
- this.mapping.set(key, this.core.add(data));
157
- }
158
- return this.mapping.get(key);
159
- }
160
- find(data) {
161
- return this.core.find(this.getOrAdd(data));
162
- }
163
- setEquality(lhs, rhs) {
164
- const lhsId = this.getOrAdd(lhs);
165
- const rhsId = this.getOrAdd(rhs);
166
- this.core.merge(lhsId, rhsId);
167
- }
168
- getEquality(lhs, rhs) {
169
- const lhsId = this.getOrAdd(lhs);
170
- const rhsId = this.getOrAdd(rhs);
171
- return this.core.find(lhsId) === this.core.find(rhsId);
172
- }
173
- rebuild() {
174
- this.core.rebuild();
175
- }
176
- }
177
- class Search {
178
- egraph;
179
- terms;
180
- facts;
181
- newlyAddedTerms;
182
- newlyAddedFacts;
183
- factMatchingCache;
184
- constructor() {
185
- this.egraph = new InternalEGraph();
186
- this.terms = new Set();
187
- this.facts = new Set();
188
- this.newlyAddedTerms = new Set();
189
- this.newlyAddedFacts = new Set();
190
- this.factMatchingCache = new Map();
191
- }
192
- rebuild() {
193
- this.egraph.rebuild();
194
- const newlyAddedTermsList = Array.from(this.newlyAddedTerms).map((s) => new Term(s));
195
- for (const factStr of this.facts) {
196
- const fact = new Term(factStr);
197
- if (!this.factMatchingCache.has(factStr)) {
198
- this.factMatchingCache.set(factStr, new Set());
199
- }
200
- const candidates = this.collectMatchingCandidates(fact, newlyAddedTermsList);
201
- for (const c of candidates) {
202
- this.factMatchingCache.get(factStr).add(c.toString());
203
- }
204
- }
205
- const termsList = Array.from(this.terms).map((s) => new Term(s));
206
- for (const factStr of this.newlyAddedFacts) {
207
- const fact = new Term(factStr);
208
- if (!this.factMatchingCache.has(factStr)) {
209
- this.factMatchingCache.set(factStr, new Set());
210
- }
211
- const candidates = this.collectMatchingCandidates(fact, termsList);
212
- for (const c of candidates) {
213
- this.factMatchingCache.get(factStr).add(c.toString());
214
- }
215
- }
216
- this.newlyAddedTerms.clear();
217
- this.newlyAddedFacts.clear();
218
- }
219
- add(data) {
220
- this.addExpr(data);
221
- this.addFact(data);
222
- }
223
- addExpr(data) {
224
- const lhsRhs = extractLhsRhsFromRule(data);
225
- if (!lhsRhs)
226
- return;
227
- const [lhs, rhs] = lhsRhs;
228
- this.terms.add(lhs.toString());
229
- this.newlyAddedTerms.add(lhs.toString());
230
- this.terms.add(rhs.toString());
231
- this.newlyAddedTerms.add(rhs.toString());
232
- this.egraph.setEquality(lhs, rhs);
233
- }
234
- addFact(data) {
235
- if (data.length() !== 0)
236
- return;
237
- const term = data.conclusion();
238
- this.terms.add(term.toString());
239
- this.newlyAddedTerms.add(term.toString());
240
- this.facts.add(term.toString());
241
- this.newlyAddedFacts.add(term.toString());
242
- }
243
- *execute(data) {
244
- yield* this.executeExpr(data);
245
- yield* this.executeFact(data);
246
- }
247
- *executeExpr(data) {
248
- const lhsRhs = extractLhsRhsFromRule(data);
249
- if (!lhsRhs)
250
- return;
251
- const [lhs, rhs] = lhsRhs;
252
- if (this.egraph.getEquality(lhs, rhs)) {
253
- yield data;
254
- }
255
- const termsList = Array.from(this.terms).map((s) => new Term(s));
256
- const lhsPool = this.collectMatchingCandidates(lhs, termsList);
257
- const rhsPool = this.collectMatchingCandidates(rhs, termsList);
258
- if (lhsPool.length === 0 || rhsPool.length === 0)
259
- return;
260
- const lhsGroups = this.groupByEquivalenceClass(lhsPool);
261
- const rhsGroups = this.groupByEquivalenceClass(rhsPool);
262
- for (const lhsGroup of lhsGroups) {
263
- for (const rhsGroup of rhsGroups) {
264
- if (lhsGroup.size > 0 && rhsGroup.size > 0) {
265
- const firstLhs = new Term(lhsGroup.values().next().value);
266
- const firstRhs = new Term(rhsGroup.values().next().value);
267
- if (this.egraph.getEquality(firstLhs, firstRhs)) {
268
- for (const xStr of lhsGroup) {
269
- for (const yStr of rhsGroup) {
270
- const x = new Term(xStr);
271
- const y = new Term(yStr);
272
- const target = buildLhsRhsToTerm(x, y);
273
- const query = data.conclusion();
274
- const unification = target.match(query);
275
- if (unification) {
276
- const result = target.ground(unification, "1");
277
- if (result) {
278
- yield buildTermToRule(result);
279
- }
280
- }
281
- }
282
- }
283
- }
284
- }
285
- }
286
- }
287
- }
288
- *executeFact(data) {
289
- if (data.length() !== 0)
290
- return;
291
- const idea = data.conclusion();
292
- for (const factStr of this.facts) {
293
- if (this.egraph.getEquality(idea, new Term(factStr))) {
294
- yield data;
295
- }
296
- }
297
- const termsList = Array.from(this.terms).map((s) => new Term(s));
298
- const ideaPool = this.collectMatchingCandidates(idea, termsList);
299
- if (ideaPool.length === 0)
300
- return;
301
- const ideaGroups = this.groupByEquivalenceClass(ideaPool);
302
- for (const factStr of this.facts) {
303
- const factPoolStr = this.factMatchingCache.get(factStr);
304
- if (!factPoolStr || factPoolStr.size === 0)
305
- continue;
306
- const factPool = Array.from(factPoolStr).map((s) => new Term(s));
307
- const factGroups = this.groupByEquivalenceClass(factPool);
308
- for (const ideaGroup of ideaGroups) {
309
- for (const factGroup of factGroups) {
310
- if (ideaGroup.size > 0 && factGroup.size > 0) {
311
- const firstIdea = new Term(ideaGroup.values().next().value);
312
- const firstFact = new Term(factGroup.values().next().value);
313
- if (this.egraph.getEquality(firstIdea, firstFact)) {
314
- for (const xStr of ideaGroup) {
315
- for (const yStr of factGroup) {
316
- const x = new Term(xStr);
317
- const y = new Term(yStr);
318
- const target = buildLhsRhsToTerm(x, y);
319
- const query = buildLhsRhsToTerm(idea, new Term(factStr));
320
- const unification = target.match(query);
321
- if (unification) {
322
- const result = target.ground(unification, "1");
323
- if (result) {
324
- const inner = result.term();
325
- if (inner instanceof List) {
326
- yield buildTermToRule(inner.getitem(2));
327
- }
328
- }
329
- }
330
- }
331
- }
332
- }
333
- }
334
- }
335
- }
336
- }
337
- }
338
- collectMatchingCandidates(pattern, candidates) {
339
- return candidates.filter((c) => pattern.match(c) !== null);
340
- }
341
- groupByEquivalenceClass(terms) {
342
- if (terms.length === 0)
343
- return [];
344
- const eidToTerms = new Map();
345
- for (const term of terms) {
346
- const eid = this.egraph.find(term).toString();
347
- if (!eidToTerms.has(eid)) {
348
- eidToTerms.set(eid, new Set());
349
- }
350
- eidToTerms.get(eid).add(term.toString());
351
- }
352
- return Array.from(eidToTerms.values());
353
- }
354
- }
355
-
356
- async function main$3(addr, sequelize) {
357
- if (!sequelize) {
358
- sequelize = await initializeDatabase(addr);
359
- }
360
- const search = new Search();
361
- let pool = [];
362
- let maxFact = -1;
363
- let maxIdea = -1;
364
- while (true) {
365
- const begin = Date.now();
366
- let count = 0;
367
- const newIdeas = await Idea.findAll({
368
- where: { id: { [Op.gt]: maxIdea } },
369
- });
370
- for (const idea of newIdeas) {
371
- maxIdea = Math.max(maxIdea, idea.id);
372
- pool.push(new Rule(idea.data));
373
- }
374
- const newFacts = await Fact.findAll({
375
- where: { id: { [Op.gt]: maxFact } },
376
- });
377
- for (const fact of newFacts) {
378
- maxFact = Math.max(maxFact, fact.id);
379
- search.add(new Rule(fact.data));
380
- }
381
- search.rebuild();
382
- const tasks = [];
383
- const nextPool = [];
384
- for (const i of pool) {
385
- let found = false;
386
- for (const o of search.execute(i)) {
387
- tasks.push(insertOrIgnore(Fact, o.toString()));
388
- count++;
389
- if (i.toString() === o.toString()) {
390
- found = true;
391
- break;
392
- }
393
- }
394
- if (!found) {
395
- nextPool.push(i);
396
- }
397
- }
398
- pool = nextPool;
399
- await Promise.all(tasks);
400
- const end = Date.now();
401
- const duration = (end - begin) / 1000;
402
- if (count === 0) {
403
- const delay = Math.max(0, 0.1 - duration);
404
- await new Promise((resolve) => setTimeout(resolve, delay * 1000));
405
- }
406
- }
407
- }
408
-
409
- async function main$2(addr, sequelize) {
410
- if (!sequelize) {
411
- sequelize = await initializeDatabase(addr);
412
- }
413
- const rl = readline.createInterface({ input: stdin, output: stdout });
414
- rl.setPrompt("input: ");
415
- const unpatch = patchStdout(rl);
416
- rl.prompt();
417
- for await (const line of rl) {
418
- const data = line.trim();
419
- if (data === "" || data.startsWith("//")) {
420
- rl.prompt();
421
- continue;
422
- }
423
- try {
424
- const ds = parse(data);
425
- const dsStr = ds.toString();
426
- await insertOrIgnore(Fact, dsStr);
427
- const idea = strRuleGetStrIdea(dsStr);
428
- if (idea) {
429
- await insertOrIgnore(Idea, idea);
430
- }
431
- }
432
- catch (e) {
433
- console.error(`error: ${e}`);
434
- }
435
- rl.prompt();
436
- }
437
- unpatch();
438
- rl.close();
439
- }
440
-
441
- async function main$1(addr, sequelize) {
442
- if (!sequelize) {
443
- sequelize = await initializeDatabase(addr);
444
- }
445
- const rl = readline.createInterface({
446
- input: stdin,
447
- terminal: false,
448
- });
449
- for await (const line of rl) {
450
- const data = line.trim();
451
- if (data === "" || data.startsWith("//")) {
452
- continue;
453
- }
454
- try {
455
- const ds = parse(data);
456
- const dsStr = ds.toString();
457
- await insertOrIgnore(Fact, dsStr);
458
- const idea = strRuleGetStrIdea(dsStr);
459
- if (idea) {
460
- await insertOrIgnore(Idea, idea);
461
- }
462
- }
463
- catch (e) {
464
- console.error(`error: ${e}`);
465
- }
466
- }
467
- rl.close();
468
- }
469
-
470
- async function main(addr, sequelize) {
471
- if (!sequelize) {
472
- sequelize = await initializeDatabase(addr);
473
- }
474
- let maxFact = -1;
475
- let maxIdea = -1;
476
- while (true) {
477
- const begin = Date.now();
478
- let count = 0;
479
- const newIdeas = await Idea.findAll({
480
- where: { id: { [Op.gt]: maxIdea } },
481
- });
482
- for (const idea of newIdeas) {
483
- maxIdea = Math.max(maxIdea, idea.id);
484
- console.log("idea:", unparse(idea.data));
485
- count++;
486
- }
487
- const newFacts = await Fact.findAll({
488
- where: { id: { [Op.gt]: maxFact } },
489
- });
490
- for (const fact of newFacts) {
491
- maxFact = Math.max(maxFact, fact.id);
492
- console.log("fact:", unparse(fact.data));
493
- count++;
494
- }
495
- const end = Date.now();
496
- const duration = (end - begin) / 1000;
497
- if (count === 0) {
498
- const delay = Math.max(0, 0.1 - duration);
499
- await new Promise((resolve) => setTimeout(resolve, delay * 1000));
500
- }
501
- }
502
- }
503
-
504
- const componentMap = {
505
- ds: main$5,
506
- egg: main$3,
507
- input: main$2,
508
- output: main,
509
- load: main$1,
510
- dump: main$4,
511
- };
512
- async function run(addr, components) {
513
- for (const name of components) {
514
- if (!(name in componentMap)) {
515
- console.error(`error: unsupported component: ${name}`);
516
- return;
517
- }
518
- }
519
- const sequelize = await initializeDatabase(addr);
520
- const promises = components.map((name) => {
521
- const component = componentMap[name];
522
- return component(addr, sequelize);
523
- });
524
- await Promise.race(promises);
525
- await sequelize.close();
526
- }
527
- function cli() {
528
- const program = new Command();
529
- program
530
- .name("ddss")
531
- .description("DDSS - Distributed Deductive System Sorts: Run DDSS with an interactive deductive environment.")
532
- .option("-a, --addr <url>", "Database address URL. If not provided, uses a temporary SQLite database.")
533
- .option("-c, --component <names...>", "Components to run.", ["input", "output", "ds", "egg"])
534
- .action(async (options) => {
535
- let addr = options.addr;
536
- let tmpDir;
537
- if (!addr) {
538
- tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "ddss-"));
539
- const dbPath = path.join(tmpDir, "ddss.db");
540
- addr = `sqlite:///${dbPath}`;
541
- }
542
- if (addr.startsWith("sqlite://")) {
543
- addr = addr.replace("sqlite:///", "sqlite:");
544
- }
545
- else if (addr.startsWith("mysql:///")) ;
546
- else if (addr.startsWith("mariadb://")) ;
547
- else if (addr.startsWith("postgresql://")) {
548
- addr = addr.replace("postgresql://", "postgres://");
549
- }
550
- else {
551
- console.error(`error: unsupported database: ${addr}`);
552
- return;
553
- }
554
- console.log(`addr: ${addr}`);
555
- await run(addr, options.component);
556
- if (tmpDir) {
557
- await fs.rm(tmpDir, { recursive: true, force: true });
558
- }
559
- });
560
- program.parse();
561
- }
562
- if (import.meta.main) {
563
- cli();
564
- }
565
-
566
- export { cli };
2
+ import*as t from"node:fs/promises";import*as e from"node:os";import*as n from"node:path";import{Command as o}from"commander";import{Sequelize as s,DataTypes as i,Model as a,Op as r}from"sequelize";import{Search as c,Term as d,List as l,Rule as f}from"atsds";import{format as h}from"node:util";import{stdout as u,stdin as m}from"node:process";import{unparse as g,parse as p}from"atsds-bnf";import{EGraph as w}from"atsds-egg";import*as y from"node:readline/promises";class S extends a{}class A extends a{}async function x(t){const e=new s(t,{logging:!1});return S.init({id:{type:i.INTEGER,primaryKey:!0,autoIncrement:!0},data:{type:i.TEXT,unique:!0,allowNull:!1}},{sequelize:e,tableName:"facts",timestamps:!1}),A.init({id:{type:i.INTEGER,primaryKey:!0,autoIncrement:!0},data:{type:i.TEXT,unique:!0,allowNull:!1}},{sequelize:e,tableName:"ideas",timestamps:!1}),await e.sync(),e}async function M(t,e){await t.bulkCreate([{data:e}],{ignoreDuplicates:!0})}function q(t){if(!t.startsWith("--")){return`----\n${t.split("\n")[0]}\n`}return null}function v(t){return new f(`----\n${t.toString()}\n`)}function C(t){if(0!==t.length())return null;const e=t.conclusion().term();return e instanceof l?4!==e.length()||"binary"!==e.getitem(0).toString()||"=="!==e.getitem(1).toString()?null:[e.getitem(2),e.getitem(3)]:null}function E(t,e){return new d(`(binary == ${t.toString()} ${e.toString()})`)}class b{core;mapping;constructor(){this.core=new w,this.mapping=new Map}getOrAdd(t){const e=t.toString();return this.mapping.has(e)||this.mapping.set(e,this.core.add(t)),this.mapping.get(e)}find(t){return this.core.find(this.getOrAdd(t))}setEquality(t,e){const n=this.getOrAdd(t),o=this.getOrAdd(e);this.core.merge(n,o)}getEquality(t,e){const n=this.getOrAdd(t),o=this.getOrAdd(e);return this.core.find(n)===this.core.find(o)}rebuild(){this.core.rebuild()}}class T{egraph;terms;facts;newlyAddedTerms;newlyAddedFacts;factMatchingCache;constructor(){this.egraph=new b,this.terms=new Set,this.facts=new Set,this.newlyAddedTerms=new Set,this.newlyAddedFacts=new Set,this.factMatchingCache=new Map}rebuild(){this.egraph.rebuild();const t=Array.from(this.newlyAddedTerms).map(t=>new d(t));for(const e of this.facts){const n=new d(e);this.factMatchingCache.has(e)||this.factMatchingCache.set(e,new Set);const o=this.collectMatchingCandidates(n,t);for(const t of o)this.factMatchingCache.get(e).add(t.toString())}const e=Array.from(this.terms).map(t=>new d(t));for(const t of this.newlyAddedFacts){const n=new d(t);this.factMatchingCache.has(t)||this.factMatchingCache.set(t,new Set);const o=this.collectMatchingCandidates(n,e);for(const e of o)this.factMatchingCache.get(t).add(e.toString())}this.newlyAddedTerms.clear(),this.newlyAddedFacts.clear()}add(t){this.addExpr(t),this.addFact(t)}addExpr(t){const e=C(t);if(!e)return;const[n,o]=e;this.terms.add(n.toString()),this.newlyAddedTerms.add(n.toString()),this.terms.add(o.toString()),this.newlyAddedTerms.add(o.toString()),this.egraph.setEquality(n,o)}addFact(t){if(0!==t.length())return;const e=t.conclusion();this.terms.add(e.toString()),this.newlyAddedTerms.add(e.toString()),this.facts.add(e.toString()),this.newlyAddedFacts.add(e.toString())}*execute(t){yield*this.executeExpr(t),yield*this.executeFact(t)}*executeExpr(t){const e=C(t);if(!e)return;const[n,o]=e;this.egraph.getEquality(n,o)&&(yield t);const s=Array.from(this.terms).map(t=>new d(t)),i=this.collectMatchingCandidates(n,s),a=this.collectMatchingCandidates(o,s);if(0===i.length||0===a.length)return;const r=this.groupByEquivalenceClass(i),c=this.groupByEquivalenceClass(a);for(const e of r)for(const n of c)if(e.size>0&&n.size>0){const o=new d(e.values().next().value),s=new d(n.values().next().value);if(this.egraph.getEquality(o,s))for(const o of e)for(const e of n){const n=E(new d(o),new d(e)),s=t.conclusion(),i=n.match(s);if(i){const t=n.ground(i,"1");t&&(yield v(t))}}}}*executeFact(t){if(0!==t.length())return;const e=t.conclusion();for(const n of this.facts)this.egraph.getEquality(e,new d(n))&&(yield t);const n=Array.from(this.terms).map(t=>new d(t)),o=this.collectMatchingCandidates(e,n);if(0===o.length)return;const s=this.groupByEquivalenceClass(o);for(const t of this.facts){const n=this.factMatchingCache.get(t);if(!n||0===n.size)continue;const o=Array.from(n).map(t=>new d(t)),i=this.groupByEquivalenceClass(o);for(const n of s)for(const o of i)if(n.size>0&&o.size>0){const s=new d(n.values().next().value),i=new d(o.values().next().value);if(this.egraph.getEquality(s,i))for(const s of n)for(const n of o){const o=E(new d(s),new d(n)),i=E(e,new d(t)),a=o.match(i);if(a){const t=o.ground(a,"1");if(t){const e=t.term();e instanceof l&&(yield v(e.getitem(2)))}}}}}}collectMatchingCandidates(t,e){return e.filter(e=>null!==t.match(e))}groupByEquivalenceClass(t){if(0===t.length)return[];const e=new Map;for(const n of t){const t=this.egraph.find(n).toString();e.has(t)||e.set(t,new Set),e.get(t).add(n.toString())}return Array.from(e.values())}}const D={ds:async function(t,e){e||(e=await x(t));const n=new c;let o=-1;for(;;){const t=Date.now();let e=0;const s=await S.findAll({where:{id:{[r.gt]:o}}});for(const t of s)o=Math.max(o,t.id),n.add(t.data);const i=[],a=t=>{const e=t.toString();i.push(M(S,e));const n=q(e);return n&&i.push(M(A,n)),!1};e=n.execute(a),await Promise.all(i);const c=(Date.now()-t)/1e3;if(0===e){const t=Math.max(0,.1-c);await new Promise(e=>setTimeout(e,1e3*t))}}},egg:async function(t,e){e||(e=await x(t));const n=new T;let o=[],s=-1,i=-1;for(;;){const t=Date.now();let e=0;const a=await A.findAll({where:{id:{[r.gt]:i}}});for(const t of a)i=Math.max(i,t.id),o.push(new f(t.data));const c=await S.findAll({where:{id:{[r.gt]:s}}});for(const t of c)s=Math.max(s,t.id),n.add(new f(t.data));n.rebuild();const d=[],l=[];for(const t of o){let o=!1;for(const s of n.execute(t))if(d.push(M(S,s.toString())),e++,t.toString()===s.toString()){o=!0;break}o||l.push(t)}o=l,await Promise.all(d);const h=(Date.now()-t)/1e3;if(0===e){const t=Math.max(0,.1-h);await new Promise(e=>setTimeout(e,1e3*t))}}},input:async function(t,e){e||(e=await x(t));const n=y.createInterface({input:m,output:u});n.setPrompt("input: ");const o=function(t){const e=u.write,n=console.log,o=console.error;let s=!1;return u.write=(n,o,i)=>{if(s)return e.call(u,n,o,i);if("\n"===n||"\r\n"===n)return e.call(u,n,o,i);if(n.includes("\n")){e.call(u,"\r");const a=e.call(u,n,o,i);return s=!0,t.prompt(),s=!1,a}return e.call(u,n,o,i)},console.log=(...t)=>{u.write(h(...t)+"\n")},console.error=(...t)=>{u.write(h(...t)+"\n")},()=>{u.write=e,console.log=n,console.error=o}}(n);n.prompt();for await(const t of n){const e=t.trim();if(""===e||e.startsWith("//"))n.prompt();else{try{const t=p(e).toString();await M(S,t);const n=q(t);n&&await M(A,n)}catch(t){console.error(`error: ${t}`)}n.prompt()}}o(),n.close()},output:async function(t,e){e||(e=await x(t));let n=-1,o=-1;for(;;){const t=Date.now();let e=0;const s=await A.findAll({where:{id:{[r.gt]:o}}});for(const t of s)o=Math.max(o,t.id),console.log("idea:",g(t.data)),e++;const i=await S.findAll({where:{id:{[r.gt]:n}}});for(const t of i)n=Math.max(n,t.id),console.log("fact:",g(t.data)),e++;const a=(Date.now()-t)/1e3;if(0===e){const t=Math.max(0,.1-a);await new Promise(e=>setTimeout(e,1e3*t))}}},load:async function(t,e){e||(e=await x(t));const n=y.createInterface({input:m,terminal:!1});for await(const t of n){const e=t.trim();if(""!==e&&!e.startsWith("//"))try{const t=p(e).toString();await M(S,t);const n=q(t);n&&await M(A,n)}catch(t){console.error(`error: ${t}`)}}n.close()},dump:async function(t,e){e||(e=await x(t));const n=await A.findAll();for(const t of n)console.log("idea:",g(t.data));const o=await S.findAll();for(const t of o)console.log("fact:",g(t.data))}};function $(){const s=new o;s.name("ddss").description("DDSS - Distributed Deductive System Sorts: Run DDSS with an interactive deductive environment.").option("-a, --addr <url>","Database address URL. If not provided, uses a temporary SQLite database.").option("-c, --component <names...>","Components to run.",["input","output","ds","egg"]).action(async o=>{let s,i=o.addr;if(!i){s=await t.mkdtemp(n.join(e.tmpdir(),"ddss-"));i=`sqlite:///${n.join(s,"ddss.db")}`}if(i.startsWith("sqlite://"))i=i.replace("sqlite:///","sqlite:");else if(i.startsWith("mysql://"));else if(i.startsWith("mariadb://"));else{if(!i.startsWith("postgresql://"))return void console.error(`error: unsupported database: ${i}`);i=i.replace("postgresql://","postgres://")}console.log(`addr: ${i}`),await async function(t,e){for(const t of e)if(!(t in D))return void console.error(`error: unsupported component: ${t}`);const n=await x(t),o=e.map(e=>(0,D[e])(t,n));await Promise.race(o),await n.close()}(i,o.component),s&&await t.rm(s,{recursive:!0,force:!0})}),s.parse()}import.meta.main&&$();export{$ as cli};
package/package.json CHANGED
@@ -21,9 +21,9 @@
21
21
  "all": "run-s build test"
22
22
  },
23
23
  "dependencies": {
24
- "atsds": "^0.0.13",
25
- "atsds-bnf": "^0.0.13",
26
- "atsds-egg": "^0.0.13",
24
+ "atsds": "^0.0.14",
25
+ "atsds-bnf": "^0.0.14",
26
+ "atsds-egg": "^0.0.14",
27
27
  "commander": "^14.0.2",
28
28
  "mariadb": "^3.4.5",
29
29
  "mysql2": "^3.16.0",
@@ -32,6 +32,7 @@
32
32
  "sqlite3": "^5.1.7"
33
33
  },
34
34
  "devDependencies": {
35
+ "@rollup/plugin-terser": "^0.4.4",
35
36
  "@rollup/plugin-typescript": "^12.3.0",
36
37
  "@types/jest": "^30.0.0",
37
38
  "@types/node": "^25.0.3",
@@ -44,5 +45,5 @@
44
45
  "tslib": "^2.8.1",
45
46
  "typescript": "^5.9.3"
46
47
  },
47
- "version": "0.0.30"
48
+ "version": "0.0.32"
48
49
  }