eyeling 1.15.0 → 1.15.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.
@@ -1,18 +1,95 @@
1
1
  #include <stdio.h>
2
2
  #include <stdlib.h>
3
+ #include <string.h>
4
+
5
+ enum { DEPTH = 100000 };
6
+
7
+ static int emit(const char *s) {
8
+ return fputs(s, stdout) != EOF;
9
+ }
10
+
11
+ static int emit_type(const char *kind, int index) {
12
+ return printf(":ind a :%s%d .\n", kind, index) >= 0;
13
+ }
3
14
 
4
15
  int main(void) {
5
- if (printf("@prefix : <http://eulersharp.sourceforge.net/2009/12dtb/test#> .\n\n") < 0) {
16
+ unsigned char hasN[DEPTH + 1];
17
+ unsigned char hasI[DEPTH + 1];
18
+ unsigned char hasJ[DEPTH + 1];
19
+ unsigned char hasA2 = 0;
20
+ unsigned char hasTest = 0;
21
+ int changed = 1;
22
+
23
+ memset(hasN, 0, sizeof(hasN));
24
+ memset(hasI, 0, sizeof(hasI));
25
+ memset(hasJ, 0, sizeof(hasJ));
26
+
27
+ /* fact: :ind a :N0. */
28
+ hasN[0] = 1;
29
+
30
+ /*
31
+ * Forward-chain the rules to a fixpoint.
32
+ *
33
+ * {?X a :N0} => {?X a :N1, :I1, :J1}.
34
+ * {?X a :N1} => {?X a :N2, :I2, :J2}.
35
+ * ...
36
+ * {?X a :N99999} => {?X a :N100000, :I100000, :J100000}.
37
+ * {?X a :N100000} => {?X a :A2}.
38
+ * {:ind a :A2} => {:test :is true}.
39
+ */
40
+ while (changed) {
41
+ changed = 0;
42
+
43
+ for (int i = 0; i < DEPTH; i++) {
44
+ if (!hasN[i]) {
45
+ continue;
46
+ }
47
+
48
+ if (!hasN[i + 1]) {
49
+ hasN[i + 1] = 1;
50
+ changed = 1;
51
+ }
52
+ if (!hasI[i + 1]) {
53
+ hasI[i + 1] = 1;
54
+ changed = 1;
55
+ }
56
+ if (!hasJ[i + 1]) {
57
+ hasJ[i + 1] = 1;
58
+ changed = 1;
59
+ }
60
+ }
61
+
62
+ if (hasN[DEPTH] && !hasA2) {
63
+ hasA2 = 1;
64
+ changed = 1;
65
+ }
66
+
67
+ if (hasA2 && !hasTest) {
68
+ hasTest = 1;
69
+ changed = 1;
70
+ }
71
+ }
72
+
73
+ if (!emit("@prefix : <http://eulersharp.sourceforge.net/2009/12dtb/test#> .\n\n")) {
6
74
  return EXIT_FAILURE;
7
75
  }
8
76
 
9
- for (int i = 1; i <= 100000; i++) {
10
- if (printf(":ind a :N%d .\n:ind a :I%d .\n:ind a :J%d .\n", i, i, i) < 0) {
77
+ for (int i = 1; i <= DEPTH; i++) {
78
+ if (!hasN[i] || !hasI[i] || !hasJ[i]) {
79
+ fprintf(stderr, "incomplete closure at depth %d\n", i);
11
80
  return EXIT_FAILURE;
12
81
  }
82
+ if (!emit_type("N", i) || !emit_type("I", i) || !emit_type("J", i)) {
83
+ return EXIT_FAILURE;
84
+ }
85
+ }
86
+
87
+ if (!hasA2 || !hasTest) {
88
+ fputs("expected conclusions were not derived\n", stderr);
89
+ return EXIT_FAILURE;
13
90
  }
14
91
 
15
- if (printf(":ind a :A2 .\n:test :is true .\n") < 0) {
92
+ if (!emit(":ind a :A2 .\n:test :is true .\n")) {
16
93
  return EXIT_FAILURE;
17
94
  }
18
95
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.15.0",
3
+ "version": "1.15.1",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
@@ -6,20 +6,36 @@ const os = require('node:os');
6
6
  const path = require('node:path');
7
7
  const cp = require('node:child_process');
8
8
 
9
- const TTY = process.stdout.isTTY;
10
- const C = TTY
11
- ? { g: '\x1b[32m', r: '\x1b[31m', y: '\x1b[33m', dim: '\x1b[2m', n: '\x1b[0m' }
12
- : { g: '', r: '', y: '', dim: '', n: '' };
13
- const msTag = (ms) => `${C.dim}(${ms} ms)${C.n}`;
9
+ const C = process.stdout.isTTY
10
+ ? {
11
+ red: '\x1b[31m',
12
+ green: '\x1b[32m',
13
+ yellow: '\x1b[33m',
14
+ dim: '\x1b[2m',
15
+ reset: '\x1b[0m',
16
+ }
17
+ : {
18
+ red: '',
19
+ green: '',
20
+ yellow: '',
21
+ dim: '',
22
+ reset: '',
23
+ };
14
24
 
15
25
  function ok(msg) {
16
- console.log(`${C.g}OK${C.n} ${msg}`);
26
+ console.log(`${C.green}OK${C.reset} ${msg}`);
17
27
  }
28
+
18
29
  function fail(msg) {
19
- console.error(`${C.r}FAIL${C.n} ${msg}`);
30
+ console.log(`${C.red}FAIL${C.reset} ${msg}`);
20
31
  }
32
+
21
33
  function info(msg) {
22
- console.log(`${C.y}==${C.n} ${msg}`);
34
+ console.log(`${C.yellow}==${C.reset} ${msg}`);
35
+ }
36
+
37
+ function msTag(ms) {
38
+ return `(${ms} ms)`;
23
39
  }
24
40
 
25
41
  function run(cmd, args, opts = {}) {
@@ -33,8 +49,8 @@ function run(cmd, args, opts = {}) {
33
49
  function normalizeForCompare(n3Text) {
34
50
  return String(n3Text)
35
51
  .split(/\r?\n/)
36
- .map((l) => l.replace(/[\t ]+$/g, ''))
37
- .filter((l) => l.length > 0)
52
+ .map((line) => line.replace(/[ \t]+$/g, ''))
53
+ .filter((line) => line.length > 0)
38
54
  .sort((a, b) => a.localeCompare(b))
39
55
  .join('\n');
40
56
  }
@@ -77,7 +93,7 @@ function main() {
77
93
  .sort((a, b) => a.localeCompare(b));
78
94
 
79
95
  info(`Running ${files.length} C check tests`);
80
- console.log(`${C.dim}compiler ${compiler}; node ${process.version}${C.n}`);
96
+ console.log(`${C.dim}compiler ${compiler}; node ${process.version}${C.reset}`);
81
97
 
82
98
  if (files.length === 0) {
83
99
  ok('No .c files found in examples/check/input/');
@@ -100,6 +116,8 @@ function main() {
100
116
  const tmpDir = mkTmpDir();
101
117
  const executablePath = path.join(tmpDir, stem + (process.platform === 'win32' ? '.exe' : ''));
102
118
 
119
+ let outFd = null;
120
+
103
121
  try {
104
122
  if (!fs.existsSync(expectedPath)) {
105
123
  throw new Error(`Missing expected output: ${path.relative(root, expectedPath)}`);
@@ -120,23 +138,32 @@ function main() {
120
138
  throw new Error(`Cannot run compiler '${compiler}': ${compile.error.message}`);
121
139
  }
122
140
  if (compile.status !== 0) {
123
- throw new Error(`Compilation failed\n${compile.stderr || compile.stdout || ''}`.trim());
141
+ throw new Error(`Compilation failed\n${(compile.stderr || compile.stdout || '').trim()}`);
124
142
  }
125
143
 
126
- const execResult = run(executablePath, [], { cwd: root });
144
+ outFd = fs.openSync(generatedPath, 'w');
145
+
146
+ const execResult = cp.spawnSync(executablePath, [], {
147
+ cwd: root,
148
+ stdio: ['ignore', outFd, 'pipe'],
149
+ encoding: 'utf8',
150
+ });
151
+
152
+ fs.closeSync(outFd);
153
+ outFd = null;
154
+
127
155
  if (execResult.error) {
128
156
  throw new Error(`Cannot run executable: ${execResult.error.message}`);
129
157
  }
130
-
131
- fs.writeFileSync(generatedPath, execResult.stdout || '', 'utf8');
132
-
133
158
  if (execResult.status !== 0) {
134
- throw new Error(`Executable exited with ${execResult.status}\n${execResult.stderr || ''}`.trim());
159
+ const why = execResult.signal ? `signal ${execResult.signal}` : `code ${execResult.status}`;
160
+ throw new Error(`Executable exited with ${why}\n${(execResult.stderr || '').trim()}`);
135
161
  }
136
162
 
137
163
  const expectedText = fs.readFileSync(expectedPath, 'utf8');
138
164
  const generatedText = fs.readFileSync(generatedPath, 'utf8');
139
165
  const same = normalizeForCompare(expectedText) === normalizeForCompare(generatedText);
166
+
140
167
  const ms = Date.now() - start;
141
168
 
142
169
  if (same) {
@@ -151,9 +178,14 @@ function main() {
151
178
  } catch (err) {
152
179
  const ms = Date.now() - start;
153
180
  fail(`${idx} ${file} ${msTag(ms)}`);
154
- fail(err.message);
181
+ fail(err && err.message ? err.message : String(err));
155
182
  failed++;
156
183
  } finally {
184
+ if (outFd !== null) {
185
+ try {
186
+ fs.closeSync(outFd);
187
+ } catch {}
188
+ }
157
189
  rmrf(tmpDir);
158
190
  }
159
191
  }