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.tuprolog;
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.IO;
27 import static io.github.prolobjectlink.prolog.PrologLogger.SYNTAX_ERROR;
28
29 import java.io.BufferedReader;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.io.Reader;
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.LinkedList;
40 import java.util.List;
41 import java.util.Set;
42
43 import alice.tuprolog.Int;
44 import alice.tuprolog.InvalidTheoryException;
45 import alice.tuprolog.Library;
46 import alice.tuprolog.MalformedGoalException;
47 import alice.tuprolog.Operator;
48 import alice.tuprolog.Parser;
49 import alice.tuprolog.PrimitiveInfo;
50 import alice.tuprolog.Prolog;
51 import alice.tuprolog.Struct;
52 import alice.tuprolog.Term;
53 import alice.tuprolog.Theory;
54 import alice.tuprolog.TheoryManager;
55 import io.github.prolobjectlink.prolog.AbstractEngine;
56 import io.github.prolobjectlink.prolog.Licenses;
57 import io.github.prolobjectlink.prolog.PrologClause;
58 import io.github.prolobjectlink.prolog.PrologEngine;
59 import io.github.prolobjectlink.prolog.PrologIndicator;
60 import io.github.prolobjectlink.prolog.PrologOperator;
61 import io.github.prolobjectlink.prolog.PrologProgram;
62 import io.github.prolobjectlink.prolog.PrologProvider;
63 import io.github.prolobjectlink.prolog.PrologQuery;
64 import io.github.prolobjectlink.prolog.PrologTerm;
65 import io.github.prolobjectlink.prolog.SyntaxError;
66
67
68
69
70
71
72 public class TuPrologEngine extends AbstractEngine implements PrologEngine {
73
74 final Prolog engine;
75
76 protected TuPrologEngine(PrologProvider provider, Prolog engine) {
77 super(provider);
78 this.engine = engine;
79 }
80
81 public void consult(String path) {
82 try {
83 Theory theory = new Theory(new FileInputStream(path));
84 engine.setTheory(theory);
85 } catch (FileNotFoundException e) {
86 getLogger().warn(getClass(), FILE_NOT_FOUND + path, e);
87 getLogger().info(getClass(), DONT_WORRY + path);
88 } catch (IOException e) {
89 getLogger().warn(getClass(), IO + path, e);
90 getLogger().info(getClass(), DONT_WORRY + path);
91 } catch (InvalidTheoryException e) {
92 getLogger().error(getClass(), SYNTAX_ERROR + path, e);
93 }
94 }
95
96 public void consult(Reader reader) {
97 BufferedReader bfr = new BufferedReader(reader);
98 StringBuilder script = new StringBuilder();
99 try {
100 String line = bfr.readLine();
101 while (line != null) {
102 script.append(line);
103 script.append("\n");
104 line = bfr.readLine();
105 }
106 engine.setTheory(new Theory("" + script + ""));
107 } catch (InvalidTheoryException e) {
108 getLogger().error(getClass(), SYNTAX_ERROR + script, e);
109 } catch (IOException e) {
110 getLogger().warn(getClass(), IO + script, e);
111 }
112 }
113
114 public void include(String path) {
115 TheoryManager manager = engine.getTheoryManager();
116 try {
117 manager.consult(new Theory(new FileInputStream(path)), true, null);
118 } catch (FileNotFoundException e) {
119 getLogger().error(getClass(), FILE_NOT_FOUND + path, e);
120 } catch (IOException e) {
121 getLogger().error(getClass(), IO + path, e);
122 } catch (InvalidTheoryException e) {
123 getLogger().error(getClass(), SYNTAX_ERROR + path, e);
124 }
125 }
126
127 public void include(Reader reader) {
128 TheoryManager manager = engine.getTheoryManager();
129 BufferedReader bfr = new BufferedReader(reader);
130 StringBuilder script = new StringBuilder();
131 try {
132 String line = bfr.readLine();
133 while (line != null) {
134 script.append(line);
135 script.append("\n");
136 line = bfr.readLine();
137 }
138 manager.consult(new Theory("" + script + ""), true, null);
139 } catch (InvalidTheoryException e) {
140 getLogger().error(getClass(), SYNTAX_ERROR + script, e);
141 } catch (IOException e) {
142 getLogger().warn(getClass(), IO + script, e);
143 }
144 }
145
146 public void persist(String path) {
147 PrintWriter writer = null;
148 try {
149 writer = new PrintWriter(path);
150 writer.write(engine.getTheoryManager().getTheory(true));
151 } catch (IOException e) {
152 getLogger().warn(getClass(), IO + path, e);
153 getLogger().info(getClass(), DONT_WORRY + path);
154 } finally {
155 if (writer != null) {
156 writer.close();
157 }
158 }
159 }
160
161 public void abolish(String functor, int arity) {
162 Struct pi = new Struct("/", new Struct(functor), new Int(arity));
163 engine.getTheoryManager().abolish(pi);
164 }
165
166 public void asserta(String stringClause) {
167 TheoryManager manager = engine.getTheoryManager();
168 if (stringClause != null && !clause(stringClause)) {
169 manager.assertA((Struct) Term.createTerm(stringClause), true, null, false);
170 }
171 }
172
173 public void asserta(PrologTerm term) {
174 TheoryManager manager = engine.getTheoryManager();
175 if (term != null && !clause(term)) {
176 manager.assertA(fromTerm(term, Struct.class), true, null, false);
177 }
178 }
179
180 public void asserta(PrologTerm head, PrologTerm... body) {
181 boolean hasBody = body != null && body.length > 0;
182 if (hasBody ? !clause(head, body) : !clause(head)) {
183 TheoryManager manager = engine.getTheoryManager();
184 manager.assertA(fromTerm(head, body, Struct.class), true, null, false);
185 }
186 }
187
188 public void assertz(String stringClause) {
189 TheoryManager manager = engine.getTheoryManager();
190 if (stringClause != null && !clause(stringClause)) {
191 manager.assertZ((Struct) Term.createTerm(stringClause), true, null, false);
192 }
193 }
194
195 public void assertz(PrologTerm term) {
196 TheoryManager manager = engine.getTheoryManager();
197 if (term != null && !clause(term)) {
198 manager.assertZ(fromTerm(term, Struct.class), true, null, false);
199 }
200 }
201
202 public void assertz(PrologTerm head, PrologTerm... body) {
203 boolean hasBody = body != null && body.length > 0;
204 if (hasBody ? !clause(head, body) : !clause(head)) {
205 TheoryManager manager = engine.getTheoryManager();
206 manager.assertZ(fromTerm(head, body, Struct.class), true, null, false);
207 }
208 }
209
210 public boolean clause(String stringClause) {
211 Term toBeMatched = Term.createTerm(stringClause);
212 TheoryManager manager = engine.getTheoryManager();
213 try {
214 Theory theory = new Theory(manager.getTheory(true));
215 Iterator<? extends Term> iterator = theory.iterator(engine);
216 while (iterator.hasNext()) {
217 Term term = iterator.next();
218 if (term.match(toBeMatched)) {
219 return true;
220 }
221 }
222 } catch (InvalidTheoryException e) {
223 getLogger().error(getClass(), SYNTAX_ERROR, e);
224 }
225 return false;
226 }
227
228 public boolean clause(PrologTerm head) {
229 TheoryManager manager = engine.getTheoryManager();
230 try {
231 Theory theory = new Theory(manager.getTheory(true));
232 Iterator<? extends Term> iterator = theory.iterator(engine);
233 while (iterator.hasNext()) {
234 Term term = iterator.next();
235 if (term.match(fromTerm(head, Struct.class))) {
236 return true;
237 }
238 }
239 } catch (InvalidTheoryException e) {
240 getLogger().error(getClass(), SYNTAX_ERROR, e);
241 }
242 return false;
243 }
244
245 public boolean clause(PrologTerm head, PrologTerm... body) {
246 TheoryManager manager = engine.getTheoryManager();
247 try {
248 Theory theory = new Theory(manager.getTheory(true));
249 Iterator<? extends Term> iterator = theory.iterator(engine);
250 while (iterator.hasNext()) {
251 Term term = iterator.next();
252 if (term.match(fromTerm(head, body, Struct.class))) {
253 return true;
254 }
255 }
256 } catch (InvalidTheoryException e) {
257 getLogger().error(getClass(), SYNTAX_ERROR, e);
258 }
259 return false;
260 }
261
262 public void retract(String stringClause) {
263 try {
264 engine.solve("retract(" + stringClause + ").");
265 } catch (MalformedGoalException e) {
266 throw new SyntaxError("Syntax error", e);
267 }
268 }
269
270 public void retract(PrologTerm head) {
271 retract("" + fromTerm(head, Struct.class) + "");
272 }
273
274 public void retract(PrologTerm head, PrologTerm... body) {
275 retract("" + fromTerm(head, body, Struct.class) + "");
276 }
277
278 public PrologQuery query(String stringQuery) {
279 return new TuPrologQuery(this, stringQuery);
280 }
281
282 public PrologQuery query(PrologTerm term) {
283 return new TuPrologQuery(this, term);
284 }
285
286 public PrologQuery query(PrologTerm[] terms) {
287 return new TuPrologQuery(this, terms);
288 }
289
290 public PrologQuery query(PrologTerm term, PrologTerm... terms) {
291 return new TuPrologQuery(this, term, terms);
292 }
293
294 public void operator(int priority, String specifier, String operator) {
295 engine.getOperatorManager().opNew(operator, specifier, priority);
296 }
297
298 public boolean currentPredicate(String functor, int arity) {
299 String newFunctor = removeQuoted(functor);
300 PrologIndicator pi = new TuPrologIndicator(newFunctor, arity);
301 return currentPredicates().contains(pi);
302 }
303
304 public boolean currentOperator(int priority, String specifier, String operator) {
305 return engine.getOperatorManager().opPrio(operator, specifier) == priority;
306 }
307
308 public Set<PrologOperator> currentOperators() {
309 List<Operator> operatorsList = engine.getOperatorManager().getOperators();
310 Set<PrologOperator> operators = new HashSet<PrologOperator>(operatorsList.size());
311 for (Operator operator : operatorsList) {
312 String name = operator.name;
313 int priority = operator.prio;
314 String specifier = operator.type;
315 PrologOperator op = new TuPrologOperator(priority, specifier, name);
316 operators.add(op);
317 }
318 return operators;
319 }
320
321 public Iterator<PrologClause> iterator() {
322 Collection<PrologClause> cls = new LinkedList<PrologClause>();
323 Parser parser = new Parser(engine.getTheoryManager().getTheory(true));
324 for (Iterator<Term> iterator = parser.iterator(); iterator.hasNext();) {
325 Term term = iterator.next();
326 if (term instanceof Struct) {
327 Struct struct = (Struct) term;
328 if (struct.getName().equals(":-") && struct.getArity() == 2) {
329 PrologTerm head = toTerm(struct.getArg(0), PrologTerm.class);
330 PrologTerm body = toTerm(struct.getArg(1), PrologTerm.class);
331 cls.add(new TuPrologClause(provider, head, body, false, false, false));
332 } else {
333 PrologTerm head = toTerm(struct, PrologTerm.class);
334 cls.add(new TuPrologClause(provider, head, false, false, false));
335 }
336 }
337 }
338 return new PrologProgramIterator(cls);
339 }
340
341 public int getProgramSize() {
342 int counter = 0;
343 Iterator<? extends Term> i = engine.getTheory().iterator(engine);
344 while (i.hasNext()) {
345 i.next();
346 counter++;
347 }
348 return counter;
349 }
350
351 @Override
352 public PrologProgram getProgram() {
353 return new TuPrologProgram(this);
354 }
355
356 public Set<PrologIndicator> getPredicates() {
357 Set<PrologIndicator> predicates = new HashSet<PrologIndicator>();
358 TheoryManager manager = engine.getTheoryManager();
359 try {
360 Theory theory = new Theory(manager.getTheory(true));
361 Iterator<? extends Term> iterator = theory.iterator(engine);
362 while (iterator.hasNext()) {
363 Term term = iterator.next();
364 if (term instanceof Struct) {
365 Struct struct = (Struct) term;
366 int arity = struct.getArity();
367 String functor = struct.getName();
368 if (functor.equals(":-") && arity == 2) {
369 Term head = struct.getArg(0);
370 if (head instanceof Struct) {
371 Struct headStruct = (Struct) head;
372 arity = headStruct.getArity();
373 functor = headStruct.getName();
374 TuPrologIndicator pi = new TuPrologIndicator(functor, arity);
375 predicates.add(pi);
376 }
377 } else {
378 TuPrologIndicator pi = new TuPrologIndicator(functor, arity);
379 predicates.add(pi);
380 }
381 }
382 }
383 } catch (InvalidTheoryException e) {
384 getLogger().error(getClass(), SYNTAX_ERROR, e);
385 }
386
387 return predicates;
388 }
389
390 public Set<PrologIndicator> getBuiltIns() {
391 String[] libraries = engine.getCurrentLibraries();
392 Set<PrologIndicator> builtins = new HashSet<PrologIndicator>();
393 for (String libraryName : libraries) {
394 Library library = engine.getLibrary(libraryName);
395 Collection<List<PrimitiveInfo>> c = library.getPrimitives().values();
396 for (List<PrimitiveInfo> list : c) {
397 for (PrimitiveInfo primitiveInfo : list) {
398 String key = primitiveInfo.getKey();
399 String functor = key.substring(0, key.lastIndexOf('/'));
400 int arity = Integer.parseInt(key.substring(key.lastIndexOf('/') + 1));
401 TuPrologIndicator pi = new TuPrologIndicator(functor, arity);
402 builtins.add(pi);
403 }
404 }
405 }
406 return builtins;
407 }
408
409 public String getLicense() {
410 return Licenses.LGPL_V3;
411 }
412
413 public String getVersion() {
414 return TuProlog.VERSION;
415 }
416
417 public final String getVendor() {
418 return TuProlog.NAME;
419 }
420
421 public String getName() {
422 return TuProlog.NAME;
423 }
424
425 @Override
426 public int hashCode() {
427 final int prime = 31;
428 int result = 1;
429 result = prime * result + ((engine == null) ? 0 : engine.hashCode());
430 return result;
431 }
432
433 @Override
434 public boolean equals(Object obj) {
435 if (this == obj)
436 return true;
437 if (obj == null)
438 return false;
439 if (getClass() != obj.getClass())
440 return false;
441 TuPrologEngine other = (TuPrologEngine) obj;
442
443
444 return engine != null && other.engine != null;
445 }
446
447 public void dispose() {
448 if (engine != null) {
449 engine.clearTheory();
450 }
451 }
452
453 public final List<String> verify() {
454 return Arrays.asList("OK");
455 }
456
457 }