eyeling 1.15.13 → 1.16.0

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 (60) hide show
  1. package/HANDBOOK.md +25 -5
  2. package/README.md +78 -1
  3. package/arctifacts/README.md +57 -0
  4. package/eyeling.js +894 -9
  5. package/index.d.ts +184 -1
  6. package/index.js +17 -7
  7. package/lib/engine.js +92 -8
  8. package/lib/entry.js +3 -0
  9. package/lib/rdfjs.js +795 -0
  10. package/package.json +2 -2
  11. package/test/api.test.js +263 -0
  12. package/tools/bundle.js +1 -1
  13. package/follows-from/index.html +0 -549
  14. package/follows-from/library/index.md +0 -22
  15. package/follows-from/logo.svg +0 -12
  16. package/follows-from/manifesto.md +0 -48
  17. package/follows-from/method/index.md +0 -30
  18. package/follows-from/path/index.md +0 -20
  19. /package/{follows-from/artifacts → arctifacts}/ackermann.html +0 -0
  20. /package/{follows-from/artifacts → arctifacts}/auroracare.html +0 -0
  21. /package/{follows-from/artifacts → arctifacts}/bike-trip.html +0 -0
  22. /package/{follows-from/artifacts → arctifacts}/binomial-theorem.html +0 -0
  23. /package/{follows-from/artifacts → arctifacts}/bmi.html +0 -0
  24. /package/{follows-from/artifacts → arctifacts}/building-performance.html +0 -0
  25. /package/{follows-from/artifacts → arctifacts}/clinical-care.html +0 -0
  26. /package/{follows-from/artifacts → arctifacts}/collatz.html +0 -0
  27. /package/{follows-from/artifacts → arctifacts}/complex.html +0 -0
  28. /package/{follows-from/artifacts → arctifacts}/control-system.html +0 -0
  29. /package/{follows-from/artifacts → arctifacts}/delfour.html +0 -0
  30. /package/{follows-from/artifacts → arctifacts}/earthquake-epicenter.html +0 -0
  31. /package/{follows-from/artifacts → arctifacts}/eco-route.html +0 -0
  32. /package/{follows-from/artifacts → arctifacts}/euclid-infinitude.html +0 -0
  33. /package/{follows-from/artifacts → arctifacts}/euler-identity.html +0 -0
  34. /package/{follows-from/artifacts → arctifacts}/exoplanet-transit.html +0 -0
  35. /package/{follows-from/artifacts → arctifacts}/faltings-theorem.html +0 -0
  36. /package/{follows-from/artifacts → arctifacts}/fibonacci.html +0 -0
  37. /package/{follows-from/artifacts → arctifacts}/fundamental-theorem-arithmetic.html +0 -0
  38. /package/{follows-from/artifacts → arctifacts}/godel-numbering.html +0 -0
  39. /package/{follows-from/artifacts → arctifacts}/gps-bike.html +0 -0
  40. /package/{follows-from/artifacts → arctifacts}/gps-clinical-bench.html +0 -0
  41. /package/{follows-from/artifacts → arctifacts}/graph-french.html +0 -0
  42. /package/{follows-from/artifacts → arctifacts}/grass-molecular.html +0 -0
  43. /package/{follows-from/artifacts → arctifacts}/group-theory.html +0 -0
  44. /package/{follows-from/artifacts → arctifacts}/health-info.html +0 -0
  45. /package/{follows-from/artifacts → arctifacts}/kaprekar-constant.html +0 -0
  46. /package/{follows-from/artifacts → arctifacts}/lee.html +0 -0
  47. /package/{follows-from/artifacts → arctifacts}/linked-lists.html +0 -0
  48. /package/{follows-from/artifacts → arctifacts}/lldm.html +0 -0
  49. /package/{follows-from/artifacts → arctifacts}/matrix-multiplication.html +0 -0
  50. /package/{follows-from/artifacts → arctifacts}/matrix.html +0 -0
  51. /package/{follows-from/artifacts → arctifacts}/newton-raphson.html +0 -0
  52. /package/{follows-from/artifacts → arctifacts}/peano-factorial.html +0 -0
  53. /package/{follows-from/artifacts → arctifacts}/pi.html +0 -0
  54. /package/{follows-from/artifacts → arctifacts}/polynomial.html +0 -0
  55. /package/{follows-from/artifacts → arctifacts}/prime.html +0 -0
  56. /package/{follows-from/artifacts → arctifacts}/pythagorean-theorem.html +0 -0
  57. /package/{follows-from/artifacts → arctifacts}/rest-path.html +0 -0
  58. /package/{follows-from/artifacts → arctifacts}/roots-of-unity.html +0 -0
  59. /package/{follows-from/artifacts → arctifacts}/turing.html +0 -0
  60. /package/{follows-from/artifacts → arctifacts}/wind-turbines.html +0 -0
package/index.d.ts CHANGED
@@ -1,3 +1,186 @@
1
1
  declare module 'eyeling' {
2
- export function reason(opts: any, input: string): string;
2
+ export interface RdfJsTerm {
3
+ termType: string;
4
+ value: string;
5
+ equals(other: RdfJsTerm | null | undefined): boolean;
6
+ }
7
+
8
+ export interface RdfJsNamedNode extends RdfJsTerm {
9
+ termType: 'NamedNode';
10
+ }
11
+
12
+ export interface RdfJsBlankNode extends RdfJsTerm {
13
+ termType: 'BlankNode';
14
+ }
15
+
16
+ export interface RdfJsVariable extends RdfJsTerm {
17
+ termType: 'Variable';
18
+ }
19
+
20
+ export interface RdfJsDefaultGraph extends RdfJsTerm {
21
+ termType: 'DefaultGraph';
22
+ value: '';
23
+ }
24
+
25
+ export interface RdfJsLiteral extends RdfJsTerm {
26
+ termType: 'Literal';
27
+ language: string;
28
+ datatype: RdfJsNamedNode;
29
+ }
30
+
31
+ export interface RdfJsQuad extends RdfJsTerm {
32
+ termType: 'Quad';
33
+ value: '';
34
+ subject: RdfJsTerm;
35
+ predicate: RdfJsTerm;
36
+ object: RdfJsTerm;
37
+ graph: RdfJsTerm;
38
+ }
39
+
40
+ export interface RdfJsDataFactory {
41
+ namedNode(value: string): RdfJsNamedNode;
42
+ blankNode(value?: string): RdfJsBlankNode;
43
+ literal(value: string, languageOrDatatype?: string | RdfJsNamedNode): RdfJsLiteral;
44
+ variable(value: string): RdfJsVariable;
45
+ defaultGraph(): RdfJsDefaultGraph;
46
+ quad(subject: RdfJsTerm, predicate: RdfJsTerm, object: RdfJsTerm, graph?: RdfJsTerm): RdfJsQuad;
47
+ }
48
+
49
+ export interface EyelingPrefixEnv {
50
+ _type?: 'PrefixEnv';
51
+ map: Record<string, string>;
52
+ baseIri?: string;
53
+ }
54
+
55
+ export interface EyelingIri {
56
+ _type?: 'Iri';
57
+ value: string;
58
+ }
59
+
60
+ export interface EyelingLiteral {
61
+ _type?: 'Literal';
62
+ value: string;
63
+ }
64
+
65
+ export interface EyelingVar {
66
+ _type?: 'Var';
67
+ name: string;
68
+ }
69
+
70
+ export interface EyelingBlank {
71
+ _type?: 'Blank';
72
+ label: string;
73
+ }
74
+
75
+ export interface EyelingListTerm {
76
+ _type?: 'ListTerm';
77
+ elems: EyelingTerm[];
78
+ }
79
+
80
+ export interface EyelingOpenListTerm {
81
+ _type?: 'OpenListTerm';
82
+ prefix: EyelingTerm[];
83
+ tailVar: string;
84
+ }
85
+
86
+ export interface EyelingGraphTerm {
87
+ _type?: 'GraphTerm';
88
+ triples: EyelingTriple[];
89
+ }
90
+
91
+ export type EyelingTerm =
92
+ | EyelingIri
93
+ | EyelingLiteral
94
+ | EyelingVar
95
+ | EyelingBlank
96
+ | EyelingListTerm
97
+ | EyelingOpenListTerm
98
+ | EyelingGraphTerm
99
+ | RdfJsNamedNode
100
+ | RdfJsBlankNode
101
+ | RdfJsVariable
102
+ | RdfJsLiteral;
103
+
104
+ export interface EyelingTriple {
105
+ _type?: 'Triple';
106
+ s: EyelingTerm;
107
+ p: EyelingTerm;
108
+ o: EyelingTerm;
109
+ }
110
+
111
+ export interface EyelingRule {
112
+ _type?: 'Rule';
113
+ premise: EyelingTriple[];
114
+ conclusion: EyelingTriple[];
115
+ isForward?: boolean;
116
+ isFuse?: boolean;
117
+ headBlankLabels?: Iterable<string> | string[];
118
+ __dynamicConclusionTerm?: EyelingTerm;
119
+ }
120
+
121
+ export type EyelingAstBundle = [EyelingPrefixEnv, EyelingTriple[], EyelingRule[], EyelingRule[], EyelingRule[]?];
122
+
123
+ export interface RdfJsReasonInput {
124
+ n3?: string;
125
+ quads?: Iterable<RdfJsQuad> | AsyncIterable<RdfJsQuad>;
126
+ facts?: Iterable<RdfJsQuad> | AsyncIterable<RdfJsQuad>;
127
+ dataset?: Iterable<RdfJsQuad> | AsyncIterable<RdfJsQuad>;
128
+ rules?: EyelingRule[] | EyelingAstBundle;
129
+ factsN3?: string;
130
+ n3Facts?: string;
131
+ prefixesN3?: string;
132
+ n3Prefixes?: string;
133
+ prefixes?: EyelingPrefixEnv;
134
+ triples?: EyelingTriple[];
135
+ forwardRules?: EyelingRule[];
136
+ frules?: EyelingRule[];
137
+ backwardRules?: EyelingRule[];
138
+ brules?: EyelingRule[];
139
+ queryRules?: EyelingRule[];
140
+ logQueryRules?: EyelingRule[];
141
+ qrules?: EyelingRule[];
142
+ ast?: EyelingAstBundle;
143
+ document?: EyelingAstBundle;
144
+ }
145
+
146
+ export interface ReasonOptions {
147
+ proofComments?: boolean;
148
+ noProofComments?: boolean;
149
+ args?: string[];
150
+ maxBuffer?: number;
151
+ }
152
+
153
+ export interface ReasonStreamOptions {
154
+ baseIri?: string | null;
155
+ proof?: boolean;
156
+ includeInputFactsInClosure?: boolean;
157
+ enforceHttps?: boolean;
158
+ rdfjs?: boolean;
159
+ dataFactory?: RdfJsDataFactory | null;
160
+ onDerived?: (item: { triple: string; quad?: RdfJsQuad; df: any }) => void;
161
+ }
162
+
163
+ export interface ReasonStreamResult {
164
+ prefixes: any;
165
+ facts: any[];
166
+ derived: any[];
167
+ queryMode: boolean;
168
+ queryTriples: any[];
169
+ queryDerived: any[];
170
+ closureN3: string;
171
+ closureQuads?: RdfJsQuad[];
172
+ queryQuads?: RdfJsQuad[];
173
+ }
174
+
175
+ export function reason(opts: ReasonOptions, input: string | RdfJsReasonInput | EyelingAstBundle): string;
176
+ export function reasonStream(
177
+ input: string | RdfJsReasonInput | EyelingAstBundle,
178
+ opts?: ReasonStreamOptions,
179
+ ): ReasonStreamResult;
180
+ export function reasonRdfJs(
181
+ input: string | RdfJsReasonInput | EyelingAstBundle,
182
+ opts?: Omit<ReasonStreamOptions, 'rdfjs' | 'onDerived'>,
183
+ ): AsyncIterable<RdfJsQuad>;
184
+
185
+ export const rdfjs: RdfJsDataFactory;
3
186
  }
package/index.js CHANGED
@@ -5,16 +5,21 @@ const os = require('node:os');
5
5
  const path = require('node:path');
6
6
  const cp = require('node:child_process');
7
7
 
8
- function reason(opt = {}, n3_input = '') {
9
- if (n3_input == null) n3_input = '';
10
- if (typeof n3_input !== 'string') {
11
- throw new TypeError('reason(opt, n3_input): n3_input must be a string');
12
- }
8
+ const bundleApi = require('./eyeling.js');
9
+ const { dataFactory, normalizeReasonerInputSync } = require('./lib/rdfjs');
10
+
11
+ function reason(opt = {}, input = '') {
12
+ if (input == null) input = '';
13
13
 
14
14
  // allow passing an args array directly
15
15
  if (Array.isArray(opt)) opt = { args: opt };
16
16
  if (opt == null || typeof opt !== 'object') opt = {};
17
17
 
18
+ const n3Input = normalizeReasonerInputSync(input);
19
+ if (typeof n3Input !== 'string') {
20
+ throw new TypeError('reason(opt, input): input must resolve to an N3 string');
21
+ }
22
+
18
23
  const args = [];
19
24
 
20
25
  // default: proof comments OFF for API output (machine-friendly)
@@ -43,7 +48,7 @@ function reason(opt = {}, n3_input = '') {
43
48
  const inputFile = path.join(dir, 'input.n3');
44
49
 
45
50
  try {
46
- fs.writeFileSync(inputFile, n3_input, 'utf8');
51
+ fs.writeFileSync(inputFile, n3Input, 'utf8');
47
52
 
48
53
  const eyelingPath = path.join(__dirname, 'eyeling.js');
49
54
  const res = cp.spawnSync(process.execPath, [eyelingPath, ...args, inputFile], { encoding: 'utf8', maxBuffer });
@@ -67,7 +72,12 @@ function reason(opt = {}, n3_input = '') {
67
72
  }
68
73
  }
69
74
 
70
- module.exports = { reason };
75
+ module.exports = {
76
+ reason,
77
+ reasonStream: bundleApi.reasonStream,
78
+ reasonRdfJs: bundleApi.reasonRdfJs,
79
+ rdfjs: dataFactory,
80
+ };
71
81
 
72
82
  // small interop nicety for ESM default import
73
83
  module.exports.default = module.exports;
package/lib/engine.js CHANGED
@@ -53,6 +53,13 @@ const {
53
53
  const { makeExplain } = require('./explain');
54
54
 
55
55
  const { tripleToN3, prettyPrintQueryTriples } = require('./printing');
56
+ const {
57
+ getDataFactory,
58
+ internalTripleToRdfJsQuad,
59
+ normalizeParsedReasonerInputSync,
60
+ normalizeReasonerInputSync,
61
+ normalizeReasonerInputAsync,
62
+ } = require('./rdfjs');
56
63
 
57
64
  const trace = require('./trace');
58
65
  const { deterministicSkolemIdFromKey } = require('./skolem');
@@ -2867,24 +2874,41 @@ function forwardChainAndCollectLogQueryConclusions(facts, forwardRules, backRule
2867
2874
 
2868
2875
  // (proof printing + log:outputString moved to lib/explain.js)
2869
2876
 
2870
- function reasonStream(n3Text, opts = {}) {
2877
+ function reasonStream(input, opts = {}) {
2871
2878
  const {
2872
2879
  baseIri = null,
2873
2880
  proof = false,
2874
2881
  onDerived = null,
2875
2882
  includeInputFactsInClosure = true,
2876
2883
  enforceHttps = false,
2884
+ rdfjs = false,
2885
+ dataFactory = null,
2877
2886
  } = opts;
2878
2887
 
2888
+ const parsedInput = normalizeParsedReasonerInputSync(input);
2889
+ const rdfFactory = rdfjs ? getDataFactory(dataFactory) : null;
2890
+
2879
2891
  const __oldEnforceHttps = deref.getEnforceHttpsEnabled();
2880
2892
  deref.setEnforceHttpsEnabled(!!enforceHttps);
2881
2893
  proofCommentsEnabled = !!proof;
2882
2894
 
2883
- const toks = lex(n3Text);
2884
- const parser = new Parser(toks);
2885
- if (baseIri) parser.prefixes.setBase(baseIri);
2895
+ let prefixes, triples, frules, brules, logQueryRules;
2896
+
2897
+ if (parsedInput) {
2898
+ prefixes = parsedInput.prefixes;
2899
+ triples = parsedInput.triples;
2900
+ frules = parsedInput.frules;
2901
+ brules = parsedInput.brules;
2902
+ logQueryRules = parsedInput.logQueryRules;
2903
+ if (baseIri) prefixes.setBase(baseIri);
2904
+ } else {
2905
+ const n3Text = normalizeReasonerInputSync(input);
2906
+ const toks = lex(n3Text);
2907
+ const parser = new Parser(toks);
2908
+ if (baseIri) parser.prefixes.setBase(baseIri);
2886
2909
 
2887
- const [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
2910
+ [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
2911
+ }
2888
2912
  // Make the parsed prefixes available to log:trace output
2889
2913
  trace.setTracePrefixes(prefixes);
2890
2914
 
@@ -2913,17 +2937,21 @@ function reasonStream(n3Text, opts = {}) {
2913
2937
  // query-selected triples (not all derived facts).
2914
2938
  if (typeof onDerived === 'function') {
2915
2939
  for (const qdf of queryDerived) {
2916
- onDerived({ triple: tripleToN3(qdf.fact, prefixes), df: qdf });
2940
+ const payload = { triple: tripleToN3(qdf.fact, prefixes), df: qdf };
2941
+ if (rdfFactory) payload.quad = internalTripleToRdfJsQuad(qdf.fact, rdfFactory);
2942
+ onDerived(payload);
2917
2943
  }
2918
2944
  }
2919
2945
  } else {
2920
2946
  // Default mode: output only newly derived forward facts.
2921
2947
  derived = forwardChain(facts, frules, brules, (df) => {
2922
2948
  if (typeof onDerived === 'function') {
2923
- onDerived({
2949
+ const payload = {
2924
2950
  triple: tripleToN3(df.fact, prefixes),
2925
2951
  df,
2926
- });
2952
+ };
2953
+ if (rdfFactory) payload.quad = internalTripleToRdfJsQuad(df.fact, rdfFactory);
2954
+ onDerived(payload);
2927
2955
  }
2928
2956
  });
2929
2957
  }
@@ -2949,10 +2977,65 @@ function reasonStream(n3Text, opts = {}) {
2949
2977
  queryDerived,
2950
2978
  closureN3,
2951
2979
  };
2980
+
2981
+ if (rdfFactory) {
2982
+ __out.closureQuads = closureTriples.map((t) => internalTripleToRdfJsQuad(t, rdfFactory));
2983
+ __out.queryQuads = queryTriples.map((t) => internalTripleToRdfJsQuad(t, rdfFactory));
2984
+ }
2952
2985
  deref.setEnforceHttpsEnabled(__oldEnforceHttps);
2953
2986
  return __out;
2954
2987
  }
2955
2988
 
2989
+ function reasonRdfJs(input, opts = {}) {
2990
+ const { dataFactory = null, ...restOpts } = opts || {};
2991
+ const rdfFactory = getDataFactory(dataFactory);
2992
+
2993
+ const queue = [];
2994
+ const waiters = [];
2995
+ let done = false;
2996
+ let failure = null;
2997
+
2998
+ const flush = () => {
2999
+ while (waiters.length && (queue.length || done)) {
3000
+ const resolve = waiters.shift();
3001
+ if (queue.length) resolve({ value: queue.shift(), done: false });
3002
+ else if (failure) resolve(Promise.reject(failure));
3003
+ else resolve({ value: undefined, done: true });
3004
+ }
3005
+ };
3006
+
3007
+ Promise.resolve().then(async () => {
3008
+ try {
3009
+ const normalizedInput = await normalizeReasonerInputAsync(input);
3010
+ reasonStream(normalizedInput, {
3011
+ ...restOpts,
3012
+ rdfjs: false,
3013
+ onDerived: ({ df }) => {
3014
+ queue.push(internalTripleToRdfJsQuad(df.fact, rdfFactory));
3015
+ flush();
3016
+ },
3017
+ });
3018
+ } catch (e) {
3019
+ failure = e;
3020
+ } finally {
3021
+ done = true;
3022
+ flush();
3023
+ }
3024
+ });
3025
+
3026
+ return {
3027
+ [Symbol.asyncIterator]() {
3028
+ return this;
3029
+ },
3030
+ next() {
3031
+ if (queue.length) return Promise.resolve({ value: queue.shift(), done: false });
3032
+ if (failure) return Promise.reject(failure);
3033
+ if (done) return Promise.resolve({ value: undefined, done: true });
3034
+ return new Promise((resolve) => waiters.push(resolve));
3035
+ },
3036
+ };
3037
+ }
3038
+
2956
3039
  // Minimal export surface for Node + browser/worker
2957
3040
  function main() {
2958
3041
  // Lazily require to avoid hard cycles in the module graph.
@@ -2999,6 +3082,7 @@ function setTracePrefixes(v) {
2999
3082
 
3000
3083
  module.exports = {
3001
3084
  reasonStream,
3085
+ reasonRdfJs,
3002
3086
  collectLogQueryConclusions,
3003
3087
  forwardChainAndCollectLogQueryConclusions,
3004
3088
  collectOutputStringsFromFacts,
package/lib/entry.js CHANGED
@@ -12,10 +12,13 @@
12
12
  // can call into the reasoner like the original monolithic build did.
13
13
 
14
14
  const engine = require('./engine');
15
+ const { dataFactory } = require('./rdfjs');
15
16
 
16
17
  module.exports = {
17
18
  // public
18
19
  reasonStream: engine.reasonStream,
20
+ reasonRdfJs: engine.reasonRdfJs,
21
+ rdfjs: dataFactory,
19
22
  main: engine.main,
20
23
  version: engine.version,
21
24