eyelang 1.7.13 → 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 +5 -0
- package/examples/abstract-interpretation.eye +50 -0
- package/examples/output/abstract-interpretation.eye +16 -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 +5 -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) |
|
|
@@ -438,6 +439,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
438
439
|
| [`peasant.eye`](../examples/peasant.eye) | Performs peasant multiplication and exponentiation. | [`output/peasant.eye`](../examples/output/peasant.eye) |
|
|
439
440
|
| [`pell-equation.eye`](../examples/pell-equation.eye) | Generates Pell-equation solutions by recurrence. | [`output/pell-equation.eye`](../examples/output/pell-equation.eye) |
|
|
440
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) |
|
|
441
443
|
| [`polynomial.eye`](../examples/polynomial.eye) | Finds complex integer polynomial roots. | [`output/polynomial.eye`](../examples/output/polynomial.eye) |
|
|
442
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) |
|
|
443
445
|
| [`proof-contrapositive.eye`](../examples/proof-contrapositive.eye) | Models proof by contrapositive. | [`output/proof-contrapositive.eye`](../examples/output/proof-contrapositive.eye) |
|
|
@@ -446,6 +448,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
446
448
|
| [`reusable-builtins.eye`](../examples/reusable-builtins.eye) | Tours reusable numeric, list, and string builtins. | [`output/reusable-builtins.eye`](../examples/output/reusable-builtins.eye) |
|
|
447
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) |
|
|
448
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) |
|
|
449
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) |
|
|
450
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) |
|
|
451
454
|
| [`service-impact.eye`](../examples/service-impact.eye) | Analyzes service impact over cyclic dependencies. | [`output/service-impact.eye`](../examples/output/service-impact.eye) |
|
|
@@ -464,6 +467,8 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
464
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) |
|
|
465
468
|
| [`totient-summatory.eye`](../examples/totient-summatory.eye) | Computes Euler totients and their summatory function. | [`output/totient-summatory.eye`](../examples/output/totient-summatory.eye) |
|
|
466
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) |
|
|
467
472
|
| [`turing.eye`](../examples/turing.eye) | Simulates a binary-increment Turing machine. | [`output/turing.eye`](../examples/output/turing.eye) |
|
|
468
473
|
| [`vector-similarity.eye`](../examples/vector-similarity.eye) | Computes dot product, norm, and cosine similarity. | [`output/vector-similarity.eye`](../examples/output/vector-similarity.eye) |
|
|
469
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,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,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",
|
|
@@ -562,6 +563,7 @@
|
|
|
562
563
|
"peasant",
|
|
563
564
|
"pell-equation",
|
|
564
565
|
"pendulum-period",
|
|
566
|
+
"pointer-analysis",
|
|
565
567
|
"polynomial",
|
|
566
568
|
"prime-range",
|
|
567
569
|
"proof-contrapositive",
|
|
@@ -570,6 +572,7 @@
|
|
|
570
572
|
"reusable-builtins",
|
|
571
573
|
"riemann-hypothesis",
|
|
572
574
|
"route-planning",
|
|
575
|
+
"sat-solver-dpll",
|
|
573
576
|
"security-incident-correlation",
|
|
574
577
|
"send-more-money",
|
|
575
578
|
"service-impact",
|
|
@@ -588,6 +591,8 @@
|
|
|
588
591
|
"term-tools",
|
|
589
592
|
"totient-summatory",
|
|
590
593
|
"trust-flow-provenance-threshold",
|
|
594
|
+
"truth-maintenance-system",
|
|
595
|
+
"type-inference",
|
|
591
596
|
"turing",
|
|
592
597
|
"vector-similarity",
|
|
593
598
|
"vulnerability-impact",
|