eyeling 1.14.13 → 1.15.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 (29) hide show
  1. package/examples/check/input/deep-taxonomy-100000.c +20 -0
  2. package/examples/check/input/gps.c +127 -0
  3. package/examples/check/input/high-trust-rdf-bloom-envelope.c +148 -0
  4. package/examples/check/input/high-trust-rdf-bloom-tamper-contrast.c +247 -0
  5. package/examples/check/input/odrl-dpv-risk-ranked.c +275 -0
  6. package/examples/check/output/deep-taxonomy-100000.n3 +300004 -0
  7. package/examples/check/output/gps.n3 +6 -0
  8. package/examples/check/output/high-trust-rdf-bloom-envelope.n3 +7 -0
  9. package/examples/check/output/high-trust-rdf-bloom-tamper-contrast.n3 +27 -0
  10. package/examples/check/output/odrl-dpv-risk-ranked.n3 +13 -0
  11. package/examples/decimal-ebike-motor-thermal-envelope.n3 +286 -0
  12. package/examples/decimal-transcendental-servo-envelope.n3 +197 -0
  13. package/examples/deck/high-trust-rdf-bloom-envelope.md +371 -0
  14. package/examples/deck/schema-foaf-mapping.md +3 -1
  15. package/examples/high-trust-rdf-bloom-envelope.n3 +281 -0
  16. package/examples/high-trust-rdf-bloom-tamper-contrast.n3 +395 -0
  17. package/examples/integer-first-control-tank-level.n3 +209 -0
  18. package/examples/integer-first-sqrt2-mediants.n3 +174 -0
  19. package/examples/output/decimal-ebike-motor-thermal-envelope.n3 +25 -0
  20. package/examples/output/decimal-transcendental-servo-envelope.n3 +29 -0
  21. package/examples/output/high-trust-rdf-bloom-envelope.n3 +7 -0
  22. package/examples/output/high-trust-rdf-bloom-tamper-contrast.n3 +27 -0
  23. package/examples/output/integer-first-control-tank-level.n3 +70 -0
  24. package/examples/output/integer-first-sqrt2-mediants.n3 +57 -0
  25. package/eyeling.js +90 -1
  26. package/lib/lexer.js +90 -1
  27. package/package.json +3 -2
  28. package/test/api.test.js +221 -0
  29. package/test/check.test.js +174 -0
package/test/api.test.js CHANGED
@@ -567,6 +567,227 @@ bad.:example a bad.:Person.
567
567
  `,
568
568
  expectError: true,
569
569
  },
570
+ {
571
+ name: '12h invalid syntax: space is not allowed inside IRIREF',
572
+ opt: { proofComments: false },
573
+ input: `
574
+ @prefix : <http://example.org/> .
575
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
576
+
577
+ <http://bad example.org/> a :BadExample.
578
+
579
+ {
580
+ :subject :predicate ?X.
581
+ }
582
+ =>
583
+ {
584
+ :result :has :crash-syntax-7.
585
+ }.
586
+
587
+ {} => {
588
+ :test :contains :crash-syntax-7.
589
+ }.
590
+
591
+ {
592
+ :result :has :crash-syntax-7.
593
+ }
594
+ =>
595
+ {
596
+ :test :is false.
597
+ }.
598
+ `,
599
+ expectError: true,
600
+ },
601
+ {
602
+ name: '12i invalid syntax: UCHAR escape is not allowed inside IRIREF',
603
+ opt: { proofComments: false },
604
+ input: String.raw`
605
+ @prefix : <http://example.org/> .
606
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
607
+
608
+ <http://bad\u0020example.org/> a :BadExample.
609
+
610
+ {
611
+ :subject :predicate ?X.
612
+ }
613
+ =>
614
+ {
615
+ :result :has :crash-syntax-8.
616
+ }.
617
+
618
+ {} => {
619
+ :test :contains :crash-syntax-8.
620
+ }.
621
+
622
+ {
623
+ :result :has :crash-syntax-8.
624
+ }
625
+ =>
626
+ {
627
+ :test :is false.
628
+ }.
629
+ `,
630
+ expectError: true,
631
+ },
632
+ {
633
+ name: '12j invalid syntax: control characters are not allowed inside IRIREF',
634
+ opt: { proofComments: false },
635
+ input: `
636
+ @prefix : <http://example.org/> .
637
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
638
+
639
+ <http://badexample.org> :foo <http://example.org/> .
640
+
641
+ {
642
+ :subject :predicate ?X.
643
+ }
644
+ =>
645
+ {
646
+ :result :has :crash-syntax-9.
647
+ }.
648
+
649
+ {} => {
650
+ :test :contains :crash-syntax-9.
651
+ }.
652
+
653
+ {
654
+ :result :has :crash-syntax-9.
655
+ }
656
+ =>
657
+ {
658
+ :test :is false.
659
+ }.
660
+ `,
661
+ expectError: true,
662
+ },
663
+ {
664
+ name: '12k invalid syntax: control-character UCHAR is not allowed inside IRIREF',
665
+ opt: { proofComments: false },
666
+ input: String.raw`
667
+ @prefix : <http://example.org/> .
668
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
669
+
670
+ <http://bad\u0007example.org> :foo <http://example.org/> .
671
+
672
+ {
673
+ :subject :predicate ?X.
674
+ }
675
+ =>
676
+ {
677
+ :result :has :crash-syntax-10.
678
+ }.
679
+
680
+ {} => {
681
+ :test :contains :crash-syntax-10.
682
+ }.
683
+
684
+ {
685
+ :result :has :crash-syntax-10.
686
+ }
687
+ =>
688
+ {
689
+ :test :is false.
690
+ }.
691
+ `,
692
+ expectError: true,
693
+ },
694
+ {
695
+ name: '12l regression: IRIREF \\u escape decodes before log:uri comparison (mismatch stays falsey)',
696
+ opt: { proofComments: false },
697
+ input: String.raw`
698
+ @prefix : <http://example.org/> .
699
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
700
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
701
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
702
+ @base <http://example.org/>.
703
+
704
+ {
705
+ <http://example.org/\u0041> log:uri "http://example.org/\\u0041".
706
+ }
707
+ =>
708
+ {
709
+ :result :has :fail-literal-1.
710
+ }.
711
+
712
+ { } => {
713
+ :test :contains :fail-literal-1.
714
+ }.
715
+ `,
716
+ expect: [/:(?:test)\s+:(?:contains)\s+:(?:fail-literal-1)\s*\./],
717
+ notExpect: [/:(?:result)\s+:(?:has)\s+:(?:fail-literal-1)\s*\./, /:(?:test)\s+:(?:is)\s+true\s*\./],
718
+ },
719
+ {
720
+ name: '12m regression: IRIREF \\u escape matches plain-A literal via log:uri',
721
+ opt: { proofComments: false },
722
+ input: String.raw`
723
+ @prefix : <http://example.org/> .
724
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
725
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
726
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
727
+ @base <http://example.org/>.
728
+
729
+ {
730
+ <http://example.org/\u0041> log:uri "http://example.org/A".
731
+ }
732
+ =>
733
+ {
734
+ :result :has :success-literal-5.
735
+ }.
736
+
737
+ { } => {
738
+ :test :contains :success-literal-5.
739
+ }.
740
+
741
+ {
742
+ :result :has :success-literal-5.
743
+ }
744
+ =>
745
+ {
746
+ :test :is true.
747
+ }.
748
+ `,
749
+ expect: [
750
+ /:(?:result)\s+:(?:has)\s+:(?:success-literal-5)\s*\./,
751
+ /:(?:test)\s+:(?:contains)\s+:(?:success-literal-5)\s*\./,
752
+ /:(?:test)\s+:(?:is)\s+true\s*\./,
753
+ ],
754
+ },
755
+ {
756
+ name: '12n regression: IRIREF \\u escape matches decoded literal escape via log:uri',
757
+ opt: { proofComments: false },
758
+ input: String.raw`
759
+ @prefix : <http://example.org/> .
760
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
761
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
762
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
763
+ @base <http://example.org/>.
764
+
765
+ {
766
+ <http://example.org/\u0041> log:uri "http://example.org/\u0041".
767
+ }
768
+ =>
769
+ {
770
+ :result :has :success-literal-6.
771
+ }.
772
+
773
+ { } => {
774
+ :test :contains :success-literal-6.
775
+ }.
776
+
777
+ {
778
+ :result :has :success-literal-6.
779
+ }
780
+ =>
781
+ {
782
+ :test :is true.
783
+ }.
784
+ `,
785
+ expect: [
786
+ /:(?:result)\s+:(?:has)\s+:(?:success-literal-6)\s*\./,
787
+ /:(?:test)\s+:(?:contains)\s+:(?:success-literal-6)\s*\./,
788
+ /:(?:test)\s+:(?:is)\s+true\s*\./,
789
+ ],
790
+ },
570
791
  {
571
792
  name: '13 heavier recursion: ancestor closure over 15 links',
572
793
  opt: { proofComments: false, maxBuffer: 200 * 1024 * 1024 },
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('node:fs');
5
+ const os = require('node:os');
6
+ const path = require('node:path');
7
+ const cp = require('node:child_process');
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}`;
14
+
15
+ function ok(msg) {
16
+ console.log(`${C.g}OK${C.n} ${msg}`);
17
+ }
18
+ function fail(msg) {
19
+ console.error(`${C.r}FAIL${C.n} ${msg}`);
20
+ }
21
+ function info(msg) {
22
+ console.log(`${C.y}==${C.n} ${msg}`);
23
+ }
24
+
25
+ function run(cmd, args, opts = {}) {
26
+ return cp.spawnSync(cmd, args, {
27
+ encoding: 'utf8',
28
+ maxBuffer: 200 * 1024 * 1024,
29
+ ...opts,
30
+ });
31
+ }
32
+
33
+ function normalizeForCompare(n3Text) {
34
+ return String(n3Text)
35
+ .split(/\r?\n/)
36
+ .map((l) => l.replace(/[\t ]+$/g, ''))
37
+ .filter((l) => l.length > 0)
38
+ .sort((a, b) => a.localeCompare(b))
39
+ .join('\n');
40
+ }
41
+
42
+ function mkTmpDir() {
43
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'eyeling-check-'));
44
+ }
45
+
46
+ function rmrf(p) {
47
+ try {
48
+ fs.rmSync(p, { recursive: true, force: true });
49
+ } catch {}
50
+ }
51
+
52
+ function showDiff(expectedPath, generatedPath) {
53
+ const d = run('diff', ['-u', expectedPath, generatedPath]);
54
+ if (d.stdout) process.stdout.write(d.stdout);
55
+ if (d.stderr) process.stderr.write(d.stderr);
56
+ }
57
+
58
+ function main() {
59
+ const suiteStart = Date.now();
60
+
61
+ const root = path.resolve(__dirname, '..');
62
+ const inputDir = path.join(root, 'examples', 'check', 'input');
63
+ const generatedDir = path.join(root, 'examples', 'check', 'output');
64
+ const expectedDir = path.join(root, 'examples', 'output');
65
+ const compiler = process.env.CC || 'cc';
66
+
67
+ if (!fs.existsSync(inputDir)) {
68
+ ok(`No check inputs directory found: ${inputDir}`);
69
+ process.exit(0);
70
+ }
71
+
72
+ fs.mkdirSync(generatedDir, { recursive: true });
73
+
74
+ const files = fs
75
+ .readdirSync(inputDir)
76
+ .filter((f) => f.endsWith('.c'))
77
+ .sort((a, b) => a.localeCompare(b));
78
+
79
+ info(`Running ${files.length} C check tests`);
80
+ console.log(`${C.dim}compiler ${compiler}; node ${process.version}${C.n}`);
81
+
82
+ if (files.length === 0) {
83
+ ok('No .c files found in examples/check/input/');
84
+ process.exit(0);
85
+ }
86
+
87
+ let passed = 0;
88
+ let failed = 0;
89
+ const idxWidth = String(files.length).length;
90
+
91
+ for (let i = 0; i < files.length; i++) {
92
+ const idx = String(i + 1).padStart(idxWidth, '0');
93
+ const file = files[i];
94
+ const start = Date.now();
95
+
96
+ const sourcePath = path.join(inputDir, file);
97
+ const stem = path.basename(file, '.c');
98
+ const expectedPath = path.join(expectedDir, `${stem}.n3`);
99
+ const generatedPath = path.join(generatedDir, `${stem}.n3`);
100
+ const tmpDir = mkTmpDir();
101
+ const executablePath = path.join(tmpDir, stem + (process.platform === 'win32' ? '.exe' : ''));
102
+
103
+ try {
104
+ if (!fs.existsSync(expectedPath)) {
105
+ throw new Error(`Missing expected output: ${path.relative(root, expectedPath)}`);
106
+ }
107
+
108
+ const compile = run(compiler, [
109
+ '-std=c11',
110
+ '-Wall',
111
+ '-Wextra',
112
+ '-pedantic',
113
+ sourcePath,
114
+ '-lm',
115
+ '-o',
116
+ executablePath,
117
+ ]);
118
+
119
+ if (compile.error) {
120
+ throw new Error(`Cannot run compiler '${compiler}': ${compile.error.message}`);
121
+ }
122
+ if (compile.status !== 0) {
123
+ throw new Error(`Compilation failed\n${compile.stderr || compile.stdout || ''}`.trim());
124
+ }
125
+
126
+ const execResult = run(executablePath, [], { cwd: root });
127
+ if (execResult.error) {
128
+ throw new Error(`Cannot run executable: ${execResult.error.message}`);
129
+ }
130
+
131
+ fs.writeFileSync(generatedPath, execResult.stdout || '', 'utf8');
132
+
133
+ if (execResult.status !== 0) {
134
+ throw new Error(`Executable exited with ${execResult.status}\n${execResult.stderr || ''}`.trim());
135
+ }
136
+
137
+ const expectedText = fs.readFileSync(expectedPath, 'utf8');
138
+ const generatedText = fs.readFileSync(generatedPath, 'utf8');
139
+ const same = normalizeForCompare(expectedText) === normalizeForCompare(generatedText);
140
+ const ms = Date.now() - start;
141
+
142
+ if (same) {
143
+ ok(`${idx} ${file} ${msTag(ms)}`);
144
+ passed++;
145
+ } else {
146
+ fail(`${idx} ${file} ${msTag(ms)}`);
147
+ fail('Output differs');
148
+ showDiff(expectedPath, generatedPath);
149
+ failed++;
150
+ }
151
+ } catch (err) {
152
+ const ms = Date.now() - start;
153
+ fail(`${idx} ${file} ${msTag(ms)}`);
154
+ fail(err.message);
155
+ failed++;
156
+ } finally {
157
+ rmrf(tmpDir);
158
+ }
159
+ }
160
+
161
+ console.log('');
162
+ const suiteMs = Date.now() - suiteStart;
163
+ info(`Total elapsed: ${suiteMs} ms (${(suiteMs / 1000).toFixed(2)} s)`);
164
+
165
+ if (failed === 0) {
166
+ ok(`All C check tests passed (${passed}/${files.length})`);
167
+ process.exit(0);
168
+ }
169
+
170
+ fail(`Some C check tests failed (${passed}/${files.length})`);
171
+ process.exit(2);
172
+ }
173
+
174
+ main();