eyeling 1.22.3 → 1.22.5

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 (44) hide show
  1. package/HANDBOOK.md +50 -10
  2. package/dist/browser/eyeling.browser.js +10 -0
  3. package/examples/arcling/README.md +6 -50
  4. package/examples/output/{sudoku.n3 → sudoku.txt} +1 -0
  5. package/examples/sudoku.n3 +2 -2
  6. package/eyeling.js +10 -0
  7. package/lib/builtins.js +10 -0
  8. package/package.json +1 -1
  9. package/test/api.test.js +26 -0
  10. package/test/examples.test.js +20 -2
  11. /package/examples/output/{auroracare.n3 → auroracare.txt} +0 -0
  12. /package/examples/output/{bmi.n3 → bmi.txt} +0 -0
  13. /package/examples/output/{calidor.n3 → calidor.txt} +0 -0
  14. /package/examples/output/{control-system.n3 → control-system.txt} +0 -0
  15. /package/examples/output/{deep-taxonomy-10.n3 → deep-taxonomy-10.txt} +0 -0
  16. /package/examples/output/{deep-taxonomy-100.n3 → deep-taxonomy-100.txt} +0 -0
  17. /package/examples/output/{deep-taxonomy-1000.n3 → deep-taxonomy-1000.txt} +0 -0
  18. /package/examples/output/{deep-taxonomy-10000.n3 → deep-taxonomy-10000.txt} +0 -0
  19. /package/examples/output/{deep-taxonomy-100000.n3 → deep-taxonomy-100000.txt} +0 -0
  20. /package/examples/output/{delfour.n3 → delfour.txt} +0 -0
  21. /package/examples/output/{digital-product-passport.n3 → digital-product-passport.txt} +0 -0
  22. /package/examples/output/{easter.n3 → easter.txt} +0 -0
  23. /package/examples/output/{flandor.n3 → flandor.txt} +0 -0
  24. /package/examples/output/{french-cities.n3 → french-cities.txt} +0 -0
  25. /package/examples/output/{genetic-algorithm-knapsack.n3 → genetic-algorithm-knapsack.txt} +0 -0
  26. /package/examples/output/{genetic-algorithm.n3 → genetic-algorithm.txt} +0 -0
  27. /package/examples/output/{gps.n3 → gps.txt} +0 -0
  28. /package/examples/output/{interop-demo.n3 → interop-demo.txt} +0 -0
  29. /package/examples/output/{matrix-mechanics.n3 → matrix-mechanics.txt} +0 -0
  30. /package/examples/output/{medior.n3 → medior.txt} +0 -0
  31. /package/examples/output/{n3-speaks-for-itself.n3 → n3-speaks-for-itself.txt} +0 -0
  32. /package/examples/output/{odrl-dpv-ehds-risk-ranked.n3 → odrl-dpv-ehds-risk-ranked.txt} +0 -0
  33. /package/examples/output/{odrl-dpv-healthcare-risk-ranked.n3 → odrl-dpv-healthcare-risk-ranked.txt} +0 -0
  34. /package/examples/output/{odrl-dpv-risk-ranked.n3 → odrl-dpv-risk-ranked.txt} +0 -0
  35. /package/examples/output/{odrl-risk-mitigation.n3 → odrl-risk-mitigation.txt} +0 -0
  36. /package/examples/output/{odrl-risk.n3 → odrl-risk.txt} +0 -0
  37. /package/examples/output/{parcellocker.n3 → parcellocker.txt} +0 -0
  38. /package/examples/output/{pn-junction-tunneling.n3 → pn-junction-tunneling.txt} +0 -0
  39. /package/examples/output/{resto.n3 → resto.txt} +0 -0
  40. /package/examples/output/{sqrt2-cauchy.n3 → sqrt2-cauchy.txt} +0 -0
  41. /package/examples/output/{sqrt2-dedekind.n3 → sqrt2-dedekind.txt} +0 -0
  42. /package/examples/output/{transcendental-numbers-stretched.n3 → transcendental-numbers-stretched.txt} +0 -0
  43. /package/examples/output/{transistor-switch.n3 → transistor-switch.txt} +0 -0
  44. /package/examples/output/{wind-turbine.n3 → wind-turbine.txt} +0 -0
package/HANDBOOK.md CHANGED
@@ -3131,29 +3131,69 @@ Sometimes that means recomputing a quantity from another angle. Sometimes it mea
3131
3131
 
3132
3132
  The point is not to make checks large. The point is to make them real.
3133
3133
 
3134
- ### F.6 Examples in `examples/` that read well in ARC style
3134
+ ### F.6 ARC and the Insight Economy
3135
3135
 
3136
- The following examples are especially good places to see this style in practice.
3136
+ One reason ARC matters beyond pedagogy is that it matches a broader way of thinking about data and computation that Ruben Verborgh has called the **Insight Economy**.
3137
3137
 
3138
- - [`examples/delfour.n3`](examples/delfour.n3) privacy-preserving shopping assistance with a concrete recommendation, an explanation, and policy checks. Expected output: [`examples/output/delfour.n3`](examples/output/delfour.n3)
3139
- - [`examples/control-system.n3`](examples/control-system.n3) — derives actuator decisions, explains the control basis, and checks the result. Expected output: [`examples/output/control-system.n3`](examples/output/control-system.n3)
3140
- - [`examples/deep-taxonomy-100000.n3`](examples/deep-taxonomy-100000.n3) — a deep classification stress test whose answer is whether the final goal class is reached. Expected output: [`examples/output/deep-taxonomy-100000.n3`](examples/output/deep-taxonomy-100000.n3)
3141
- - [`examples/gps.n3`](examples/gps.n3) — route planning with readable route output. Expected output: [`examples/output/gps.n3`](examples/output/gps.n3)
3142
- - [`examples/sudoku.n3`](examples/sudoku.n3) — solver output plus legality and consistency checks. Expected output: [`examples/output/sudoku.n3`](examples/output/sudoku.n3)
3138
+ The basic claim is simple: raw data is usually the wrong thing to exchange directly. A better system refines source data into a **specific, purpose-limited, time-bound insight** that is useful in one context, loses much of its value when copied without that context, and can be governed more safely than an unrestricted dump of the original data.
3143
3139
 
3144
- ### F.7 How to read an ARC-style example
3140
+ That fits Eyeling remarkably well. Eyeling can derive narrow conclusions explicitly, show why they follow, and attach checks that make sure a decision still respects policy, scope, thresholds, or consistency constraints. In other words, an Eyeling program can act as a small governed insight refinery rather than as a black box that merely emits a verdict.
3141
+
3142
+ This is also why ARC is a good mental model here. The **Answer** is the bounded insight. The **Reason Why** makes the governing basis visible. The **Check** ensures the result can be trusted for the stated purpose instead of silently drifting beyond it.
3143
+
3144
+ ### F.7 ARC-style examples in `examples/`
3145
+
3146
+ The following examples are especially useful if you want to see Eyeling files that derive an answer, expose the key reason, and include meaningful checks. Each entry links to both the source example and the corresponding generated output file in `examples/output/`.
3147
+
3148
+ #### Insight Economy and governed-data cases
3149
+
3150
+ - [`examples/auroracare.n3`](examples/auroracare.n3) · [`examples/output/auroracare.txt`](examples/output/auroracare.txt) — purpose-based medical data exchange with explicit allow/deny reasoning and checks around role, purpose, and conditions.
3151
+ - [`examples/calidor.n3`](examples/calidor.n3) · [`examples/output/calidor.txt`](examples/output/calidor.txt) — heatwave-response case where private household signals become a narrow, expiring cooling-support insight.
3152
+ - [`examples/delfour.n3`](examples/delfour.n3) · [`examples/output/delfour.txt`](examples/output/delfour.txt) — shopping-assistance case where a private condition becomes a bounded “prefer lower-sugar products” insight.
3153
+ - [`examples/flandor.n3`](examples/flandor.n3) · [`examples/output/flandor.txt`](examples/output/flandor.txt) — macro-economic coordination case for Flanders that turns sensitive local signals into a regional retooling insight.
3154
+ - [`examples/medior.n3`](examples/medior.n3) · [`examples/output/medior.txt`](examples/output/medior.txt) — post-discharge care-coordination case that derives a minimal continuity-bundle insight without sharing the full record.
3155
+ - [`examples/parcellocker.n3`](examples/parcellocker.n3) · [`examples/output/parcellocker.txt`](examples/output/parcellocker.txt) — one-time parcel pickup authorization with a clear permit decision, justification, and misuse checks.
3156
+
3157
+ #### Core ARC-style walkthroughs
3158
+
3159
+ - [`examples/bmi.n3`](examples/bmi.n3) · [`examples/output/bmi.txt`](examples/output/bmi.txt) — Body Mass Index calculation with normalization, WHO category assignment, and boundary checks.
3160
+ - [`examples/control-system.n3`](examples/control-system.n3) · [`examples/output/control-system.txt`](examples/output/control-system.txt) — small control-system example that derives actuator commands and explains feedforward and feedback contributions.
3161
+ - [`examples/easter.n3`](examples/easter.n3) · [`examples/output/easter.txt`](examples/output/easter.txt) — Gregorian Easter computus with a readable explanation and date-window checks.
3162
+ - [`examples/french-cities.n3`](examples/french-cities.n3) · [`examples/output/french-cities.txt`](examples/output/french-cities.txt) — graph reachability over French cities with explicit path reasoning.
3163
+ - [`examples/gps.n3`](examples/gps.n3) · [`examples/output/gps.txt`](examples/output/gps.txt) — tiny route-planning example for western Belgium with route comparison and metric checks.
3164
+ - [`examples/resto.n3`](examples/resto.n3) · [`examples/output/resto.txt`](examples/output/resto.txt) — RESTdesc-style service composition from person and date to a concrete restaurant reservation.
3165
+ - [`examples/sudoku.n3`](examples/sudoku.n3) · [`examples/output/sudoku.txt`](examples/output/sudoku.txt) — Sudoku solver and report generator with consistency checks over the solved grid.
3166
+ - [`examples/wind-turbine.n3`](examples/wind-turbine.n3) · [`examples/output/wind-turbine.txt`](examples/output/wind-turbine.txt) — predictive-maintenance example that turns sensor readings into an auditable inspection decision.
3167
+
3168
+ #### Technical and scientific ARC demos
3169
+
3170
+ - [`examples/matrix-mechanics.n3`](examples/matrix-mechanics.n3) · [`examples/output/matrix-mechanics.txt`](examples/output/matrix-mechanics.txt) — small 2×2 matrix example deriving trace, determinant, products, and a non-zero commutator.
3171
+ - [`examples/pn-junction-tunneling.n3`](examples/pn-junction-tunneling.n3) · [`examples/output/pn-junction-tunneling.txt`](examples/output/pn-junction-tunneling.txt) — semiconductor toy model that explains current-proxy behavior across bias points.
3172
+ - [`examples/transistor-switch.n3`](examples/transistor-switch.n3) · [`examples/output/transistor-switch.txt`](examples/output/transistor-switch.txt) — NPN low-side switch model with exact arithmetic and cutoff-versus-saturation checks.
3173
+
3174
+ #### Deep-classification stress tests
3175
+
3176
+ - [`examples/deep-taxonomy-10.n3`](examples/deep-taxonomy-10.n3) · [`examples/output/deep-taxonomy-10.txt`](examples/output/deep-taxonomy-10.txt) — ARC-style deep-taxonomy benchmark at depth 10.
3177
+ - [`examples/deep-taxonomy-100.n3`](examples/deep-taxonomy-100.n3) · [`examples/output/deep-taxonomy-100.txt`](examples/output/deep-taxonomy-100.txt) — ARC-style deep-taxonomy benchmark at depth 100.
3178
+ - [`examples/deep-taxonomy-1000.n3`](examples/deep-taxonomy-1000.n3) · [`examples/output/deep-taxonomy-1000.txt`](examples/output/deep-taxonomy-1000.txt) — ARC-style deep-taxonomy benchmark at depth 1000.
3179
+ - [`examples/deep-taxonomy-10000.n3`](examples/deep-taxonomy-10000.n3) · [`examples/output/deep-taxonomy-10000.txt`](examples/output/deep-taxonomy-10000.txt) — ARC-style deep-taxonomy benchmark at depth 10000.
3180
+ - [`examples/deep-taxonomy-100000.n3`](examples/deep-taxonomy-100000.n3) · [`examples/output/deep-taxonomy-100000.txt`](examples/output/deep-taxonomy-100000.txt) — ARC-style deep-taxonomy benchmark at depth 100000.
3181
+
3182
+ These files fit together because they all present reasoning in a recognizably ARC-like way: they derive an answer, make the reason visible in a compact report, and include checks that are meant to catch real mistakes. Some are classical logic or numeric examples; others show how Eyeling can express policy-aware, insight-oriented decision flows without collapsing everything into opaque application code.
3183
+
3184
+ ### F.8 How to read an ARC-style example
3145
3185
 
3146
3186
  A good way to read one of these files is to start with the question in the comments or input facts. Then find the part that gives the answer. Then trace the few rules that explain why that answer follows. Finally, look for the checks: the validation facts, the recomputation, or the `=> false` fuse that would stop the run if something important were wrong.
3147
3187
 
3148
3188
  That reading order keeps the example grounded in observable behavior rather than in source code alone.
3149
3189
 
3150
- ### F.8 What ARC is not
3190
+ ### F.9 What ARC is not
3151
3191
 
3152
3192
  ARC does not mean wrapping every file in ceremony. It does not mean long prose explanations. It does not mean hiding important assumptions in comments while the executable part stays thin. And it does not mean replacing checks with a confident tone.
3153
3193
 
3154
3194
  A file really follows ARC only when the answer, the explanation, and the validation all live in the program itself.
3155
3195
 
3156
- ### F.9 Why this style is worth using
3196
+ ### F.10 Why this style is worth using
3157
3197
 
3158
3198
  This style is worth using because it makes an Eyeling file easier to run, easier to inspect, and easier to trust. The result is visible. The key reason is visible. The check is visible. That makes examples better teaching material, makes policy or computation examples easier to audit, and makes the whole file more reusable as a small reasoning artifact instead of an opaque session transcript.
3159
3199
 
@@ -1343,6 +1343,15 @@
1343
1343
  return null;
1344
1344
  }
1345
1345
 
1346
+ function inferDatatypeForShorthandLexical(lex) {
1347
+ if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
1348
+ if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
1349
+ if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
1350
+ if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
1351
+ if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
1352
+ return null;
1353
+ }
1354
+
1346
1355
  // ===========================================================================
1347
1356
  // Math builtin helpers
1348
1357
  // ===========================================================================
@@ -3864,6 +3873,7 @@
3864
3873
  if (oDt === null) {
3865
3874
  if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
3866
3875
  else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
3876
+ else oDt = inferDatatypeForShorthandLexical(oLex);
3867
3877
  }
3868
3878
 
3869
3879
  if (oDt !== null) {
@@ -1,55 +1,11 @@
1
1
  # ARC-style examples in Eyeling
2
2
 
3
- This page points to the ARC-style examples that currently live in [`examples/`](../). The files themselves are one level up; this folder exists as a convenient index for readers who want to browse Eyeling examples that follow the same presentation pattern.
3
+ This content is now integrated into the handbook:
4
4
 
5
- ## What ARC is
5
+ - [Appendix F — The ARC approach: Answer • Reason Why • Check](../../HANDBOOK.md#app-f)
6
6
 
7
- [ARC](https://josd.github.io/arc/) stands for **Answer • Reason Why • Check**. The idea is to make a program do three things at once: give the result, explain the small reason that matters, and include a check that can fail loudly when an assumption is wrong. In practice, ARC turns a runnable example into a small, auditable artifact rather than a black box.
7
+ That appendix now includes:
8
8
 
9
- In Eyeling, ARC fits naturally: facts hold the data, rules derive the result, `log:outputString` can render a human-readable report, and `=> false` rules can act as hard validation fuses.
10
-
11
- ## What the Insight Economy is
12
-
13
- Ruben Verborgh’s [Insight Economy](https://ruben.verborgh.org/blog/2025/08/12/inside-the-insight-economy/) argues that raw data is a bad thing to trade directly. Instead of handing over the source data, a system should refine it into a **specific, purpose-limited, time-bound insight** that is useful in one context, loses value when copied, and can be governed more safely.
14
-
15
- That makes the examples below especially relevant: Eyeling can derive those narrow insights explicitly, explain why they hold, and check that the resulting decision respects policy, purpose, and consistency constraints.
16
-
17
- ## ARC-style examples in `examples/`
18
-
19
- ### Insight Economy and governed-data cases
20
-
21
- - [`../auroracare.n3`](../auroracare.n3) — Purpose-based medical data exchange with explicit allow/deny reasoning and checks around role, purpose, and conditions.
22
- - [`../calidor.n3`](../calidor.n3) — Heatwave-response case where private household signals become a narrow, expiring cooling-support insight.
23
- - [`../delfour.n3`](../delfour.n3) — Shopping-assistance case where a private condition becomes a bounded “prefer lower-sugar products” insight.
24
- - [`../flandor.n3`](../flandor.n3) — Macro-economic coordination case for Flanders that turns sensitive local signals into a regional retooling insight.
25
- - [`../medior.n3`](../medior.n3) — Post-discharge care-coordination case that derives a minimal continuity-bundle insight without sharing the full record.
26
- - [`../parcellocker.n3`](../parcellocker.n3) — One-time parcel pickup authorization with a clear permit decision, justification, and misuse checks.
27
-
28
- ### Core ARC-style walkthroughs
29
-
30
- - [`../bmi.n3`](../bmi.n3) — Body Mass Index calculation with normalization, WHO category assignment, and boundary checks.
31
- - [`../control-system.n3`](../control-system.n3) — Small control-system example that derives actuator commands and explains feedforward and feedback contributions.
32
- - [`../easter.n3`](../easter.n3) — Gregorian Easter computus with a readable explanation and date-window checks.
33
- - [`../french-cities.n3`](../french-cities.n3) — Graph reachability over French cities with explicit path reasoning.
34
- - [`../gps.n3`](../gps.n3) — Tiny route-planning example for western Belgium with route comparison and metric checks.
35
- - [`../resto.n3`](../resto.n3) — RESTdesc-style service composition from person and date to a concrete restaurant reservation.
36
- - [`../sudoku.n3`](../sudoku.n3) — Sudoku solver and report generator with consistency checks over the solved grid.
37
- - [`../wind-turbine.n3`](../wind-turbine.n3) — Predictive-maintenance example that turns sensor readings into an auditable inspection decision.
38
-
39
- ### Technical and scientific ARC demos
40
-
41
- - [`../matrix-mechanics.n3`](../matrix-mechanics.n3) — Small 2×2 matrix example deriving trace, determinant, products, and a non-zero commutator.
42
- - [`../pn-junction-tunneling.n3`](../pn-junction-tunneling.n3) — Semiconductor toy model that explains current-proxy behavior across bias points.
43
- - [`../transistor-switch.n3`](../transistor-switch.n3) — NPN low-side switch model with exact arithmetic and cutoff-versus-saturation checks.
44
-
45
- ### Deep-classification stress tests
46
-
47
- - [`../deep-taxonomy-10.n3`](../deep-taxonomy-10.n3) — ARC-style deep-taxonomy benchmark at depth 10.
48
- - [`../deep-taxonomy-100.n3`](../deep-taxonomy-100.n3) — ARC-style deep-taxonomy benchmark at depth 100.
49
- - [`../deep-taxonomy-1000.n3`](../deep-taxonomy-1000.n3) — ARC-style deep-taxonomy benchmark at depth 1000.
50
- - [`../deep-taxonomy-10000.n3`](../deep-taxonomy-10000.n3) — ARC-style deep-taxonomy benchmark at depth 10000.
51
- - [`../deep-taxonomy-100000.n3`](../deep-taxonomy-100000.n3) — ARC-style deep-taxonomy benchmark at depth 100000.
52
-
53
- ## Why these examples fit together
54
-
55
- These files all present reasoning in a recognizably ARC-like way: they derive an answer, make the reason visible in a compact report, and include checks that are meant to catch real mistakes. Some are classical logic or numeric examples; others show how Eyeling can express policy-aware, insight-oriented decision flows without collapsing everything into opaque application code.
9
+ - a brief explanation of ARC,
10
+ - a brief explanation of the Insight Economy,
11
+ - and links to the ARC-style examples in `examples/` together with their outputs in `examples/output/`.
@@ -28,6 +28,7 @@ Completed grid
28
28
  3 5 6 | 4 7 8 | 2 1 9
29
29
  2 4 1 | 9 3 5 | 8 6 7
30
30
  8 9 7 | 2 6 1 | 3 5 4
31
+
31
32
  === Reason Why ===
32
33
  The solver starts from 23 clues and fills the remaining 58 cells by combining constraint propagation with depth-first search. At each step it chooses the empty cell with the fewest legal digits, places forced singles immediately, and only guesses when more than one candidate remains. Across the search it made 213 forced placements and tried 22 guesses, visited 23 search nodes overall, and backtracked 12 times before reaching the completed grid. The solver also confirmed that the solution is unique. Early steps: r2c3=4: guess, r5c3=3: forced, r2c1=5: guess, r2c4=1: guess, r2c6=9: forced, r2c7=6: guess, r2c8=7: forced, r1c7=4: guess, … and 50 more placements
33
34
 
@@ -114,8 +114,8 @@
114
114
  log:outputString ?puzzleText ;
115
115
  log:outputString "\n" ;
116
116
  log:outputString "Completed grid\n" ;
117
- log:outputString ?solutionText ;
118
- log:outputString "\n\n" .
117
+ log:outputString ?solutionText .
118
+ :01b-answer log:outputString "\n" .
119
119
  :02-reason log:outputString "=== Reason Why ===\n" ;
120
120
  log:outputString ?reasonText ;
121
121
  log:outputString "\n\n" .
package/eyeling.js CHANGED
@@ -1338,6 +1338,15 @@ function parseXsdFloatSpecialLex(s) {
1338
1338
  return null;
1339
1339
  }
1340
1340
 
1341
+ function inferDatatypeForShorthandLexical(lex) {
1342
+ if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
1343
+ if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
1344
+ if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
1345
+ if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
1346
+ if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
1347
+ return null;
1348
+ }
1349
+
1341
1350
  // ===========================================================================
1342
1351
  // Math builtin helpers
1343
1352
  // ===========================================================================
@@ -3850,6 +3859,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3850
3859
  if (oDt === null) {
3851
3860
  if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
3852
3861
  else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
3862
+ else oDt = inferDatatypeForShorthandLexical(oLex);
3853
3863
  }
3854
3864
 
3855
3865
  if (oDt !== null) {
package/lib/builtins.js CHANGED
@@ -859,6 +859,15 @@ function parseXsdFloatSpecialLex(s) {
859
859
  return null;
860
860
  }
861
861
 
862
+ function inferDatatypeForShorthandLexical(lex) {
863
+ if (typeof lex !== 'string' || isQuotedLexical(lex)) return null;
864
+ if (lex === 'true' || lex === 'false') return XSD_NS + 'boolean';
865
+ if (/^[+-]?\d+$/.test(lex)) return XSD_NS + 'integer';
866
+ if (/^[+-]?(?:\d+\.\d*|\.\d+)$/.test(lex)) return XSD_NS + 'decimal';
867
+ if (/^[+-]?(?:\d+\.\d*|\.\d+|\d+)(?:[eE][+-]?\d+)$/.test(lex)) return XSD_NS + 'double';
868
+ return null;
869
+ }
870
+
862
871
  // ===========================================================================
863
872
  // Math builtin helpers
864
873
  // ===========================================================================
@@ -3371,6 +3380,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
3371
3380
  if (oDt === null) {
3372
3381
  if (literalHasLangTag(g.o.value)) oDt = RDF_NS + 'langString';
3373
3382
  else if (isPlainStringLiteralValue(g.o.value)) oDt = XSD_NS + 'string';
3383
+ else oDt = inferDatatypeForShorthandLexical(oLex);
3374
3384
  }
3375
3385
 
3376
3386
  if (oDt !== null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.22.3",
3
+ "version": "1.22.5",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [
package/test/api.test.js CHANGED
@@ -2152,6 +2152,32 @@ _:x :hates { _:foo :making :mess }.
2152
2152
  ],
2153
2153
  notExpect: [/:result\s+:sumX\s+"329"\^\^xsd:decimal\s*\./, /:result\s+:meanX\s+"47"\^\^xsd:decimal\s*\./],
2154
2154
  },
2155
+ {
2156
+ name: '244 regression: log:dtlit recognizes shorthand numeric and boolean literals',
2157
+ opt: { proofComments: false },
2158
+ input: `@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
2159
+ @prefix log: <http://www.w3.org/2000/10/swap/log#> .
2160
+ @prefix : <http://example.org#> .
2161
+
2162
+ :let :term 4, 2.5, 3e1, true, "3"^^xsd:integer .
2163
+
2164
+ {
2165
+ :let :term ?term .
2166
+ (?text ?datatype) log:dtlit ?term .
2167
+ }
2168
+ =>
2169
+ {
2170
+ ?term :is (?text ?datatype) .
2171
+ }.
2172
+ `,
2173
+ expect: [
2174
+ /^4\s+:is\s+\("4"\s+xsd:integer\)\s*\./m,
2175
+ /^2\.5\s+:is\s+\("2\.5"\s+xsd:decimal\)\s*\./m,
2176
+ /^3e1\s+:is\s+\("3e1"\s+xsd:double\)\s*\./m,
2177
+ /^true\s+:is\s+\("true"\s+xsd:boolean\)\s*\./m,
2178
+ /^"3"\^\^xsd:integer\s+:is\s+\("3"\s+xsd:integer\)\s*\./m,
2179
+ ],
2180
+ },
2155
2181
  ];
2156
2182
 
2157
2183
  let passed = 0;
@@ -78,6 +78,24 @@ function showDiff({ examplesDir, expectedPath, generatedPath }) {
78
78
  if (d.stderr) process.stderr.write(d.stderr);
79
79
  }
80
80
 
81
+ function resolveExpectedPath(outputDir, inputFile) {
82
+ const exactPath = path.join(outputDir, inputFile);
83
+ if (fs.existsSync(exactPath)) return exactPath;
84
+
85
+ const stem = path.basename(inputFile, path.extname(inputFile));
86
+ const candidates = fs
87
+ .readdirSync(outputDir)
88
+ .filter((name) => path.basename(name, path.extname(name)) === stem)
89
+ .sort((a, b) => {
90
+ if (path.extname(a) === '.txt' && path.extname(b) !== '.txt') return -1;
91
+ if (path.extname(a) !== '.txt' && path.extname(b) === '.txt') return 1;
92
+ return a.localeCompare(b);
93
+ });
94
+
95
+ if (candidates.length === 0) return null;
96
+ return path.join(outputDir, candidates[0]);
97
+ }
98
+
81
99
  function main() {
82
100
  const suiteStart = Date.now();
83
101
 
@@ -123,7 +141,7 @@ function main() {
123
141
  const start = Date.now();
124
142
 
125
143
  const filePath = path.join(examplesDir, file);
126
- const expectedPath = path.join(outputDir, file);
144
+ const expectedPath = resolveExpectedPath(outputDir, file);
127
145
 
128
146
  let n3Text;
129
147
  try {
@@ -144,7 +162,7 @@ function main() {
144
162
  if (!fs.existsSync(expectedPath)) {
145
163
  const ms = Date.now() - start;
146
164
  fail(`${idx} ${file} ${msTag(ms)}`);
147
- fail(`Missing expected output/${file}`);
165
+ fail(`Missing expected output for ${path.basename(file, path.extname(file))}.*`);
148
166
  failed++;
149
167
  continue;
150
168
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes