1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package io.github.prolobjectlink.prolog.jtrolog;
23
24 import static io.github.prolobjectlink.prolog.PrologLogger.DONT_WORRY;
25 import static io.github.prolobjectlink.prolog.PrologLogger.FILE_NOT_FOUND;
26 import static io.github.prolobjectlink.prolog.PrologLogger.INDICATOR_NOT_FOUND;
27 import static io.github.prolobjectlink.prolog.PrologLogger.IO;
28 import static io.github.prolobjectlink.prolog.PrologLogger.RUNTIME_ERROR;
29 import static io.github.prolobjectlink.prolog.PrologLogger.SYNTAX_ERROR;
30
31 import java.io.BufferedReader;
32 import java.io.FileInputStream;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.PrintWriter;
37 import java.io.Reader;
38 import java.lang.reflect.Method;
39 import java.util.Arrays;
40 import java.util.Collection;
41 import java.util.HashSet;
42 import java.util.Iterator;
43 import java.util.LinkedList;
44 import java.util.List;
45 import java.util.Set;
46
47 import io.github.prolobjectlink.prolog.AbstractEngine;
48 import io.github.prolobjectlink.prolog.Licenses;
49 import io.github.prolobjectlink.prolog.PrologClause;
50 import io.github.prolobjectlink.prolog.PrologEngine;
51 import io.github.prolobjectlink.prolog.PrologIndicator;
52 import io.github.prolobjectlink.prolog.PrologLogger;
53 import io.github.prolobjectlink.prolog.PrologOperator;
54 import io.github.prolobjectlink.prolog.PrologProgram;
55 import io.github.prolobjectlink.prolog.PrologProvider;
56 import io.github.prolobjectlink.prolog.PrologQuery;
57 import io.github.prolobjectlink.prolog.PrologTerm;
58 import jTrolog.engine.Prolog;
59 import jTrolog.errors.PrologException;
60 import jTrolog.lib.BuiltIn;
61 import jTrolog.lib.IOLibrary;
62 import jTrolog.lib.Library;
63 import jTrolog.parser.Parser;
64 import jTrolog.terms.Clause;
65 import jTrolog.terms.Struct;
66 import jTrolog.terms.StructAtom;
67 import jTrolog.terms.Term;
68
69
70
71
72
73
74 public class JTrologEngine extends AbstractEngine implements PrologEngine {
75
76 final Prolog engine;
77
78 protected JTrologEngine(PrologProvider provider, Prolog engine) {
79 super(provider);
80 this.engine = engine;
81 }
82
83 public void consult(String path) {
84 engine.clearTheory();
85 include(path);
86 }
87
88 public void consult(Reader reader) {
89 engine.clearTheory();
90 include(reader);
91 }
92
93 public void include(String path) {
94 try {
95 InputStream is = new FileInputStream(path);
96 engine.addTheory(IOLibrary.readStream(is));
97 } catch (FileNotFoundException e) {
98 getLogger().warn(getClass(), FILE_NOT_FOUND + path, e);
99 } catch (PrologException e) {
100 getLogger().error(getClass(), SYNTAX_ERROR + path, e);
101 } catch (IOException e) {
102 getLogger().warn(getClass(), IO + path, e);
103 }
104 }
105
106 public void include(Reader reader) {
107 BufferedReader bfr = new BufferedReader(reader);
108 StringBuilder script = new StringBuilder();
109 try {
110 String line = bfr.readLine();
111 while (line != null) {
112 script.append(line);
113 script.append("\n");
114 line = bfr.readLine();
115 }
116 engine.addTheory("" + script + "");
117 } catch (PrologException e) {
118 getLogger().error(getClass(), SYNTAX_ERROR + script, e);
119 } catch (IOException e) {
120 getLogger().warn(getClass(), IO + script, e);
121 }
122 }
123
124 public void persist(String path) {
125 PrintWriter writer = null;
126 try {
127 writer = new PrintWriter(path);
128 writer.write(engine.getTheory());
129 } catch (IOException e) {
130 getLogger().warn(getClass(), IO + path, e);
131 getLogger().info(getClass(), DONT_WORRY + path);
132 } finally {
133 if (writer != null) {
134 writer.close();
135 }
136 }
137 }
138
139 public void abolish(String functor, int arity) {
140 String pi = functor + "/" + arity;
141 try {
142 engine.abolish(pi);
143 } catch (PrologException e) {
144 getLogger().error(getClass(), INDICATOR_NOT_FOUND, e);
145 }
146 }
147
148 private boolean exist(Clause clause) {
149 String name = clause.head.name;
150 StructAtom functor = new StructAtom(name);
151 String key = functor + "/" + clause.head.arity;
152 Iterator<?> i = engine.dynamicPredicateIndicators();
153 while (i.hasNext()) {
154 String predIndicator = (String) i.next();
155 if (predIndicator.equals(key)) {
156 try {
157 List<?> list = engine.find(predIndicator);
158 for (Object object : list) {
159 if (object instanceof Clause) {
160 Clause iclause = (Clause) object;
161 if (iclause.head.equals(clause.head)) {
162
163 Struct[] xclausetail = iclause.tail.length > 0 ? iclause.tail
164 : new Struct[] { (Struct) Term.TRUE };
165 Struct[] yclausetail = clause.tail.length > 0 ? clause.tail
166 : new Struct[] { (Struct) Term.TRUE };
167
168 if (xclausetail.length != yclausetail.length) {
169 return false;
170 }
171
172 for (int j = 0; j < yclausetail.length; j++) {
173 if (!xclausetail[j].equals(yclausetail[j])) {
174 return false;
175 }
176
177 }
178
179 return true;
180 }
181 }
182 }
183 } catch (PrologException e) {
184 getLogger().error(getClass(), INDICATOR_NOT_FOUND, e);
185 }
186 }
187 }
188 return false;
189 }
190
191 public void asserta(String stringClause) {
192 try {
193 Term term = new Parser(stringClause).nextTerm(false);
194 asserta(BuiltIn.convertTermToClause(term));
195 } catch (PrologException e) {
196 getLogger().error(getClass(), SYNTAX_ERROR + stringClause, e);
197 }
198 }
199
200 @Override
201 public void asserta(PrologTerm term) {
202 asserta("" + term + "");
203 }
204
205 public void asserta(PrologTerm head, PrologTerm... body) {
206 Struct h = fromTerm(head, Struct.class);
207 Struct[] b = new Struct[body.length];
208 for (int i = 0; i < body.length; i++) {
209 b[i] = fromTerm(body[i], Struct.class);
210 }
211 Struct o = fromTerm(head, body, Struct.class);
212 asserta(new Clause(b, h, o));
213 }
214
215 private void asserta(Clause clause) {
216 if (!exist(clause)) {
217 try {
218 engine.assertA(clause);
219 } catch (PrologException e) {
220 getLogger().error(getClass(), RUNTIME_ERROR, e);
221 }
222 }
223 }
224
225 public void assertz(String stringClause) {
226 try {
227 Term term = new Parser(stringClause).nextTerm(false);
228 assertz(BuiltIn.convertTermToClause(term));
229 } catch (PrologException e) {
230 getLogger().error(getClass(), SYNTAX_ERROR + stringClause, e);
231 }
232 }
233
234 @Override
235 public void assertz(PrologTerm term) {
236 assertz("" + term + "");
237 }
238
239 public void assertz(PrologTerm head, PrologTerm... body) {
240 Struct h = fromTerm(head, Struct.class);
241 Struct[] b = new Struct[body.length];
242 for (int i = 0; i < body.length; i++) {
243 b[i] = fromTerm(body[i], Struct.class);
244 }
245 Struct o = fromTerm(head, body, Struct.class);
246 assertz(new Clause(b, h, o));
247 }
248
249 private void assertz(Clause clause) {
250 if (!exist(clause)) {
251 try {
252 engine.assertZ(clause);
253 } catch (PrologException e) {
254 getLogger().error(getClass(), RUNTIME_ERROR, e);
255 }
256 }
257 }
258
259 public boolean clause(String stringClause) {
260 try {
261 Term term = new Parser(stringClause).nextTerm(false);
262 return clause(BuiltIn.convertTermToClause(term));
263 } catch (PrologException e) {
264 getLogger().error(getClass(), SYNTAX_ERROR + stringClause, e);
265 }
266 return false;
267 }
268
269 @Override
270 public boolean clause(PrologTerm term) {
271 return clause("" + term + "");
272 }
273
274 public boolean clause(PrologTerm head, PrologTerm... body) {
275 Struct h = fromTerm(head, Struct.class);
276 Struct[] b = new Struct[body.length];
277 for (int i = 0; i < body.length; i++) {
278 b[i] = fromTerm(body[i], Struct.class);
279 }
280 Struct o = fromTerm(head, body, Struct.class);
281 return clause(new Clause(b, h, o));
282 }
283
284 private boolean clause(Clause clause) {
285 String key = clause.head.name + "/" + clause.head.arity;
286 Iterator<?> i = engine.dynamicPredicateIndicators();
287 while (i.hasNext()) {
288 String predIndicator = (String) i.next();
289 if (predIndicator.equals(key)) {
290 try {
291 List<?> list = engine.find(predIndicator);
292 for (Object object : list) {
293 if (object instanceof Clause) {
294 Clause c = (Clause) object;
295 if (Prolog.match(c.original, clause.original)) {
296 return true;
297 }
298 }
299 }
300 } catch (PrologException e) {
301 getLogger().error(getClass(), INDICATOR_NOT_FOUND + predIndicator, e);
302 }
303 }
304 }
305 return false;
306 }
307
308 public void retract(String stringClause) {
309 try {
310 Term term = new Parser(stringClause).nextTerm(false);
311 retract(BuiltIn.convertTermToClause(term));
312 } catch (PrologException e) {
313 getLogger().error(getClass(), SYNTAX_ERROR + stringClause, e);
314 }
315 }
316
317 @Override
318 public void retract(PrologTerm term) {
319 retract("" + term + "");
320 }
321
322 public void retract(PrologTerm head, PrologTerm... body) {
323 Struct h = fromTerm(head, Struct.class);
324 Struct[] b = new Struct[body.length];
325 for (int i = 0; i < body.length; i++) {
326 b[i] = fromTerm(body[i], Struct.class);
327 }
328 Struct o = fromTerm(head, body, Struct.class);
329 retract(new Clause(b, h, o));
330 }
331
332 private void retract(Clause clause) {
333 try {
334 engine.retract(clause.original);
335 } catch (PrologException e) {
336 getLogger().error(getClass(), RUNTIME_ERROR, e);
337 }
338 }
339
340 @Override
341 public PrologQuery query(PrologTerm goal) {
342 return new JTrologQuery(this, goal);
343 }
344
345 public PrologQuery query(String stringQuery) {
346 return new JTrologQuery(this, stringQuery);
347 }
348
349 public PrologQuery query(PrologTerm[] terms) {
350 return new JTrologQuery(this, terms);
351 }
352
353 public PrologQuery query(PrologTerm term, PrologTerm... terms) {
354 return new JTrologQuery(this, term, terms);
355 }
356
357 public void operator(int priority, String specifier, String operator) {
358 engine.opNew(operator, specifier, priority);
359 }
360
361 public boolean currentPredicate(String functor, int arity) {
362 String key = Parser.wrapAtom(functor) + "/" + arity;
363
364
365 boolean isBuiltin = engine.hasPrimitive(key) || engine.hasPrimitiveExp(key);
366
367
368 if (!isBuiltin) {
369 try {
370 if (!engine.find(key).isEmpty()) {
371 return true;
372 }
373 } catch (PrologException e) {
374 getLogger().error(getClass(), PrologLogger.INDICATOR_NOT_FOUND + key, e);
375 }
376 }
377
378
379 return isBuiltin;
380 }
381
382 public boolean currentOperator(int priority, String specifier, String operator) {
383 return currentOperators().contains(new JTrologOperator(priority, specifier, operator));
384 }
385
386 public Set<PrologOperator> currentOperators() {
387 return JTrologUtil.getOperatorSet(engine);
388 }
389
390 public Iterator<PrologClause> iterator() {
391 Collection<PrologClause> cls = new LinkedList<PrologClause>();
392 Parser parser = new Parser(engine.getTheory());
393 for (Iterator<?> iterator = parser.iterator(); iterator.hasNext();) {
394 Term term = (Term) iterator.next();
395 if (term instanceof Struct) {
396 Struct struct = (Struct) term;
397 if (struct.name.equals(":-") && struct.arity == 2) {
398 PrologTerm head = toTerm(struct.getArg(0), PrologTerm.class);
399 PrologTerm body = toTerm(struct.getArg(1), PrologTerm.class);
400 cls.add(new JTrologClause(provider, head, body, false, false, false));
401 } else {
402 PrologTerm head = toTerm(struct, PrologTerm.class);
403 cls.add(new JTrologClause(provider, head, false, false, false));
404 }
405 }
406 }
407 return new PrologProgramIterator(cls);
408 }
409
410 public int getProgramSize() {
411 int counter = 0;
412 Iterator<?> i = engine.dynamicPredicateIndicators();
413 while (i.hasNext()) {
414 String predIndicator = (String) i.next();
415 try {
416 List<?> list = engine.find(predIndicator);
417 counter += list.size();
418 } catch (PrologException e) {
419 getLogger().error(getClass(), PrologLogger.INDICATOR_NOT_FOUND + predIndicator, e);
420 }
421 }
422 return counter;
423 }
424
425 @Override
426 public PrologProgram getProgram() {
427 return new JTrologProgram(this);
428 }
429
430 public Set<PrologIndicator> getPredicates() {
431 Set<PrologIndicator> predicates = new HashSet<PrologIndicator>();
432 Iterator<?> i = engine.dynamicPredicateIndicators();
433 while (i.hasNext()) {
434 String predIndicator = (String) i.next();
435 try {
436 List<?> list = engine.find(predIndicator);
437 for (Object object : list) {
438 if (object instanceof Clause) {
439 Clause clause = (Clause) object;
440 String functor = clause.head.name;
441 int arity = clause.head.arity;
442 JTrologIndicator p = new JTrologIndicator(functor, arity);
443 predicates.add(p);
444 }
445 }
446 } catch (PrologException e) {
447 getLogger().error(getClass(), PrologLogger.INDICATOR_NOT_FOUND + predIndicator, e);
448 }
449 }
450 return predicates;
451 }
452
453 public Set<PrologIndicator> getBuiltIns() {
454 Iterator<?> libraries = engine.getCurrentLibraries();
455 Set<PrologIndicator> builtins = new HashSet<PrologIndicator>();
456 while (libraries.hasNext()) {
457 Object object = libraries.next();
458 if (object instanceof Library) {
459 Library library = (Library) object;
460 Class<? extends Library> c = library.getClass();
461 Method[] methods = c.getDeclaredMethods();
462 String regex = "\\.|\\?|#|[a-z][A-Za-z0-9_]*_[0-9]+";
463 for (Method method1 : methods) {
464 String method = method1.getName();
465 if (method.matches(regex)) {
466 int j = method.lastIndexOf('_');
467 String f = method.substring(0, j);
468 int a = Integer.parseInt(method.substring(j + 1));
469 builtins.add(new JTrologIndicator(f, a));
470 }
471 }
472 }
473 }
474 return builtins;
475 }
476
477 public String getLicense() {
478 return Licenses.NO_SPECIFIED;
479 }
480
481 public String getVersion() {
482 return JTrolog.VERSION;
483 }
484
485 public final String getVendor() {
486 return JTrolog.NAME;
487 }
488
489 public String getName() {
490 return JTrolog.NAME;
491 }
492
493 @Override
494 public int hashCode() {
495 final int prime = 31;
496 int result = 1;
497 result = prime * result + ((engine == null) ? 0 : engine.hashCode());
498 return result;
499 }
500
501 @Override
502 public boolean equals(Object obj) {
503 if (this == obj)
504 return true;
505 if (obj == null)
506 return false;
507 if (getClass() != obj.getClass())
508 return false;
509 JTrologEngine other = (JTrologEngine) obj;
510 return engine != null && other.engine != null;
511 }
512
513 public void dispose() {
514 if (engine != null) {
515 engine.clearTheory();
516 }
517 }
518
519 public final List<String> verify() {
520 return Arrays.asList("OK");
521 }
522
523 }