eyelang 1.6.0 → 1.7.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 (1072) hide show
  1. package/README.md +39 -602
  2. package/bin/eyelang.js +7 -0
  3. package/docs/guide.md +591 -0
  4. package/docs/language-reference.md +763 -0
  5. package/examples/access-control-policy.eye +52 -0
  6. package/examples/ackermann.eye +47 -0
  7. package/examples/age.eye +26 -0
  8. package/examples/aliases-and-namespaces.eye +20 -0
  9. package/examples/alignment-demo.eye +44 -0
  10. package/examples/allen-interval-calculus.eye +64 -0
  11. package/examples/ancestor.eye +22 -0
  12. package/examples/animal.eye +21 -0
  13. package/examples/annotation.eye +34 -0
  14. package/examples/auroracare.eye +309 -0
  15. package/examples/backward.eye +11 -0
  16. package/examples/basic-monadic.eye +10032 -0
  17. package/examples/bayes-diagnosis.eye +108 -0
  18. package/examples/bayes-therapy.eye +189 -0
  19. package/examples/beam-deflection.eye +48 -0
  20. package/examples/binomial-vandermonde.eye +49 -0
  21. package/examples/blocks-world-planning.eye +77 -0
  22. package/examples/bmi.eye +232 -0
  23. package/examples/braking-safety-worlds.eye +69 -0
  24. package/examples/buck-converter-design.eye +83 -0
  25. package/examples/cache-performance.eye +56 -0
  26. package/examples/canary-release.eye +51 -0
  27. package/examples/cat-koko.eye +24 -0
  28. package/examples/catalan-convolution.eye +37 -0
  29. package/examples/chart-parser.eye +65 -0
  30. package/examples/clinical-trial-screening.eye +97 -0
  31. package/examples/collatz-1000.eye +45 -0
  32. package/examples/combinatorics-findall-sort.eye +38 -0
  33. package/examples/competitive-enzyme-kinetics.eye +78 -0
  34. package/examples/complex.eye +133 -0
  35. package/examples/composition-of-injective-functions-is-injective.eye +50 -0
  36. package/examples/context-association.eye +53 -0
  37. package/examples/context-schema-audit.eye +46 -0
  38. package/examples/continued-fraction-sqrt2.eye +36 -0
  39. package/examples/control-system.eye +76 -0
  40. package/examples/critical-path-schedule.eye +82 -0
  41. package/examples/cyclic-path.eye +18 -0
  42. package/examples/d3-group.eye +99 -0
  43. package/examples/dairy-energy-balance.eye +66 -0
  44. package/examples/data-negotiation.eye +38 -0
  45. package/examples/deep-taxonomy-10.eye +115 -0
  46. package/examples/deep-taxonomy-100.eye +385 -0
  47. package/examples/deep-taxonomy-1000.eye +3085 -0
  48. package/examples/deep-taxonomy-10000.eye +30094 -0
  49. package/examples/deep-taxonomy-100000.eye +300184 -0
  50. package/examples/delfour.eye +281 -0
  51. package/examples/deontic-logic.eye +52 -0
  52. package/examples/derived-backward-rule.eye +30 -0
  53. package/examples/derived-rule.eye +27 -0
  54. package/examples/diamond-property.eye +38 -0
  55. package/examples/dijkstra-findall-sort.eye +43 -0
  56. package/examples/dijkstra-risk-path.eye +87 -0
  57. package/examples/dijkstra.eye +50 -0
  58. package/examples/dining-philosophers.eye +147 -0
  59. package/examples/dog.eye +25 -0
  60. package/examples/dpv-odrl-purpose-mapping.eye +48 -0
  61. package/examples/drone-corridor-planner.eye +48 -0
  62. package/examples/easter-computus.eye +88 -0
  63. package/examples/electrical-rc-filter.eye +37 -0
  64. package/examples/epidemic-policy.eye +66 -0
  65. package/examples/equivalence-classes-overlap-implies-same-class.eye +27 -0
  66. package/examples/eulerian-path.eye +87 -0
  67. package/examples/ev-range-worlds.eye +87 -0
  68. package/examples/existential-rule.eye +21 -0
  69. package/examples/exoplanet-validation-worlds.eye +94 -0
  70. package/examples/expression-eval.eye +45 -0
  71. package/examples/family-cousins.eye +67 -0
  72. package/examples/fastpow.eye +61 -0
  73. package/examples/fft8-numeric.eye +85 -0
  74. package/examples/fibonacci.eye +60 -0
  75. package/examples/field-nitrogen-balance.eye +73 -0
  76. package/examples/flandor.eye +296 -0
  77. package/examples/floating-point.eye +28 -0
  78. package/examples/four-color-map.eye +133 -0
  79. package/examples/fundamental-theorem-arithmetic.eye +119 -0
  80. package/examples/gd-step-certified.eye +162 -0
  81. package/examples/gdpr-compliance.eye +69 -0
  82. package/examples/good-cobbler.eye +16 -0
  83. package/examples/gps.eye +146 -0
  84. package/examples/graph-reachability.eye +33 -0
  85. package/examples/graph.eye +35 -0
  86. package/examples/gray-code-counter.eye +47 -0
  87. package/examples/greatest-lower-bound-uniqueness.eye +30 -0
  88. package/examples/group-inverse-uniqueness.eye +36 -0
  89. package/examples/hamiltonian-path.eye +51 -0
  90. package/examples/hamming-code.eye +109 -0
  91. package/examples/hanoi.eye +19 -0
  92. package/examples/heat-loss.eye +56 -0
  93. package/examples/heron-theorem.eye +42 -0
  94. package/examples/ideal-gas-law.eye +39 -0
  95. package/examples/illegitimate-reasoning.eye +88 -0
  96. package/examples/integer-partitions.eye +35 -0
  97. package/examples/intuitionistic-logic-kripke.eye +69 -0
  98. package/examples/job-shop-scheduling.eye +48 -0
  99. package/examples/knapsack-optimization.eye +46 -0
  100. package/examples/knowledge-engineering-alignment-flow.eye +46 -0
  101. package/examples/language.eye +25 -0
  102. package/examples/law-of-cosines.eye +37 -0
  103. package/examples/least-squares-regression.eye +85 -0
  104. package/examples/linear-logic-resources.eye +51 -0
  105. package/examples/list-collection.eye +35 -0
  106. package/examples/lldm.eye +80 -0
  107. package/examples/manufacturing-quality-control.eye +73 -0
  108. package/examples/matrix-chain-order.eye +79 -0
  109. package/examples/microgrid-dispatch.eye +89 -0
  110. package/examples/missionaries-cannibals.eye +53 -0
  111. package/examples/modal-logic-kripke.eye +45 -0
  112. package/examples/modular-exponentiation.eye +35 -0
  113. package/examples/monkey-bananas.eye +45 -0
  114. package/examples/n-queens-8.eye +35 -0
  115. package/examples/network-sla.eye +48 -0
  116. package/examples/newton-raphson.eye +48 -0
  117. package/examples/nixon-diamond.eye +37 -0
  118. package/examples/observability-log-correlation.eye +40 -0
  119. package/examples/odrl-dpv-fpv-trust-flow.eye +51 -0
  120. package/examples/odrl-dpv-healthcare-risk-ranked.eye +270 -0
  121. package/examples/odrl-dpv-risk-ranked.eye +320 -0
  122. package/examples/orbital-transfer-design.eye +116 -0
  123. package/examples/output/basic-monadic.eye +1518 -0
  124. package/examples/output/binomial-vandermonde.eye +4 -0
  125. package/examples/output/catalan-convolution.eye +4 -0
  126. package/examples/output/chart-parser.eye +6 -0
  127. package/examples/output/collatz-1000.eye +1000 -0
  128. package/examples/output/complex.eye +6 -0
  129. package/examples/output/context-schema-audit.eye +12 -0
  130. package/examples/output/continued-fraction-sqrt2.eye +4 -0
  131. package/examples/output/critical-path-schedule.eye +19 -0
  132. package/examples/output/dpv-odrl-purpose-mapping.eye +18 -0
  133. package/examples/output/graph.eye +21 -0
  134. package/examples/output/integer-partitions.eye +4 -0
  135. package/examples/output/intuitionistic-logic-kripke.eye +5 -0
  136. package/examples/output/job-shop-scheduling.eye +3 -0
  137. package/examples/output/knapsack-optimization.eye +4 -0
  138. package/examples/output/knowledge-engineering-alignment-flow.eye +17 -0
  139. package/examples/output/language.eye +6 -0
  140. package/examples/output/linear-logic-resources.eye +2 -0
  141. package/examples/output/matrix-chain-order.eye +4 -0
  142. package/examples/output/missionaries-cannibals.eye +3 -0
  143. package/examples/output/modal-logic-kripke.eye +4 -0
  144. package/examples/output/modular-exponentiation.eye +4 -0
  145. package/examples/output/n-queens-8.eye +1 -0
  146. package/examples/output/observability-log-correlation.eye +28 -0
  147. package/examples/output/odrl-dpv-fpv-trust-flow.eye +9 -0
  148. package/examples/output/path-discovery.eye +3 -0
  149. package/examples/output/pell-equation.eye +4 -0
  150. package/examples/output/reusable-builtins.eye +5 -0
  151. package/examples/output/send-more-money.eye +3 -0
  152. package/examples/output/stable-marriage.eye +2 -0
  153. package/examples/output/stirling-bell-numbers.eye +4 -0
  154. package/examples/output/sudoku-4x4.eye +2 -0
  155. package/examples/output/term-tools.eye +6 -0
  156. package/examples/output/totient-summatory.eye +4 -0
  157. package/examples/output/trust-flow-provenance-threshold.eye +6 -0
  158. package/examples/output/vulnerability-impact.eye +20 -0
  159. package/examples/output/web-names.eye +10 -0
  160. package/examples/output/weighted-interval-scheduling.eye +5 -0
  161. package/examples/path-discovery.eye +45013 -0
  162. package/examples/peano-arithmetic.eye +33 -0
  163. package/examples/peasant.eye +29 -0
  164. package/examples/pell-equation.eye +34 -0
  165. package/examples/pendulum-period.eye +50 -0
  166. package/examples/polynomial.eye +124 -0
  167. package/examples/proof/access-control-policy.eye +158 -0
  168. package/examples/proof/age.eye +71 -0
  169. package/examples/proof/aliases-and-namespaces.eye +78 -0
  170. package/examples/proof/ancestor.eye +140 -0
  171. package/examples/proof/animal.eye +68 -0
  172. package/examples/proof/annotation.eye +80 -0
  173. package/examples/proof/backward.eye +22 -0
  174. package/examples/proof/bayes-diagnosis.eye +208 -0
  175. package/examples/proof/beam-deflection.eye +227 -0
  176. package/examples/proof/cache-performance.eye +310 -0
  177. package/examples/proof/canary-release.eye +172 -0
  178. package/examples/proof/cat-koko.eye +86 -0
  179. package/examples/proof/chart-parser.eye +474 -0
  180. package/examples/proof/clinical-trial-screening.eye +389 -0
  181. package/examples/proof/composition-of-injective-functions-is-injective.eye +258 -0
  182. package/examples/proof/context-association.eye +78 -0
  183. package/examples/proof/data-negotiation.eye +76 -0
  184. package/examples/proof/deontic-logic.eye +109 -0
  185. package/examples/proof/derived-backward-rule.eye +74 -0
  186. package/examples/proof/derived-rule.eye +43 -0
  187. package/examples/proof/diamond-property.eye +307 -0
  188. package/examples/proof/dog.eye +31 -0
  189. package/examples/proof/dpv-odrl-purpose-mapping.eye +348 -0
  190. package/examples/proof/electrical-rc-filter.eye +105 -0
  191. package/examples/proof/epidemic-policy.eye +774 -0
  192. package/examples/proof/equivalence-classes-overlap-implies-same-class.eye +1098 -0
  193. package/examples/proof/existential-rule.eye +40 -0
  194. package/examples/proof/expression-eval.eye +105 -0
  195. package/examples/proof/floating-point.eye +160 -0
  196. package/examples/proof/gdpr-compliance.eye +199 -0
  197. package/examples/proof/good-cobbler.eye +16 -0
  198. package/examples/proof/graph-reachability.eye +151 -0
  199. package/examples/proof/greatest-lower-bound-uniqueness.eye +150 -0
  200. package/examples/proof/group-inverse-uniqueness.eye +84 -0
  201. package/examples/proof/hanoi.eye +185 -0
  202. package/examples/proof/heat-loss.eye +228 -0
  203. package/examples/proof/ideal-gas-law.eye +151 -0
  204. package/examples/proof/intuitionistic-logic-kripke.eye +133 -0
  205. package/examples/proof/linear-logic-resources.eye +205 -0
  206. package/examples/proof/list-collection.eye +52 -0
  207. package/examples/proof/modal-logic-kripke.eye +125 -0
  208. package/examples/proof/nixon-diamond.eye +181 -0
  209. package/examples/proof/proof-contrapositive.eye +78 -0
  210. package/examples/proof/reusable-builtins.eye +124 -0
  211. package/examples/proof/security-incident-correlation.eye +270 -0
  212. package/examples/proof/socket-age.eye +32 -0
  213. package/examples/proof/socket-family.eye +59 -0
  214. package/examples/proof/socrates.eye +38 -0
  215. package/examples/proof/term-tools.eye +95 -0
  216. package/examples/proof/witch.eye +216 -0
  217. package/examples/proof-contrapositive.eye +27 -0
  218. package/examples/quadratic-formula.eye +56 -0
  219. package/examples/radioactive-decay.eye +58 -0
  220. package/examples/reusable-builtins.eye +36 -0
  221. package/examples/riemann-hypothesis.eye +110 -0
  222. package/examples/security-incident-correlation.eye +69 -0
  223. package/examples/send-more-money.eye +71 -0
  224. package/examples/service-impact.eye +41 -0
  225. package/examples/sieve.eye +20 -0
  226. package/examples/skolem-functions.eye +52 -0
  227. package/examples/socket-age.eye +39 -0
  228. package/examples/socket-family.eye +28 -0
  229. package/examples/socrates.eye +19 -0
  230. package/examples/stable-marriage.eye +92 -0
  231. package/examples/statistics-summary.eye +56 -0
  232. package/examples/stirling-bell-numbers.eye +32 -0
  233. package/examples/sudoku-4x4.eye +54 -0
  234. package/examples/superdense-coding.eye +84 -0
  235. package/examples/term-tools.eye +32 -0
  236. package/examples/totient-summatory.eye +33 -0
  237. package/examples/trust-flow-provenance-threshold.eye +47 -0
  238. package/examples/turing.eye +69 -0
  239. package/examples/vector-similarity.eye +60 -0
  240. package/examples/vulnerability-impact.eye +69 -0
  241. package/examples/web-names.eye +83 -0
  242. package/examples/weighted-interval-scheduling.eye +81 -0
  243. package/examples/witch.eye +38 -0
  244. package/examples/wolf-goat-cabbage.eye +56 -0
  245. package/examples/zebra.eye +45 -0
  246. package/index.d.ts +230 -0
  247. package/index.js +4 -0
  248. package/package.json +23 -17
  249. package/playground.html +1065 -1201
  250. package/src/bin.js +7 -0
  251. package/src/builtins/arithmetic.js +19 -8
  252. package/src/builtins/context.js +42 -0
  253. package/src/builtins/control.js +12 -0
  254. package/src/builtins/lists.js +144 -10
  255. package/src/builtins/registry.js +3 -9
  256. package/src/builtins/strings.js +207 -14
  257. package/src/builtins/terms.js +68 -0
  258. package/src/cli.js +20 -16
  259. package/src/explain.js +1 -1
  260. package/src/hash.js +294 -0
  261. package/src/index.js +0 -1
  262. package/src/parser.js +101 -33
  263. package/src/program.js +222 -19
  264. package/src/solver.js +163 -35
  265. package/src/term.js +14 -1
  266. package/test/conformance/README.md +43 -0
  267. package/test/conformance/cases/001_fact_output.eye +4 -0
  268. package/test/conformance/cases/002_rule_recursion.eye +7 -0
  269. package/test/conformance/cases/002_rule_recursion.query +1 -0
  270. package/test/conformance/cases/003_terms_and_readback.eye +16 -0
  271. package/test/conformance/cases/003_terms_and_readback.query +1 -0
  272. package/test/conformance/cases/004_conjunction_and_parentheses.eye +5 -0
  273. package/test/conformance/cases/004_conjunction_and_parentheses.query +1 -0
  274. package/test/conformance/cases/005_list_deconstruction.eye +6 -0
  275. package/test/conformance/cases/005_list_deconstruction.query +1 -0
  276. package/test/conformance/cases/006_comma_formula_data.eye +4 -0
  277. package/test/conformance/cases/006_comma_formula_data.query +1 -0
  278. package/test/conformance/cases/007_anonymous_variables.eye +5 -0
  279. package/test/conformance/cases/007_anonymous_variables.query +1 -0
  280. package/test/conformance/cases/008_graphic_atoms.eye +6 -0
  281. package/test/conformance/cases/008_graphic_atoms.query +1 -0
  282. package/test/conformance/cases/009_comments_and_whitespace.eye +5 -0
  283. package/test/conformance/cases/009_comments_and_whitespace.query +1 -0
  284. package/test/conformance/cases/010_variable_scope_and_reuse.eye +8 -0
  285. package/test/conformance/cases/010_variable_scope_and_reuse.query +1 -0
  286. package/test/conformance/cases/011_predicate_arity.eye +6 -0
  287. package/test/conformance/cases/011_predicate_arity.query +1 -0
  288. package/test/conformance/cases/012_nested_compound_unification.eye +5 -0
  289. package/test/conformance/cases/012_nested_compound_unification.query +1 -0
  290. package/test/conformance/cases/013_multiple_clauses_order.eye +6 -0
  291. package/test/conformance/cases/013_multiple_clauses_order.query +1 -0
  292. package/test/conformance/cases/014_failure_filters_answers.eye +7 -0
  293. package/test/conformance/cases/014_failure_filters_answers.query +1 -0
  294. package/test/conformance/cases/015_improper_list_unification.eye +6 -0
  295. package/test/conformance/cases/015_improper_list_unification.query +1 -0
  296. package/test/conformance/cases/016_arity_zero_atom.eye +4 -0
  297. package/test/conformance/cases/017_three_step_recursion.eye +8 -0
  298. package/test/conformance/cases/017_three_step_recursion.query +1 -0
  299. package/test/conformance/cases/018_quoted_atom_readback.eye +6 -0
  300. package/test/conformance/cases/018_quoted_atom_readback.query +1 -0
  301. package/test/conformance/cases/019_parenthesized_three_conjuncts.eye +7 -0
  302. package/test/conformance/cases/019_parenthesized_three_conjuncts.query +1 -0
  303. package/test/conformance/cases/020_nested_list_terms.eye +5 -0
  304. package/test/conformance/cases/020_nested_list_terms.query +1 -0
  305. package/test/conformance/cases/021_repeated_variable_head.eye +7 -0
  306. package/test/conformance/cases/022_rule_head_structure.eye +5 -0
  307. package/test/conformance/cases/023_quoted_escapes_readback.eye +5 -0
  308. package/test/conformance/cases/024_numeric_literal_readback.eye +6 -0
  309. package/test/conformance/cases/025_body_parentheses_with_formula_data.eye +5 -0
  310. package/test/conformance/cases/026_question_underscore_named_variable_reuse.eye +5 -0
  311. package/test/conformance/cases/027_default_derived_output.eye +5 -0
  312. package/test/conformance/cases/028_materialize_focus.eye +5 -0
  313. package/test/conformance/cases/029_arithmetic_and_comparison.eye +11 -0
  314. package/test/conformance/cases/029_arithmetic_and_comparison.query +1 -0
  315. package/test/conformance/cases/030_strings_and_atoms.eye +4 -0
  316. package/test/conformance/cases/030_strings_and_atoms.query +1 -0
  317. package/test/conformance/cases/031_lists_aggregation_ordering.eye +10 -0
  318. package/test/conformance/cases/031_lists_aggregation_ordering.query +1 -0
  319. package/test/conformance/cases/032_holds_parts.eye +4 -0
  320. package/test/conformance/cases/033_negation_once_generators.eye +7 -0
  321. package/test/conformance/cases/033_negation_once_generators.query +1 -0
  322. package/test/conformance/cases/034_equality_and_inequality.eye +6 -0
  323. package/test/conformance/cases/034_equality_and_inequality.query +1 -0
  324. package/test/conformance/cases/035_list_relations.eye +5 -0
  325. package/test/conformance/cases/035_list_relations.query +1 -0
  326. package/test/conformance/cases/036_append_splits.eye +3 -0
  327. package/test/conformance/cases/036_append_splits.query +1 -0
  328. package/test/conformance/cases/037_matching_and_comparison.eye +7 -0
  329. package/test/conformance/cases/037_matching_and_comparison.query +1 -0
  330. package/test/conformance/cases/038_table_declaration.eye +8 -0
  331. package/test/conformance/cases/038_table_declaration.query +1 -0
  332. package/test/conformance/cases/039_numeric_functions.eye +9 -0
  333. package/test/conformance/cases/039_numeric_functions.query +1 -0
  334. package/test/conformance/cases/040_between_enumeration.eye +3 -0
  335. package/test/conformance/cases/040_between_enumeration.query +1 -0
  336. package/test/conformance/cases/041_smallest_divisor.eye +3 -0
  337. package/test/conformance/cases/041_smallest_divisor.query +1 -0
  338. package/test/conformance/cases/042_negation_filter.eye +7 -0
  339. package/test/conformance/cases/042_negation_filter.query +1 -0
  340. package/test/conformance/cases/043_once_user_predicate.eye +5 -0
  341. package/test/conformance/cases/043_once_user_predicate.query +1 -0
  342. package/test/conformance/cases/044_findall_user_goal.eye +6 -0
  343. package/test/conformance/cases/044_findall_user_goal.query +1 -0
  344. package/test/conformance/cases/045_sort_deduplicates_atoms.eye +3 -0
  345. package/test/conformance/cases/045_sort_deduplicates_atoms.query +1 -0
  346. package/test/conformance/cases/046_append_bound_prefix_suffix.eye +4 -0
  347. package/test/conformance/cases/046_append_bound_prefix_suffix.query +1 -0
  348. package/test/conformance/cases/047_nth0_index_generation.eye +3 -0
  349. package/test/conformance/cases/047_nth0_index_generation.query +1 -0
  350. package/test/conformance/cases/048_set_nth0_edges.eye +4 -0
  351. package/test/conformance/cases/048_set_nth0_edges.query +1 -0
  352. package/test/conformance/cases/049_select_duplicate_occurrences.eye +3 -0
  353. package/test/conformance/cases/049_select_duplicate_occurrences.query +1 -0
  354. package/test/conformance/cases/050_not_member_filter.eye +6 -0
  355. package/test/conformance/cases/050_not_member_filter.query +1 -0
  356. package/test/conformance/cases/051_nested_holds_parts.eye +4 -0
  357. package/test/conformance/cases/052_holds_member.eye +3 -0
  358. package/test/conformance/cases/053_materialize_excludes_source_fact.eye +6 -0
  359. package/test/conformance/cases/054_numeric_and_lexical_comparison.eye +5 -0
  360. package/test/conformance/cases/054_numeric_and_lexical_comparison.query +1 -0
  361. package/test/conformance/cases/055_string_matching_filters.eye +6 -0
  362. package/test/conformance/cases/055_string_matching_filters.query +1 -0
  363. package/test/conformance/cases/056_string_and_atom_concat.eye +3 -0
  364. package/test/conformance/cases/056_string_and_atom_concat.query +1 -0
  365. package/test/conformance/cases/057_countall_empty_and_nonempty.eye +4 -0
  366. package/test/conformance/cases/057_countall_empty_and_nonempty.query +1 -0
  367. package/test/conformance/cases/058_sumall_numeric_template.eye +5 -0
  368. package/test/conformance/cases/058_sumall_numeric_template.query +1 -0
  369. package/test/conformance/cases/059_aggregate_min_template.eye +5 -0
  370. package/test/conformance/cases/059_aggregate_min_template.query +1 -0
  371. package/test/conformance/cases/060_aggregate_max_compound_key.eye +5 -0
  372. package/test/conformance/cases/060_aggregate_max_compound_key.query +1 -0
  373. package/test/conformance/cases/061_date_difference.eye +4 -0
  374. package/test/conformance/cases/062_reusable_numeric_builtins.eye +10 -0
  375. package/test/conformance/cases/063_reusable_list_builtins.eye +11 -0
  376. package/test/conformance/cases/064_reusable_string_builtins.eye +12 -0
  377. package/test/conformance/cases/065_reusable_term_control_builtins.eye +11 -0
  378. package/test/conformance/cases/066_numeric_edges.eye +14 -0
  379. package/test/conformance/cases/067_list_edges.eye +10 -0
  380. package/test/conformance/cases/068_list_generation_order.eye +7 -0
  381. package/test/conformance/cases/069_list_summaries_and_sets.eye +9 -0
  382. package/test/conformance/cases/070_matches_named_captures.eye +13 -0
  383. package/test/conformance/cases/071_string_edges.eye +10 -0
  384. package/test/conformance/cases/072_string_conversions.eye +10 -0
  385. package/test/conformance/cases/073_term_introspection_edges.eye +11 -0
  386. package/test/conformance/cases/074_forall_edges.eye +10 -0
  387. package/test/conformance/cases/075_aggregation_edges.eye +12 -0
  388. package/test/conformance/cases/076_composed_reusable_builtins.eye +8 -0
  389. package/test/conformance/cases/077_recursive_path_with_lists.eye +10 -0
  390. package/test/conformance/cases/078_mutual_recursion_with_arithmetic.eye +7 -0
  391. package/test/conformance/cases/079_big_integer_arithmetic.eye +8 -0
  392. package/test/conformance/cases/080_rounding_modes.eye +10 -0
  393. package/test/conformance/cases/081_zero_safe_numeric_functions.eye +9 -0
  394. package/test/conformance/cases/082_comparison_semantics.eye +10 -0
  395. package/test/conformance/cases/083_between_modes_and_empty_ranges.eye +8 -0
  396. package/test/conformance/cases/084_append_and_select_composition.eye +7 -0
  397. package/test/conformance/cases/085_nth_and_update_edges.eye +8 -0
  398. package/test/conformance/cases/086_slicing_pipeline.eye +10 -0
  399. package/test/conformance/cases/087_sort_reverse_length.eye +8 -0
  400. package/test/conformance/cases/088_list_summaries_failures.eye +8 -0
  401. package/test/conformance/cases/089_string_split_join_pipeline.eye +7 -0
  402. package/test/conformance/cases/090_string_substring_replace_edges.eye +9 -0
  403. package/test/conformance/cases/091_string_case_and_trim.eye +7 -0
  404. package/test/conformance/cases/092_scalar_string_conversions.eye +9 -0
  405. package/test/conformance/cases/093_regex_named_captures_context.eye +8 -0
  406. package/test/conformance/cases/094_context_holds_enumeration.eye +7 -0
  407. package/test/conformance/cases/095_term_introspection_roundtrip.eye +8 -0
  408. package/test/conformance/cases/096_functor_scalar_edges.eye +8 -0
  409. package/test/conformance/cases/097_control_negation_once_forall.eye +13 -0
  410. package/test/conformance/cases/098_aggregation_nested_templates.eye +11 -0
  411. package/test/conformance/cases/099_materialize_multiple_arities.eye +8 -0
  412. package/test/conformance/cases/100_reusable_builtin_workflow.eye +10 -0
  413. package/test/conformance/cases/101_question_mark_variables.eye +7 -0
  414. package/test/conformance/cases/102_table_declaration.eye +11 -0
  415. package/test/conformance/cases/103_angle_iri_atoms.eye +7 -0
  416. package/test/conformance/cases/104_mode_determinism_declarations.eye +11 -0
  417. package/test/conformance/expected/003_terms_and_readback.eye +13 -0
  418. package/test/conformance/expected/016_arity_zero_atom.eye +1 -0
  419. package/test/conformance/expected/029_arithmetic_and_comparison.eye +9 -0
  420. package/test/conformance/expected/030_strings_and_atoms.eye +2 -0
  421. package/test/conformance/expected/032_holds_parts.eye +3 -0
  422. package/test/conformance/expected/035_list_relations.eye +4 -0
  423. package/test/conformance/expected/051_nested_holds_parts.eye +3 -0
  424. package/test/conformance/expected/052_holds_member.eye +2 -0
  425. package/test/conformance/expected/056_string_and_atom_concat.eye +1 -0
  426. package/test/conformance/expected/062_reusable_numeric_builtins.eye +8 -0
  427. package/test/conformance/expected/063_reusable_list_builtins.eye +9 -0
  428. package/test/conformance/expected/064_reusable_string_builtins.eye +10 -0
  429. package/test/conformance/expected/065_reusable_term_control_builtins.eye +6 -0
  430. package/test/conformance/expected/066_numeric_edges.eye +12 -0
  431. package/test/conformance/expected/067_list_edges.eye +8 -0
  432. package/test/conformance/expected/068_list_generation_order.eye +10 -0
  433. package/test/conformance/expected/069_list_summaries_and_sets.eye +7 -0
  434. package/test/conformance/expected/070_matches_named_captures.eye +1 -0
  435. package/test/conformance/expected/071_string_edges.eye +8 -0
  436. package/test/conformance/expected/072_string_conversions.eye +8 -0
  437. package/test/conformance/expected/073_term_introspection_edges.eye +9 -0
  438. package/test/conformance/expected/074_forall_edges.eye +5 -0
  439. package/test/conformance/expected/075_aggregation_edges.eye +7 -0
  440. package/test/conformance/expected/076_composed_reusable_builtins.eye +5 -0
  441. package/test/conformance/expected/077_recursive_path_with_lists.eye +3 -0
  442. package/test/conformance/expected/078_mutual_recursion_with_arithmetic.eye +7 -0
  443. package/test/conformance/expected/079_big_integer_arithmetic.eye +6 -0
  444. package/test/conformance/expected/080_rounding_modes.eye +8 -0
  445. package/test/conformance/expected/081_zero_safe_numeric_functions.eye +7 -0
  446. package/test/conformance/expected/082_comparison_semantics.eye +8 -0
  447. package/test/conformance/expected/083_between_modes_and_empty_ranges.eye +8 -0
  448. package/test/conformance/expected/084_append_and_select_composition.eye +10 -0
  449. package/test/conformance/expected/085_nth_and_update_edges.eye +8 -0
  450. package/test/conformance/expected/086_slicing_pipeline.eye +7 -0
  451. package/test/conformance/expected/087_sort_reverse_length.eye +6 -0
  452. package/test/conformance/expected/088_list_summaries_failures.eye +6 -0
  453. package/test/conformance/expected/089_string_split_join_pipeline.eye +4 -0
  454. package/test/conformance/expected/090_string_substring_replace_edges.eye +7 -0
  455. package/test/conformance/expected/091_string_case_and_trim.eye +5 -0
  456. package/test/conformance/expected/092_scalar_string_conversions.eye +7 -0
  457. package/test/conformance/expected/093_regex_named_captures_context.eye +5 -0
  458. package/test/conformance/expected/094_context_holds_enumeration.eye +8 -0
  459. package/test/conformance/expected/095_term_introspection_roundtrip.eye +6 -0
  460. package/test/conformance/expected/096_functor_scalar_edges.eye +6 -0
  461. package/test/conformance/expected/097_control_negation_once_forall.eye +5 -0
  462. package/test/conformance/expected/098_aggregation_nested_templates.eye +5 -0
  463. package/test/conformance/expected/099_materialize_multiple_arities.eye +4 -0
  464. package/test/conformance/expected/100_reusable_builtin_workflow.eye +6 -0
  465. package/test/conformance/expected/101_question_mark_variables.eye +3 -0
  466. package/test/conformance/expected/102_table_declaration.eye +6 -0
  467. package/test/conformance/expected/103_angle_iri_atoms.eye +3 -0
  468. package/test/conformance/expected/104_mode_determinism_declarations.eye +4 -0
  469. package/test/run-all.mjs +20 -0
  470. package/test/run-conformance.mjs +78 -0
  471. package/test/run-examples.mjs +155 -0
  472. package/test/run-regression.mjs +1215 -0
  473. package/test/test-style.mjs +94 -0
  474. package/SPEC.md +0 -684
  475. package/bin/eyelang +0 -7
  476. package/conformance/README.md +0 -45
  477. package/conformance/cases/core/001_fact_output.pl +0 -4
  478. package/conformance/cases/core/001_fact_query.query +0 -1
  479. package/conformance/cases/core/002_rule_recursion.pl +0 -7
  480. package/conformance/cases/core/002_rule_recursion.query +0 -1
  481. package/conformance/cases/core/003_terms_and_readback.pl +0 -16
  482. package/conformance/cases/core/003_terms_and_readback.query +0 -1
  483. package/conformance/cases/core/004_conjunction_and_parentheses.pl +0 -5
  484. package/conformance/cases/core/004_conjunction_and_parentheses.query +0 -1
  485. package/conformance/cases/core/005_list_deconstruction.pl +0 -6
  486. package/conformance/cases/core/005_list_deconstruction.query +0 -1
  487. package/conformance/cases/core/006_comma_formula_data.pl +0 -4
  488. package/conformance/cases/core/006_comma_formula_data.query +0 -1
  489. package/conformance/cases/core/007_anonymous_variables.pl +0 -5
  490. package/conformance/cases/core/007_anonymous_variables.query +0 -1
  491. package/conformance/cases/core/008_graphic_atoms.pl +0 -6
  492. package/conformance/cases/core/008_graphic_atoms.query +0 -1
  493. package/conformance/cases/core/009_comments_and_whitespace.pl +0 -5
  494. package/conformance/cases/core/009_comments_and_whitespace.query +0 -1
  495. package/conformance/cases/core/010_variable_scope_and_reuse.pl +0 -8
  496. package/conformance/cases/core/010_variable_scope_and_reuse.query +0 -1
  497. package/conformance/cases/core/011_predicate_arity.pl +0 -6
  498. package/conformance/cases/core/011_predicate_arity.query +0 -1
  499. package/conformance/cases/core/012_nested_compound_unification.pl +0 -5
  500. package/conformance/cases/core/012_nested_compound_unification.query +0 -1
  501. package/conformance/cases/core/013_multiple_clauses_order.pl +0 -6
  502. package/conformance/cases/core/013_multiple_clauses_order.query +0 -1
  503. package/conformance/cases/core/014_failure_filters_answers.pl +0 -7
  504. package/conformance/cases/core/014_failure_filters_answers.query +0 -1
  505. package/conformance/cases/core/015_improper_list_unification.pl +0 -6
  506. package/conformance/cases/core/015_improper_list_unification.query +0 -1
  507. package/conformance/cases/core/016_zero_arity_compound.pl +0 -4
  508. package/conformance/cases/core/016_zero_arity_compound.query +0 -1
  509. package/conformance/cases/core/017_three_step_recursion.pl +0 -8
  510. package/conformance/cases/core/017_three_step_recursion.query +0 -1
  511. package/conformance/cases/core/018_quoted_atom_readback.pl +0 -6
  512. package/conformance/cases/core/018_quoted_atom_readback.query +0 -1
  513. package/conformance/cases/core/019_parenthesized_three_conjuncts.pl +0 -7
  514. package/conformance/cases/core/019_parenthesized_three_conjuncts.query +0 -1
  515. package/conformance/cases/core/020_nested_list_terms.pl +0 -5
  516. package/conformance/cases/core/020_nested_list_terms.query +0 -1
  517. package/conformance/cases/core/021_repeated_variable_head.pl +0 -7
  518. package/conformance/cases/core/022_rule_head_structure.pl +0 -5
  519. package/conformance/cases/core/023_quoted_escapes_readback.pl +0 -5
  520. package/conformance/cases/core/024_numeric_literal_readback.pl +0 -6
  521. package/conformance/cases/core/025_body_parentheses_with_formula_data.pl +0 -5
  522. package/conformance/cases/core/026_underscore_named_variable_reuse.pl +0 -5
  523. package/conformance/cases/extension/001_default_derived_output.pl +0 -5
  524. package/conformance/cases/extension/002_materialize_focus.pl +0 -5
  525. package/conformance/cases/extension/003_arithmetic_and_comparison.pl +0 -12
  526. package/conformance/cases/extension/003_arithmetic_and_comparison.query +0 -1
  527. package/conformance/cases/extension/004_strings_and_atoms.pl +0 -6
  528. package/conformance/cases/extension/004_strings_and_atoms.query +0 -1
  529. package/conformance/cases/extension/005_lists_aggregation_ordering.pl +0 -10
  530. package/conformance/cases/extension/005_lists_aggregation_ordering.query +0 -1
  531. package/conformance/cases/extension/006_formula_terms.pl +0 -5
  532. package/conformance/cases/extension/006_formula_terms.query +0 -1
  533. package/conformance/cases/extension/007_negation_once_generators.pl +0 -7
  534. package/conformance/cases/extension/007_negation_once_generators.query +0 -1
  535. package/conformance/cases/extension/008_equality_and_inequality.pl +0 -6
  536. package/conformance/cases/extension/008_equality_and_inequality.query +0 -1
  537. package/conformance/cases/extension/009_list_relations.pl +0 -6
  538. package/conformance/cases/extension/009_list_relations.query +0 -1
  539. package/conformance/cases/extension/010_append_splits.pl +0 -3
  540. package/conformance/cases/extension/010_append_splits.query +0 -1
  541. package/conformance/cases/extension/011_matching_and_comparison.pl +0 -7
  542. package/conformance/cases/extension/011_matching_and_comparison.query +0 -1
  543. package/conformance/cases/extension/012_memoize_declaration.pl +0 -8
  544. package/conformance/cases/extension/012_memoize_declaration.query +0 -1
  545. package/conformance/cases/extension/013_numeric_functions.pl +0 -9
  546. package/conformance/cases/extension/013_numeric_functions.query +0 -1
  547. package/conformance/cases/extension/014_between_enumeration.pl +0 -3
  548. package/conformance/cases/extension/014_between_enumeration.query +0 -1
  549. package/conformance/cases/extension/015_smallest_divisor.pl +0 -3
  550. package/conformance/cases/extension/015_smallest_divisor.query +0 -1
  551. package/conformance/cases/extension/016_negation_filter.pl +0 -7
  552. package/conformance/cases/extension/016_negation_filter.query +0 -1
  553. package/conformance/cases/extension/017_once_user_predicate.pl +0 -5
  554. package/conformance/cases/extension/017_once_user_predicate.query +0 -1
  555. package/conformance/cases/extension/018_findall_user_goal.pl +0 -6
  556. package/conformance/cases/extension/018_findall_user_goal.query +0 -1
  557. package/conformance/cases/extension/019_sort_deduplicates_atoms.pl +0 -3
  558. package/conformance/cases/extension/019_sort_deduplicates_atoms.query +0 -1
  559. package/conformance/cases/extension/020_append_bound_prefix_suffix.pl +0 -4
  560. package/conformance/cases/extension/020_append_bound_prefix_suffix.query +0 -1
  561. package/conformance/cases/extension/021_nth0_index_generation.pl +0 -3
  562. package/conformance/cases/extension/021_nth0_index_generation.query +0 -1
  563. package/conformance/cases/extension/022_set_nth0_edges.pl +0 -4
  564. package/conformance/cases/extension/022_set_nth0_edges.query +0 -1
  565. package/conformance/cases/extension/023_select_duplicate_occurrences.pl +0 -3
  566. package/conformance/cases/extension/023_select_duplicate_occurrences.query +0 -1
  567. package/conformance/cases/extension/024_not_member_filter.pl +0 -6
  568. package/conformance/cases/extension/024_not_member_filter.query +0 -1
  569. package/conformance/cases/extension/025_is_list_filter.pl +0 -5
  570. package/conformance/cases/extension/025_is_list_filter.query +0 -1
  571. package/conformance/cases/extension/026_nested_formula_terms.pl +0 -5
  572. package/conformance/cases/extension/026_nested_formula_terms.query +0 -1
  573. package/conformance/cases/extension/027_materialize_excludes_source_fact.pl +0 -6
  574. package/conformance/cases/extension/028_numeric_and_lexical_comparison.pl +0 -5
  575. package/conformance/cases/extension/028_numeric_and_lexical_comparison.query +0 -1
  576. package/conformance/cases/extension/029_string_matching_filters.pl +0 -6
  577. package/conformance/cases/extension/029_string_matching_filters.query +0 -1
  578. package/conformance/cases/extension/030_string_and_atom_concat.pl +0 -4
  579. package/conformance/cases/extension/030_string_and_atom_concat.query +0 -1
  580. package/conformance/cases/extension/031_countall_empty_and_nonempty.pl +0 -4
  581. package/conformance/cases/extension/031_countall_empty_and_nonempty.query +0 -1
  582. package/conformance/cases/extension/032_sumall_numeric_template.pl +0 -5
  583. package/conformance/cases/extension/032_sumall_numeric_template.query +0 -1
  584. package/conformance/cases/extension/033_aggregate_min_template.pl +0 -5
  585. package/conformance/cases/extension/033_aggregate_min_template.query +0 -1
  586. package/conformance/cases/extension/034_aggregate_max_compound_key.pl +0 -5
  587. package/conformance/cases/extension/034_aggregate_max_compound_key.query +0 -1
  588. package/conformance/cases/extension/035_date_difference.pl +0 -4
  589. package/conformance/cases/extension/036_extended_gcd.pl +0 -3
  590. package/conformance/cases/extension/037_collatz_trajectory.pl +0 -3
  591. package/conformance/cases/extension/038_kaprekar_steps.pl +0 -3
  592. package/conformance/cases/extension/039_goldbach_pair.pl +0 -3
  593. package/conformance/cases/extension/040_matrix_operations.pl +0 -5
  594. package/conformance/cases/extension/041_atom_range_generators.pl +0 -5
  595. package/conformance/cases/extension/042_n_queens_small.pl +0 -3
  596. package/conformance/cases/extension/043_cnf_model.pl +0 -3
  597. package/conformance/cases/extension/044_cover9_filter.pl +0 -6
  598. package/conformance/cases/extension/045_alphametic_sum_small.pl +0 -3
  599. package/conformance/cases/extension/046_bounded_subset.pl +0 -4
  600. package/conformance/expected/core/003_terms_and_readback.out +0 -13
  601. package/conformance/expected/core/016_zero_arity_compound.out +0 -1
  602. package/conformance/expected/extension/003_arithmetic_and_comparison.out +0 -10
  603. package/conformance/expected/extension/004_strings_and_atoms.out +0 -4
  604. package/conformance/expected/extension/006_formula_terms.out +0 -4
  605. package/conformance/expected/extension/009_list_relations.out +0 -5
  606. package/conformance/expected/extension/025_is_list_filter.out +0 -1
  607. package/conformance/expected/extension/026_nested_formula_terms.out +0 -6
  608. package/conformance/expected/extension/030_string_and_atom_concat.out +0 -2
  609. package/conformance/expected/extension/036_extended_gcd.out +0 -1
  610. package/conformance/expected/extension/037_collatz_trajectory.out +0 -1
  611. package/conformance/expected/extension/038_kaprekar_steps.out +0 -1
  612. package/conformance/expected/extension/039_goldbach_pair.out +0 -2
  613. package/conformance/expected/extension/040_matrix_operations.out +0 -3
  614. package/conformance/expected/extension/041_atom_range_generators.out +0 -8
  615. package/conformance/expected/extension/042_n_queens_small.out +0 -2
  616. package/conformance/expected/extension/043_cnf_model.out +0 -1
  617. package/conformance/expected/extension/044_cover9_filter.out +0 -2
  618. package/conformance/expected/extension/045_alphametic_sum_small.out +0 -4
  619. package/conformance/expected/extension/046_bounded_subset.out +0 -5
  620. package/examples/access-control-policy.pl +0 -52
  621. package/examples/ackermann.pl +0 -46
  622. package/examples/age.pl +0 -28
  623. package/examples/aliases-and-namespaces.pl +0 -22
  624. package/examples/alignment-demo.pl +0 -44
  625. package/examples/allen-interval-calculus.pl +0 -64
  626. package/examples/ancestor.pl +0 -21
  627. package/examples/animal.pl +0 -21
  628. package/examples/annotation-rdf12.ttl +0 -12
  629. package/examples/annotation.pl +0 -34
  630. package/examples/auroracare.pl +0 -309
  631. package/examples/backward.pl +0 -12
  632. package/examples/basic-monadic.pl +0 -10018
  633. package/examples/bayes-diagnosis.pl +0 -108
  634. package/examples/bayes-therapy.pl +0 -182
  635. package/examples/beam-deflection.pl +0 -50
  636. package/examples/blocks-world-planning.pl +0 -75
  637. package/examples/bmi.pl +0 -232
  638. package/examples/braking-safety-worlds.pl +0 -69
  639. package/examples/buck-converter-design.pl +0 -78
  640. package/examples/cache-performance.pl +0 -54
  641. package/examples/canary-release.pl +0 -49
  642. package/examples/cat-koko.pl +0 -24
  643. package/examples/clinical-trial-screening.pl +0 -92
  644. package/examples/collatz-1000.pl +0 -14
  645. package/examples/combinatorics-findall-sort.pl +0 -37
  646. package/examples/competitive-enzyme-kinetics.pl +0 -78
  647. package/examples/complex-matrix-stability.pl +0 -45
  648. package/examples/complex.pl +0 -121
  649. package/examples/composition-of-injective-functions-is-injective.pl +0 -50
  650. package/examples/context-association.pl +0 -53
  651. package/examples/control-system.pl +0 -72
  652. package/examples/cryptarithmetic-send-more-money.pl +0 -49
  653. package/examples/cyclic-path.pl +0 -16
  654. package/examples/d3-group.pl +0 -100
  655. package/examples/dairy-energy-balance.pl +0 -65
  656. package/examples/data-negotiation.pl +0 -39
  657. package/examples/deep-taxonomy-10.pl +0 -115
  658. package/examples/deep-taxonomy-100.pl +0 -385
  659. package/examples/deep-taxonomy-1000.pl +0 -3085
  660. package/examples/deep-taxonomy-10000.pl +0 -30094
  661. package/examples/deep-taxonomy-100000.pl +0 -300184
  662. package/examples/delfour.pl +0 -281
  663. package/examples/dense-hamiltonian-cycle.pl +0 -92
  664. package/examples/deontic-logic.pl +0 -52
  665. package/examples/derived-backward-rule.pl +0 -30
  666. package/examples/derived-rule.pl +0 -27
  667. package/examples/diamond-property.pl +0 -38
  668. package/examples/dijkstra-findall-sort.pl +0 -44
  669. package/examples/dijkstra-risk-path.pl +0 -86
  670. package/examples/dijkstra.pl +0 -46
  671. package/examples/dining-philosophers.pl +0 -140
  672. package/examples/directional-language.ttl +0 -9
  673. package/examples/dog.pl +0 -25
  674. package/examples/drone-corridor-planner.pl +0 -51
  675. package/examples/easter-computus.pl +0 -89
  676. package/examples/electrical-rc-filter.pl +0 -36
  677. package/examples/epidemic-policy.pl +0 -67
  678. package/examples/equivalence-classes-overlap-implies-same-class.pl +0 -27
  679. package/examples/eulerian-path.pl +0 -85
  680. package/examples/ev-range-worlds.pl +0 -82
  681. package/examples/exact-cover-sudoku.pl +0 -113
  682. package/examples/existential-rule.pl +0 -18
  683. package/examples/exoplanet-validation-worlds.pl +0 -88
  684. package/examples/expression-eval.pl +0 -43
  685. package/examples/eyeling-ackermann.n3 +0 -41
  686. package/examples/eyeling-age-threshold.n3 +0 -12
  687. package/examples/eyeling-alignment-demo.n3 +0 -11
  688. package/examples/eyeling-allen-interval-calculus-small.n3 +0 -13
  689. package/examples/eyeling-backward-recursion.n3 +0 -11
  690. package/examples/eyeling-backward.n3 +0 -10
  691. package/examples/eyeling-basic-monadic-small.n3 +0 -11
  692. package/examples/eyeling-bmi.n3 +0 -10
  693. package/examples/eyeling-cat-koko.n3 +0 -15
  694. package/examples/eyeling-collatz-small.n3 +0 -11
  695. package/examples/eyeling-collection.n3 +0 -11
  696. package/examples/eyeling-complex-arithmetic.n3 +0 -10
  697. package/examples/eyeling-context-association.n3 +0 -11
  698. package/examples/eyeling-control-system-small.n3 +0 -11
  699. package/examples/eyeling-crypto-builtins-extra.n3 +0 -10
  700. package/examples/eyeling-crypto-builtins.n3 +0 -8
  701. package/examples/eyeling-deep-taxonomy-10.n3 +0 -18
  702. package/examples/eyeling-derived-backward-rule-flat.n3 +0 -10
  703. package/examples/eyeling-derived-rule-flat.n3 +0 -9
  704. package/examples/eyeling-digital-product-passport-small.n3 +0 -11
  705. package/examples/eyeling-dijkstra-tiny.n3 +0 -14
  706. package/examples/eyeling-dog-license.n3 +0 -13
  707. package/examples/eyeling-drone-corridor-planner-small.n3 +0 -13
  708. package/examples/eyeling-equals.n3 +0 -8
  709. package/examples/eyeling-equivalence-classes.n3 +0 -11
  710. package/examples/eyeling-euler-identity.n3 +0 -9
  711. package/examples/eyeling-existential-rule.n3 +0 -9
  712. package/examples/eyeling-expression-eval.n3 +0 -11
  713. package/examples/eyeling-family-cousins-extended.n3 +0 -12
  714. package/examples/eyeling-fastpow.n3 +0 -10
  715. package/examples/eyeling-fibonacci.n3 +0 -44
  716. package/examples/eyeling-french-cities-reachability.n3 +0 -22
  717. package/examples/eyeling-goldbach-small.n3 +0 -22
  718. package/examples/eyeling-good-cobbler.n3 +0 -9
  719. package/examples/eyeling-list-builtins.n3 +0 -10
  720. package/examples/eyeling-list-collection-extra.n3 +0 -9
  721. package/examples/eyeling-math-builtins.n3 +0 -9
  722. package/examples/eyeling-string-builtins-extra.n3 +0 -9
  723. package/examples/eyeling-string-builtins.n3 +0 -10
  724. package/examples/eyeling-time-builtins.n3 +0 -11
  725. package/examples/eyeling-time-components-extra.n3 +0 -10
  726. package/examples/eyeling-witch.n3 +0 -10
  727. package/examples/family-cousins.n3 +0 -17
  728. package/examples/family-cousins.pl +0 -65
  729. package/examples/fastpow.pl +0 -53
  730. package/examples/fft8-numeric.pl +0 -83
  731. package/examples/fibonacci.pl +0 -53
  732. package/examples/field-nitrogen-balance.pl +0 -70
  733. package/examples/flandor.pl +0 -296
  734. package/examples/floating-point.pl +0 -23
  735. package/examples/four-color-map.pl +0 -127
  736. package/examples/fundamental-theorem-arithmetic.pl +0 -113
  737. package/examples/gcd-bezout-identity.pl +0 -48
  738. package/examples/gd-step-certified.pl +0 -158
  739. package/examples/gdpr-compliance.pl +0 -69
  740. package/examples/goldbach-1000.pl +0 -185
  741. package/examples/good-cobbler.pl +0 -14
  742. package/examples/gps.pl +0 -152
  743. package/examples/graph-reachability.pl +0 -36
  744. package/examples/gray-code-counter.pl +0 -48
  745. package/examples/greatest-lower-bound-uniqueness.pl +0 -28
  746. package/examples/group-inverse-uniqueness.pl +0 -34
  747. package/examples/hamiltonian-cycle.pl +0 -55
  748. package/examples/hamiltonian-path.pl +0 -49
  749. package/examples/hamming-code.pl +0 -105
  750. package/examples/hanoi.pl +0 -20
  751. package/examples/heat-loss.pl +0 -51
  752. package/examples/heron-theorem.pl +0 -36
  753. package/examples/ideal-gas-law.pl +0 -37
  754. package/examples/illegitimate-reasoning.pl +0 -88
  755. package/examples/kaprekar.pl +0 -32
  756. package/examples/law-of-cosines.pl +0 -31
  757. package/examples/least-squares-regression.pl +0 -81
  758. package/examples/list-collection.pl +0 -33
  759. package/examples/lldm.pl +0 -78
  760. package/examples/manufacturing-quality-control.pl +0 -73
  761. package/examples/matrix.pl +0 -296
  762. package/examples/microgrid-dispatch.pl +0 -85
  763. package/examples/monkey-bananas.pl +0 -45
  764. package/examples/n-queens.pl +0 -23
  765. package/examples/n3-builtins.n3 +0 -28
  766. package/examples/network-sla.pl +0 -48
  767. package/examples/newton-raphson.pl +0 -49
  768. package/examples/nixon-diamond.pl +0 -37
  769. package/examples/odrl-dpv-healthcare-risk-ranked.pl +0 -266
  770. package/examples/odrl-dpv-risk-ranked.pl +0 -320
  771. package/examples/orbital-transfer-design.pl +0 -113
  772. package/examples/output/annotation-rdf12.ttl +0 -1
  773. package/examples/output/basic-monadic.pl +0 -1518
  774. package/examples/output/collatz-1000.pl +0 -1000
  775. package/examples/output/complex-matrix-stability.pl +0 -5
  776. package/examples/output/complex.pl +0 -1
  777. package/examples/output/cryptarithmetic-send-more-money.pl +0 -6
  778. package/examples/output/dense-hamiltonian-cycle.pl +0 -4
  779. package/examples/output/directional-language.ttl +0 -1
  780. package/examples/output/exact-cover-sudoku.pl +0 -3
  781. package/examples/output/eyeling-ackermann.n3 +0 -12
  782. package/examples/output/eyeling-age-threshold.n3 +0 -4
  783. package/examples/output/eyeling-alignment-demo.n3 +0 -1
  784. package/examples/output/eyeling-allen-interval-calculus-small.n3 +0 -3
  785. package/examples/output/eyeling-backward-recursion.n3 +0 -9
  786. package/examples/output/eyeling-backward.n3 +0 -1
  787. package/examples/output/eyeling-basic-monadic-small.n3 +0 -8
  788. package/examples/output/eyeling-bmi.n3 +0 -2
  789. package/examples/output/eyeling-cat-koko.n3 +0 -3
  790. package/examples/output/eyeling-collatz-small.n3 +0 -3
  791. package/examples/output/eyeling-collection.n3 +0 -1
  792. package/examples/output/eyeling-complex-arithmetic.n3 +0 -5
  793. package/examples/output/eyeling-context-association.n3 +0 -4
  794. package/examples/output/eyeling-control-system-small.n3 +0 -4
  795. package/examples/output/eyeling-crypto-builtins-extra.n3 +0 -3
  796. package/examples/output/eyeling-crypto-builtins.n3 +0 -2
  797. package/examples/output/eyeling-deep-taxonomy-10.n3 +0 -32
  798. package/examples/output/eyeling-derived-backward-rule-flat.n3 +0 -4
  799. package/examples/output/eyeling-derived-rule-flat.n3 +0 -2
  800. package/examples/output/eyeling-digital-product-passport-small.n3 +0 -3
  801. package/examples/output/eyeling-dijkstra-tiny.n3 +0 -9
  802. package/examples/output/eyeling-dog-license.n3 +0 -1
  803. package/examples/output/eyeling-drone-corridor-planner-small.n3 +0 -5
  804. package/examples/output/eyeling-equals.n3 +0 -1
  805. package/examples/output/eyeling-equivalence-classes.n3 +0 -2
  806. package/examples/output/eyeling-euler-identity.n3 +0 -3
  807. package/examples/output/eyeling-existential-rule.n3 +0 -4
  808. package/examples/output/eyeling-expression-eval.n3 +0 -3
  809. package/examples/output/eyeling-family-cousins-extended.n3 +0 -6
  810. package/examples/output/eyeling-fastpow.n3 +0 -4
  811. package/examples/output/eyeling-fibonacci.n3 +0 -6
  812. package/examples/output/eyeling-french-cities-reachability.n3 +0 -25
  813. package/examples/output/eyeling-goldbach-small.n3 +0 -2
  814. package/examples/output/eyeling-good-cobbler.n3 +0 -2
  815. package/examples/output/eyeling-list-builtins.n3 +0 -6
  816. package/examples/output/eyeling-list-collection-extra.n3 +0 -5
  817. package/examples/output/eyeling-math-builtins.n3 +0 -5
  818. package/examples/output/eyeling-string-builtins-extra.n3 +0 -3
  819. package/examples/output/eyeling-string-builtins.n3 +0 -4
  820. package/examples/output/eyeling-time-builtins.n3 +0 -4
  821. package/examples/output/eyeling-time-components-extra.n3 +0 -5
  822. package/examples/output/eyeling-witch.n3 +0 -2
  823. package/examples/output/family-cousins.n3 +0 -8
  824. package/examples/output/gcd-bezout-identity.pl +0 -36
  825. package/examples/output/goldbach-1000.pl +0 -667
  826. package/examples/output/hamiltonian-cycle.pl +0 -4
  827. package/examples/output/kaprekar.pl +0 -8
  828. package/examples/output/matrix.pl +0 -10
  829. package/examples/output/n-queens.pl +0 -93
  830. package/examples/output/n3-builtins.n3 +0 -6
  831. package/examples/output/path-discovery.pl +0 -3
  832. package/examples/output/project-portfolio-optimization.pl +0 -6
  833. package/examples/output/quine-mccluskey.pl +0 -3
  834. package/examples/output/resilient-city-orchestration.pl +0 -67
  835. package/examples/output/sat-dpll.pl +0 -5
  836. package/examples/output/socrates.n3 +0 -1
  837. package/examples/output/sudoku.pl +0 -2
  838. package/examples/output/traveling-salesman.pl +0 -1
  839. package/examples/output/triple-term.n3 +0 -2
  840. package/examples/path-discovery.pl +0 -44998
  841. package/examples/peano-arithmetic.pl +0 -31
  842. package/examples/peasant.pl +0 -30
  843. package/examples/pendulum-period.pl +0 -50
  844. package/examples/polynomial.pl +0 -124
  845. package/examples/project-portfolio-optimization.pl +0 -101
  846. package/examples/proof/age.pl +0 -71
  847. package/examples/proof/aliases-and-namespaces.pl +0 -78
  848. package/examples/proof/ancestor.pl +0 -140
  849. package/examples/proof/animal.pl +0 -68
  850. package/examples/proof/annotation.pl +0 -80
  851. package/examples/proof/backward.pl +0 -22
  852. package/examples/proof/cat-koko.pl +0 -86
  853. package/examples/proof/data-negotiation.pl +0 -76
  854. package/examples/proof/derived-rule.pl +0 -43
  855. package/examples/proof/dog.pl +0 -31
  856. package/examples/proof/electrical-rc-filter.pl +0 -105
  857. package/examples/proof/existential-rule.pl +0 -40
  858. package/examples/proof/floating-point.pl +0 -160
  859. package/examples/proof/good-cobbler.pl +0 -16
  860. package/examples/proof/group-inverse-uniqueness.pl +0 -84
  861. package/examples/proof/list-collection.pl +0 -52
  862. package/examples/proof/proof-contrapositive.pl +0 -78
  863. package/examples/proof/socket-age.pl +0 -32
  864. package/examples/proof/socket-family.pl +0 -59
  865. package/examples/proof/socrates.pl +0 -38
  866. package/examples/proof-contrapositive.pl +0 -27
  867. package/examples/quadratic-formula.pl +0 -54
  868. package/examples/quine-mccluskey.pl +0 -143
  869. package/examples/radioactive-decay.pl +0 -56
  870. package/examples/resilient-city-orchestration.pl +0 -303
  871. package/examples/riemann-hypothesis.pl +0 -110
  872. package/examples/sat-dpll.pl +0 -80
  873. package/examples/security-incident-correlation.pl +0 -69
  874. package/examples/service-impact.pl +0 -41
  875. package/examples/sieve.pl +0 -20
  876. package/examples/skolem-functions.pl +0 -52
  877. package/examples/socket-age.pl +0 -39
  878. package/examples/socket-family.pl +0 -28
  879. package/examples/socrates.n3 +0 -11
  880. package/examples/socrates.pl +0 -19
  881. package/examples/statistics-summary.pl +0 -54
  882. package/examples/sudoku.pl +0 -20
  883. package/examples/superdense-coding.pl +0 -84
  884. package/examples/traveling-salesman.pl +0 -64
  885. package/examples/triple-term.n3 +0 -9
  886. package/examples/turing.pl +0 -67
  887. package/examples/vector-similarity.pl +0 -56
  888. package/examples/witch.pl +0 -38
  889. package/examples/wolf-goat-cabbage.pl +0 -56
  890. package/examples/zebra.pl +0 -44
  891. package/playground-worker.mjs +0 -141
  892. package/src/builtins/alphametic.js +0 -144
  893. package/src/builtins/formula.js +0 -42
  894. package/src/builtins/matrix.js +0 -226
  895. package/src/builtins/n3.js +0 -483
  896. package/src/builtins/number-theory.js +0 -114
  897. package/src/builtins/portfolio.js +0 -73
  898. package/src/builtins/search.js +0 -579
  899. package/src/builtins/sudoku.js +0 -141
  900. package/src/rdf.js +0 -747
  901. package/test/run-all.js +0 -20
  902. package/test/run-conformance.js +0 -80
  903. package/test/run-examples.js +0 -125
  904. package/test/run-regression.js +0 -603
  905. package/test/test-style.js +0 -91
  906. /package/examples/output/{access-control-policy.pl → access-control-policy.eye} +0 -0
  907. /package/examples/output/{ackermann.pl → ackermann.eye} +0 -0
  908. /package/examples/output/{age.pl → age.eye} +0 -0
  909. /package/examples/output/{aliases-and-namespaces.pl → aliases-and-namespaces.eye} +0 -0
  910. /package/examples/output/{alignment-demo.pl → alignment-demo.eye} +0 -0
  911. /package/examples/output/{allen-interval-calculus.pl → allen-interval-calculus.eye} +0 -0
  912. /package/examples/output/{ancestor.pl → ancestor.eye} +0 -0
  913. /package/examples/output/{animal.pl → animal.eye} +0 -0
  914. /package/examples/output/{annotation.pl → annotation.eye} +0 -0
  915. /package/examples/output/{auroracare.pl → auroracare.eye} +0 -0
  916. /package/examples/output/{backward.pl → backward.eye} +0 -0
  917. /package/examples/output/{bayes-diagnosis.pl → bayes-diagnosis.eye} +0 -0
  918. /package/examples/output/{bayes-therapy.pl → bayes-therapy.eye} +0 -0
  919. /package/examples/output/{beam-deflection.pl → beam-deflection.eye} +0 -0
  920. /package/examples/output/{blocks-world-planning.pl → blocks-world-planning.eye} +0 -0
  921. /package/examples/output/{bmi.pl → bmi.eye} +0 -0
  922. /package/examples/output/{braking-safety-worlds.pl → braking-safety-worlds.eye} +0 -0
  923. /package/examples/output/{buck-converter-design.pl → buck-converter-design.eye} +0 -0
  924. /package/examples/output/{cache-performance.pl → cache-performance.eye} +0 -0
  925. /package/examples/output/{canary-release.pl → canary-release.eye} +0 -0
  926. /package/examples/output/{cat-koko.pl → cat-koko.eye} +0 -0
  927. /package/examples/output/{clinical-trial-screening.pl → clinical-trial-screening.eye} +0 -0
  928. /package/examples/output/{combinatorics-findall-sort.pl → combinatorics-findall-sort.eye} +0 -0
  929. /package/examples/output/{competitive-enzyme-kinetics.pl → competitive-enzyme-kinetics.eye} +0 -0
  930. /package/examples/output/{composition-of-injective-functions-is-injective.pl → composition-of-injective-functions-is-injective.eye} +0 -0
  931. /package/examples/output/{context-association.pl → context-association.eye} +0 -0
  932. /package/examples/output/{control-system.pl → control-system.eye} +0 -0
  933. /package/examples/output/{cyclic-path.pl → cyclic-path.eye} +0 -0
  934. /package/examples/output/{d3-group.pl → d3-group.eye} +0 -0
  935. /package/examples/output/{dairy-energy-balance.pl → dairy-energy-balance.eye} +0 -0
  936. /package/examples/output/{data-negotiation.pl → data-negotiation.eye} +0 -0
  937. /package/examples/output/{deep-taxonomy-10.pl → deep-taxonomy-10.eye} +0 -0
  938. /package/examples/output/{deep-taxonomy-100.pl → deep-taxonomy-100.eye} +0 -0
  939. /package/examples/output/{deep-taxonomy-1000.pl → deep-taxonomy-1000.eye} +0 -0
  940. /package/examples/output/{deep-taxonomy-10000.pl → deep-taxonomy-10000.eye} +0 -0
  941. /package/examples/output/{deep-taxonomy-100000.pl → deep-taxonomy-100000.eye} +0 -0
  942. /package/examples/output/{delfour.pl → delfour.eye} +0 -0
  943. /package/examples/output/{deontic-logic.pl → deontic-logic.eye} +0 -0
  944. /package/examples/output/{derived-backward-rule.pl → derived-backward-rule.eye} +0 -0
  945. /package/examples/output/{derived-rule.pl → derived-rule.eye} +0 -0
  946. /package/examples/output/{diamond-property.pl → diamond-property.eye} +0 -0
  947. /package/examples/output/{dijkstra-findall-sort.pl → dijkstra-findall-sort.eye} +0 -0
  948. /package/examples/output/{dijkstra-risk-path.pl → dijkstra-risk-path.eye} +0 -0
  949. /package/examples/output/{dijkstra.pl → dijkstra.eye} +0 -0
  950. /package/examples/output/{dining-philosophers.pl → dining-philosophers.eye} +0 -0
  951. /package/examples/output/{dog.pl → dog.eye} +0 -0
  952. /package/examples/output/{drone-corridor-planner.pl → drone-corridor-planner.eye} +0 -0
  953. /package/examples/output/{easter-computus.pl → easter-computus.eye} +0 -0
  954. /package/examples/output/{electrical-rc-filter.pl → electrical-rc-filter.eye} +0 -0
  955. /package/examples/output/{epidemic-policy.pl → epidemic-policy.eye} +0 -0
  956. /package/examples/output/{equivalence-classes-overlap-implies-same-class.pl → equivalence-classes-overlap-implies-same-class.eye} +0 -0
  957. /package/examples/output/{eulerian-path.pl → eulerian-path.eye} +0 -0
  958. /package/examples/output/{ev-range-worlds.pl → ev-range-worlds.eye} +0 -0
  959. /package/examples/output/{existential-rule.pl → existential-rule.eye} +0 -0
  960. /package/examples/output/{exoplanet-validation-worlds.pl → exoplanet-validation-worlds.eye} +0 -0
  961. /package/examples/output/{expression-eval.pl → expression-eval.eye} +0 -0
  962. /package/examples/output/{family-cousins.pl → family-cousins.eye} +0 -0
  963. /package/examples/output/{fastpow.pl → fastpow.eye} +0 -0
  964. /package/examples/output/{fft8-numeric.pl → fft8-numeric.eye} +0 -0
  965. /package/examples/output/{fibonacci.pl → fibonacci.eye} +0 -0
  966. /package/examples/output/{field-nitrogen-balance.pl → field-nitrogen-balance.eye} +0 -0
  967. /package/examples/output/{flandor.pl → flandor.eye} +0 -0
  968. /package/examples/output/{floating-point.pl → floating-point.eye} +0 -0
  969. /package/examples/output/{four-color-map.pl → four-color-map.eye} +0 -0
  970. /package/examples/output/{fundamental-theorem-arithmetic.pl → fundamental-theorem-arithmetic.eye} +0 -0
  971. /package/examples/output/{gd-step-certified.pl → gd-step-certified.eye} +0 -0
  972. /package/examples/output/{gdpr-compliance.pl → gdpr-compliance.eye} +0 -0
  973. /package/examples/output/{good-cobbler.pl → good-cobbler.eye} +0 -0
  974. /package/examples/output/{gps.pl → gps.eye} +0 -0
  975. /package/examples/output/{graph-reachability.pl → graph-reachability.eye} +0 -0
  976. /package/examples/output/{gray-code-counter.pl → gray-code-counter.eye} +0 -0
  977. /package/examples/output/{greatest-lower-bound-uniqueness.pl → greatest-lower-bound-uniqueness.eye} +0 -0
  978. /package/examples/output/{group-inverse-uniqueness.pl → group-inverse-uniqueness.eye} +0 -0
  979. /package/examples/output/{hamiltonian-path.pl → hamiltonian-path.eye} +0 -0
  980. /package/examples/output/{hamming-code.pl → hamming-code.eye} +0 -0
  981. /package/examples/output/{hanoi.pl → hanoi.eye} +0 -0
  982. /package/examples/output/{heat-loss.pl → heat-loss.eye} +0 -0
  983. /package/examples/output/{heron-theorem.pl → heron-theorem.eye} +0 -0
  984. /package/examples/output/{ideal-gas-law.pl → ideal-gas-law.eye} +0 -0
  985. /package/examples/output/{illegitimate-reasoning.pl → illegitimate-reasoning.eye} +0 -0
  986. /package/examples/output/{law-of-cosines.pl → law-of-cosines.eye} +0 -0
  987. /package/examples/output/{least-squares-regression.pl → least-squares-regression.eye} +0 -0
  988. /package/examples/output/{list-collection.pl → list-collection.eye} +0 -0
  989. /package/examples/output/{lldm.pl → lldm.eye} +0 -0
  990. /package/examples/output/{manufacturing-quality-control.pl → manufacturing-quality-control.eye} +0 -0
  991. /package/examples/output/{microgrid-dispatch.pl → microgrid-dispatch.eye} +0 -0
  992. /package/examples/output/{monkey-bananas.pl → monkey-bananas.eye} +0 -0
  993. /package/examples/output/{network-sla.pl → network-sla.eye} +0 -0
  994. /package/examples/output/{newton-raphson.pl → newton-raphson.eye} +0 -0
  995. /package/examples/output/{nixon-diamond.pl → nixon-diamond.eye} +0 -0
  996. /package/examples/output/{odrl-dpv-healthcare-risk-ranked.pl → odrl-dpv-healthcare-risk-ranked.eye} +0 -0
  997. /package/examples/output/{odrl-dpv-risk-ranked.pl → odrl-dpv-risk-ranked.eye} +0 -0
  998. /package/examples/output/{orbital-transfer-design.pl → orbital-transfer-design.eye} +0 -0
  999. /package/examples/output/{peano-arithmetic.pl → peano-arithmetic.eye} +0 -0
  1000. /package/examples/output/{peasant.pl → peasant.eye} +0 -0
  1001. /package/examples/output/{pendulum-period.pl → pendulum-period.eye} +0 -0
  1002. /package/examples/output/{polynomial.pl → polynomial.eye} +0 -0
  1003. /package/examples/output/{proof-contrapositive.pl → proof-contrapositive.eye} +0 -0
  1004. /package/examples/output/{quadratic-formula.pl → quadratic-formula.eye} +0 -0
  1005. /package/examples/output/{radioactive-decay.pl → radioactive-decay.eye} +0 -0
  1006. /package/examples/output/{riemann-hypothesis.pl → riemann-hypothesis.eye} +0 -0
  1007. /package/examples/output/{security-incident-correlation.pl → security-incident-correlation.eye} +0 -0
  1008. /package/examples/output/{service-impact.pl → service-impact.eye} +0 -0
  1009. /package/examples/output/{sieve.pl → sieve.eye} +0 -0
  1010. /package/examples/output/{skolem-functions.pl → skolem-functions.eye} +0 -0
  1011. /package/examples/output/{socket-age.pl → socket-age.eye} +0 -0
  1012. /package/{conformance/expected/extension/001_default_derived_output.out → examples/output/socket-family.eye} +0 -0
  1013. /package/examples/output/{socrates.pl → socrates.eye} +0 -0
  1014. /package/examples/output/{statistics-summary.pl → statistics-summary.eye} +0 -0
  1015. /package/examples/output/{superdense-coding.pl → superdense-coding.eye} +0 -0
  1016. /package/examples/output/{turing.pl → turing.eye} +0 -0
  1017. /package/examples/output/{vector-similarity.pl → vector-similarity.eye} +0 -0
  1018. /package/examples/output/{witch.pl → witch.eye} +0 -0
  1019. /package/examples/output/{wolf-goat-cabbage.pl → wolf-goat-cabbage.eye} +0 -0
  1020. /package/examples/output/{zebra.pl → zebra.eye} +0 -0
  1021. /package/{conformance/expected/core/001_fact_output.out → test/conformance/expected/001_fact_output.eye} +0 -0
  1022. /package/{conformance/expected/core/002_rule_recursion.out → test/conformance/expected/002_rule_recursion.eye} +0 -0
  1023. /package/{conformance/expected/core/004_conjunction_and_parentheses.out → test/conformance/expected/004_conjunction_and_parentheses.eye} +0 -0
  1024. /package/{conformance/expected/core/005_list_deconstruction.out → test/conformance/expected/005_list_deconstruction.eye} +0 -0
  1025. /package/{conformance/expected/core/006_comma_formula_data.out → test/conformance/expected/006_comma_formula_data.eye} +0 -0
  1026. /package/{conformance/expected/core/007_anonymous_variables.out → test/conformance/expected/007_anonymous_variables.eye} +0 -0
  1027. /package/{conformance/expected/core/008_graphic_atoms.out → test/conformance/expected/008_graphic_atoms.eye} +0 -0
  1028. /package/{conformance/expected/core/009_comments_and_whitespace.out → test/conformance/expected/009_comments_and_whitespace.eye} +0 -0
  1029. /package/{conformance/expected/core/010_variable_scope_and_reuse.out → test/conformance/expected/010_variable_scope_and_reuse.eye} +0 -0
  1030. /package/{conformance/expected/core/011_predicate_arity.out → test/conformance/expected/011_predicate_arity.eye} +0 -0
  1031. /package/{conformance/expected/core/012_nested_compound_unification.out → test/conformance/expected/012_nested_compound_unification.eye} +0 -0
  1032. /package/{conformance/expected/core/013_multiple_clauses_order.out → test/conformance/expected/013_multiple_clauses_order.eye} +0 -0
  1033. /package/{conformance/expected/core/014_failure_filters_answers.out → test/conformance/expected/014_failure_filters_answers.eye} +0 -0
  1034. /package/{conformance/expected/core/015_improper_list_unification.out → test/conformance/expected/015_improper_list_unification.eye} +0 -0
  1035. /package/{conformance/expected/core/017_three_step_recursion.out → test/conformance/expected/017_three_step_recursion.eye} +0 -0
  1036. /package/{conformance/expected/core/018_quoted_atom_readback.out → test/conformance/expected/018_quoted_atom_readback.eye} +0 -0
  1037. /package/{conformance/expected/core/019_parenthesized_three_conjuncts.out → test/conformance/expected/019_parenthesized_three_conjuncts.eye} +0 -0
  1038. /package/{conformance/expected/core/020_nested_list_terms.out → test/conformance/expected/020_nested_list_terms.eye} +0 -0
  1039. /package/{conformance/expected/core/021_repeated_variable_head.out → test/conformance/expected/021_repeated_variable_head.eye} +0 -0
  1040. /package/{conformance/expected/core/022_rule_head_structure.out → test/conformance/expected/022_rule_head_structure.eye} +0 -0
  1041. /package/{conformance/expected/core/023_quoted_escapes_readback.out → test/conformance/expected/023_quoted_escapes_readback.eye} +0 -0
  1042. /package/{conformance/expected/core/024_numeric_literal_readback.out → test/conformance/expected/024_numeric_literal_readback.eye} +0 -0
  1043. /package/{conformance/expected/core/025_body_parentheses_with_formula_data.out → test/conformance/expected/025_body_parentheses_with_formula_data.eye} +0 -0
  1044. /package/{conformance/expected/core/026_underscore_named_variable_reuse.out → test/conformance/expected/026_question_underscore_named_variable_reuse.eye} +0 -0
  1045. /package/{examples/output/socket-family.pl → test/conformance/expected/027_default_derived_output.eye} +0 -0
  1046. /package/{conformance/expected/extension/002_materialize_focus.out → test/conformance/expected/028_materialize_focus.eye} +0 -0
  1047. /package/{conformance/expected/extension/005_lists_aggregation_ordering.out → test/conformance/expected/031_lists_aggregation_ordering.eye} +0 -0
  1048. /package/{conformance/expected/extension/007_negation_once_generators.out → test/conformance/expected/033_negation_once_generators.eye} +0 -0
  1049. /package/{conformance/expected/extension/008_equality_and_inequality.out → test/conformance/expected/034_equality_and_inequality.eye} +0 -0
  1050. /package/{conformance/expected/extension/010_append_splits.out → test/conformance/expected/036_append_splits.eye} +0 -0
  1051. /package/{conformance/expected/extension/011_matching_and_comparison.out → test/conformance/expected/037_matching_and_comparison.eye} +0 -0
  1052. /package/{conformance/expected/extension/012_memoize_declaration.out → test/conformance/expected/038_table_declaration.eye} +0 -0
  1053. /package/{conformance/expected/extension/013_numeric_functions.out → test/conformance/expected/039_numeric_functions.eye} +0 -0
  1054. /package/{conformance/expected/extension/014_between_enumeration.out → test/conformance/expected/040_between_enumeration.eye} +0 -0
  1055. /package/{conformance/expected/extension/015_smallest_divisor.out → test/conformance/expected/041_smallest_divisor.eye} +0 -0
  1056. /package/{conformance/expected/extension/016_negation_filter.out → test/conformance/expected/042_negation_filter.eye} +0 -0
  1057. /package/{conformance/expected/extension/017_once_user_predicate.out → test/conformance/expected/043_once_user_predicate.eye} +0 -0
  1058. /package/{conformance/expected/extension/018_findall_user_goal.out → test/conformance/expected/044_findall_user_goal.eye} +0 -0
  1059. /package/{conformance/expected/extension/019_sort_deduplicates_atoms.out → test/conformance/expected/045_sort_deduplicates_atoms.eye} +0 -0
  1060. /package/{conformance/expected/extension/020_append_bound_prefix_suffix.out → test/conformance/expected/046_append_bound_prefix_suffix.eye} +0 -0
  1061. /package/{conformance/expected/extension/021_nth0_index_generation.out → test/conformance/expected/047_nth0_index_generation.eye} +0 -0
  1062. /package/{conformance/expected/extension/022_set_nth0_edges.out → test/conformance/expected/048_set_nth0_edges.eye} +0 -0
  1063. /package/{conformance/expected/extension/023_select_duplicate_occurrences.out → test/conformance/expected/049_select_duplicate_occurrences.eye} +0 -0
  1064. /package/{conformance/expected/extension/024_not_member_filter.out → test/conformance/expected/050_not_member_filter.eye} +0 -0
  1065. /package/{conformance/expected/extension/027_materialize_excludes_source_fact.out → test/conformance/expected/053_materialize_excludes_source_fact.eye} +0 -0
  1066. /package/{conformance/expected/extension/028_numeric_and_lexical_comparison.out → test/conformance/expected/054_numeric_and_lexical_comparison.eye} +0 -0
  1067. /package/{conformance/expected/extension/029_string_matching_filters.out → test/conformance/expected/055_string_matching_filters.eye} +0 -0
  1068. /package/{conformance/expected/extension/031_countall_empty_and_nonempty.out → test/conformance/expected/057_countall_empty_and_nonempty.eye} +0 -0
  1069. /package/{conformance/expected/extension/032_sumall_numeric_template.out → test/conformance/expected/058_sumall_numeric_template.eye} +0 -0
  1070. /package/{conformance/expected/extension/033_aggregate_min_template.out → test/conformance/expected/059_aggregate_min_template.eye} +0 -0
  1071. /package/{conformance/expected/extension/034_aggregate_max_compound_key.out → test/conformance/expected/060_aggregate_max_compound_key.eye} +0 -0
  1072. /package/{conformance/expected/extension/035_date_difference.out → test/conformance/expected/061_date_difference.eye} +0 -0
@@ -0,0 +1,1215 @@
1
+ #!/usr/bin/env node
2
+ // Supplemental regression runner.
3
+ // This file collects focused checks that do not belong to the public
4
+ // conformance corpus or the example-output corpus: CLI regressions, public API
5
+ // checks, and small white-box tests for maintenance-sensitive internals.
6
+ import fs from 'node:fs';
7
+ import os from 'node:os';
8
+ import path from 'node:path';
9
+ import { spawnSync } from 'node:child_process';
10
+ import { fileURLToPath } from 'node:url';
11
+ import * as publicApi from '../src/index.js';
12
+ import {
13
+ run,
14
+ Program,
15
+ makeProgram,
16
+ Solver,
17
+ Env,
18
+ BuiltinRegistry,
19
+ createDefaultRegistry,
20
+ atom,
21
+ compound,
22
+ listFromItems,
23
+ numberTerm,
24
+ stringTerm,
25
+ variable,
26
+ copyResolved,
27
+ flattenConjunction,
28
+ properListItems,
29
+ termIsGround,
30
+ termToString,
31
+ unify,
32
+ variantTerms,
33
+ parseProgramText,
34
+ } from '../src/index.js';
35
+ import { parseGoalText } from '../src/parser.js';
36
+ import { selectClauseCandidates } from '../src/program.js';
37
+ import { TestReporter, isMainModule } from './test-style.mjs';
38
+ import { hashHex } from '../src/hash.js';
39
+
40
+ const testRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
41
+ const packageRoot = path.resolve(testRoot, '..');
42
+ const runtimeRoot = path.join(packageRoot, 'src');
43
+ const bin = path.join(runtimeRoot, 'bin.js');
44
+ const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
45
+ let tmp = null;
46
+ let tmpCounter = 0;
47
+
48
+ export function runRegression(reporter = new TestReporter()) {
49
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'eyelang-regression.'));
50
+ tmpCounter = 0;
51
+
52
+ try {
53
+ runSection(reporter, 'Regression', regressionCases());
54
+ runSection(reporter, 'Documentation sync', documentationSyncCases());
55
+ runSection(reporter, 'API', apiCases());
56
+ runSection(reporter, 'White-box', whiteBoxCases());
57
+ } finally {
58
+ fs.rmSync(tmp, { recursive: true, force: true });
59
+ tmp = null;
60
+ }
61
+ }
62
+
63
+ function regressionCases() {
64
+ return [
65
+ {
66
+ name: '--proof rule fact explanation output',
67
+ run: () => runWhy({
68
+ program: 'type(socrates, man).\ntype(?x, mortal) :- type(?x, man).\n',
69
+ goalText: 'type(socrates, mortal)',
70
+ expected: `type(socrates, mortal).
71
+ why(
72
+ type(socrates, mortal),
73
+ proof(
74
+ goal(type(socrates, mortal)),
75
+ by(rule("__FILE__", clause(2))),
76
+ bindings([binding("?x", socrates)]),
77
+ uses([
78
+ proof(
79
+ goal(type(socrates, man)),
80
+ by(fact("__FILE__", clause(1)))
81
+ )
82
+ ])
83
+ )
84
+ ).
85
+
86
+ `,
87
+ }),
88
+ },
89
+ {
90
+ name: '--proof numeric builtin explanation output',
91
+ run: () => runWhy({
92
+ program: 'p(?x) :- between(536, 536, ?x).\n',
93
+ goalText: 'p(536)',
94
+ expected: `p(536).
95
+ why(
96
+ p(536),
97
+ proof(
98
+ goal(p(536)),
99
+ by(rule("__FILE__", clause(1))),
100
+ bindings([binding("?x", 536)]),
101
+ uses([
102
+ proof(
103
+ goal(between(536, 536, 536)),
104
+ by(builtin(between, 3))
105
+ )
106
+ ])
107
+ )
108
+ ).
109
+
110
+ `,
111
+ }),
112
+ },
113
+ {
114
+ name: '--proof list builtin explanation output',
115
+ run: () => runWhy({
116
+ program: 'p(?x) :- member(?x, [a]).\n',
117
+ goalText: 'p(a)',
118
+ expected: `p(a).
119
+ why(
120
+ p(a),
121
+ proof(
122
+ goal(p(a)),
123
+ by(rule("__FILE__", clause(1))),
124
+ bindings([binding("?x", a)]),
125
+ uses([
126
+ proof(
127
+ goal(member(a, [a])),
128
+ by(builtin(member, 2))
129
+ )
130
+ ])
131
+ )
132
+ ).
133
+
134
+ `,
135
+ }),
136
+ },
137
+ {
138
+ name: 'explanation backtracks across earlier subgoal alternatives',
139
+ run: () => {
140
+ const result = runWhyLoose({
141
+ program: 'p(ok) :- q(?x), r(?x).\nq(a).\nq(b).\nr(b).\n',
142
+ goalText: 'p(ok)',
143
+ });
144
+ assertIncludes(result.stdout, 'goal(q(b)),\n by(fact("', 'stdout');
145
+ assertIncludes(result.stdout, 'goal(r(b)),\n by(fact("', 'stdout');
146
+ assertNotIncludes(result.stdout, 'no_proof', 'stdout');
147
+ },
148
+ },
149
+ {
150
+ name: 'explanation releases active call before caller rest goals',
151
+ run: () => {
152
+ const result = runWhyLoose({
153
+ program: 'p(ok) :- q(1), q(1).\nq(0).\nq(1) :- q(0).\n',
154
+ goalText: 'p(ok)',
155
+ });
156
+ assertIncludes(result.stdout, 'goal(p(ok)),\n by(rule("', 'stdout');
157
+ assertIncludes(result.stdout, 'goal(q(1)),\n by(rule("', 'stdout');
158
+ assertNotIncludes(result.stdout, 'no_proof', 'stdout');
159
+ },
160
+ },
161
+ {
162
+ name: 'EYELANG_LOCAL_TIME fixes local_time builtin',
163
+ run: () => {
164
+ const result = runCli(['-'], {
165
+ input: 'materialize(local_time_answer, 1).\nlocal_time_answer(?d) :- local_time(?d).\n',
166
+ env: { EYELANG_LOCAL_TIME: '2024-01-02' },
167
+ });
168
+ assertEqual(result.status, 0, 'exit status');
169
+ assertEqual(result.stdout, 'local_time_answer("2024-01-02").\n', 'stdout');
170
+ assertEqual(result.stderr, '', 'stderr');
171
+ },
172
+ },
173
+ {
174
+ name: 'help with no arguments',
175
+ run: () => {
176
+ const result = runCli([]);
177
+ assertEqual(result.status, 0, 'exit status');
178
+ assertIncludes(result.stdout, 'Usage:\n eyelang [options] [file-or-url.eye|- ...]', 'stdout');
179
+ assertIncludes(result.stdout, '-p, --proof', 'stdout');
180
+ assertIncludes(result.stdout, '-s, --stats', 'stdout');
181
+ assertIncludes(result.stdout, '-w, --warnings', 'stdout');
182
+ assertEqual(result.stderr, '', 'stderr');
183
+ },
184
+ },
185
+ {
186
+ name: 'version comes from package.json',
187
+ run: () => {
188
+ const result = runCli(['--version']);
189
+ assertEqual(result.status, 0, 'exit status');
190
+ assertEqual(result.stdout, `eyelang ${pkg.version}\n`, 'stdout');
191
+ assertEqual(result.stderr, '', 'stderr');
192
+ },
193
+ },
194
+ {
195
+ name: 'npm exec can run package CLI bin from checkout',
196
+ run: () => {
197
+ const result = spawnSync('npm', ['exec', '--', 'eyelang', '--version'], {
198
+ cwd: packageRoot,
199
+ encoding: 'utf8',
200
+ env: { ...process.env, npm_config_update_notifier: 'false' },
201
+ });
202
+ assertEqual(result.status, 0, 'exit status');
203
+ assertEqual(result.stdout, `eyelang ${pkg.version}\n`, 'stdout');
204
+ assertEqual(result.stderr, '', 'stderr');
205
+ },
206
+ },
207
+ {
208
+ name: 'stdin input is accepted',
209
+ run: () => {
210
+ const result = runCli(['-'], { input: 'p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n' });
211
+ assertEqual(result.status, 0, 'exit status');
212
+ assertEqual(result.stdout, 'q(a, b).\n', 'stdout');
213
+ assertEqual(result.stderr, '', 'stderr');
214
+ },
215
+ },
216
+
217
+ {
218
+ name: '--proof enables materialization explanations',
219
+ run: () => {
220
+ const result = runCli(['--proof', '-'], { input: 'p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n' });
221
+ assertEqual(result.status, 0, 'exit status');
222
+ assertIncludes(result.stdout, 'q(a, b).\nwhy(', 'stdout');
223
+ assertEqual(result.stderr, '', 'stderr');
224
+ },
225
+ },
226
+ {
227
+ name: '-p enables materialization explanations',
228
+ run: () => {
229
+ const result = runCli(['-p', '-'], { input: 'p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n' });
230
+ assertEqual(result.status, 0, 'exit status');
231
+ assertIncludes(result.stdout, 'q(a, b).\nwhy(', 'stdout');
232
+ assertEqual(result.stderr, '', 'stderr');
233
+ },
234
+ },
235
+
236
+
237
+ {
238
+ name: '--stats prints solver statistics to stderr',
239
+ run: () => {
240
+ const result = runCli(['--stats', '-'], { input: 'p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n' });
241
+ assertEqual(result.status, 0, 'exit status');
242
+ assertEqual(result.stdout, 'q(a, b).\n', 'stdout');
243
+ assertIncludes(result.stderr, 'eyelang stats:\n', 'stderr');
244
+ assertIncludes(result.stderr, ' solve_goals_calls:', 'stderr');
245
+ },
246
+ },
247
+ {
248
+ name: '-s prints solver statistics to stderr',
249
+ run: () => {
250
+ const result = runCli(['-s', '-'], { input: 'p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n' });
251
+ assertEqual(result.status, 0, 'exit status');
252
+ assertEqual(result.stdout, 'q(a, b).\n', 'stdout');
253
+ assertIncludes(result.stderr, 'eyelang stats:\n', 'stderr');
254
+ assertIncludes(result.stderr, ' solve_goals_calls:', 'stderr');
255
+ },
256
+ },
257
+ {
258
+ name: '--warnings prints unstratified negation diagnostics without failing',
259
+ run: () => {
260
+ const input = [
261
+ 'materialize(answer, 1).',
262
+ 'p(a) :- not(q(a)).',
263
+ 'q(a) :- not(p(a)).',
264
+ 'answer(ok).',
265
+ '',
266
+ ].join('\n');
267
+ const result = runCli(['--warnings', '-'], { input });
268
+ assertEqual(result.status, 0, 'exit status');
269
+ assertEqual(result.stdout, '', 'stdout');
270
+ assertIncludes(result.stderr, 'eyelang warning: unstratified negation\n', 'stderr');
271
+ assertIncludes(result.stderr, 'p/1 depends negatively on q/1', 'stderr');
272
+ assertIncludes(result.stderr, 'q/1 depends negatively on p/1', 'stderr');
273
+ },
274
+ },
275
+ {
276
+ name: '-w prints unstratified negation diagnostics without failing',
277
+ run: () => {
278
+ const input = [
279
+ 'materialize(answer, 1).',
280
+ 'p(a) :- not(q(a)).',
281
+ 'q(a) :- not(p(a)).',
282
+ 'answer(ok).',
283
+ '',
284
+ ].join('\n');
285
+ const result = runCli(['-w', '-'], { input });
286
+ assertEqual(result.status, 0, 'exit status');
287
+ assertEqual(result.stdout, '', 'stdout');
288
+ assertIncludes(result.stderr, 'eyelang warning: unstratified negation\n', 'stderr');
289
+ },
290
+ },
291
+ {
292
+ name: '--warnings stays quiet for stratified negation',
293
+ run: () => {
294
+ const input = 'materialize(answer, 1).\np(a).\nanswer(ok) :- not(q(a)).\n';
295
+ const result = runCli(['--warnings', '-'], { input });
296
+ assertEqual(result.status, 0, 'exit status');
297
+ assertEqual(result.stdout, 'answer(ok).\n', 'stdout');
298
+ assertEqual(result.stderr, '', 'stderr');
299
+ },
300
+ },
301
+ {
302
+ name: 'double dash permits option-shaped file names',
303
+ run: () => {
304
+ const file = path.join(tmp, '-h');
305
+ fs.writeFileSync(file, 'p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n');
306
+ const result = runCli(['--', file]);
307
+ assertEqual(result.status, 0, 'exit status');
308
+ assertEqual(result.stdout, 'q(a, b).\n', 'stdout');
309
+ assertEqual(result.stderr, '', 'stderr');
310
+ },
311
+ },
312
+ ];
313
+ }
314
+
315
+
316
+ function documentationSyncCases() {
317
+ return [
318
+ {
319
+ name: 'language reference builtins match runtime registry',
320
+ run: () => assertArrayEqual(languageReferenceBuiltinNames(), registeredBuiltinNames(), 'builtins'),
321
+ },
322
+ {
323
+ name: 'guide builtin catalog matches runtime registry',
324
+ run: () => {
325
+ assertArrayEqual(guideBuiltinNames(), registeredBuiltinNames(), 'builtins');
326
+ const summary = guideBuiltinSummary();
327
+ const actual = registeredBuiltinSummary();
328
+ assertEqual(summary.entries, actual.entries, 'builtin entry count');
329
+ assertEqual(summary.names, actual.names, 'builtin predicate name count');
330
+ },
331
+ },
332
+ {
333
+ name: 'guide example catalog source and output links match examples directory',
334
+ run: () => assertArrayEqual(guideExampleCatalogIssues(), [], 'guide example catalog'),
335
+ },
336
+ {
337
+ name: 'playground example catalog and relative loaders match examples directory',
338
+ run: () => assertArrayEqual(playgroundExampleIssues(), [], 'playground examples'),
339
+ },
340
+ {
341
+ name: 'playground static page is browser-ready and packaged',
342
+ run: () => assertArrayEqual(playgroundStaticIssues(), [], 'playground static page'),
343
+ },
344
+ {
345
+ name: 'documentation local links and anchors resolve',
346
+ run: () => assertArrayEqual(findBrokenDocLinks(), [], 'broken documentation links'),
347
+ },
348
+ {
349
+ name: 'documentation uses eyelang source style',
350
+ run: () => assertArrayEqual(documentationSourceStyleIssues(), [], 'documentation source style'),
351
+ },
352
+ {
353
+ name: 'documented npm scripts exist in package.json',
354
+ run: () => assertArrayEqual(missingDocumentedPackageScripts(), [], 'missing documented npm scripts'),
355
+ },
356
+ {
357
+ name: 'source-checkout setup docs match package bin',
358
+ run: () => {
359
+ assertEqual(pkg.bin?.eyelang, './bin/eyelang.js', 'package eyelang bin');
360
+ const binPath = path.join(packageRoot, pkg.bin.eyelang);
361
+ const binText = fs.readFileSync(binPath, 'utf8');
362
+ assertEqual(binText.startsWith('#!/usr/bin/env node\n'), true, 'bin shebang');
363
+ assertArrayEqual(misleadingDependencyInstallDocs(), [], 'misleading dependency install docs');
364
+ },
365
+ },
366
+ ];
367
+ }
368
+
369
+ function apiCases() {
370
+ return [
371
+ {
372
+ name: 'public type declarations match runtime exports',
373
+ run: () => assertArrayEqual(declaredValueExportNames(), runtimeExportNames(), 'public value exports'),
374
+ },
375
+ {
376
+ name: 'run materialization through public API without proof by default',
377
+ run: () => {
378
+ const result = run('p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n');
379
+ assertEqual(result.stdout, 'q(a, b).\n', 'stdout');
380
+ },
381
+ },
382
+
383
+ {
384
+ name: 'compound factory canonicalizes zero arity to atoms',
385
+ run: () => {
386
+ const nil = compound('nil', []);
387
+ assertEqual(nil.type, 'atom', 'type');
388
+ assertEqual(nil.name, 'nil', 'name');
389
+ assertEqual(nil.arity, 0, 'arity');
390
+ assertEqual(termToString(nil, new Env(), true), 'nil', 'readback');
391
+ assertEqual(unify(nil, atom('nil'), new Env()), true, 'unifies with atom');
392
+ },
393
+ },
394
+
395
+ {
396
+ name: 'portable hash helpers match standard vectors',
397
+ run: () => {
398
+ assertEqual(hashHex('md5', 'abc'), '900150983cd24fb0d6963f7d28e17f72', 'md5');
399
+ assertEqual(hashHex('sha', 'abc'), 'a9993e364706816aba3e25717850c26c9cd0d89d', 'sha1');
400
+ assertEqual(hashHex('sha256', 'abc'), 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', 'sha256');
401
+ assertEqual(hashHex('sha512', 'abc'), 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'sha512');
402
+ },
403
+ },
404
+
405
+
406
+ {
407
+ name: 'run materialization can enable proof explanations',
408
+ run: () => {
409
+ const result = run('p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n', { proof: true });
410
+ assertIncludes(result.stdout, 'q(a, b).\nwhy(', 'stdout');
411
+ },
412
+ },
413
+
414
+ {
415
+ name: 'run accepts Program instances',
416
+ run: () => {
417
+ const program = Program.parse('p(a, b).\nq(?x, ?y) :- p(?x, ?y).\n');
418
+ const result = run(program);
419
+ assertEqual(result.stdout, 'q(a, b).\n', 'stdout');
420
+ },
421
+ },
422
+ {
423
+ name: 'run keeps recursive materializations independent in one solver',
424
+ run: () => {
425
+ const text = fs.readFileSync(path.join(packageRoot, 'examples', 'alignment-demo.eye'), 'utf8');
426
+ const program = Program.parseSources([{ text, filename: 'alignment-demo.eye' }]);
427
+ const result = run(program);
428
+ assertIncludes(result.stdout, 'broaderTransitive(anpr_passenger_car, ref_car).\n', 'stdout');
429
+ assertIncludes(result.stdout, 'narrowerOrEqualOf(anpr_passenger_car, ref_car).\n', 'stdout');
430
+ },
431
+ },
432
+ {
433
+ name: 'makeProgram creates indexed programs',
434
+ run: () => {
435
+ const program = makeProgram('edge(a, b).\npath(?x, ?y) :- edge(?x, ?y).\n');
436
+ const group = program.findGroup('path', 2);
437
+ assertEqual(Boolean(group), true, 'path/2 group exists');
438
+ assertEqual(group.groupName ?? group.name, 'path', 'group name');
439
+ assertEqual(group.arity, 2, 'group arity');
440
+ },
441
+ },
442
+ {
443
+ name: 'program keeps negation diagnostics lazy by default',
444
+ run: () => {
445
+ const program = Program.parse('p(a).\nq(?x) :- not(p(?x)).\n');
446
+ assertEqual(program._negationAnalysis, null, 'analysis starts lazy');
447
+ assertEqual(program.negationDependencies.length, 1, 'dependency count');
448
+ assertEqual(program._negationAnalysis !== null, true, 'analysis computed on demand');
449
+ },
450
+ },
451
+ {
452
+ name: 'analyzeNegation option computes diagnostics eagerly',
453
+ run: () => {
454
+ const program = Program.parse('p(a).\nq(?x) :- not(p(?x)).\n', { analyzeNegation: true });
455
+ assertEqual(program._negationAnalysis !== null, true, 'analysis computed eagerly');
456
+ assertEqual(program.stratifiedNegation, true, 'stratified negation');
457
+ },
458
+ },
459
+ {
460
+ name: 'program reports stratified negation metadata',
461
+ run: () => {
462
+ const program = Program.parse(`
463
+ materialize(open, 1).
464
+ candidate(a).
465
+ blocked(b).
466
+ closed(?x) :- blocked(?x).
467
+ open(?x) :- candidate(?x), not(closed(?x)).
468
+ `);
469
+ assertEqual(program.isStratifiedNegation(), true, 'stratified negation');
470
+ assertEqual(program.negationStratificationErrors.length, 0, 'stratification errors');
471
+ assertEqual(program.findGroup('closed', 1).negationStratum, 0, 'closed stratum');
472
+ assertEqual(program.findGroup('open', 1).negationStratum, 1, 'open stratum');
473
+ },
474
+ },
475
+ {
476
+ name: 'program detects unstratified negation cycles',
477
+ run: () => {
478
+ const program = Program.parse('p(?x) :- q(?x).\nq(?x) :- not(p(?x)).\n');
479
+ assertEqual(program.isStratifiedNegation(), false, 'unstratified negation');
480
+ assertEqual(program.negationStratificationErrors.length, 1, 'stratification error count');
481
+ assertEqual(program.negationStratificationErrors[0].from, 'q/1', 'error source');
482
+ assertEqual(program.negationStratificationErrors[0].to, 'p/1', 'error target');
483
+ let threw = false;
484
+ try { program.assertStratifiedNegation(); } catch (err) {
485
+ threw = true;
486
+ assertIncludes(err.message, 'unstratified negation', 'error message');
487
+ }
488
+ assertEqual(threw, true, 'assertion throws');
489
+ },
490
+ },
491
+ {
492
+ name: 'strictNegation option rejects unstratified programs',
493
+ run: () => {
494
+ let threw = false;
495
+ try { Program.parse('p(?x) :- not(p(?x)).\n', { strictNegation: true }); } catch (err) {
496
+ threw = true;
497
+ assertIncludes(err.message, 'p/1 depends negatively on p/1', 'error message');
498
+ }
499
+ assertEqual(threw, true, 'strict negation throws');
500
+ },
501
+ },
502
+ {
503
+ name: 'program and solver public classes',
504
+ run: () => {
505
+ const program = Program.parse('p(a).\np(b).\n');
506
+ const solver = new Solver(program);
507
+ const goal = parseGoalText('p(?x)');
508
+ const answers = [...solver.solve([goal], new Env(), 0)].map((env) => termToString(goal, env, true));
509
+ assertEqual(answers.join('\n'), 'p(a)\np(b)', 'answers');
510
+ },
511
+ },
512
+ {
513
+ name: 'solver honors solution limits',
514
+ run: () => {
515
+ const program = Program.parse('p(a).\np(b).\np(c).\n');
516
+ const solver = new Solver(program, { solutionLimit: 2 });
517
+ const goal = parseGoalText('p(?x)');
518
+ const answers = [...solver.solve([goal], new Env(), 0)].map((env) => termToString(goal, env, true));
519
+ assertEqual(answers.join('\n'), 'p(a)\np(b)', 'answers');
520
+ },
521
+ },
522
+ {
523
+ name: 'custom builtin registry can be embedded',
524
+ run: () => {
525
+ const registry = new BuiltinRegistry();
526
+ registry.add('hello', 1, function* ({ goal, env }) {
527
+ const next = env.clone();
528
+ if (unify(goal.args[0], atom('world'), next)) yield next;
529
+ });
530
+ const program = Program.parse('answer(?x) :- hello(?x).\n');
531
+ const solver = new Solver(program, { registry });
532
+ const goal = parseGoalText('answer(?x)');
533
+ const answers = [...solver.solve([goal], new Env(), 0)].map((env) => termToString(goal, env, true));
534
+ assertEqual(answers.join('\n'), 'answer(world)', 'answers');
535
+ },
536
+ },
537
+ {
538
+ name: 'default builtin registry exposes expected metadata',
539
+ run: () => {
540
+ const registry = createDefaultRegistry();
541
+ const between = registry.get('between', 3);
542
+ const append = registry.get('append', 3);
543
+ assertEqual(Boolean(between), true, 'between/3 exists');
544
+ assertEqual(Boolean(append), true, 'append/3 exists');
545
+ assertEqual(between.name, 'between', 'between name');
546
+ assertEqual(append.arity, 3, 'append arity');
547
+ },
548
+ },
549
+ ];
550
+ }
551
+
552
+ function whiteBoxCases() {
553
+ return [
554
+ {
555
+ name: 'unification binds variables in Env',
556
+ run: () => {
557
+ const env = new Env();
558
+ assertEqual(unify(variable('?x'), atom('socrates'), env), true, 'unify result');
559
+ assertEqual(termToString(variable('?x'), env, true), 'socrates', 'binding');
560
+ },
561
+ },
562
+ {
563
+ name: 'copyResolved and termIsGround follow bindings',
564
+ run: () => {
565
+ const env = new Env();
566
+ const term = compound('p', [variable('?x'), atom('b')]);
567
+ assertEqual(termIsGround(term, env), false, 'not ground before binding');
568
+ assertEqual(unify(variable('?x'), atom('a'), env), true, 'bind ?x');
569
+ const resolved = copyResolved(term, env);
570
+ assertEqual(termToString(resolved, new Env(), true), 'p(a, b)', 'resolved term');
571
+ assertEqual(termIsGround(resolved), true, 'ground after copy');
572
+ },
573
+ },
574
+
575
+ {
576
+ name: 'parser rejects non-Prolog unquoted atom spelling',
577
+ run: () => {
578
+ let threw = false;
579
+ try { parseProgramText('value(a-b, ok).\n'); } catch (_) { threw = true; }
580
+ assertEqual(threw, true, 'a-b must be quoted');
581
+ },
582
+ },
583
+ {
584
+ name: 'parser rejects zero-arity compound syntax',
585
+ run: () => {
586
+ let threw = false;
587
+ try { parseProgramText('value(nil(), ok).\n'); } catch (_) { threw = true; }
588
+ assertEqual(threw, true, 'zero-arity compound rejection');
589
+ },
590
+ },
591
+ {
592
+ name: 'parser preserves list syntax readback',
593
+ run: () => {
594
+ const goal = parseGoalText('member(?x, [a, b])');
595
+ assertEqual(termToString(goal, new Env(), true), 'member(?x, [a, b])', 'goal');
596
+ },
597
+ },
598
+ {
599
+ name: 'parser accepts question-mark variables',
600
+ run: () => {
601
+ const goal = parseGoalText('member(?x, [a, b])');
602
+ assertEqual(termToString(goal, new Env(), true), 'member(?x, [a, b])', 'goal');
603
+ },
604
+ },
605
+ {
606
+ name: 'parser treats question-mark underscore as anonymous',
607
+ run: () => {
608
+ const clauses = parseProgramText('p(?_, ?_).\n');
609
+ const left = clauses[0].head.args[0].name;
610
+ const right = clauses[0].head.args[1].name;
611
+ assertEqual(left.startsWith('__anon'), true, 'left anonymous');
612
+ assertEqual(right.startsWith('__anon'), true, 'right anonymous');
613
+ assertEqual(left === right, false, 'fresh anonymous variables');
614
+ },
615
+ },
616
+ {
617
+ name: 'parser rejects old uppercase variable spelling',
618
+ run: () => {
619
+ let threw = false;
620
+ try { parseProgramText('p(X).\n'); } catch (_) { threw = true; }
621
+ assertEqual(threw, true, 'uppercase variable syntax rejected');
622
+ },
623
+ },
624
+ {
625
+ name: 'parser rejects bare underscore variable spelling',
626
+ run: () => {
627
+ let threw = false;
628
+ try { parseProgramText('p(_).\n'); } catch (_) { threw = true; }
629
+ assertEqual(threw, true, 'bare underscore syntax rejected');
630
+ },
631
+ },
632
+ {
633
+ name: 'parser rejects unquoted dotted atoms to stay ISO-compatible',
634
+ run: () => {
635
+ let threw = false;
636
+ try { parseProgramText('p(web(be.ugent, josd)).\n'); } catch (_) { threw = true; }
637
+ assertEqual(threw, true, 'unquoted dotted atoms must be quoted');
638
+ },
639
+ },
640
+ {
641
+ name: 'parser preserves quoted dotted atoms for web-style terms',
642
+ run: () => {
643
+ const clauses = parseProgramText("p(web('be.ugent', josd), 'org.schema').\n");
644
+ assertEqual(termToString(clauses[0].head, new Env(), true), "p(web('be.ugent', josd), 'org.schema')", 'head');
645
+ },
646
+ },
647
+ {
648
+ name: 'parser accepts angle-bracket absolute IRI atoms',
649
+ run: () => {
650
+ const clauses = parseProgramText('p(<https://example.org/alice>, <urn:example:bob>).\n');
651
+ assertEqual(termToString(clauses[0].head, new Env(), true), 'p(<https://example.org/alice>, <urn:example:bob>)', 'head');
652
+ },
653
+ },
654
+ {
655
+ name: 'readback prints absolute IRI atoms with angle brackets',
656
+ run: () => {
657
+ const clauses = parseProgramText("p('https://example.org/alice').\n");
658
+ assertEqual(termToString(clauses[0].head, new Env(), true), 'p(<https://example.org/alice>)', 'head');
659
+ },
660
+ },
661
+ {
662
+ name: 'angle IRI syntax does not steal graphic atom syntax',
663
+ run: () => {
664
+ const clauses = parseProgramText('p(<=>).\n');
665
+ assertEqual(termToString(clauses[0].head, new Env(), true), 'p(<=>)', 'head');
666
+ },
667
+ },
668
+ {
669
+ name: 'list construction round-trips through properListItems',
670
+ run: () => {
671
+ const list = listFromItems([atom('a'), numberTerm(2), stringTerm('c')]);
672
+ const items = properListItems(list, new Env());
673
+ assertEqual(items.length, 3, 'length');
674
+ assertEqual(termToString(list, new Env(), true), '[a, 2, "c"]', 'list text');
675
+ },
676
+ },
677
+ {
678
+ name: 'variantTerms recognizes alpha-equivalent goals',
679
+ run: () => {
680
+ const left = parseGoalText('edge(?x, ?y)');
681
+ const right = parseGoalText('edge(?a, ?b)');
682
+ const nonVariant = parseGoalText('edge(?a, ?a)');
683
+ assertEqual(variantTerms(left, new Env(), right, new Env()), true, 'variant');
684
+ assertEqual(variantTerms(left, new Env(), nonVariant, new Env()), false, 'non-variant');
685
+ },
686
+ },
687
+ {
688
+ name: 'flattenConjunction preserves left-to-right order',
689
+ run: () => {
690
+ const goal = parseGoalText('(a, b, c)');
691
+ const parts = flattenConjunction(goal).map((part) => termToString(part, new Env(), true));
692
+ assertEqual(parts.join(' | '), 'a | b | c', 'order');
693
+ },
694
+ },
695
+ {
696
+ name: 'parseProgramText returns clause objects',
697
+ run: () => {
698
+ const clauses = parseProgramText('p(a).\nq(?x) :- p(?x).\n');
699
+ assertEqual(clauses.length, 2, 'clause count');
700
+ assertEqual(termToString(clauses[1].head, new Env(), true), 'q(?x)', 'rule head');
701
+ assertEqual(clauses[1].body.length, 1, 'body length');
702
+ },
703
+ },
704
+ {
705
+ name: 'clause candidate selection uses scalar indexes with fallback',
706
+ run: () => {
707
+ const program = Program.parse('edge(a, b).\nedge(c, d).\nedge(?x, z).\n');
708
+ const group = program.findGroup('edge', 2);
709
+ const goal = parseGoalText('edge(a, ?y)');
710
+ const candidates = selectClauseCandidates(group, goal, new Env());
711
+ assertEqual(candidates.primary.length, 1, 'primary bucket length');
712
+ assertEqual(candidates.fallback.length, 1, 'fallback length');
713
+ assertEqual(termToString(candidates.primary[0].head, new Env(), true), 'edge(a, b)', 'primary head');
714
+ },
715
+ },
716
+ {
717
+ name: 'table declaration marks predicate group tabled',
718
+ run: () => {
719
+ const program = Program.parse('table(path, 2).\nedge(a, b).\npath(?x, ?y) :- edge(?x, ?y).\n');
720
+ const group = program.findGroup('path', 2);
721
+ assertEqual(Boolean(group), true, 'path/2 group exists');
722
+ assertEqual(group.tabled, true, 'path/2 tabled through table/2');
723
+ },
724
+ },
725
+ {
726
+ name: 'memoize fact does not table predicates',
727
+ run: () => {
728
+ const program = Program.parse('memoize(path, 2).\nedge(a, b).\npath(?x, ?y) :- edge(?x, ?y).\n');
729
+ const group = program.findGroup('path', 2);
730
+ assertEqual(Boolean(group), true, 'path/2 group exists');
731
+ assertEqual(group.tabled, false, 'memoize/2 is not a table declaration');
732
+ },
733
+ },
734
+ {
735
+ name: 'mode and determinism declarations annotate predicate groups',
736
+ run: () => {
737
+ const program = Program.parse('mode(path, 2, [in, out]).\ndet(path, 2).\nedge(a, b).\npath(?x, ?y) :- edge(?x, ?y).\n');
738
+ const group = program.findGroup('path', 2);
739
+ assertEqual(Boolean(group), true, 'path/2 group exists');
740
+ assertEqual(group.mode.join(','), 'in,out', 'path/2 mode');
741
+ assertEqual(group.determinism, 'det', 'path/2 determinism');
742
+ },
743
+ },
744
+ {
745
+ name: 'semidet declaration annotates predicate groups',
746
+ run: () => {
747
+ const program = Program.parse('semidet(edge, 2).\nedge(a, b).\n');
748
+ const group = program.findGroup('edge', 2);
749
+ assertEqual(Boolean(group), true, 'edge/2 group exists');
750
+ assertEqual(group.determinism, 'semidet', 'edge/2 determinism');
751
+ },
752
+ },
753
+ {
754
+ name: 'challenging examples keep dynamic-programming predicates tabled',
755
+ run: () => {
756
+ const checks = [
757
+ ['binomial-vandermonde.eye', 'choose_step', 5, true],
758
+ ['catalan-convolution.eye', 'catalan', 2, false],
759
+ ['chart-parser.eye', 'span', 4, true],
760
+ ['continued-fraction-sqrt2.eye', 'conv', 3, true],
761
+ ['critical-path-schedule.eye', 'earliest_start', 2, false],
762
+ ['critical-path-schedule.eye', 'finish_time', 2, false],
763
+ ['integer-partitions.eye', 'partitions', 3, true],
764
+ ['matrix-chain-order.eye', 'cost', 3, false],
765
+ ['modular-exponentiation.eye', 'pow_mod', 4, true],
766
+ ['pell-equation.eye', 'pell', 3, true],
767
+ ['stirling-bell-numbers.eye', 'stirling2', 3, true],
768
+ ['totient-summatory.eye', 'gcd', 3, true],
769
+ ['totient-summatory.eye', 'totient', 2, false],
770
+ ['weighted-interval-scheduling.eye', 'best_from', 2, true],
771
+ ];
772
+ for (const [filename, name, arity, recursive] of checks) {
773
+ const text = fs.readFileSync(path.join(packageRoot, 'examples', filename), 'utf8');
774
+ const program = Program.parseSources([{ text, filename }]);
775
+ const group = program.findGroup(name, arity);
776
+ assertEqual(Boolean(group), true, `${filename} ${name}/${arity} group exists`);
777
+ assertEqual(group.tabled, true, `${filename} ${name}/${arity} tabled`);
778
+ assertEqual(group.recursive, recursive, `${filename} ${name}/${arity} recursive`);
779
+ }
780
+ },
781
+ },
782
+ {
783
+ name: 'n-queens example keeps diagonal checks tabled',
784
+ run: () => {
785
+ const text = fs.readFileSync(path.join(packageRoot, 'examples', 'n-queens-8.eye'), 'utf8');
786
+ const program = Program.parseSources([{ text, filename: 'n-queens-8.eye' }]);
787
+ const group = program.findGroup('no_diagonal_attack', 3);
788
+ assertEqual(Boolean(group), true, 'no_diagonal_attack/3 group exists');
789
+ assertEqual(group.tabled, true, 'no_diagonal_attack/3 tabled');
790
+ assertEqual(group.recursive, true, 'no_diagonal_attack/3 recursive');
791
+ },
792
+ },
793
+ {
794
+ name: 'collatz example keeps recursive trajectory predicate tabled',
795
+ run: () => {
796
+ const text = fs.readFileSync(path.join(packageRoot, 'examples', 'collatz-1000.eye'), 'utf8');
797
+ const program = Program.parseSources([{ text, filename: 'collatz-1000.eye' }]);
798
+ const group = program.findGroup('collatz', 2);
799
+ assertEqual(Boolean(group), true, 'collatz/2 group exists');
800
+ assertEqual(group.tabled, true, 'collatz/2 tabled');
801
+ assertEqual(group.recursive, true, 'collatz/2 recursive');
802
+ },
803
+ },
804
+ {
805
+ name: 'collatz example remains stack-safe for browser-sized stacks',
806
+ run: () => {
807
+ // Use a deliberately tiny stack to catch browser-worker recursion regressions.
808
+ const result = spawnSync(process.execPath, ['--stack-size=100', bin, 'examples/collatz-1000.eye'], {
809
+ cwd: packageRoot,
810
+ encoding: 'utf8',
811
+ });
812
+ assertEqual(result.status, 0, `exit status${result.stderr ? `\nstderr: ${result.stderr}` : ''}`);
813
+ assertEqual(result.stderr, '', 'stderr');
814
+ assertIncludes(result.stdout, 'collatzTrajectory(1000, [1000, 500, 250, 125', 'stdout');
815
+ assertIncludes(result.stdout, 'collatzTrajectory(1, [1]).\n', 'stdout');
816
+ },
817
+ },
818
+ ];
819
+ }
820
+
821
+ function runSection(reporter, name, cases) {
822
+ reporter.section(name);
823
+ for (const testCase of cases) reporter.test(testCase.name, testCase.run);
824
+ reporter.sectionTotal(sectionLabel(name));
825
+ }
826
+
827
+ function sectionLabel(name) {
828
+ if (name === 'Documentation sync') return 'documentation sync';
829
+ if (name === 'API') return 'API';
830
+ if (name === 'White-box') return 'white-box';
831
+ return name.toLowerCase();
832
+ }
833
+
834
+ function runWhy({ program, goalText, expected }) {
835
+ const programFile = path.join(tmp, `${++tmpCounter}.eye`);
836
+ fs.writeFileSync(programFile, program);
837
+ const goal = parseGoalText(goalText);
838
+ fs.appendFileSync(programFile, `\nmaterialize(${goal.name}, ${goal.arity}).\n`);
839
+ const result = runCli(['--proof', programFile]);
840
+ assertEqual(result.status, 0, 'exit status');
841
+ assertEqual(result.stderr, '', 'stderr');
842
+ const expectedText = expected.replaceAll('__FILE__', path.basename(programFile));
843
+ assertEqual(result.stdout, expectedText, 'stdout');
844
+
845
+ Program.parse(result.stdout);
846
+ assertIncludes(result.stdout, ' proof(\n', 'stdout');
847
+ assertIncludes(result.stdout, ' by(rule("', 'stdout');
848
+ assertIncludes(result.stdout, ', clause(', 'stdout');
849
+ assertNotIncludes(result.stdout, 'source(head(', 'stdout');
850
+ assertIncludes(result.stdout, '\n).\n\n', 'stdout');
851
+ }
852
+
853
+ function runWhyLoose({ program, goalText }) {
854
+ const programFile = path.join(tmp, `${++tmpCounter}.eye`);
855
+ fs.writeFileSync(programFile, program);
856
+ const goal = parseGoalText(goalText);
857
+ fs.appendFileSync(programFile, `\nmaterialize(${goal.name}, ${goal.arity}).\n`);
858
+ const result = runCli(['--proof', programFile]);
859
+ assertEqual(result.status, 0, 'exit status');
860
+ assertEqual(result.stderr, '', 'stderr');
861
+ Program.parse(result.stdout);
862
+ assertIncludes(result.stdout, '\n).\n\n', 'stdout');
863
+ return result;
864
+ }
865
+
866
+ function listExampleNames() {
867
+ return fs.readdirSync(path.join(packageRoot, 'examples'))
868
+ .filter((name) => name.endsWith('.eye'))
869
+ .map((name) => name.slice(0, -4))
870
+ .sort();
871
+ }
872
+
873
+ function guideExampleCatalogIssues() {
874
+ const issues = [];
875
+ const expected = listExampleNames();
876
+ const guide = fs.readFileSync(path.join(packageRoot, 'docs', 'guide.md'), 'utf8');
877
+ const section = between(guide, '## Example catalog', '## Golden outputs, tests, and conformance');
878
+ const rows = [...section.matchAll(/^\| \[`([A-Za-z0-9_-]+)\.eye`\]\(\.\.\/examples\/\1\.eye\) \|[^|]+\| \[`output\/\1\.eye`\]\(\.\.\/examples\/output\/\1\.eye\) \|$/gm)]
879
+ .map((match) => match[1]);
880
+ const sourceNames = [...section.matchAll(/\.\.\/examples\/([A-Za-z0-9_-]+)\.eye/g)].map((match) => match[1]).sort();
881
+ const outputNames = [...section.matchAll(/\.\.\/examples\/output\/([A-Za-z0-9_-]+)\.eye/g)].map((match) => match[1]).sort();
882
+ if (rows.length !== expected.length) issues.push(`expected ${expected.length} complete example rows, found ${rows.length}`);
883
+ issues.push(...arrayDiffMessages(rows.sort(), expected, 'complete example rows'));
884
+ issues.push(...arrayDiffMessages(sourceNames, expected, 'source links'));
885
+ issues.push(...arrayDiffMessages(outputNames, expected, 'output links'));
886
+ for (const name of expected) {
887
+ const outputPath = path.join(packageRoot, 'examples', 'output', `${name}.eye`);
888
+ if (!fs.existsSync(outputPath)) issues.push(`missing examples/output/${name}.eye`);
889
+ }
890
+ return issues.sort();
891
+ }
892
+
893
+ function playgroundExampleIssues() {
894
+ const issues = [];
895
+ const expected = listExampleNames();
896
+ const html = fs.readFileSync(path.join(packageRoot, 'playground.html'), 'utf8');
897
+ const match = html.match(/const EXAMPLES = (\[[\s\S]*?\]);/);
898
+ if (match == null) return ['playground EXAMPLES array not found'];
899
+ const examples = JSON.parse(match[1]).sort();
900
+ issues.push(...arrayDiffMessages(examples, expected, 'playground EXAMPLES'));
901
+ if (!html.includes('new URL(`./examples/${name}.eye`, location.href)')) {
902
+ issues.push('playground must load selected examples from relative ./examples/*.eye URLs');
903
+ }
904
+ if (!html.includes("fetch(exampleUrl, { cache: 'no-store' })")) {
905
+ issues.push('playground must fetch selected example source from its relative URL');
906
+ }
907
+ return issues.sort();
908
+ }
909
+
910
+ function playgroundStaticIssues() {
911
+ const issues = [];
912
+ const playgroundPath = path.join(packageRoot, 'playground.html');
913
+ const html = fs.readFileSync(playgroundPath, 'utf8');
914
+ const readme = fs.readFileSync(path.join(packageRoot, 'README.md'), 'utf8');
915
+ if (!pkg.files?.includes('playground.html')) issues.push('package files must include playground.html');
916
+ if (!readme.includes('[Playground](https://eyereasoner.github.io/eyelang/playground)')) issues.push('README must link to the GitHub Pages playground URL');
917
+ if (!html.includes('<meta name="viewport" content="width=device-width, initial-scale=1">')) issues.push('missing mobile viewport meta');
918
+ if (!html.includes('main {') || !html.includes('display: block;')) {
919
+ issues.push('playground must use a simple vertical layout');
920
+ }
921
+ if (!html.includes('@media (max-width: 560px)') || !html.includes('button,') || !html.includes('width: 100%')) {
922
+ issues.push('playground must make controls usable at phone widths');
923
+ }
924
+ if (!html.includes('<summary id="advanced-heading">⚙ Advanced configuration</summary>')) {
925
+ issues.push('playground must keep URL/proof controls inside advanced configuration');
926
+ }
927
+ if (!html.includes('id="load-background"') || !html.includes('backgroundSource') || !html.includes('combinedSource()')) {
928
+ issues.push('playground must support loading URL content as background knowledge');
929
+ }
930
+ if (!html.includes('HIGHLIGHT_LIMIT') || !html.includes('text.length > HIGHLIGHT_LIMIT')) {
931
+ issues.push('playground must avoid full syntax coloring for very large examples');
932
+ }
933
+ if (!html.includes('<script type="module">')) issues.push('playground script must be an ES module');
934
+ if (!html.includes("new URL('./src/index.js', location.href)")) issues.push('playground must import the public browser API');
935
+ if (!html.includes('class="editor"') || !html.includes('id="highlight"') || !html.includes('id="source"')) {
936
+ issues.push('playground must include layered syntax-colored editor');
937
+ }
938
+ if (!html.includes('--editor-bg: #ffffff') || !html.includes('background: var(--editor-bg)')) {
939
+ issues.push('playground editor must use a light editor background');
940
+ }
941
+ if (!html.includes('id="error-line-marker"') || !html.includes('extractParseErrorLine') || !html.includes('markSyntaxErrorLine') || !html.includes('--editor-error-line')) {
942
+ issues.push('playground must highlight syntax-error lines in the editor');
943
+ }
944
+ if (!html.includes('id="line-numbers"') || !html.includes('updateLineNumbers') || !html.includes('lineNumbersInner.style.transform') || !html.includes('--line-number-bg')) {
945
+ issues.push('playground editor must include synced line numbers');
946
+ }
947
+ if (!html.includes('MAX_SHARE_URL_LENGTH') || !html.includes('buildReferenceShareLink') || !html.includes("params.set('example'") || !html.includes("params.set('url'")) {
948
+ issues.push('playground share links must avoid embedding large example or URL-loaded sources');
949
+ }
950
+ if (!html.includes('id="create-gist"') || !html.includes('createGistShare') || !html.includes('GIST_STATE_FILENAME') || !html.includes("fetch('https://api.github.com/gists'")) {
951
+ issues.push('playground must support Gist-backed sharing for large programs');
952
+ }
953
+ if (!html.includes('await createGistShare({') || html.includes('Use “Create Gist share” instead')) {
954
+ issues.push('playground Copy share link must automatically fall back to Gist sharing for large programs');
955
+ }
956
+ if (!html.includes("params.has('state-url')") || !html.includes('#state-url=')) {
957
+ issues.push('playground must restore state from raw Gist state URLs');
958
+ }
959
+ if (!html.includes('id="example-search"') || !html.includes('id="examples"')) issues.push('playground must include searchable examples');
960
+ const scriptMatch = html.match(new RegExp('<script type="module">\\n([\\s\\S]*?)\\n <\\/script>'));
961
+ if (scriptMatch == null) {
962
+ issues.push('module script not found');
963
+ } else {
964
+ const scriptFile = path.join(tmp, 'playground-script.mjs');
965
+ fs.writeFileSync(scriptFile, scriptMatch[1]);
966
+ const result = spawnSync(process.execPath, ['--check', scriptFile], { encoding: 'utf8' });
967
+ if (result.status !== 0) issues.push(`playground module syntax check failed: ${result.stderr.trim()}`);
968
+ }
969
+ return issues.sort();
970
+ }
971
+
972
+ function registeredBuiltinNames() {
973
+ return [...createDefaultRegistry().defs.keys()].sort();
974
+ }
975
+
976
+ function registeredBuiltinSummary() {
977
+ const names = registeredBuiltinNames();
978
+ return {
979
+ entries: names.length,
980
+ names: new Set(names.map((name) => name.split('/')[0])).size,
981
+ };
982
+ }
983
+
984
+ function guideBuiltinNames() {
985
+ const guide = fs.readFileSync(path.join(packageRoot, 'docs', 'guide.md'), 'utf8');
986
+ return documentedBuiltinNames(between(guide, '### Builtins', '## Aggregation helpers'));
987
+ }
988
+
989
+ function guideBuiltinSummary() {
990
+ const guide = fs.readFileSync(path.join(packageRoot, 'docs', 'guide.md'), 'utf8');
991
+ const section = between(guide, '### Builtins', '## Aggregation helpers');
992
+ const match = section.match(/currently registers (\d+) name\/arity entries across (\d+) predicate names/);
993
+ if (match == null) throw new Error('guide builtin summary not found');
994
+ return { entries: Number(match[1]), names: Number(match[2]) };
995
+ }
996
+
997
+ function languageReferenceBuiltinNames() {
998
+ const reference = fs.readFileSync(path.join(packageRoot, 'docs', 'language-reference.md'), 'utf8');
999
+ return documentedBuiltinNames(between(reference, '## 9. Standard built-in predicates', '## 10. Implementation-specific built-ins'));
1000
+ }
1001
+
1002
+ function documentedBuiltinNames(section) {
1003
+ const names = [];
1004
+ for (const line of section.split('\n')) {
1005
+ if (!line.trim().startsWith('|') || !line.includes('`')) continue;
1006
+ for (const match of line.matchAll(/`([A-Za-z_][A-Za-z0-9_]*)\(([^`)]*)\)`/g)) {
1007
+ const arity = match[2].trim() === '' ? 0 : match[2].split(',').length;
1008
+ names.push(`${match[1]}/${arity}`);
1009
+ }
1010
+ for (const match of line.matchAll(/`([A-Za-z_][A-Za-z0-9_]*)\/(\d+)`/g)) {
1011
+ names.push(`${match[1]}/${match[2]}`);
1012
+ }
1013
+ }
1014
+ return [...new Set(names)].sort();
1015
+ }
1016
+
1017
+ function runtimeExportNames() {
1018
+ return Object.keys(publicApi).sort();
1019
+ }
1020
+
1021
+ function declaredValueExportNames() {
1022
+ const dts = fs.readFileSync(path.join(packageRoot, 'index.d.ts'), 'utf8');
1023
+ return [...dts.matchAll(/^export\s+(?:declare\s+)?(?:class|function|const)\s+([A-Za-z_][A-Za-z0-9_]*)/gm)]
1024
+ .map((match) => match[1])
1025
+ .filter((name, index, names) => names.indexOf(name) === index)
1026
+ .sort();
1027
+ }
1028
+
1029
+ function missingDocumentedPackageScripts() {
1030
+ const docs = documentationFiles();
1031
+ const missing = [];
1032
+ const nativeCommands = new Set(['exec', 'install', 'link']);
1033
+ for (const file of docs) {
1034
+ const text = fs.readFileSync(file, 'utf8');
1035
+ for (const line of text.split('\n')) {
1036
+ const trimmed = line.trim();
1037
+ const commandTexts = [];
1038
+ if (trimmed.startsWith('npm ')) commandTexts.push(trimmed);
1039
+ for (const match of line.matchAll(/`([^`]*\bnpm\s+[^`]*)`/g)) commandTexts.push(match[1].trim());
1040
+ for (const commandText of commandTexts) {
1041
+ const match = commandText.match(/^npm\s+(?:run\s+)?([A-Za-z0-9:_-]+)/);
1042
+ if (match == null) continue;
1043
+ const command = match[1];
1044
+ if (nativeCommands.has(command)) continue;
1045
+ const script = command === 'test' ? 'test' : command;
1046
+ if (!pkg.scripts?.[script]) missing.push(`${path.relative(packageRoot, file)}: npm ${command === 'test' ? 'test' : `run ${script}`}`);
1047
+ }
1048
+ }
1049
+ }
1050
+ return [...new Set(missing)].sort();
1051
+ }
1052
+
1053
+ function misleadingDependencyInstallDocs() {
1054
+ const misleading = [];
1055
+ for (const file of documentationFiles()) {
1056
+ const text = fs.readFileSync(file, 'utf8');
1057
+ if (text.includes('Install dependencies')) misleading.push(`${path.relative(packageRoot, file)}: Install dependencies`);
1058
+ if (text.includes('npm install\n```') || text.includes('npm install\r\n```')) {
1059
+ misleading.push(`${path.relative(packageRoot, file)}: bare npm install setup block`);
1060
+ }
1061
+ }
1062
+ return [...new Set(misleading)].sort();
1063
+ }
1064
+
1065
+ function documentationSourceStyleIssues() {
1066
+ const issues = [];
1067
+ const docsRoot = path.join(packageRoot, 'docs');
1068
+ const docs = [
1069
+ path.join(docsRoot, 'guide.md'),
1070
+ path.join(docsRoot, 'language-reference.md'),
1071
+ ];
1072
+ for (const file of docs) {
1073
+ const text = fs.readFileSync(file, 'utf8');
1074
+ if (text.includes('```prolog')) {
1075
+ issues.push(`${path.relative(packageRoot, file)}: use eyelang code fences instead of prolog fences`);
1076
+ }
1077
+ }
1078
+
1079
+ const reference = fs.readFileSync(path.join(docsRoot, 'language-reference.md'), 'utf8');
1080
+ const builtins = between(reference, '## 9. Standard built-in predicates', '## 10. Implementation-specific built-ins');
1081
+ const staleMetaVariables = /`[^`]*(?<!\?)(?:\b(?:A|B|C|D|N|T|Low|High|Start|Needle|Context|Search|Generator|Test|Goal)\b)[^`]*`/;
1082
+ for (const [index, line] of builtins.split('\n').entries()) {
1083
+ if (!line.trim().startsWith('|')) continue;
1084
+ if (line.includes('EYELANG_LOCAL_TIME=')) continue;
1085
+ if (staleMetaVariables.test(line)) {
1086
+ issues.push(`docs/language-reference.md section 9 line ${index + 1}: stale Prolog-style metavariable in built-in description: ${line.trim()}`);
1087
+ }
1088
+ }
1089
+ return issues.sort();
1090
+ }
1091
+
1092
+ function findBrokenDocLinks() {
1093
+ const broken = [];
1094
+ const anchorsByFile = new Map();
1095
+ for (const file of documentationFiles()) {
1096
+ const text = fs.readFileSync(file, 'utf8');
1097
+ for (const target of markdownLinkTargets(text)) {
1098
+ if (/^(?:https?:|mailto:)/i.test(target)) continue;
1099
+ const [targetPathRaw, fragmentRaw] = target.split('#');
1100
+ const targetPath = targetPathRaw === '' ? file : path.resolve(path.dirname(file), decodeURI(targetPathRaw));
1101
+ const display = `${path.relative(packageRoot, file)} -> ${target}`;
1102
+ if (!fs.existsSync(targetPath)) {
1103
+ broken.push(`${display} (missing target)`);
1104
+ continue;
1105
+ }
1106
+ if (fragmentRaw != null && fragmentRaw !== '') {
1107
+ const anchors = anchorsByFile.get(targetPath) ?? markdownAnchors(targetPath);
1108
+ anchorsByFile.set(targetPath, anchors);
1109
+ if (!anchors.has(fragmentRaw)) broken.push(`${display} (missing heading #${fragmentRaw})`);
1110
+ }
1111
+ }
1112
+ }
1113
+ return broken.sort();
1114
+ }
1115
+
1116
+ function documentationFiles() {
1117
+ return [
1118
+ path.join(packageRoot, 'README.md'),
1119
+ path.join(packageRoot, 'docs', 'guide.md'),
1120
+ path.join(packageRoot, 'docs', 'language-reference.md'),
1121
+ ];
1122
+ }
1123
+
1124
+ function markdownLinkTargets(text) {
1125
+ return [...text.matchAll(/!?\[[^\]\n]*\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g)].map((match) => match[1]);
1126
+ }
1127
+
1128
+ function markdownAnchors(file) {
1129
+ if (!file.endsWith('.md')) return new Set();
1130
+ const text = fs.readFileSync(file, 'utf8');
1131
+ const anchors = new Set();
1132
+ const counts = new Map();
1133
+ for (const match of text.matchAll(/^#{1,6}\s+(.+)$/gm)) {
1134
+ const base = githubSlug(match[1]);
1135
+ const count = counts.get(base) ?? 0;
1136
+ counts.set(base, count + 1);
1137
+ anchors.add(count === 0 ? base : `${base}-${count}`);
1138
+ }
1139
+ return anchors;
1140
+ }
1141
+
1142
+ function githubSlug(heading) {
1143
+ return heading
1144
+ .replace(/`([^`]*)`/g, '$1')
1145
+ .replace(/<[^>]+>/g, '')
1146
+ .trim()
1147
+ .toLowerCase()
1148
+ .replace(/[^\p{Letter}\p{Number}\s-]/gu, '')
1149
+ .trim()
1150
+ .replace(/\s+/g, '-');
1151
+ }
1152
+
1153
+ function between(text, startMarker, endMarker) {
1154
+ const start = text.indexOf(startMarker);
1155
+ if (start === -1) throw new Error(`${startMarker} not found`);
1156
+ const contentStart = start + startMarker.length;
1157
+ const end = text.indexOf(endMarker, contentStart);
1158
+ if (end === -1) throw new Error(`${endMarker} not found`);
1159
+ return text.slice(contentStart, end);
1160
+ }
1161
+
1162
+ function runCli(args, options = {}) {
1163
+ return spawnSync(process.execPath, [bin, ...args], {
1164
+ cwd: packageRoot,
1165
+ encoding: 'utf8',
1166
+ env: options.env ? { ...process.env, ...options.env } : process.env,
1167
+ input: options.input ?? undefined,
1168
+ });
1169
+ }
1170
+
1171
+ function assertEqual(actual, expected, label) {
1172
+ if (actual !== expected) throw new Error(`${label} mismatch\nexpected: ${format(expected)}\nactual: ${format(actual)}`);
1173
+ }
1174
+
1175
+ function assertIncludes(actual, expected, label) {
1176
+ if (!actual.includes(expected)) throw new Error(`${label} did not include ${format(expected)}\nactual: ${format(actual)}`);
1177
+ }
1178
+
1179
+ function assertNotIncludes(actual, expected, label) {
1180
+ if (String(actual).includes(expected)) throw new Error(`${label} unexpectedly included ${format(expected)}\nactual: ${format(actual)}`);
1181
+ }
1182
+
1183
+ function arrayDiffMessages(actual, expected, label) {
1184
+ const messages = [];
1185
+ const actualSet = new Set(actual);
1186
+ const expectedSet = new Set(expected);
1187
+ for (const item of expected) if (!actualSet.has(item)) messages.push(`${label} missing ${item}`);
1188
+ for (const item of actual) if (!expectedSet.has(item)) messages.push(`${label} has unexpected ${item}`);
1189
+ if (new Set(actual).size !== actual.length) messages.push(`${label} has duplicate entries`);
1190
+ return messages;
1191
+ }
1192
+
1193
+ function assertArrayEqual(actual, expected, label) {
1194
+ const actualText = actual.join('\n');
1195
+ const expectedText = expected.join('\n');
1196
+ if (actualText !== expectedText) {
1197
+ const onlyActual = actual.filter((item) => !expected.includes(item));
1198
+ const onlyExpected = expected.filter((item) => !actual.includes(item));
1199
+ throw new Error(`${label} mismatch\nonly actual: ${format(onlyActual)}\nonly expected: ${format(onlyExpected)}`);
1200
+ }
1201
+ }
1202
+
1203
+ function format(value) {
1204
+ return typeof value === 'string' ? JSON.stringify(value) : String(value);
1205
+ }
1206
+
1207
+ if (isMainModule(import.meta.url)) {
1208
+ const reporter = new TestReporter();
1209
+ try {
1210
+ runRegression(reporter);
1211
+ reporter.totalLine();
1212
+ } catch (_) {
1213
+ process.exit(1);
1214
+ }
1215
+ }