eyelang 1.7.12 → 1.7.14
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/docs/guide.md +6 -0
- package/examples/abstract-interpretation.eye +50 -0
- package/examples/markov-logic-network.eye +87 -0
- package/examples/output/abstract-interpretation.eye +16 -0
- package/examples/output/markov-logic-network.eye +32 -0
- package/examples/output/pointer-analysis.eye +8 -0
- package/examples/output/sat-solver-dpll.eye +11 -0
- package/examples/output/truth-maintenance-system.eye +25 -0
- package/examples/output/type-inference.eye +8 -0
- package/examples/pointer-analysis.eye +50 -0
- package/examples/sat-solver-dpll.eye +88 -0
- package/examples/truth-maintenance-system.eye +62 -0
- package/examples/type-inference.eye +58 -0
- package/package.json +1 -1
- package/playground.html +6 -0
package/docs/guide.md
CHANGED
|
@@ -310,6 +310,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
310
310
|
|
|
311
311
|
| Example | Description | Golden output |
|
|
312
312
|
| --- | --- | --- |
|
|
313
|
+
| [`abstract-interpretation.eye`](../examples/abstract-interpretation.eye) | Performs a sign-domain abstract interpretation and reports a possible divide-by-zero warning. | [`output/abstract-interpretation.eye`](../examples/output/abstract-interpretation.eye) |
|
|
313
314
|
| [`access-control-policy.eye`](../examples/access-control-policy.eye) | Evaluates role and condition based access decisions. | [`output/access-control-policy.eye`](../examples/output/access-control-policy.eye) |
|
|
314
315
|
| [`ackermann.eye`](../examples/ackermann.eye) | Computes Ackermann-style hyperoperation values. | [`output/ackermann.eye`](../examples/output/ackermann.eye) |
|
|
315
316
|
| [`age.eye`](../examples/age.eye) | Checks whether people meet age thresholds. | [`output/age.eye`](../examples/output/age.eye) |
|
|
@@ -414,6 +415,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
414
415
|
| [`list-collection.eye`](../examples/list-collection.eye) | Demonstrates list and collection built-ins. | [`output/list-collection.eye`](../examples/output/list-collection.eye) |
|
|
415
416
|
| [`lldm.eye`](../examples/lldm.eye) | Calculates leg-length discrepancy measurements. | [`output/lldm.eye`](../examples/output/lldm.eye) |
|
|
416
417
|
| [`manufacturing-quality-control.eye`](../examples/manufacturing-quality-control.eye) | Evaluates process capability and quality. | [`output/manufacturing-quality-control.eye`](../examples/output/manufacturing-quality-control.eye) |
|
|
418
|
+
| [`markov-logic-network.eye`](../examples/markov-logic-network.eye) | Scores finite possible worlds with weighted soft formulas in a Markov Logic Network style. | [`output/markov-logic-network.eye`](../examples/output/markov-logic-network.eye) |
|
|
417
419
|
| [`map-four-color-search.eye`](../examples/map-four-color-search.eye) | Searches for a valid four-colouring of the EU neighbour graph. | [`output/map-four-color-search.eye`](../examples/output/map-four-color-search.eye) |
|
|
418
420
|
| [`matrix-chain-order.eye`](../examples/matrix-chain-order.eye) | Finds an optimal matrix-chain multiplication order. | [`output/matrix-chain-order.eye`](../examples/output/matrix-chain-order.eye) |
|
|
419
421
|
| [`matrix-noncommutativity.eye`](../examples/matrix-noncommutativity.eye) | Multiplies 2x2 matrices and shows non-commutativity. | [`output/matrix-noncommutativity.eye`](../examples/output/matrix-noncommutativity.eye) |
|
|
@@ -437,6 +439,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
437
439
|
| [`peasant.eye`](../examples/peasant.eye) | Performs peasant multiplication and exponentiation. | [`output/peasant.eye`](../examples/output/peasant.eye) |
|
|
438
440
|
| [`pell-equation.eye`](../examples/pell-equation.eye) | Generates Pell-equation solutions by recurrence. | [`output/pell-equation.eye`](../examples/output/pell-equation.eye) |
|
|
439
441
|
| [`pendulum-period.eye`](../examples/pendulum-period.eye) | Computes simple pendulum periods. | [`output/pendulum-period.eye`](../examples/output/pendulum-period.eye) |
|
|
442
|
+
| [`pointer-analysis.eye`](../examples/pointer-analysis.eye) | Computes Andersen-style inclusion-based points-to facts over address, assign, store, and load constraints. | [`output/pointer-analysis.eye`](../examples/output/pointer-analysis.eye) |
|
|
440
443
|
| [`polynomial.eye`](../examples/polynomial.eye) | Finds complex integer polynomial roots. | [`output/polynomial.eye`](../examples/output/polynomial.eye) |
|
|
441
444
|
| [`prime-range.eye`](../examples/prime-range.eye) | Finds primes in a finite range and computes a totient value. | [`output/prime-range.eye`](../examples/output/prime-range.eye) |
|
|
442
445
|
| [`proof-contrapositive.eye`](../examples/proof-contrapositive.eye) | Models proof by contrapositive. | [`output/proof-contrapositive.eye`](../examples/output/proof-contrapositive.eye) |
|
|
@@ -445,6 +448,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
445
448
|
| [`reusable-builtins.eye`](../examples/reusable-builtins.eye) | Tours reusable numeric, list, and string builtins. | [`output/reusable-builtins.eye`](../examples/output/reusable-builtins.eye) |
|
|
446
449
|
| [`riemann-hypothesis.eye`](../examples/riemann-hypothesis.eye) | Checks a finite catalogue of non-trivial zeta zeros against the Riemann-hypothesis condition. | [`output/riemann-hypothesis.eye`](../examples/output/riemann-hypothesis.eye) |
|
|
447
450
|
| [`route-planning.eye`](../examples/route-planning.eye) | Finds routes and records them as explicit route terms. | [`output/route-planning.eye`](../examples/output/route-planning.eye) |
|
|
451
|
+
| [`sat-solver-dpll.eye`](../examples/sat-solver-dpll.eye) | Searches a CNF formula with DPLL-style recursive decisions and early contradiction pruning. | [`output/sat-solver-dpll.eye`](../examples/output/sat-solver-dpll.eye) |
|
|
448
452
|
| [`security-incident-correlation.eye`](../examples/security-incident-correlation.eye) | Correlates security incidents across signals. | [`output/security-incident-correlation.eye`](../examples/output/security-incident-correlation.eye) |
|
|
449
453
|
| [`send-more-money.eye`](../examples/send-more-money.eye) | Solves the SEND + MORE = MONEY cryptarithm. | [`output/send-more-money.eye`](../examples/output/send-more-money.eye) |
|
|
450
454
|
| [`service-impact.eye`](../examples/service-impact.eye) | Analyzes service impact over cyclic dependencies. | [`output/service-impact.eye`](../examples/output/service-impact.eye) |
|
|
@@ -463,6 +467,8 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
463
467
|
| [`term-tools.eye`](../examples/term-tools.eye) | Inspects, builds, renders, and validates terms with reusable term/control builtins. | [`output/term-tools.eye`](../examples/output/term-tools.eye) |
|
|
464
468
|
| [`totient-summatory.eye`](../examples/totient-summatory.eye) | Computes Euler totients and their summatory function. | [`output/totient-summatory.eye`](../examples/output/totient-summatory.eye) |
|
|
465
469
|
| [`trust-flow-provenance-threshold.eye`](../examples/trust-flow-provenance-threshold.eye) | Classifies message trust from provenance confidence scores. | [`output/trust-flow-provenance-threshold.eye`](../examples/output/trust-flow-provenance-threshold.eye) |
|
|
470
|
+
| [`truth-maintenance-system.eye`](../examples/truth-maintenance-system.eye) | Tracks assumptions, justifications, supported beliefs, and inconsistent environments in a tiny TMS. | [`output/truth-maintenance-system.eye`](../examples/output/truth-maintenance-system.eye) |
|
|
471
|
+
| [`type-inference.eye`](../examples/type-inference.eye) | Infers/checks types for a tiny lambda language using logic unification over expression syntax trees. | [`output/type-inference.eye`](../examples/output/type-inference.eye) |
|
|
466
472
|
| [`turing.eye`](../examples/turing.eye) | Simulates a binary-increment Turing machine. | [`output/turing.eye`](../examples/output/turing.eye) |
|
|
467
473
|
| [`vector-similarity.eye`](../examples/vector-similarity.eye) | Computes dot product, norm, and cosine similarity. | [`output/vector-similarity.eye`](../examples/output/vector-similarity.eye) |
|
|
468
474
|
| [`vulnerability-impact.eye`](../examples/vulnerability-impact.eye) | Analyzes vulnerable transitive dependencies and urgent patch impact. | [`output/vulnerability-impact.eye`](../examples/output/vulnerability-impact.eye) |
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
% Abstract interpretation over a tiny imperative program.
|
|
2
|
+
%
|
|
3
|
+
% The concrete program is:
|
|
4
|
+
%
|
|
5
|
+
% x := input();
|
|
6
|
+
% if x < 0 then y := -x else y := x;
|
|
7
|
+
% z := 10 / y;
|
|
8
|
+
%
|
|
9
|
+
% Instead of executing the program for every integer input, this example tracks
|
|
10
|
+
% only the abstract sign of each variable: neg, zero, or pos. The analysis is
|
|
11
|
+
% deliberately conservative: if the join point can see y = zero on any path, the
|
|
12
|
+
% division is reported as a possible division-by-zero warning.
|
|
13
|
+
|
|
14
|
+
materialize(absState, 3).
|
|
15
|
+
materialize(absWarning, 2).
|
|
16
|
+
materialize(absConclusion, 2).
|
|
17
|
+
|
|
18
|
+
table(abs_state, 3).
|
|
19
|
+
|
|
20
|
+
% The abstract domain.
|
|
21
|
+
input_sign(neg).
|
|
22
|
+
input_sign(zero).
|
|
23
|
+
input_sign(pos).
|
|
24
|
+
|
|
25
|
+
% The input statement gives x any of the three abstract signs.
|
|
26
|
+
abs_state(input, x, ?sign) :- input_sign(?sign).
|
|
27
|
+
|
|
28
|
+
% The branch refines the sign of x. The negative branch only receives neg; the
|
|
29
|
+
% non-negative branch receives zero or pos.
|
|
30
|
+
abs_state(negative_branch, x, neg) :- abs_state(input, x, neg).
|
|
31
|
+
abs_state(nonnegative_branch, x, zero) :- abs_state(input, x, zero).
|
|
32
|
+
abs_state(nonnegative_branch, x, pos) :- abs_state(input, x, pos).
|
|
33
|
+
|
|
34
|
+
% Transfer functions for assignments. In the negative branch, y := -x turns a
|
|
35
|
+
% negative x into a positive y. In the non-negative branch, y := x preserves the
|
|
36
|
+
% zero/positive information.
|
|
37
|
+
abs_state(negative_branch, y, pos) :- abs_state(negative_branch, x, neg).
|
|
38
|
+
abs_state(nonnegative_branch, y, ?sign) :- abs_state(nonnegative_branch, x, ?sign).
|
|
39
|
+
|
|
40
|
+
% The join point merges abstract states from both branches.
|
|
41
|
+
abs_state(join, ?var, ?sign) :- abs_state(negative_branch, ?var, ?sign).
|
|
42
|
+
abs_state(join, ?var, ?sign) :- abs_state(nonnegative_branch, ?var, ?sign).
|
|
43
|
+
|
|
44
|
+
% A possible zero denominator is enough to raise a conservative warning.
|
|
45
|
+
possible_division_by_zero(join) :- abs_state(join, y, zero).
|
|
46
|
+
|
|
47
|
+
absState(?point, ?var, sign(?sign)) :- abs_state(?point, ?var, ?sign).
|
|
48
|
+
absWarning(division_by_zero, ?point) :- possible_division_by_zero(?point).
|
|
49
|
+
absConclusion(case, "abstract interpretation keeps all feasible signs and warns because y may be zero") :-
|
|
50
|
+
possible_division_by_zero(join).
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
% Markov Logic Network style scoring over a tiny finite domain.
|
|
2
|
+
%
|
|
3
|
+
% Eyelang is deterministic, so this is not a probabilistic MLN engine. The
|
|
4
|
+
% example encodes the usual MLN MAP idea explicitly: enumerate possible worlds,
|
|
5
|
+
% mark which weighted soft formulas each world satisfies, sum the weights, and
|
|
6
|
+
% choose the highest-scoring world. Weights are stored as integer tenths of a
|
|
7
|
+
% log weight so the example stays reproducible without floating-point noise.
|
|
8
|
+
|
|
9
|
+
materialize(mlnWeight, 2).
|
|
10
|
+
materialize(mlnWorld, 2).
|
|
11
|
+
materialize(mlnSatisfied, 2).
|
|
12
|
+
materialize(mlnViolated, 2).
|
|
13
|
+
materialize(mlnContribution, 3).
|
|
14
|
+
materialize(mlnWorldScore, 2).
|
|
15
|
+
materialize(mlnMapWorld, 2).
|
|
16
|
+
materialize(mlnConclusion, 2).
|
|
17
|
+
|
|
18
|
+
% Evidence and candidate hidden assignments.
|
|
19
|
+
person(alice).
|
|
20
|
+
person(bob).
|
|
21
|
+
friend(alice, bob).
|
|
22
|
+
observed_smokes(alice).
|
|
23
|
+
|
|
24
|
+
candidate_world(w_bob_not_smokes_not_cancer, no, no).
|
|
25
|
+
candidate_world(w_bob_not_smokes_cancer, no, yes).
|
|
26
|
+
candidate_world(w_bob_smokes_not_cancer, yes, no).
|
|
27
|
+
candidate_world(w_bob_smokes_cancer, yes, yes).
|
|
28
|
+
|
|
29
|
+
% Soft formulas are weighted log features.
|
|
30
|
+
formula_weight_tenths(friend_smoking, 20).
|
|
31
|
+
formula_weight_tenths(smoking_causes_cancer, 13).
|
|
32
|
+
formula_weight_tenths(cancer_is_rare, 6).
|
|
33
|
+
|
|
34
|
+
% World interpretation for Bob. Alice's smoking status is observed evidence.
|
|
35
|
+
smokes_in_world(?world, alice) :-
|
|
36
|
+
candidate_world(?world, ?, ?),
|
|
37
|
+
observed_smokes(alice).
|
|
38
|
+
smokes_in_world(?world, bob) :- candidate_world(?world, yes, ?).
|
|
39
|
+
cancer_in_world(?world, bob) :- candidate_world(?world, ?, yes).
|
|
40
|
+
|
|
41
|
+
% Grounded soft formulas for this tiny domain:
|
|
42
|
+
% friend_smoking: friend(alice,bob) and smokes(alice) => smokes(bob)
|
|
43
|
+
% smoking_causes_cancer: smokes(bob) => cancer(bob)
|
|
44
|
+
% cancer_is_rare: not cancer(bob)
|
|
45
|
+
formula_satisfied(?world, friend_smoking) :-
|
|
46
|
+
friend(alice, bob),
|
|
47
|
+
smokes_in_world(?world, alice),
|
|
48
|
+
smokes_in_world(?world, bob).
|
|
49
|
+
|
|
50
|
+
formula_satisfied(?world, smoking_causes_cancer) :-
|
|
51
|
+
candidate_world(?world, no, ?).
|
|
52
|
+
formula_satisfied(?world, smoking_causes_cancer) :-
|
|
53
|
+
smokes_in_world(?world, bob),
|
|
54
|
+
cancer_in_world(?world, bob).
|
|
55
|
+
|
|
56
|
+
formula_satisfied(?world, cancer_is_rare) :-
|
|
57
|
+
candidate_world(?world, ?, no).
|
|
58
|
+
|
|
59
|
+
formula_violated(?world, ?formula) :-
|
|
60
|
+
candidate_world(?world, ?, ?),
|
|
61
|
+
formula_weight_tenths(?formula, ?),
|
|
62
|
+
not(formula_satisfied(?world, ?formula)).
|
|
63
|
+
|
|
64
|
+
contribution_tenths(?world, ?formula, ?weight) :-
|
|
65
|
+
formula_satisfied(?world, ?formula),
|
|
66
|
+
formula_weight_tenths(?formula, ?weight).
|
|
67
|
+
|
|
68
|
+
world_score_tenths(?world, ?score) :-
|
|
69
|
+
candidate_world(?world, ?, ?),
|
|
70
|
+
sumall(?weight, contribution_tenths(?world, ?formula, ?weight), ?score).
|
|
71
|
+
|
|
72
|
+
map_world(?world, ?score) :-
|
|
73
|
+
aggregate_max(?candidate_score, ?candidate_world,
|
|
74
|
+
world_score_tenths(?candidate_world, ?candidate_score),
|
|
75
|
+
?score, ?world).
|
|
76
|
+
|
|
77
|
+
mlnWeight(?formula, log_weight_tenths(?weight)) :- formula_weight_tenths(?formula, ?weight).
|
|
78
|
+
mlnWorld(?world, world(smokes(bob, ?smokes), cancer(bob, ?cancer))) :-
|
|
79
|
+
candidate_world(?world, ?smokes, ?cancer).
|
|
80
|
+
mlnSatisfied(?world, ?formula) :- formula_satisfied(?world, ?formula).
|
|
81
|
+
mlnViolated(?world, ?formula) :- formula_violated(?world, ?formula).
|
|
82
|
+
mlnContribution(?world, ?formula, log_weight_tenths(?weight)) :-
|
|
83
|
+
contribution_tenths(?world, ?formula, ?weight).
|
|
84
|
+
mlnWorldScore(?world, log_weight_tenths(?score)) :- world_score_tenths(?world, ?score).
|
|
85
|
+
mlnMapWorld(?world, log_weight_tenths(?score)) :- map_world(?world, ?score).
|
|
86
|
+
mlnConclusion(case, "MAP world predicts that Bob smokes and has cancer") :-
|
|
87
|
+
map_world(w_bob_smokes_cancer, ?).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
absState(input, x, sign(neg)).
|
|
2
|
+
absState(input, x, sign(zero)).
|
|
3
|
+
absState(input, x, sign(pos)).
|
|
4
|
+
absState(negative_branch, x, sign(neg)).
|
|
5
|
+
absState(nonnegative_branch, x, sign(zero)).
|
|
6
|
+
absState(nonnegative_branch, x, sign(pos)).
|
|
7
|
+
absState(negative_branch, y, sign(pos)).
|
|
8
|
+
absState(nonnegative_branch, y, sign(zero)).
|
|
9
|
+
absState(nonnegative_branch, y, sign(pos)).
|
|
10
|
+
absState(join, x, sign(neg)).
|
|
11
|
+
absState(join, y, sign(pos)).
|
|
12
|
+
absState(join, x, sign(zero)).
|
|
13
|
+
absState(join, x, sign(pos)).
|
|
14
|
+
absState(join, y, sign(zero)).
|
|
15
|
+
absWarning(division_by_zero, join).
|
|
16
|
+
absConclusion(case, "abstract interpretation keeps all feasible signs and warns because y may be zero").
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
mlnWeight(friend_smoking, log_weight_tenths(20)).
|
|
2
|
+
mlnWeight(smoking_causes_cancer, log_weight_tenths(13)).
|
|
3
|
+
mlnWeight(cancer_is_rare, log_weight_tenths(6)).
|
|
4
|
+
mlnWorld(w_bob_not_smokes_not_cancer, world(smokes(bob, no), cancer(bob, no))).
|
|
5
|
+
mlnWorld(w_bob_not_smokes_cancer, world(smokes(bob, no), cancer(bob, yes))).
|
|
6
|
+
mlnWorld(w_bob_smokes_not_cancer, world(smokes(bob, yes), cancer(bob, no))).
|
|
7
|
+
mlnWorld(w_bob_smokes_cancer, world(smokes(bob, yes), cancer(bob, yes))).
|
|
8
|
+
mlnSatisfied(w_bob_smokes_not_cancer, friend_smoking).
|
|
9
|
+
mlnSatisfied(w_bob_smokes_cancer, friend_smoking).
|
|
10
|
+
mlnSatisfied(w_bob_not_smokes_not_cancer, smoking_causes_cancer).
|
|
11
|
+
mlnSatisfied(w_bob_not_smokes_cancer, smoking_causes_cancer).
|
|
12
|
+
mlnSatisfied(w_bob_smokes_cancer, smoking_causes_cancer).
|
|
13
|
+
mlnSatisfied(w_bob_not_smokes_not_cancer, cancer_is_rare).
|
|
14
|
+
mlnSatisfied(w_bob_smokes_not_cancer, cancer_is_rare).
|
|
15
|
+
mlnViolated(w_bob_not_smokes_not_cancer, friend_smoking).
|
|
16
|
+
mlnViolated(w_bob_not_smokes_cancer, friend_smoking).
|
|
17
|
+
mlnViolated(w_bob_not_smokes_cancer, cancer_is_rare).
|
|
18
|
+
mlnViolated(w_bob_smokes_not_cancer, smoking_causes_cancer).
|
|
19
|
+
mlnViolated(w_bob_smokes_cancer, cancer_is_rare).
|
|
20
|
+
mlnContribution(w_bob_smokes_not_cancer, friend_smoking, log_weight_tenths(20)).
|
|
21
|
+
mlnContribution(w_bob_smokes_cancer, friend_smoking, log_weight_tenths(20)).
|
|
22
|
+
mlnContribution(w_bob_not_smokes_not_cancer, smoking_causes_cancer, log_weight_tenths(13)).
|
|
23
|
+
mlnContribution(w_bob_not_smokes_cancer, smoking_causes_cancer, log_weight_tenths(13)).
|
|
24
|
+
mlnContribution(w_bob_smokes_cancer, smoking_causes_cancer, log_weight_tenths(13)).
|
|
25
|
+
mlnContribution(w_bob_not_smokes_not_cancer, cancer_is_rare, log_weight_tenths(6)).
|
|
26
|
+
mlnContribution(w_bob_smokes_not_cancer, cancer_is_rare, log_weight_tenths(6)).
|
|
27
|
+
mlnWorldScore(w_bob_not_smokes_not_cancer, log_weight_tenths(19)).
|
|
28
|
+
mlnWorldScore(w_bob_not_smokes_cancer, log_weight_tenths(13)).
|
|
29
|
+
mlnWorldScore(w_bob_smokes_not_cancer, log_weight_tenths(26)).
|
|
30
|
+
mlnWorldScore(w_bob_smokes_cancer, log_weight_tenths(33)).
|
|
31
|
+
mlnMapWorld(w_bob_smokes_cancer, log_weight_tenths(33)).
|
|
32
|
+
mlnConclusion(case, "MAP world predicts that Bob smokes and has cancer").
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pointsTo(x, object_a).
|
|
2
|
+
pointsTo(z, object_b).
|
|
3
|
+
pointsTo(y, object_a).
|
|
4
|
+
pointsTo(r, object_b).
|
|
5
|
+
pointsTo(q, object_b).
|
|
6
|
+
heapField(object_a, object_b).
|
|
7
|
+
pointerFlow(load_q_from_x, object_b).
|
|
8
|
+
pointerConclusion(case, "the load q = *x recovers object_b through the store *y = z and y = x").
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
satModel([bind(d, true), bind(c, true), bind(b, true), bind(a, false)]).
|
|
2
|
+
satValue(d, true).
|
|
3
|
+
satValue(c, true).
|
|
4
|
+
satValue(b, true).
|
|
5
|
+
satValue(a, false).
|
|
6
|
+
satClauseStatus(c1, satisfied).
|
|
7
|
+
satClauseStatus(c2, satisfied).
|
|
8
|
+
satClauseStatus(c3, satisfied).
|
|
9
|
+
satClauseStatus(c4, satisfied).
|
|
10
|
+
satClauseStatus(c5, satisfied).
|
|
11
|
+
satConclusion(case, "DPLL finds a satisfying assignment after pruning clauses that become impossible").
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
tmsSupport(clear_only, clear_path).
|
|
2
|
+
tmsSupport(conflicting_sensors, clear_path).
|
|
3
|
+
tmsSupport(blocked_only, blocked_path).
|
|
4
|
+
tmsSupport(conflicting_sensors, blocked_path).
|
|
5
|
+
tmsSupport(override_blocked, blocked_path).
|
|
6
|
+
tmsSupport(clear_only, permit_go).
|
|
7
|
+
tmsSupport(conflicting_sensors, permit_go).
|
|
8
|
+
tmsSupport(blocked_only, forbid_go).
|
|
9
|
+
tmsSupport(conflicting_sensors, forbid_go).
|
|
10
|
+
tmsSupport(override_blocked, forbid_go).
|
|
11
|
+
tmsSupport(override_blocked, permit_go).
|
|
12
|
+
tmsJustification(clear_only, j_clear_path, clear_path).
|
|
13
|
+
tmsJustification(conflicting_sensors, j_clear_path, clear_path).
|
|
14
|
+
tmsJustification(blocked_only, j_blocked_path, blocked_path).
|
|
15
|
+
tmsJustification(conflicting_sensors, j_blocked_path, blocked_path).
|
|
16
|
+
tmsJustification(override_blocked, j_blocked_path, blocked_path).
|
|
17
|
+
tmsJustification(clear_only, j_permit_from_clear, permit_go).
|
|
18
|
+
tmsJustification(conflicting_sensors, j_permit_from_clear, permit_go).
|
|
19
|
+
tmsJustification(blocked_only, j_forbid_from_blocked, forbid_go).
|
|
20
|
+
tmsJustification(conflicting_sensors, j_forbid_from_blocked, forbid_go).
|
|
21
|
+
tmsJustification(override_blocked, j_forbid_from_blocked, forbid_go).
|
|
22
|
+
tmsJustification(override_blocked, j_override, permit_go).
|
|
23
|
+
tmsInconsistent(conflicting_sensors).
|
|
24
|
+
tmsInconsistent(override_blocked).
|
|
25
|
+
tmsConclusion(case, "truth maintenance separates support from consistency across assumption environments").
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type_answer(id, fun(t0, t0)).
|
|
2
|
+
type_answer(const, fun(t0, fun(t1, t0))).
|
|
3
|
+
type_answer(apply_id, int).
|
|
4
|
+
type_answer(compose, fun(fun(t1, t2), fun(fun(t0, t1), fun(t0, t2)))).
|
|
5
|
+
type_answer(branch, int).
|
|
6
|
+
type_answer(first_of_pair, bool).
|
|
7
|
+
type_reason(compose, "application unifies f with t1 -> t2 and g with t0 -> t1").
|
|
8
|
+
type_reason(apply_id, "the identity function's parameter type is unified with int").
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
% Andersen-style inclusion-based pointer analysis.
|
|
2
|
+
%
|
|
3
|
+
% The program being analyzed has address-taking, assignment, store, and load
|
|
4
|
+
% statements. The logic rules compute a fixed point of points_to/2 and
|
|
5
|
+
% field_points_to/2 facts. This is the classic Datalog shape used in scalable
|
|
6
|
+
% pointer-analysis papers, reduced to a small readable instance.
|
|
7
|
+
|
|
8
|
+
materialize(pointsTo, 2).
|
|
9
|
+
materialize(heapField, 2).
|
|
10
|
+
materialize(pointerFlow, 2).
|
|
11
|
+
materialize(pointerConclusion, 2).
|
|
12
|
+
|
|
13
|
+
table(points_to, 2).
|
|
14
|
+
table(field_points_to, 2).
|
|
15
|
+
|
|
16
|
+
% Source-program statements:
|
|
17
|
+
% x = &object_a
|
|
18
|
+
% z = &object_b
|
|
19
|
+
% y = x
|
|
20
|
+
% *y = z
|
|
21
|
+
% q = *x
|
|
22
|
+
% r = q
|
|
23
|
+
addr(x, object_a).
|
|
24
|
+
addr(z, object_b).
|
|
25
|
+
assign(y, x).
|
|
26
|
+
store(y, z).
|
|
27
|
+
load(q, x).
|
|
28
|
+
assign(r, q).
|
|
29
|
+
|
|
30
|
+
% Address-taking and assignment constraints.
|
|
31
|
+
points_to(?var, ?object) :- addr(?var, ?object).
|
|
32
|
+
points_to(?to, ?object) :- assign(?to, ?from), points_to(?from, ?object).
|
|
33
|
+
|
|
34
|
+
% Store and load constraints. If y may point to object_a and z may point to
|
|
35
|
+
% object_b, then object_a's abstract field may point to object_b. A later load
|
|
36
|
+
% from x therefore gives q the same target.
|
|
37
|
+
field_points_to(?heap_object, ?value_object) :-
|
|
38
|
+
store(?pointer, ?value),
|
|
39
|
+
points_to(?pointer, ?heap_object),
|
|
40
|
+
points_to(?value, ?value_object).
|
|
41
|
+
points_to(?to, ?value_object) :-
|
|
42
|
+
load(?to, ?pointer),
|
|
43
|
+
points_to(?pointer, ?heap_object),
|
|
44
|
+
field_points_to(?heap_object, ?value_object).
|
|
45
|
+
|
|
46
|
+
pointsTo(?var, ?object) :- points_to(?var, ?object).
|
|
47
|
+
heapField(?heap_object, ?value_object) :- field_points_to(?heap_object, ?value_object).
|
|
48
|
+
pointerFlow(load_q_from_x, ?object) :- points_to(q, ?object).
|
|
49
|
+
pointerConclusion(case, "the load q = *x recovers object_b through the store *y = z and y = x") :-
|
|
50
|
+
points_to(q, object_b).
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
% DPLL-style SAT solving for a small CNF formula.
|
|
2
|
+
%
|
|
3
|
+
% The example keeps the solver itself in Eyelang. It recursively assigns
|
|
4
|
+
% variables in a fixed order, prunes a branch as soon as any clause is already
|
|
5
|
+
% impossible, and accepts a complete assignment when every clause is satisfied.
|
|
6
|
+
% aggregate_min/5 is then used only to choose one canonical satisfying model.
|
|
7
|
+
|
|
8
|
+
materialize(satModel, 1).
|
|
9
|
+
materialize(satValue, 2).
|
|
10
|
+
materialize(satClauseStatus, 2).
|
|
11
|
+
materialize(satConclusion, 2).
|
|
12
|
+
|
|
13
|
+
% CNF formula:
|
|
14
|
+
% (a or b)
|
|
15
|
+
% (not a or c)
|
|
16
|
+
% (not b or c)
|
|
17
|
+
% (not c or d)
|
|
18
|
+
% (c or not d)
|
|
19
|
+
variable_order([a, b, c, d]).
|
|
20
|
+
clause(c1, [pos(a), pos(b)]).
|
|
21
|
+
clause(c2, [neg(a), pos(c)]).
|
|
22
|
+
clause(c3, [neg(b), pos(c)]).
|
|
23
|
+
clause(c4, [neg(c), pos(d)]).
|
|
24
|
+
clause(c5, [pos(c), neg(d)]).
|
|
25
|
+
|
|
26
|
+
bool(false).
|
|
27
|
+
bool(true).
|
|
28
|
+
bit(false, 0).
|
|
29
|
+
bit(true, 1).
|
|
30
|
+
|
|
31
|
+
% Look up a variable inside a partial or complete assignment represented as a
|
|
32
|
+
% list of bind(Name, Bool) terms.
|
|
33
|
+
lookup_bool(?name, [bind(?name, ?value) | ?], ?value).
|
|
34
|
+
lookup_bool(?name, [bind(?, ?) | ?rest], ?value) :- lookup_bool(?name, ?rest, ?value).
|
|
35
|
+
|
|
36
|
+
literal_true(pos(?var), ?assignment) :- lookup_bool(?var, ?assignment, true).
|
|
37
|
+
literal_true(neg(?var), ?assignment) :- lookup_bool(?var, ?assignment, false).
|
|
38
|
+
literal_false(pos(?var), ?assignment) :- lookup_bool(?var, ?assignment, false).
|
|
39
|
+
literal_false(neg(?var), ?assignment) :- lookup_bool(?var, ?assignment, true).
|
|
40
|
+
|
|
41
|
+
clause_satisfied(?assignment, ?clause_name) :-
|
|
42
|
+
clause(?clause_name, ?literals),
|
|
43
|
+
member(?literal, ?literals),
|
|
44
|
+
literal_true(?literal, ?assignment).
|
|
45
|
+
|
|
46
|
+
% A partial branch is impossible when every literal in a clause is already false.
|
|
47
|
+
% Unassigned literals keep the branch alive, just as in DPLL.
|
|
48
|
+
clause_impossible(?assignment, ?clause_name) :-
|
|
49
|
+
clause(?clause_name, ?literals),
|
|
50
|
+
forall(member(?literal, ?literals), literal_false(?literal, ?assignment)).
|
|
51
|
+
partial_consistent(?assignment) :- not((clause(?name, ?), clause_impossible(?assignment, ?name))).
|
|
52
|
+
complete_model(?assignment) :- forall(clause(?name, ?), clause_satisfied(?assignment, ?name)).
|
|
53
|
+
|
|
54
|
+
% Recursive DPLL search: choose a truth value, prune if inconsistent, then
|
|
55
|
+
% continue with the remaining variables.
|
|
56
|
+
dpll([], ?assignment, ?assignment) :- complete_model(?assignment).
|
|
57
|
+
dpll([?var | ?rest], ?partial, ?model) :-
|
|
58
|
+
bool(?value),
|
|
59
|
+
partial_consistent([bind(?var, ?value) | ?partial]),
|
|
60
|
+
dpll(?rest, [bind(?var, ?value) | ?partial], ?model).
|
|
61
|
+
|
|
62
|
+
satisfying_model(?model) :- variable_order(?vars), dpll(?vars, [], ?model).
|
|
63
|
+
|
|
64
|
+
% Rank models so the materialized output shows one deterministic answer. The
|
|
65
|
+
% model list is in reverse decision order because each decision is pushed onto
|
|
66
|
+
% the front during recursion.
|
|
67
|
+
model_rank(?model, ?rank) :-
|
|
68
|
+
lookup_bool(a, ?model, ?a), bit(?a, ?abit),
|
|
69
|
+
lookup_bool(b, ?model, ?b), bit(?b, ?bbit),
|
|
70
|
+
lookup_bool(c, ?model, ?c), bit(?c, ?cbit),
|
|
71
|
+
lookup_bool(d, ?model, ?d), bit(?d, ?dbit),
|
|
72
|
+
mul(?abit, 8, ?arank),
|
|
73
|
+
mul(?bbit, 4, ?brank),
|
|
74
|
+
mul(?cbit, 2, ?crank),
|
|
75
|
+
add(?arank, ?brank, ?ab),
|
|
76
|
+
add(?crank, ?dbit, ?cd),
|
|
77
|
+
add(?ab, ?cd, ?rank).
|
|
78
|
+
|
|
79
|
+
best_model(?model, ?rank) :-
|
|
80
|
+
aggregate_min(?candidate_rank, ?candidate_model,
|
|
81
|
+
(satisfying_model(?candidate_model), model_rank(?candidate_model, ?candidate_rank)),
|
|
82
|
+
?rank, ?model).
|
|
83
|
+
|
|
84
|
+
satModel(?model) :- best_model(?model, ?).
|
|
85
|
+
satValue(?var, ?value) :- best_model(?model, ?), lookup_bool(?var, ?model, ?value).
|
|
86
|
+
satClauseStatus(?clause, satisfied) :- best_model(?model, ?), clause_satisfied(?model, ?clause).
|
|
87
|
+
satConclusion(case, "DPLL finds a satisfying assignment after pruning clauses that become impossible") :-
|
|
88
|
+
best_model(?, ?).
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
% A tiny assumption-based truth maintenance system.
|
|
2
|
+
%
|
|
3
|
+
% An environment is a set of assumptions. Justifications derive beliefs from
|
|
4
|
+
% assumptions and from other derived beliefs. The TMS can therefore explain
|
|
5
|
+
% which environments support a belief and which environments are inconsistent
|
|
6
|
+
% because they support contradictory conclusions.
|
|
7
|
+
|
|
8
|
+
materialize(tmsSupport, 2).
|
|
9
|
+
materialize(tmsJustification, 3).
|
|
10
|
+
materialize(tmsInconsistent, 1).
|
|
11
|
+
materialize(tmsConclusion, 2).
|
|
12
|
+
|
|
13
|
+
table(supported, 2).
|
|
14
|
+
|
|
15
|
+
% Candidate environments.
|
|
16
|
+
environment(clear_only, [sensor_clear]).
|
|
17
|
+
environment(blocked_only, [sensor_blocked]).
|
|
18
|
+
environment(conflicting_sensors, [sensor_clear, sensor_blocked]).
|
|
19
|
+
environment(override_blocked, [sensor_blocked, operator_override]).
|
|
20
|
+
|
|
21
|
+
assumes(?environment, ?assumption) :-
|
|
22
|
+
environment(?environment, ?assumptions),
|
|
23
|
+
member(?assumption, ?assumptions).
|
|
24
|
+
|
|
25
|
+
% Justifications. Preconditions are either assumption(Name) or another derived
|
|
26
|
+
% belief. The last justification says an operator override can permit motion
|
|
27
|
+
% even when the blocked-path belief is also present.
|
|
28
|
+
justification(j_clear_path, [assumption(sensor_clear)], clear_path).
|
|
29
|
+
justification(j_blocked_path, [assumption(sensor_blocked)], blocked_path).
|
|
30
|
+
justification(j_permit_from_clear, [clear_path], permit_go).
|
|
31
|
+
justification(j_forbid_from_blocked, [blocked_path], forbid_go).
|
|
32
|
+
justification(j_override, [assumption(operator_override), blocked_path], permit_go).
|
|
33
|
+
|
|
34
|
+
all_hold(?, []).
|
|
35
|
+
all_hold(?environment, [assumption(?assumption) | ?rest]) :-
|
|
36
|
+
assumes(?environment, ?assumption),
|
|
37
|
+
all_hold(?environment, ?rest).
|
|
38
|
+
all_hold(?environment, [?belief | ?rest]) :-
|
|
39
|
+
supported(?environment, ?belief),
|
|
40
|
+
all_hold(?environment, ?rest).
|
|
41
|
+
|
|
42
|
+
supported(?environment, ?belief) :-
|
|
43
|
+
justification(?, ?preconditions, ?belief),
|
|
44
|
+
all_hold(?environment, ?preconditions).
|
|
45
|
+
|
|
46
|
+
contradicts(permit_go, forbid_go).
|
|
47
|
+
contradicts(forbid_go, permit_go).
|
|
48
|
+
inconsistent(?environment) :-
|
|
49
|
+
supported(?environment, ?left),
|
|
50
|
+
supported(?environment, ?right),
|
|
51
|
+
contradicts(?left, ?right).
|
|
52
|
+
|
|
53
|
+
% Show the actual justifications that fired, not just the final supported beliefs.
|
|
54
|
+
fires(?environment, ?justification, ?belief) :-
|
|
55
|
+
justification(?justification, ?preconditions, ?belief),
|
|
56
|
+
all_hold(?environment, ?preconditions).
|
|
57
|
+
|
|
58
|
+
tmsSupport(?environment, ?belief) :- supported(?environment, ?belief).
|
|
59
|
+
tmsJustification(?environment, ?justification, ?belief) :- fires(?environment, ?justification, ?belief).
|
|
60
|
+
tmsInconsistent(?environment) :- inconsistent(?environment).
|
|
61
|
+
tmsConclusion(case, "truth maintenance separates support from consistency across assumption environments") :-
|
|
62
|
+
inconsistent(conflicting_sensors).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
% Hindley-Milner-style type inference for a tiny lambda language.
|
|
2
|
+
%
|
|
3
|
+
% The example is intentionally small and deterministic. Lambda binders carry
|
|
4
|
+
% explicit type variables or annotations, and ordinary logic unification solves
|
|
5
|
+
% the constraints created by application, arithmetic, conditionals, and pairs.
|
|
6
|
+
% The symbolic names t0, t1, and t2 stand for schematic type variables in the
|
|
7
|
+
% displayed answers; concrete examples such as apply_id annotate the argument as
|
|
8
|
+
% int so the application can be checked.
|
|
9
|
+
materialize(type_answer, 2).
|
|
10
|
+
materialize(type_reason, 2).
|
|
11
|
+
|
|
12
|
+
table(type_expr, 3).
|
|
13
|
+
|
|
14
|
+
% Tiny expression language: int_lit/1, bool_lit/1, var/1, lam/3, app/2,
|
|
15
|
+
% add/2, if/3, pair/2, fst/1, and snd/1.
|
|
16
|
+
program(id, lam(x, t0, var(x))).
|
|
17
|
+
program(const, lam(x, t0, lam(y, t1, var(x)))).
|
|
18
|
+
program(apply_id, app(lam(x, int, var(x)), int_lit(42))).
|
|
19
|
+
program(compose,
|
|
20
|
+
lam(f, fun(t1, t2),
|
|
21
|
+
lam(g, fun(t0, t1),
|
|
22
|
+
lam(x, t0,
|
|
23
|
+
app(var(f), app(var(g), var(x))))))).
|
|
24
|
+
program(branch,
|
|
25
|
+
if(bool_lit(true), add(int_lit(20), int_lit(22)), int_lit(0))).
|
|
26
|
+
program(first_of_pair, fst(pair(bool_lit(true), int_lit(7)))).
|
|
27
|
+
|
|
28
|
+
lookup(?name, [[?name, ?type] | ?], ?type).
|
|
29
|
+
lookup(?name, [[?, ?] | ?rest], ?type) :- lookup(?name, ?rest, ?type).
|
|
30
|
+
|
|
31
|
+
type_expr(?, int_lit(?), int).
|
|
32
|
+
type_expr(?, bool_lit(?), bool).
|
|
33
|
+
type_expr(?env, var(?name), ?type) :- lookup(?name, ?env, ?type).
|
|
34
|
+
type_expr(?env, lam(?name, ?arg_type, ?body), fun(?arg_type, ?body_type)) :-
|
|
35
|
+
type_expr([[?name, ?arg_type] | ?env], ?body, ?body_type).
|
|
36
|
+
type_expr(?env, app(?fn, ?arg), ?result_type) :-
|
|
37
|
+
type_expr(?env, ?fn, fun(?arg_type, ?result_type)),
|
|
38
|
+
type_expr(?env, ?arg, ?arg_type).
|
|
39
|
+
type_expr(?env, add(?left, ?right), int) :-
|
|
40
|
+
type_expr(?env, ?left, int),
|
|
41
|
+
type_expr(?env, ?right, int).
|
|
42
|
+
type_expr(?env, if(?cond, ?then, ?else), ?type) :-
|
|
43
|
+
type_expr(?env, ?cond, bool),
|
|
44
|
+
type_expr(?env, ?then, ?type),
|
|
45
|
+
type_expr(?env, ?else, ?type).
|
|
46
|
+
type_expr(?env, pair(?left, ?right), pair(?left_type, ?right_type)) :-
|
|
47
|
+
type_expr(?env, ?left, ?left_type),
|
|
48
|
+
type_expr(?env, ?right, ?right_type).
|
|
49
|
+
type_expr(?env, fst(?pair), ?left_type) :-
|
|
50
|
+
type_expr(?env, ?pair, pair(?left_type, ?)).
|
|
51
|
+
type_expr(?env, snd(?pair), ?right_type) :-
|
|
52
|
+
type_expr(?env, ?pair, pair(?, ?right_type)).
|
|
53
|
+
|
|
54
|
+
type_answer(?name, ?type) :- program(?name, ?expr), type_expr([], ?expr, ?type).
|
|
55
|
+
type_reason(compose, "application unifies f with t1 -> t2 and g with t0 -> t1") :-
|
|
56
|
+
type_answer(compose, ?).
|
|
57
|
+
type_reason(apply_id, "the identity function's parameter type is unified with int") :-
|
|
58
|
+
type_answer(apply_id, int).
|
package/package.json
CHANGED
package/playground.html
CHANGED
|
@@ -434,6 +434,7 @@
|
|
|
434
434
|
|
|
435
435
|
<script type="module">
|
|
436
436
|
const EXAMPLES = [
|
|
437
|
+
"abstract-interpretation",
|
|
437
438
|
"access-control-policy",
|
|
438
439
|
"ackermann",
|
|
439
440
|
"age",
|
|
@@ -538,6 +539,7 @@
|
|
|
538
539
|
"list-collection",
|
|
539
540
|
"lldm",
|
|
540
541
|
"manufacturing-quality-control",
|
|
542
|
+
"markov-logic-network",
|
|
541
543
|
"map-four-color-search",
|
|
542
544
|
"matrix-chain-order",
|
|
543
545
|
"matrix-noncommutativity",
|
|
@@ -561,6 +563,7 @@
|
|
|
561
563
|
"peasant",
|
|
562
564
|
"pell-equation",
|
|
563
565
|
"pendulum-period",
|
|
566
|
+
"pointer-analysis",
|
|
564
567
|
"polynomial",
|
|
565
568
|
"prime-range",
|
|
566
569
|
"proof-contrapositive",
|
|
@@ -569,6 +572,7 @@
|
|
|
569
572
|
"reusable-builtins",
|
|
570
573
|
"riemann-hypothesis",
|
|
571
574
|
"route-planning",
|
|
575
|
+
"sat-solver-dpll",
|
|
572
576
|
"security-incident-correlation",
|
|
573
577
|
"send-more-money",
|
|
574
578
|
"service-impact",
|
|
@@ -587,6 +591,8 @@
|
|
|
587
591
|
"term-tools",
|
|
588
592
|
"totient-summatory",
|
|
589
593
|
"trust-flow-provenance-threshold",
|
|
594
|
+
"truth-maintenance-system",
|
|
595
|
+
"type-inference",
|
|
590
596
|
"turing",
|
|
591
597
|
"vector-similarity",
|
|
592
598
|
"vulnerability-impact",
|