1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package io.github.prolobjectlink.prolog.jpl7;
30
31 import static io.github.prolobjectlink.prolog.PrologLogger.IO;
32
33 import java.io.File;
34 import java.io.FileNotFoundException;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.io.PrintWriter;
38 import java.io.Reader;
39 import java.util.ArrayList;
40 import java.util.HashSet;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Set;
44
45 import org.jpl7.Atom;
46 import org.jpl7.Query;
47 import org.jpl7.Term;
48 import org.jpl7.Util;
49
50 import io.github.prolobjectlink.prolog.AbstractEngine;
51 import io.github.prolobjectlink.prolog.ArrayIterator;
52 import io.github.prolobjectlink.prolog.PrologClause;
53 import io.github.prolobjectlink.prolog.PrologEngine;
54 import io.github.prolobjectlink.prolog.PrologIndicator;
55 import io.github.prolobjectlink.prolog.PrologOperator;
56 import io.github.prolobjectlink.prolog.PrologProgram;
57 import io.github.prolobjectlink.prolog.PrologProvider;
58 import io.github.prolobjectlink.prolog.PrologQuery;
59 import io.github.prolobjectlink.prolog.PrologTerm;
60 import io.github.prolobjectlink.prolog.PrologTermType;
61
62
63
64
65
66
67 public abstract class JplEngine extends AbstractEngine implements PrologEngine {
68
69
70 private static final String KEY = "X";
71
72
73 private static final Term BODY = new Atom("true");
74
75
76 private static String cache = null;
77
78
79 private final JplParser parser = new JplParser();
80
81
82 private JplProgram program = new JplProgram();
83
84
85 private static String consultCacheComma;
86 static {
87 try {
88 File f = File.createTempFile("prolobjectlink-jpi-jpl7-cache-", ".pl");
89 cache = f.getCanonicalPath().replace(File.separatorChar, '/');
90 consultCacheComma = "consult('" + cache + "'),";
91 } catch (IOException e) {
92 JplProvider.logger.error(JplEngine.class, IO, e);
93 }
94 }
95
96 protected JplEngine(PrologProvider provider) {
97 super(provider);
98 }
99
100 protected JplEngine(PrologProvider provider, String path) {
101 super(provider);
102 consult(path);
103 }
104
105 public final void consult(String path) {
106 program = parser.parseProgram(path);
107 persist(cache);
108 }
109
110 public final void consult(Reader reader) {
111 program = parser.parseProgram(reader);
112 persist(cache);
113 }
114
115 public final void include(String path) {
116 program.add(parser.parseProgram(path));
117 persist(cache);
118 }
119
120 public final void include(Reader reader) {
121 program.add(parser.parseProgram(reader));
122 persist(cache);
123 }
124
125 public final void persist(String path) {
126 PrintWriter writer = null;
127 try {
128 writer = new PrintWriter(new FileOutputStream(path, false));
129 writer.print(program);
130 } catch (FileNotFoundException e) {
131 getLogger().error(getClass(), IO + cache, e);
132 } finally {
133 if (writer != null) {
134 writer.close();
135 }
136 }
137 }
138
139 public final void abolish(String functor, int arity) {
140 program.removeAll(functor, arity);
141 persist(cache);
142 }
143
144 public final void asserta(String stringClause) {
145 asserta(Util.textToTerm(stringClause));
146 }
147
148 public final void asserta(PrologTerm term) {
149 asserta(fromTerm(term, Term.class));
150 }
151
152 public final void asserta(PrologTerm head, PrologTerm... body) {
153 asserta(fromTerm(head, body, Term.class));
154 }
155
156 private void asserta(Term t) {
157 program.push(t);
158 persist(cache);
159 }
160
161 public final void assertz(String stringClause) {
162 assertz(Util.textToTerm(stringClause));
163 }
164
165 public final void assertz(PrologTerm term) {
166 assertz(fromTerm(term, Term.class));
167 }
168
169 public final void assertz(PrologTerm head, PrologTerm... body) {
170 assertz(fromTerm(head, body, Term.class));
171 }
172
173 private void assertz(Term t) {
174 program.add(t);
175 persist(cache);
176 }
177
178 public final boolean clause(String stringClause) {
179 return clause(Util.textToTerm(stringClause));
180 }
181
182 public final boolean clause(PrologTerm term) {
183 return clause(fromTerm(term, Term.class));
184 }
185
186 public final boolean clause(PrologTerm head, PrologTerm... body) {
187 return clause(fromTerm(head, body, Term.class));
188 }
189
190 private boolean clause(Term t) {
191 Term h = t;
192 Term b = BODY;
193 if (t.hasFunctor(":-", 2)) {
194 h = t.arg(1);
195 b = t.arg(2);
196 }
197 return new JplQuery(
198
199 this, cache, "clause(" + h + "," + b + ")"
200
201 ).hasSolution();
202 }
203
204 public final void retract(String stringClause) {
205 retract(Util.textToTerm(stringClause));
206 }
207
208 public final void retract(PrologTerm term) {
209 retract(fromTerm(term, Term.class));
210 }
211
212 public final void retract(PrologTerm head, PrologTerm... body) {
213 retract(provider.fromTerm(head, body, Term.class));
214 }
215
216 private void retract(Term t) {
217 program.remove(t);
218 persist(cache);
219 }
220
221 public final PrologQuery query(String stringQuery) {
222 return new JplQuery(this, cache, stringQuery);
223 }
224
225 public final PrologQuery query(PrologTerm term) {
226 StringBuilder buffer = new StringBuilder();
227 buffer.append("" + term + ".");
228 return query("" + buffer + "");
229 }
230
231 public final PrologQuery query(PrologTerm[] terms) {
232 Iterator<PrologTerm> i = new ArrayIterator<PrologTerm>(terms);
233 StringBuilder buffer = new StringBuilder();
234 while (i.hasNext()) {
235 buffer.append(i.next());
236 if (i.hasNext()) {
237 buffer.append(',');
238 }
239 }
240 buffer.append(".");
241 return query("" + buffer + "");
242 }
243
244 public final PrologQuery query(PrologTerm term, PrologTerm... terms) {
245 Iterator<PrologTerm> i = new ArrayIterator<PrologTerm>(terms);
246 StringBuilder buffer = new StringBuilder();
247 buffer.append("" + term + "");
248 while (i.hasNext()) {
249 buffer.append(',');
250 buffer.append(i.next());
251 }
252 buffer.append(".");
253 return query("" + buffer + "");
254 }
255
256 public final void operator(int priority, String specifier, String operator) {
257 new Query(consultCacheComma + "op(" + priority + "," + specifier + ", " + operator + ")").hasSolution();
258 }
259
260 public final boolean currentPredicate(String functor, int arity) {
261 String x = functor;
262 if (x.startsWith("'") && x.endsWith("'")) {
263 x = x.substring(1, x.length() - 1);
264 }
265 return getPredicates().contains(new JplIndicator(x, arity));
266 }
267
268 public final boolean currentOperator(int priority, String specifier, String operator) {
269 return new Query(consultCacheComma + "current_op(" + priority + "," + specifier + ", " + operator + ")")
270 .hasSolution();
271 }
272
273 public final Set<PrologOperator> currentOperators() {
274 Set<PrologOperator> operators = new HashSet<PrologOperator>();
275 String opQuery = consultCacheComma + "findall(P/S/O,current_op(P,S,O)," + KEY + ")";
276 Query query = new Query(opQuery);
277 if (query.hasSolution()) {
278 Term term = query.oneSolution().get(KEY);
279 Term[] termArray = term.toTermArray();
280 for (Term t : termArray) {
281 Term prio = t.arg(1).arg(1);
282 Term pos = t.arg(1).arg(2);
283 Term op = t.arg(2);
284
285 int p = prio.intValue();
286 String s = pos.name();
287 String n = op.name();
288
289 PrologOperator o = new JplOperator(p, s, n);
290 operators.add(o);
291 }
292 }
293 query.close();
294 return operators;
295 }
296
297 public final int getProgramSize() {
298 return program.size();
299 }
300
301 public final PrologProgram getProgram() {
302 return new JplScript(this);
303 }
304
305 public final Set<PrologIndicator> getPredicates() {
306 Set<PrologIndicator> indicators = new HashSet<PrologIndicator>();
307 String opQuery = consultCacheComma + "findall(X/Y,current_predicate(X/Y)," + KEY + ")";
308 Query query = new Query(opQuery);
309 if (query.hasSolution()) {
310 Term term = query.oneSolution().get(KEY);
311 Term[] termArray = term.toTermArray();
312 for (Term t : termArray) {
313 Term f = t.arg(1);
314 Term a = t.arg(2);
315
316 int arity = a.intValue();
317 String functor = f.name();
318
319 JplIndicator pi = new JplIndicator(functor, arity);
320 indicators.add(pi);
321 }
322 }
323 return indicators;
324 }
325
326 public final Set<PrologIndicator> getBuiltIns() {
327 Set<PrologIndicator> indicators = new HashSet<PrologIndicator>();
328 String opQuery = consultCacheComma + "findall(X/Y,current_predicate(X/Y)," + KEY + ")";
329 Query query = new Query(opQuery);
330 if (query.hasSolution()) {
331 Term term = query.oneSolution().get(KEY);
332 Term[] termArray = term.toTermArray();
333 for (Term t : termArray) {
334 Term f = t.arg(1);
335 Term a = t.arg(2);
336
337 int arity = a.intValue();
338 String functor = f.name();
339
340 JplIndicator pi = new JplIndicator(functor, arity);
341 indicators.add(pi);
342 }
343 }
344 Set<PrologClause> clauses = getProgramClauses();
345 for (PrologClause prologClause : clauses) {
346 PrologIndicator pi = prologClause.getPrologIndicator();
347 if (indicators.contains(pi)) {
348 indicators.remove(pi);
349 }
350 }
351 return indicators;
352 }
353
354 public final Iterator<PrologClause> iterator() {
355 List<PrologClause> cls = new ArrayList<PrologClause>();
356 for (List<Term> family : program.getClauses().values()) {
357 for (Term clause : family) {
358 if (clause.hasFunctor(":-", 2)) {
359 PrologTerm head = toTerm(clause.arg(1), PrologTerm.class);
360 PrologTerm body = toTerm(clause.arg(2), PrologTerm.class);
361 if (body.getType() != PrologTermType.TRUE_TYPE) {
362 cls.add(new JplClause(provider, head, body, false, false, false));
363 } else {
364 cls.add(new JplClause(provider, head, false, false, false));
365 }
366 } else {
367 cls.add(new JplClause(provider, toTerm(clause, PrologTerm.class), false, false, false));
368 }
369 }
370 }
371 return new PrologProgramIterator(cls);
372 }
373
374 public final void dispose() {
375 File c = new File(cache);
376 PrintWriter writer = null;
377 try {
378 writer = new PrintWriter(new FileOutputStream(cache, false));
379 writer.print("");
380 } catch (FileNotFoundException e) {
381 getLogger().error(getClass(), IO + cache, e);
382 } finally {
383 if (writer != null) {
384 writer.close();
385 }
386 }
387 c.deleteOnExit();
388 program.clear();
389 }
390
391 public final String getCache() {
392 return cache;
393 }
394
395 @Override
396 public int hashCode() {
397 final int prime = 31;
398 int result = super.hashCode();
399 result = prime * result + ((program == null) ? 0 : program.hashCode());
400 return result;
401 }
402
403 @Override
404 public boolean equals(Object obj) {
405 if (this == obj)
406 return true;
407 if (!super.equals(obj))
408 return false;
409 if (getClass() != obj.getClass())
410 return false;
411 JplEngine other = (JplEngine) obj;
412 if (program == null) {
413 if (other.program != null)
414 return false;
415 } else if (!program.equals(other.program)) {
416 return false;
417 }
418 return true;
419 }
420
421 }