Libraryless. Click here for Pure Java version (1185L/8K/28K).
1 | !752 |
2 | |
3 | static class Prolog {
|
4 | int varCount; |
5 | boolean showStuff; |
6 | |
7 | class Var extends Lisp {
|
8 | Lisp instance; |
9 | |
10 | *() {
|
11 | this("V" + (++varCount));
|
12 | } |
13 | |
14 | *(S name) {
|
15 | super(name); |
16 | instance = this; |
17 | } |
18 | |
19 | void reset() { instance = this; }
|
20 | |
21 | public String toString() {
|
22 | if (instance == this) ret getName(); |
23 | ret instance.toString(); |
24 | } |
25 | |
26 | S getName() {
|
27 | ret head; |
28 | } |
29 | } |
30 | |
31 | class Clause {
|
32 | Lisp head; |
33 | Goal body; |
34 | |
35 | *(Lisp *head, Goal *body) {}
|
36 | *(Lisp *head) {}
|
37 | |
38 | Clause copy() {
|
39 | return new Clause(copy2(head), body == null ? null : body.copy()); |
40 | } |
41 | |
42 | public String toString() {
|
43 | //ret head + " :- " + (body == null ? "true" : body); |
44 | ret body == null ? head.toString() : head + " :- " + body; |
45 | } |
46 | }; |
47 | |
48 | static class Program {
|
49 | Clause pcar; |
50 | Program pcdr; |
51 | |
52 | *(Clause *pcar, Program *pcdr) {}
|
53 | *(L<Clause> clauses) {
|
54 | this(clauses, 0); |
55 | } |
56 | |
57 | *(L<Clause> clauses, int i) {
|
58 | pcar = clauses.get(i); |
59 | if (i+1 < l(clauses)) |
60 | pcdr = new Program(clauses, i+1); |
61 | } |
62 | |
63 | *(Clause... clauses) {
|
64 | this(asList(clauses)); |
65 | } |
66 | |
67 | public String toString() {
|
68 | ret pcdr == null ? pcar + "." : pcar + ".\n" + pcdr; |
69 | } |
70 | } |
71 | |
72 | class Trail {
|
73 | Var tcar; |
74 | Trail tcdr; |
75 | |
76 | *(Var *tcar, Trail *tcdr) {}
|
77 | } |
78 | |
79 | Trail sofar = null; |
80 | |
81 | Trail Trail_Note() { return sofar; }
|
82 | void Trail_Push(Var x) { sofar = new Trail(x, sofar); }
|
83 | void Trail_Undo(Trail whereto) {
|
84 | for (; sofar != whereto; sofar = sofar.tcdr) |
85 | sofar.tcar.reset(); |
86 | } |
87 | |
88 | static class TermVarMapping {
|
89 | new L<Var> vars; |
90 | |
91 | *(L<Var> *vars) {}
|
92 | *(Var... vars) { this.vars.addAll(asList(vars)); }
|
93 | |
94 | void showanswer() {
|
95 | print("TRUE.");
|
96 | for (Var v : vars) |
97 | print(" " + v.getName() + " = " + v);
|
98 | } |
99 | } |
100 | |
101 | class Goal {
|
102 | Lisp car; |
103 | Goal cdr; |
104 | |
105 | *(Lisp *car, Goal *cdr) {}
|
106 | *(Lisp *car) {}
|
107 | |
108 | public String toString() {
|
109 | ret cdr == null ? car.toString() : car + "; " + cdr; |
110 | } |
111 | |
112 | void solve(Program p, int level, TermVarMapping map) {
|
113 | if (showStuff) |
114 | print(indent(level) + "solve@" + level + ": " + this); |
115 | |
116 | for (Program q = p; q != null; q = q.pcdr) {
|
117 | Trail t = Trail_Note(); |
118 | Clause c = q.pcar.copy(); |
119 | Trail_Undo(t); |
120 | if (showStuff) |
121 | print(indent(level) + " try:" + c); |
122 | if (unify(car, c.head)) {
|
123 | Goal gdash = c.body == null ? cdr : c.body.append(cdr); |
124 | if (gdash == null) |
125 | map.showanswer(); |
126 | else |
127 | gdash.solve(p, level+1, map); |
128 | } else |
129 | if (showStuff) |
130 | print(indent(level) + " nomatch."); |
131 | Trail_Undo(t); |
132 | } |
133 | } |
134 | |
135 | Goal copy() {
|
136 | return new Goal(copy2(car), |
137 | cdr == null ? null : cdr.copy()); |
138 | } |
139 | |
140 | Goal append(Goal l) {
|
141 | return new Goal(car, cdr == null ? null : cdr.append(l)); |
142 | } |
143 | |
144 | } // class Goal |
145 | |
146 | boolean unify(Lisp thiz, Lisp t) {
|
147 | if (thiz instanceof Var) { // TermVar::unify
|
148 | Var v = cast thiz; |
149 | if (v.instance != v) |
150 | return unify(v.instance, t); |
151 | Trail_Push(v); |
152 | v.instance = t; |
153 | return true; |
154 | } |
155 | |
156 | // TermCons::unify |
157 | return unify2(t, thiz); |
158 | } |
159 | |
160 | boolean unify2(Lisp thiz, Lisp t) {
|
161 | if (thiz instanceof Var) |
162 | return unify(thiz, t); |
163 | |
164 | int arity = thiz.size(); |
165 | if (neq(thiz.head, t.head) || arity != t.size()) |
166 | return false; |
167 | for (int i = 0; i < arity; i++) |
168 | if (!unify(thiz.get(i), t.get(i))) |
169 | return false; |
170 | return true; |
171 | } |
172 | |
173 | Lisp copy(Lisp thiz) {
|
174 | if (thiz instanceof Var) {
|
175 | Var v = cast thiz; |
176 | if (v.instance == v) {
|
177 | Trail_Push(v); |
178 | v.instance = new Var(); |
179 | } |
180 | return v.instance; |
181 | } |
182 | |
183 | ret copy2(thiz); |
184 | } |
185 | |
186 | Lisp newTermCons(Lisp t) {
|
187 | Lisp l = new Lisp(t.head); |
188 | for (Lisp arg : t) |
189 | l.add(copy(arg)); |
190 | ret l; |
191 | } |
192 | |
193 | Lisp copy2(Lisp thiz) {
|
194 | return newTermCons(thiz); |
195 | } |
196 | |
197 | Var newVar() {
|
198 | ret new Var; |
199 | } |
200 | |
201 | Var newVar(S name) {
|
202 | ret new Var(name); |
203 | } |
204 | |
205 | Clause clause(Lisp head, Goal body) {
|
206 | ret new Clause(head, body); |
207 | } |
208 | |
209 | Clause clause(Lisp head) {
|
210 | ret new Clause(head); |
211 | } |
212 | |
213 | } // class Prolog |
214 | |
215 | p {
|
216 | new Prolog p; |
217 | |
218 | /* A sample test program: append */ |
219 | |
220 | S at_app = "app"; |
221 | S at_cons = "cons"; |
222 | Lisp f_nil = lisp("nil");
|
223 | Lisp f_1 = lisp("1");
|
224 | Lisp f_2 = lisp("2");
|
225 | Lisp f_3 = lisp("3");
|
226 | |
227 | Lisp v_x = p.newVar(); |
228 | Lisp lhs1 = lisp(at_app, f_nil, v_x, v_x); |
229 | Prolog.Clause c1 = p.clause(lhs1); |
230 | |
231 | Lisp v_l = p.newVar(); |
232 | Lisp v_m = p.newVar(); |
233 | Lisp v_n = p.newVar(); |
234 | Lisp rhs2 = lisp(at_app, v_l, v_m, v_n); |
235 | Lisp lhs2 = lisp(at_app, lisp(at_cons, v_x, v_l), |
236 | v_m, |
237 | lisp(at_cons, v_x, v_n)); |
238 | |
239 | Prolog.Clause c2 = p.clause(lhs2, p.new Goal(rhs2)); |
240 | |
241 | Prolog.Var v_i = p.newVar("I");
|
242 | Prolog.Var v_j = p.newVar("J");
|
243 | Lisp rhs3 = lisp(at_app, v_i, v_j, |
244 | lisp(at_cons, f_1, |
245 | lisp(at_cons, f_2, |
246 | lisp(at_cons, f_3, f_nil)))); |
247 | |
248 | Prolog.Goal g1 = p.new Goal(rhs3); |
249 | |
250 | Prolog.Program test_p = new Prolog.Program(c1, c2); |
251 | Prolog.Program test_p2 = new Prolog.Program(c2, c1); |
252 | |
253 | Prolog.TermVarMapping var_name_map = new Prolog.TermVarMapping(v_i, v_j); |
254 | |
255 | p.showStuff = true; |
256 | print("=======Append with normal clause order:");
|
257 | print(test_p); |
258 | print(); |
259 | g1.solve(test_p, 0, var_name_map); |
260 | print(); |
261 | /* |
262 | print("=======Append with reversed normal clause order:");
|
263 | print(test_p2); |
264 | print(); |
265 | g1.solve(test_p2, 0, var_name_map); |
266 | */ |
267 | } |
Began life as a copy of #1002819
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1002820 |
| Snippet name: | Prolog Interpreter (as class) |
| Eternal ID of this version: | #1002820/1 |
| Text MD5: | b84c5f3414fdc35b84061aba6117dd6b |
| Transpilation MD5: | f1575e8579588948981d3236be361832 |
| Author: | stefan |
| Category: | javax |
| Type: | JavaX source code |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2016-02-29 01:00:28 |
| Source code size: | 6099 bytes / 267 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 1073 / 1115 |
| Referenced in: | [show references] |