eyelang 1.7.8 → 1.7.9
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.
- package/README.md +1 -1
- package/conformance-report.md +3 -3
- package/docs/guide.md +2 -1
- package/docs/language-reference.md +12 -0
- package/examples/existential-rule.eye +8 -15
- package/examples/herbrand-witnesses.eye +31 -0
- package/examples/output/existential-rule.eye +2 -2
- package/examples/output/herbrand-witnesses.eye +7 -0
- package/examples/proof/existential-rule.eye +10 -18
- package/package.json +1 -1
- package/playground.html +1 -0
- package/src/builtins/terms.js +1 -0
- package/test/conformance/cases/terms/herbrand_witness_different_inputs_distinct.eye +2 -0
- package/test/conformance/cases/terms/herbrand_witness_one_input.eye +5 -0
- package/test/conformance/cases/terms/herbrand_witness_same_inputs_same_term.eye +2 -0
- package/test/conformance/cases/terms/herbrand_witness_two_inputs.eye +5 -0
- package/test/conformance/expected/terms/herbrand_witness_different_inputs_distinct.eye +1 -0
- package/test/conformance/expected/terms/herbrand_witness_one_input.eye +2 -0
- package/test/conformance/expected/terms/herbrand_witness_same_inputs_same_term.eye +1 -0
- package/test/conformance/expected/terms/herbrand_witness_two_inputs.eye +2 -0
- package/test/conformance/expected-proofs/proofs/herbrand_witness.eye +16 -0
- package/test/conformance/proofs/proofs/herbrand_witness.eye +3 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://doi.org/10.5281/zenodo.20761726)
|
|
5
5
|
|
|
6
6
|
Eyelang is a small logic programming language for rules, goals, answers, and proofs.
|
|
7
|
-
Its source syntax is Prolog-like Horn-clause syntax with deliberate eyelang choices, including `?x` variables for N3/SPARQL-style readability, explicit `table(path, 2).` declarations for tabled predicates, advisory `mode/3` declarations for host tooling, and stratified-negation diagnostics for portable `not/1` usage.
|
|
7
|
+
Its source syntax is Prolog-like Horn-clause syntax with deliberate eyelang choices, including `?x` variables for N3/SPARQL-style readability, explicit `table(path, 2).` declarations for tabled predicates, advisory `mode/3` declarations for host tooling, explicit Herbrand witness terms for executable existential-style consequences, and stratified-negation diagnostics for portable `not/1` usage.
|
|
8
8
|
It grew out of logic-language experiments in the EYE/N3 reasoning tradition, but is packaged here as its own project.
|
|
9
9
|
|
|
10
10
|
## Install and run
|
package/conformance-report.md
CHANGED
|
@@ -14,12 +14,12 @@ This report summarizes the file-based conformance corpus under `test/conformance
|
|
|
14
14
|
| lists | 54 | 3 | 0 | 0 | 57 |
|
|
15
15
|
| materialize | 8 | 0 | 0 | 0 | 8 |
|
|
16
16
|
| negation | 8 | 0 | 19 | 0 | 27 |
|
|
17
|
-
| proofs | 0 | 0 | 0 |
|
|
17
|
+
| proofs | 0 | 0 | 0 | 21 | 21 |
|
|
18
18
|
| rules | 12 | 3 | 0 | 0 | 15 |
|
|
19
19
|
| strings | 40 | 0 | 0 | 0 | 40 |
|
|
20
20
|
| syntax | 11 | 28 | 0 | 0 | 39 |
|
|
21
21
|
| table | 6 | 0 | 0 | 0 | 6 |
|
|
22
|
-
| terms |
|
|
22
|
+
| terms | 29 | 3 | 0 | 0 | 32 |
|
|
23
23
|
| unification | 16 | 0 | 0 | 0 | 16 |
|
|
24
24
|
| variables | 16 | 11 | 0 | 0 | 27 |
|
|
25
|
-
| **Total** | **
|
|
25
|
+
| **Total** | **321** | **56** | **19** | **21** | **417** |
|
package/docs/guide.md
CHANGED
|
@@ -373,7 +373,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
373
373
|
| [`equivalence-classes-overlap-implies-same-class.eye`](../examples/equivalence-classes-overlap-implies-same-class.eye) | Packages the shared-member proof pattern for equivalence classes. | [`output/equivalence-classes-overlap-implies-same-class.eye`](../examples/output/equivalence-classes-overlap-implies-same-class.eye) |
|
|
374
374
|
| [`eulerian-path.eye`](../examples/eulerian-path.eye) | Finds an Eulerian path using each edge once. | [`output/eulerian-path.eye`](../examples/output/eulerian-path.eye) |
|
|
375
375
|
| [`ev-range-worlds.eye`](../examples/ev-range-worlds.eye) | Estimates electric-vehicle trip feasibility. | [`output/ev-range-worlds.eye`](../examples/output/ev-range-worlds.eye) |
|
|
376
|
-
| [`existential-rule.eye`](../examples/existential-rule.eye) | Represents existential witnesses with explicit
|
|
376
|
+
| [`existential-rule.eye`](../examples/existential-rule.eye) | Represents existential-style witnesses with explicit Herbrand terms. | [`output/existential-rule.eye`](../examples/output/existential-rule.eye) |
|
|
377
377
|
| [`exoplanet-validation-worlds.eye`](../examples/exoplanet-validation-worlds.eye) | Validates exoplanet candidates across worlds. | [`output/exoplanet-validation-worlds.eye`](../examples/output/exoplanet-validation-worlds.eye) |
|
|
378
378
|
| [`expression-eval.eye`](../examples/expression-eval.eye) | Evaluates a small arithmetic expression tree. | [`output/expression-eval.eye`](../examples/output/expression-eval.eye) |
|
|
379
379
|
| [`family-cousins.eye`](../examples/family-cousins.eye) | Derives cousin and family labels. | [`output/family-cousins.eye`](../examples/output/family-cousins.eye) |
|
|
@@ -444,6 +444,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
444
444
|
| [`service-impact.eye`](../examples/service-impact.eye) | Analyzes service impact over cyclic dependencies. | [`output/service-impact.eye`](../examples/output/service-impact.eye) |
|
|
445
445
|
| [`sieve.eye`](../examples/sieve.eye) | Enumerates primes with a sieve-style program. | [`output/sieve.eye`](../examples/output/sieve.eye) |
|
|
446
446
|
| [`skolem-functions.eye`](../examples/skolem-functions.eye) | Generates deterministic functional terms. | [`output/skolem-functions.eye`](../examples/output/skolem-functions.eye) |
|
|
447
|
+
| [`herbrand-witnesses.eye`](../examples/herbrand-witnesses.eye) | Represents existential-style consequences as stable Herbrand witness terms. | [`output/herbrand-witnesses.eye`](../examples/output/herbrand-witnesses.eye) |
|
|
447
448
|
| [`socket-age.eye`](../examples/socket-age.eye) | Shows socket-declared age reasoning inputs and plugs. | [`output/socket-age.eye`](../examples/output/socket-age.eye) |
|
|
448
449
|
| [`socket-family.eye`](../examples/socket-family.eye) | Shows socket-declared family-source inputs and ancestry rules. | [`output/socket-family.eye`](../examples/output/socket-family.eye) |
|
|
449
450
|
| [`socrates.eye`](../examples/socrates.eye) | Derives that Socrates is mortal. | [`output/socrates.eye`](../examples/output/socrates.eye) |
|
|
@@ -333,6 +333,18 @@ Equivalently, the least Herbrand model is obtained by repeatedly applying the im
|
|
|
333
333
|
|
|
334
334
|
Variables do not range over external objects, records, pointers, or host-language values. In the logical reading, variables range over Herbrand terms. A rule is implicitly universally quantified over its variables. A selected goal is existential in the usual logic-programming sense: eyelang searches for substitutions of its variables by Herbrand terms that make the goal true with respect to the program.
|
|
335
335
|
|
|
336
|
+
eyelang has no blank nodes and no existential variables in rule heads. Existential-style consequences SHOULD be represented by explicit Herbrand witness terms written directly in rule heads:
|
|
337
|
+
|
|
338
|
+
```eyelang
|
|
339
|
+
has_parent(?child, parent_of(?child)) :-
|
|
340
|
+
person(?child).
|
|
341
|
+
|
|
342
|
+
registration(?student, ?course, registration_of(?student, ?course)) :-
|
|
343
|
+
takes(?student, ?course).
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
These rules may derive `parent_of(alice)` or `registration_of(alice, logic)` as ordinary visible Herbrand terms. The witness is deterministic: the same functor and inputs produce the same term, while different inputs produce different terms by normal syntactic identity. This is the practical executable form of existential-style consequences in Eyelang; it does not introduce hidden blank nodes or special quantifier syntax.
|
|
347
|
+
|
|
336
348
|
### 8.2 Equality, identity, and unification
|
|
337
349
|
|
|
338
350
|
Because the domain is Herbrand, equality in the pure language is syntactic identity of terms after substitution. Two distinct atom constants are distinct. Two compound terms are equal only when they have the same functor, the same arity, and pairwise equal arguments. Lists follow the same rule through their `[]` and `./2` representation.
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
% Existential introduction with explicit witnesses.
|
|
2
|
-
% Eyeling's original N3 rule creates existential blank nodes; in Eyelang the
|
|
3
|
-
% same idea is represented by deterministic Skolem-style witness terms so the
|
|
4
|
-
% generated individual is visible in ordinary output.
|
|
1
|
+
% Existential-style introduction with explicit Herbrand witnesses.
|
|
5
2
|
%
|
|
6
|
-
%
|
|
7
|
-
|
|
3
|
+
% Eyelang has no blank nodes and no existential variables in rule heads. A
|
|
4
|
+
% rule can still express the practical executable shape of an existential
|
|
5
|
+
% consequence by putting a named functional term directly in the head.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
% each human. The single rule below is the existential-style introduction step.
|
|
7
|
+
materialize(is, 2).
|
|
11
8
|
|
|
12
9
|
type(socrates, human).
|
|
13
10
|
type(plato, human).
|
|
14
11
|
|
|
15
|
-
witness
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
% In proof output this rule is the step that explains why each witness exists.
|
|
19
|
-
is(?person, ?witness) :-
|
|
20
|
-
type(?person, human),
|
|
21
|
-
witness(?person, ?witness).
|
|
12
|
+
% In proof output this rule is the step that explains each visible witness.
|
|
13
|
+
is(?person, human_witness(?person)) :-
|
|
14
|
+
type(?person, human).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
% Existential-style consequences as explicit Herbrand witness terms.
|
|
2
|
+
%
|
|
3
|
+
% Eyelang has no blank nodes and no existential variables in rule heads. The
|
|
4
|
+
% practical executable form is to put a named functional term directly in the
|
|
5
|
+
% rule head. The term is ordinary data: stable, visible, and proof-friendly.
|
|
6
|
+
|
|
7
|
+
materialize(has_parent, 2).
|
|
8
|
+
materialize(registration, 3).
|
|
9
|
+
materialize(same_witness, 2).
|
|
10
|
+
materialize(distinct_witnesses, 2).
|
|
11
|
+
|
|
12
|
+
person(alice).
|
|
13
|
+
person(bob).
|
|
14
|
+
|
|
15
|
+
takes(alice, logic).
|
|
16
|
+
takes(alice, math).
|
|
17
|
+
takes(bob, logic).
|
|
18
|
+
|
|
19
|
+
% One variable: every person has a deterministic parent witness.
|
|
20
|
+
has_parent(?child, parent_of(?child)) :-
|
|
21
|
+
person(?child).
|
|
22
|
+
|
|
23
|
+
% Two variables: every student/course pair has its own registration witness.
|
|
24
|
+
registration(?student, ?course, registration_of(?student, ?course)) :-
|
|
25
|
+
takes(?student, ?course).
|
|
26
|
+
|
|
27
|
+
same_witness(parent_of_alice, true) :-
|
|
28
|
+
eq(parent_of(alice), parent_of(alice)).
|
|
29
|
+
|
|
30
|
+
distinct_witnesses(alice_logic_vs_alice_math, true) :-
|
|
31
|
+
neq(registration_of(alice, logic), registration_of(alice, math)).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
is(socrates,
|
|
2
|
-
is(plato,
|
|
1
|
+
is(socrates, human_witness(socrates)).
|
|
2
|
+
is(plato, human_witness(plato)).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
has_parent(alice, parent_of(alice)).
|
|
2
|
+
has_parent(bob, parent_of(bob)).
|
|
3
|
+
registration(alice, logic, registration_of(alice, logic)).
|
|
4
|
+
registration(alice, math, registration_of(alice, math)).
|
|
5
|
+
registration(bob, logic, registration_of(bob, logic)).
|
|
6
|
+
same_witness(parent_of_alice, true).
|
|
7
|
+
distinct_witnesses(alice_logic_vs_alice_math, true).
|
|
@@ -1,38 +1,30 @@
|
|
|
1
|
-
is(socrates,
|
|
1
|
+
is(socrates, human_witness(socrates)).
|
|
2
2
|
why(
|
|
3
|
-
is(socrates,
|
|
3
|
+
is(socrates, human_witness(socrates)),
|
|
4
4
|
proof(
|
|
5
|
-
goal(is(socrates,
|
|
6
|
-
by(rule("existential-rule.eye", clause(
|
|
7
|
-
bindings([binding("?person", socrates)
|
|
5
|
+
goal(is(socrates, human_witness(socrates))),
|
|
6
|
+
by(rule("existential-rule.eye", clause(4))),
|
|
7
|
+
bindings([binding("?person", socrates)]),
|
|
8
8
|
uses([
|
|
9
9
|
proof(
|
|
10
10
|
goal(type(socrates, human)),
|
|
11
11
|
by(fact("existential-rule.eye", clause(2)))
|
|
12
|
-
),
|
|
13
|
-
proof(
|
|
14
|
-
goal(witness(socrates, sk_0)),
|
|
15
|
-
by(fact("existential-rule.eye", clause(4)))
|
|
16
12
|
)
|
|
17
13
|
])
|
|
18
14
|
)
|
|
19
15
|
).
|
|
20
16
|
|
|
21
|
-
is(plato,
|
|
17
|
+
is(plato, human_witness(plato)).
|
|
22
18
|
why(
|
|
23
|
-
is(plato,
|
|
19
|
+
is(plato, human_witness(plato)),
|
|
24
20
|
proof(
|
|
25
|
-
goal(is(plato,
|
|
26
|
-
by(rule("existential-rule.eye", clause(
|
|
27
|
-
bindings([binding("?person", plato)
|
|
21
|
+
goal(is(plato, human_witness(plato))),
|
|
22
|
+
by(rule("existential-rule.eye", clause(4))),
|
|
23
|
+
bindings([binding("?person", plato)]),
|
|
28
24
|
uses([
|
|
29
25
|
proof(
|
|
30
26
|
goal(type(plato, human)),
|
|
31
27
|
by(fact("existential-rule.eye", clause(3)))
|
|
32
|
-
),
|
|
33
|
-
proof(
|
|
34
|
-
goal(witness(plato, sk_1)),
|
|
35
|
-
by(fact("existential-rule.eye", clause(5)))
|
|
36
28
|
)
|
|
37
29
|
])
|
|
38
30
|
)
|
package/package.json
CHANGED
package/playground.html
CHANGED
package/src/builtins/terms.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
answer(true).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
answer(true).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
has_parent(alice, parent_of(alice)).
|
|
2
|
+
why(
|
|
3
|
+
has_parent(alice, parent_of(alice)),
|
|
4
|
+
proof(
|
|
5
|
+
goal(has_parent(alice, parent_of(alice))),
|
|
6
|
+
by(rule("<stdin>", clause(2))),
|
|
7
|
+
bindings([binding("?child", alice)]),
|
|
8
|
+
uses([
|
|
9
|
+
proof(
|
|
10
|
+
goal(person(alice)),
|
|
11
|
+
by(fact("<stdin>", clause(1)))
|
|
12
|
+
)
|
|
13
|
+
])
|
|
14
|
+
)
|
|
15
|
+
).
|
|
16
|
+
|