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.jlog;
23
24 import static io.github.prolobjectlink.prolog.PrologLogger.ERROR_LOADING_BUILT_INS;
25 import static io.github.prolobjectlink.prolog.PrologLogger.FILE_NOT_FOUND;
26 import static io.github.prolobjectlink.prolog.PrologLogger.IO;
27 import static ubc.cs.JLog.Parser.pOperatorEntry.FX;
28 import static ubc.cs.JLog.Parser.pOperatorEntry.FY;
29 import static ubc.cs.JLog.Parser.pOperatorEntry.XF;
30 import static ubc.cs.JLog.Parser.pOperatorEntry.XFX;
31 import static ubc.cs.JLog.Parser.pOperatorEntry.XFY;
32 import static ubc.cs.JLog.Parser.pOperatorEntry.YF;
33 import static ubc.cs.JLog.Parser.pOperatorEntry.YFX;
34
35 import java.io.FileNotFoundException;
36 import java.io.FileReader;
37 import java.io.FileWriter;
38 import java.io.IOException;
39 import java.io.PrintWriter;
40 import java.io.Reader;
41 import java.util.Arrays;
42 import java.util.Collection;
43 import java.util.Enumeration;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.LinkedList;
47 import java.util.List;
48 import java.util.Set;
49 import java.util.StringTokenizer;
50
51 import io.github.prolobjectlink.prolog.AbstractEngine;
52 import io.github.prolobjectlink.prolog.Licenses;
53 import io.github.prolobjectlink.prolog.PrologClause;
54 import io.github.prolobjectlink.prolog.PrologEngine;
55 import io.github.prolobjectlink.prolog.PrologIndicator;
56 import io.github.prolobjectlink.prolog.PrologOperator;
57 import io.github.prolobjectlink.prolog.PrologProgram;
58 import io.github.prolobjectlink.prolog.PrologProvider;
59 import io.github.prolobjectlink.prolog.PrologQuery;
60 import io.github.prolobjectlink.prolog.PrologTerm;
61 import ubc.cs.JLog.Foundation.iNameArityStub;
62 import ubc.cs.JLog.Foundation.jKnowledgeBase;
63 import ubc.cs.JLog.Foundation.jPrologFileServices;
64 import ubc.cs.JLog.Foundation.jPrologServices;
65 import ubc.cs.JLog.Foundation.jRule;
66 import ubc.cs.JLog.Foundation.jRuleDefinitions;
67 import ubc.cs.JLog.Foundation.jUnifiedVector;
68 import ubc.cs.JLog.Parser.pGenericOperatorEntry;
69 import ubc.cs.JLog.Parser.pGenericPredicateEntry;
70 import ubc.cs.JLog.Parser.pOperatorEntry;
71 import ubc.cs.JLog.Parser.pOperatorRegistry;
72 import ubc.cs.JLog.Parser.pParseStream;
73 import ubc.cs.JLog.Parser.pPredicateOperatorEntry;
74 import ubc.cs.JLog.Parser.pPredicateRegistry;
75 import ubc.cs.JLog.Terms.iNameArity;
76 import ubc.cs.JLog.Terms.jBuiltinRule;
77 import ubc.cs.JLog.Terms.jPredicate;
78 import ubc.cs.JLog.Terms.jPredicateTerms;
79
80
81
82
83
84
85 public class JLogEngine extends AbstractEngine implements PrologEngine {
86
87 final jPrologServices engine;
88 private final jKnowledgeBase kb;
89 private final pOperatorRegistry or;
90 private final pPredicateRegistry pr;
91
92 private static final String BUILT_INS = "builtins";
93
94 private final pGenericPredicateEntry multifile = new pGenericPredicateEntry("multifile", 1, jMultifile.class);
95
96
97 protected JLogEngine(PrologProvider provider) {
98 super(provider);
99 kb = new jKnowledgeBase();
100 or = new pOperatorRegistry();
101 pr = new pPredicateRegistry();
102 pr.addPredicate(multifile);
103 engine = new jPrologServices(kb, pr, or);
104 engine.setFileServices(new jPrologFileServices());
105 try {
106 engine.loadLibrary(BUILT_INS);
107 } catch (IOException e) {
108 getLogger().error(getClass(), ERROR_LOADING_BUILT_INS, e);
109 }
110 }
111
112
113
114
115
116
117
118
119
120
121 private boolean clauseOrRetract(jRule rule, boolean toBeRemove) {
122 String name = rule.getName();
123 int arity = rule.getArity();
124 jPredicate head = rule.getHead();
125 jPredicateTerms body = rule.getBase();
126 if (name.startsWith("'") && name.endsWith("'")) {
127 name = name.substring(1, name.length() - 1);
128 }
129 iNameArity na = new iNameArityStub(name, arity);
130 jRuleDefinitions rds = kb.getRuleDefinitionsMatch(na);
131 if (rds != null && rds.size() > 0) {
132 Enumeration<?> e = rds.enumRules();
133 while (e.hasMoreElements()) {
134 Object object = e.nextElement();
135 if (object instanceof jRule) {
136 jRule jRule = (jRule) object;
137 jPredicate ruleHead = jRule.getHead();
138 jPredicateTerms ruleBody = jRule.getBase();
139 jUnifiedVector v = new jUnifiedVector();
140 if (ruleHead.unify(head, v) && ruleBody.unify(body, v)) {
141 if (toBeRemove) {
142 rds.removeRule(jRule);
143 }
144 return true;
145 }
146 }
147 }
148 }
149 return false;
150 }
151
152 public void consult(String path) {
153 try {
154 kb.clearRules();
155 FileReader fileReader = new FileReader(path);
156 new pParseStream(fileReader, kb, pr, or).parseSource();
157 } catch (FileNotFoundException e) {
158 getLogger().error(getClass(), FILE_NOT_FOUND + path, e);
159 }
160 }
161
162 public void consult(Reader reader) {
163 kb.clearRules();
164 new pParseStream(reader, kb, pr, or).parseSource();
165 }
166
167 public void include(String path) {
168 try {
169 FileReader fileReader = new FileReader(path);
170 new pParseStream(fileReader, kb, pr, or).parseSource();
171 } catch (FileNotFoundException e) {
172 getLogger().error(getClass(), FILE_NOT_FOUND + path, e);
173 }
174 }
175
176 public void include(Reader reader) {
177 new pParseStream(reader, kb, pr, or).parseSource();
178 }
179
180 public void persist(String path) {
181 PrintWriter writer = null;
182 try {
183 writer = new PrintWriter(new FileWriter(path));
184 writer.print(JLogUtil.toString(engine));
185 writer.flush();
186 } catch (FileNotFoundException e) {
187 getLogger().error(getClass(), FILE_NOT_FOUND + path, e);
188 } catch (IOException e) {
189 getLogger().error(getClass(), IO + path, e);
190 } finally {
191 assert writer != null;
192 writer.close();
193 }
194 }
195
196 public void abolish(String functor, int arity) {
197 functor = JLogUtil.removeQuotesIfNeed(functor);
198 iNameArityStub na = new iNameArityStub(functor, arity);
199 jRuleDefinitions definitions = kb.getRuleDefinitionsMatch(na);
200 if (definitions != null) {
201 definitions.clearRules();
202 }
203 }
204
205 public void asserta(String stringClause) {
206 asserta(JLogUtil.toRule(stringClause, engine));
207 }
208
209 @Override
210 public void asserta(PrologTerm term) {
211 asserta(JLogUtil.toRule(provider, term));
212 }
213
214 public void asserta(PrologTerm head, PrologTerm... body) {
215 asserta(JLogUtil.toRule(provider, head, body));
216 }
217
218 private void asserta(jRule rule) {
219 if (!clause(rule)) {
220 kb.addRuleFirst(rule);
221 }
222 }
223
224 public void assertz(String stringClause) {
225 assertz(JLogUtil.toRule(stringClause, engine));
226 }
227
228 @Override
229 public void assertz(PrologTerm term) {
230 assertz(JLogUtil.toRule(provider, term));
231 }
232
233 public void assertz(PrologTerm head, PrologTerm... body) {
234 assertz(JLogUtil.toRule(provider, head, body));
235 }
236
237 private void assertz(jRule rule) {
238 if (!clause(rule)) {
239 kb.addRuleLast(rule);
240 }
241 }
242
243 public boolean clause(String stringClause) {
244 return clause(JLogUtil.toRule(stringClause, engine));
245 }
246
247 @Override
248 public boolean clause(PrologTerm term) {
249 return clause(JLogUtil.toRule(provider, term));
250 }
251
252 public boolean clause(PrologTerm head, PrologTerm... body) {
253 return clause(JLogUtil.toRule(provider, head, body));
254 }
255
256 private boolean clause(jRule rule) {
257 return clauseOrRetract(rule, false);
258 }
259
260 public void retract(String stringClause) {
261 retract(JLogUtil.toRule(stringClause, engine));
262 }
263
264 @Override
265 public void retract(PrologTerm term) {
266 retract(JLogUtil.toRule(provider, term));
267 }
268
269 public void retract(PrologTerm head, PrologTerm... body) {
270 retract(JLogUtil.toRule(provider, head, body));
271 }
272
273 private void retract(jRule rule) {
274 clauseOrRetract(rule, true);
275 }
276
277 public PrologQuery query(String stringQuery) {
278 return new JLogQuery(this, stringQuery);
279 }
280
281 @Override
282 public PrologQuery query(PrologTerm term) {
283 return new JLogQuery(this, term);
284 }
285
286 public PrologQuery query(PrologTerm[] terms) {
287 return new JLogQuery(this, terms);
288 }
289
290 public PrologQuery query(PrologTerm term, PrologTerm... terms) {
291 return new JLogQuery(this, term, terms);
292 }
293
294 public void operator(int priority, String specifier, String operator) {
295 pOperatorEntry op = new pPredicateOperatorEntry(operator, getType(specifier), priority);
296 engine.getOperatorRegistry().addOperator(op);
297 }
298
299 public boolean currentPredicate(String functor, int arity) {
300 PrologIndicator pi = new JLogIndicator(functor, arity);
301 return currentPredicates().contains(pi);
302 }
303
304 public boolean currentOperator(int priority, String specifier, String operator) {
305 pOperatorEntry op = engine.getOperatorRegistry().getOperator(operator, true);
306 op = op == null ? engine.getOperatorRegistry().getOperator(operator, false) : op;
307 return op != null && op.getPriority() == priority && op.getType() == getType(specifier);
308 }
309
310 public Set<PrologOperator> currentOperators() {
311 HashSet<PrologOperator> operators = new HashSet<PrologOperator>();
312 Enumeration<?> e = engine.getOperatorRegistry().enumOperators();
313 while (e.hasMoreElements()) {
314 Object object = e.nextElement();
315 if (object instanceof pOperatorEntry) {
316 pOperatorEntry entry = (pOperatorEntry) object;
317 String specifier = "";
318 String operator = entry.getName();
319 int priority = entry.getPriority();
320 switch (entry.getType()) {
321 case FX:
322 specifier = "fx";
323 break;
324 case FY:
325 specifier = "fy";
326 break;
327 case XFX:
328 specifier = "xfx";
329 break;
330 case XFY:
331 specifier = "xfy";
332 break;
333 case YFX:
334 specifier = "yfx";
335 break;
336 case XF:
337 specifier = "xf";
338 break;
339 default:
340 specifier = "yf";
341 break;
342 }
343 PrologOperator op = new JLogOperator(priority, specifier, operator);
344 operators.add(op);
345 }
346 }
347 return operators;
348 }
349
350 private int getType(String specifier) {
351 int type = -1;
352 if (specifier.equals("fx")) {
353 type = FX;
354 } else if (specifier.equals("fy")) {
355 type = FY;
356 } else if (specifier.equals("xfx")) {
357 type = XFX;
358 } else if (specifier.equals("xfy")) {
359 type = XFY;
360 } else if (specifier.equals("yfx")) {
361 type = YFX;
362 } else if (specifier.equals("xf")) {
363 type = XF;
364 } else if (specifier.equals("yf")) {
365 type = YF;
366 }
367 return type;
368 }
369
370 public Iterator<PrologClause> iterator() {
371 Collection<PrologClause> cls = new LinkedList<PrologClause>();
372 Enumeration<?> enumeration = kb.enumDefinitions();
373 while (enumeration.hasMoreElements()) {
374 jRuleDefinitions object = (jRuleDefinitions) enumeration.nextElement();
375 Enumeration<?> r = object.enumRules();
376 while (r.hasMoreElements()) {
377 Object object2 = r.nextElement();
378 if (!(object2 instanceof jBuiltinRule)) {
379 jRule jRule = (jRule) object2;
380
381
382 jPredicate ruleHead = jRule.getHead();
383 PrologTerm head = toTerm(ruleHead, PrologTerm.class);
384
385
386 jPredicateTerms ruleBody = jRule.getBase();
387 PrologTerm body = toTerm(ruleBody, PrologTerm.class);
388
389
390 if (!(body instanceof JLogTrue)) {
391 cls.add(new JLogClause(provider, head, body, false, false, false));
392 } else {
393 cls.add(new JLogClause(provider, head, false, false, false));
394 }
395
396 }
397 }
398 }
399 return new PrologProgramIterator(cls);
400 }
401
402 public int getProgramSize() {
403 int programSize = 0;
404 Enumeration<?> de = kb.enumDefinitions();
405 while (de.hasMoreElements()) {
406 jRuleDefinitions rules = (jRuleDefinitions) de.nextElement();
407 Enumeration<?> re = rules.enumRules();
408 while (re.hasMoreElements()) {
409 Object rule = re.nextElement();
410 if (!(rule instanceof jBuiltinRule)) {
411 programSize++;
412 }
413 }
414 }
415 return programSize;
416 }
417
418 @Override
419 public PrologProgram getProgram() {
420 return new JLogProgram(this);
421 }
422
423 public Set<PrologIndicator> getPredicates() {
424 Set<PrologIndicator> predicates = new HashSet<PrologIndicator>();
425 Enumeration<?> e = kb.enumDefinitions();
426 while (e.hasMoreElements()) {
427 jRuleDefinitions definitions = (jRuleDefinitions) e.nextElement();
428 Enumeration<?> rules = definitions.enumRules();
429 while (rules.hasMoreElements()) {
430 Object object2 = rules.nextElement();
431 if (!(object2 instanceof jBuiltinRule)) {
432 jRule jRule = (jRule) object2;
433 jPredicate ruleHead = jRule.getHead();
434 String functor = ruleHead.getName();
435 int arity = ruleHead.getArity();
436 JLogIndicator pi = new JLogIndicator(functor, arity);
437 predicates.add(pi);
438 }
439 }
440 }
441 return predicates;
442 }
443
444 public Set<PrologIndicator> getBuiltIns() {
445 Set<PrologIndicator> builtins = new HashSet<PrologIndicator>();
446 Enumeration<?> e = engine.getPredicateRegistry().enumPredicates();
447 while (e.hasMoreElements()) {
448 Object object = e.nextElement();
449 if (object instanceof pGenericPredicateEntry) {
450 pGenericPredicateEntry entry = (pGenericPredicateEntry) object;
451 String functor = entry.getName();
452 int arity = entry.getArity();
453 JLogIndicator pi = new JLogIndicator(functor, arity);
454 builtins.add(pi);
455 }
456 }
457 return builtins;
458 }
459
460 public String getLicense() {
461 return Licenses.GPL_V2;
462 }
463
464 public String getVersion() {
465 String credits = jPrologServices.getRequiredCreditInfo();
466 StringTokenizer tokenizer = new StringTokenizer(credits);
467
468 return tokenizer.nextToken();
469 }
470
471 public String getVendor() {
472 String credits = jPrologServices.getRequiredCreditInfo();
473 StringTokenizer tokenizer = new StringTokenizer(credits);
474 return tokenizer.nextToken();
475 }
476
477 public String getName() {
478 String credits = jPrologServices.getRequiredCreditInfo();
479 StringTokenizer tokenizer = new StringTokenizer(credits);
480 return tokenizer.nextToken();
481 }
482
483 @Override
484 public int hashCode() {
485 final int prime = 31;
486 int result = 1;
487 result = prime * result + engine.hashCode();
488 result = prime * result + kb.hashCode();
489 result = prime * result + or.hashCode();
490 result = prime * result + pr.hashCode();
491 return result;
492 }
493
494 @Override
495 public boolean equals(Object obj) {
496 if (this == obj)
497 return true;
498 if (obj == null)
499 return false;
500 if (getClass() != obj.getClass())
501 return false;
502 JLogEngine other = (JLogEngine) obj;
503 if (!engine.equals(other.engine))
504 return false;
505 if (!kb.equals(other.kb))
506 return false;
507 if (!or.equals(other.or))
508 return false;
509 return pr.equals(other.pr);
510 }
511
512 public void dispose() {
513 engine.release();
514 kb.clearRules();
515 }
516
517 public final List<String> verify() {
518 return Arrays.asList("OK");
519 }
520
521 }