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.PrologTermType.ATOM_TYPE;
25 import static io.github.prolobjectlink.prolog.PrologTermType.CLASS_TYPE;
26 import static io.github.prolobjectlink.prolog.PrologTermType.CUT_TYPE;
27 import static io.github.prolobjectlink.prolog.PrologTermType.DOUBLE_TYPE;
28 import static io.github.prolobjectlink.prolog.PrologTermType.FAIL_TYPE;
29 import static io.github.prolobjectlink.prolog.PrologTermType.FALSE_TYPE;
30 import static io.github.prolobjectlink.prolog.PrologTermType.FIELD_TYPE;
31 import static io.github.prolobjectlink.prolog.PrologTermType.FLOAT_TYPE;
32 import static io.github.prolobjectlink.prolog.PrologTermType.INTEGER_TYPE;
33 import static io.github.prolobjectlink.prolog.PrologTermType.LIST_TYPE;
34 import static io.github.prolobjectlink.prolog.PrologTermType.LONG_TYPE;
35 import static io.github.prolobjectlink.prolog.PrologTermType.MAP_ENTRY_TYPE;
36 import static io.github.prolobjectlink.prolog.PrologTermType.MAP_TYPE;
37 import static io.github.prolobjectlink.prolog.PrologTermType.MIXIN_TYPE;
38 import static io.github.prolobjectlink.prolog.PrologTermType.NIL_TYPE;
39 import static io.github.prolobjectlink.prolog.PrologTermType.OBJECT_TYPE;
40 import static io.github.prolobjectlink.prolog.PrologTermType.PARAMETER_TYPE;
41 import static io.github.prolobjectlink.prolog.PrologTermType.RESULT_TYPE;
42 import static io.github.prolobjectlink.prolog.PrologTermType.STRUCTURE_TYPE;
43 import static io.github.prolobjectlink.prolog.PrologTermType.TRUE_TYPE;
44 import static io.github.prolobjectlink.prolog.PrologTermType.VARIABLE_TYPE;
45
46 import java.util.ArrayList;
47 import java.util.Enumeration;
48 import java.util.Iterator;
49
50 import io.github.prolobjectlink.prolog.AbstractConverter;
51 import io.github.prolobjectlink.prolog.PrologAtom;
52 import io.github.prolobjectlink.prolog.PrologConverter;
53 import io.github.prolobjectlink.prolog.PrologDouble;
54 import io.github.prolobjectlink.prolog.PrologFloat;
55 import io.github.prolobjectlink.prolog.PrologInteger;
56 import io.github.prolobjectlink.prolog.PrologList;
57 import io.github.prolobjectlink.prolog.PrologLogger;
58 import io.github.prolobjectlink.prolog.PrologLong;
59 import io.github.prolobjectlink.prolog.PrologProvider;
60 import io.github.prolobjectlink.prolog.PrologStructure;
61 import io.github.prolobjectlink.prolog.PrologTerm;
62 import io.github.prolobjectlink.prolog.PrologVariable;
63 import io.github.prolobjectlink.prolog.UnknownTermError;
64 import ubc.cs.JLog.Foundation.jEquivalenceMapping;
65 import ubc.cs.JLog.Terms.jAtom;
66 import ubc.cs.JLog.Terms.jBinaryBuiltinPredicate;
67 import ubc.cs.JLog.Terms.jBuiltinPredicate;
68 import ubc.cs.JLog.Terms.jCompoundTerm;
69 import ubc.cs.JLog.Terms.jFail;
70 import ubc.cs.JLog.Terms.jInteger;
71 import ubc.cs.JLog.Terms.jList;
72 import ubc.cs.JLog.Terms.jListPair;
73 import ubc.cs.JLog.Terms.jNullList;
74 import ubc.cs.JLog.Terms.jObject;
75 import ubc.cs.JLog.Terms.jPredicate;
76 import ubc.cs.JLog.Terms.jPredicateTerms;
77 import ubc.cs.JLog.Terms.jReal;
78 import ubc.cs.JLog.Terms.jTerm;
79 import ubc.cs.JLog.Terms.jTrue;
80 import ubc.cs.JLog.Terms.jUnaryBuiltinPredicate;
81 import ubc.cs.JLog.Terms.jVariable;
82
83
84
85
86
87
88 class JLogConverter extends AbstractConverter<jTerm> implements PrologConverter<jTerm> {
89
90 private final jPredicateTerms emptyBody = new jPredicateTerms();
91 private final jEquivalenceMapping equivalence = new jEquivalenceMapping();
92
93 private jList adaptList(PrologTerm[] arguments) {
94 jList pList = jNullList.NULL_LIST;
95 for (int i = arguments.length - 1; i >= 0; --i) {
96 pList = new jListPair(fromTerm(arguments[i]), pList);
97 }
98 return pList;
99 }
100
101 private jCompoundTerm adaptCompound(PrologTerm[] arguments) {
102 jCompoundTerm compound = new jCompoundTerm(arguments.length);
103 for (PrologTerm iPrologTerm : arguments) {
104 compound.addTerm(fromTerm(iPrologTerm));
105 }
106 return compound;
107 }
108
109 public PrologTerm toTerm(jTerm prologTerm) {
110 switch (prologTerm.type) {
111 case jTerm.TYPE_NULLLIST:
112 return new JLogEmpty(provider);
113 case jTerm.TYPE_ATOM:
114 String value = prologTerm.getName();
115 if (value.equals(JLogNil.NIL_STR)) {
116 return new JLogNil(provider);
117 } else if (value.equals(JLogFalse.FALSE_STR)) {
118 return new JLogFalse(provider);
119 } else if (!value.matches(SIMPLE_ATOM_REGEX)) {
120 return new JLogAtom(provider, "'" + value + "'");
121 }
122 return new JLogAtom(provider, value);
123 case jTerm.TYPE_INTEGER:
124 return new JLogInteger(provider, ((jInteger) prologTerm).getIntegerValue());
125 case jTerm.TYPE_REAL:
126 JLogTerm number = null;
127 try {
128 if (prologTerm instanceof jFloat) {
129 number = new JLogFloat(provider, ((jFloat) prologTerm).getRealValue());
130 } else {
131 number = new JLogDouble(provider, ((jDouble) prologTerm).getRealValue());
132 }
133 } catch (ClassCastException e) {
134
135 if (e.getMessage().contains(jFloat.class.getName())) {
136 number = new JLogFloat(provider, ((jReal) prologTerm).getRealValue());
137 } else if (e.getMessage().contains(jDouble.class.getName())) {
138 number = new JLogDouble(provider, ((jReal) prologTerm).getRealValue());
139 } else {
140 getLogger().error(getClass(), PrologLogger.CLASS_CAST, e);
141 }
142 }
143 return number;
144 case jTerm.TYPE_VARIABLE:
145 String name = ((jVariable) prologTerm).getName();
146 PrologVariable variable = sharedVariables.get(name);
147 if (variable == null) {
148 variable = new JLogVariable(provider, name);
149 sharedVariables.put(variable.getName(), variable);
150 }
151 return variable;
152 case jTerm.TYPE_LIST:
153 jTerm[] array = new jTerm[0];
154 jList list = (jList) prologTerm;
155 ArrayList<jTerm> arguments = new ArrayList<jTerm>();
156 Iterator<jTerm> i = new JLogIterator(list);
157 while (i.hasNext()) {
158 arguments.add(i.next());
159 }
160 return new JLogList(provider, arguments.toArray(array));
161 case jTerm.TYPE_OBJECT:
162 return new JLogReference(provider, prologTerm);
163 case jTerm.TYPE_TYPE:
164 jUnaryBuiltinPredicate unary = (jUnaryBuiltinPredicate) prologTerm;
165 return new JLogStructure(provider, unary.getName(), unary.getRHS());
166 case jTerm.TYPE_COMPARE:
167 case jTerm.TYPE_OPERATOR:
168 case jTerm.TYPE_ARITHMETIC:
169 case jTerm.TYPE_UNARYOPERATOR:
170 case jTerm.TYPE_NUMERICCOMPARE:
171 case jTerm.TYPE_UNARYARITHMETIC:
172 jBinaryBuiltinPredicate binary = (jBinaryBuiltinPredicate) prologTerm;
173 return new JLogStructure(provider, binary.getLHS(), binary.getName(), binary.getRHS());
174 case jTerm.TYPE_BUILTINPREDICATE:
175 jBuiltinPredicate builtIn = (jBuiltinPredicate) prologTerm;
176 if (builtIn.equivalence(jTrue.TRUE, equivalence)) {
177 return new JLogTrue(provider);
178 } else if (builtIn.equivalence(jFail.FAIL, equivalence)) {
179 return new JLogFail(provider);
180 } else if (builtIn.equivalence(JLogCut.JCUT, equivalence)) {
181 return new JLogCut(provider);
182 } else if (builtIn.getArity() == 2) {
183 jBinaryBuiltinPredicate b = (jBinaryBuiltinPredicate) prologTerm;
184 return new JLogStructure(provider, b.getLHS(), b.getName(), b.getRHS());
185 }
186 throw new UnknownTermError(prologTerm);
187 case jTerm.TYPE_PREDICATE:
188 jPredicate predicate = (jPredicate) prologTerm;
189 jCompoundTerm compound = predicate.getArguments();
190 String functor = predicate.getName();
191 return new JLogStructure(provider, functor, compound);
192 case jTerm.TYPE_PREDICATETERMS:
193 jPredicateTerms terms = (jPredicateTerms) prologTerm;
194 Enumeration<?> k = terms.enumTerms();
195 if (k.hasMoreElements()) {
196 PrologTerm body = null;
197 while (k.hasMoreElements()) {
198 jTerm term = (jTerm) k.nextElement();
199 if (body != null) {
200 body = new JLogStructure(provider, ",", body, toTerm(term));
201 } else {
202 body = toTerm(term);
203 }
204 }
205 return body;
206 }
207 return new JLogTrue(provider);
208
209 default:
210 throw new UnknownTermError(prologTerm);
211 }
212 }
213
214 public jTerm fromTerm(PrologTerm term) {
215 switch (term.getType()) {
216 case NIL_TYPE:
217 return new jAtom("nil");
218 case CUT_TYPE:
219 return new jAtom("!");
220 case FAIL_TYPE:
221 return jFail.FAIL;
222 case TRUE_TYPE:
223 return jTrue.TRUE;
224 case FALSE_TYPE:
225 return new jAtom("false");
226 case ATOM_TYPE:
227 String value = ((PrologAtom) term).getStringValue();
228 return new jAtom(value);
229 case FLOAT_TYPE:
230 return new jFloat(((PrologFloat) term).getFloatValue());
231 case INTEGER_TYPE:
232 return new jInteger(((PrologInteger) term).getIntegerValue());
233 case DOUBLE_TYPE:
234 return new jDouble(((PrologDouble) term).getDoubleValue());
235 case LONG_TYPE:
236 return new jInteger(((PrologLong) term).getIntegerValue());
237 case VARIABLE_TYPE:
238 String name = ((PrologVariable) term).getName();
239 jTerm variable = sharedPrologVariables.get(name);
240 if (variable == null) {
241 variable = new jVariable(name);
242 sharedPrologVariables.put(name, variable);
243 }
244 return variable;
245 case LIST_TYPE:
246 case MAP_TYPE:
247 PrologTerm[] arguments = ((PrologList) term).getArguments();
248 return adaptList(arguments);
249 case STRUCTURE_TYPE:
250 case MAP_ENTRY_TYPE:
251 String functor = term.getFunctor();
252 arguments = ((PrologStructure) term).getArguments();
253 return new jPredicate(functor, adaptCompound(arguments));
254 case OBJECT_TYPE:
255 return new jObject(term.getObject());
256 case PARAMETER_TYPE:
257 case RESULT_TYPE:
258 case FIELD_TYPE:
259 name = ((PrologVariable) term).getName();
260 return new jVariable(name);
261 case MIXIN_TYPE:
262 case CLASS_TYPE:
263 arguments = term.getArguments();
264 functor = removeQuoted(term.getFunctor());
265 return new jPredicate(functor, adaptCompound(arguments));
266 default:
267 throw new UnknownTermError(term);
268 }
269 }
270
271 public jTerm[] fromTermArray(PrologTerm[] terms) {
272 jTerm[] prologTerms = new jTerm[terms.length];
273 for (int i = 0; i < terms.length; i++) {
274 prologTerms[i] = fromTerm(terms[i]);
275 }
276 return prologTerms;
277 }
278
279 public jTerm fromTerm(PrologTerm head, PrologTerm[] body) {
280 jTerm clauseHead = fromTerm(head);
281 if (body != null && body.length > 0) {
282 jTerm clauseBody = fromTerm(body[body.length - 1]);
283 for (int i = body.length - 2; i >= 0; --i) {
284 jCompoundTerm args = new jCompoundTerm(2);
285 args.addTerm(fromTerm(body[i]));
286 args.addTerm(clauseBody);
287 clauseBody = new jPredicate(",", args);
288 }
289 jCompoundTerm args = new jCompoundTerm(2);
290 args.addTerm(clauseHead);
291 args.addTerm(clauseBody);
292 return new jPredicate(":-", args);
293 }
294 return clauseHead;
295 }
296
297 public PrologProvider createProvider() {
298 return new JLog(this);
299 }
300
301 @Override
302 public int hashCode() {
303 final int prime = 31;
304 int result = super.hashCode();
305 result = prime * result + emptyBody.hashCode();
306 result = prime * result + equivalence.hashCode();
307 return result;
308 }
309
310 @Override
311 public boolean equals(Object object) {
312 if (this == object)
313 return true;
314 if (!super.equals(object))
315 return false;
316 if (getClass() != object.getClass())
317 return false;
318 JLogConverter other = (JLogConverter) object;
319 if (!emptyBody.equals(other.emptyBody))
320 return false;
321 return equivalence.equals(other.equivalence);
322 }
323
324 @Override
325 public String toString() {
326 return "JLogConverter";
327 }
328
329 }