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.PrologTermType.ATOM_TYPE;
25 import static io.github.prolobjectlink.prolog.PrologTermType.CUT_TYPE;
26 import static io.github.prolobjectlink.prolog.PrologTermType.DOUBLE_TYPE;
27 import static io.github.prolobjectlink.prolog.PrologTermType.FAIL_TYPE;
28 import static io.github.prolobjectlink.prolog.PrologTermType.FALSE_TYPE;
29 import static io.github.prolobjectlink.prolog.PrologTermType.FLOAT_TYPE;
30 import static io.github.prolobjectlink.prolog.PrologTermType.INTEGER_TYPE;
31 import static io.github.prolobjectlink.prolog.PrologTermType.LIST_TYPE;
32 import static io.github.prolobjectlink.prolog.PrologTermType.LONG_TYPE;
33 import static io.github.prolobjectlink.prolog.PrologTermType.NIL_TYPE;
34 import static io.github.prolobjectlink.prolog.PrologTermType.OBJECT_TYPE;
35 import static io.github.prolobjectlink.prolog.PrologTermType.STRUCTURE_TYPE;
36 import static io.github.prolobjectlink.prolog.PrologTermType.TRUE_TYPE;
37 import static io.github.prolobjectlink.prolog.PrologTermType.VARIABLE_TYPE;
38
39 import java.util.Iterator;
40
41 import io.github.prolobjectlink.prolog.AbstractTerm;
42 import io.github.prolobjectlink.prolog.PrologNumber;
43 import io.github.prolobjectlink.prolog.PrologProvider;
44 import io.github.prolobjectlink.prolog.PrologTerm;
45 import jTrolog.engine.Prolog;
46 import jTrolog.terms.Double;
47 import jTrolog.terms.Float;
48 import jTrolog.terms.Int;
49 import jTrolog.terms.Long;
50 import jTrolog.terms.Number;
51 import jTrolog.terms.Struct;
52 import jTrolog.terms.StructAtom;
53 import jTrolog.terms.Term;
54 import jTrolog.terms.Var;
55
56
57
58
59
60
61 abstract class JTrologTerm extends AbstractTerm implements PrologTerm {
62
63
64 protected int vIndex;
65 protected Term value;
66
67 static final JTrologOperatorSet ops = new JTrologOperatorSet();
68
69 protected JTrologTerm(int type, PrologProvider provider) {
70 super(type, provider);
71 }
72
73 protected JTrologTerm(int type, PrologProvider provider, Term value) {
74 super(type, provider);
75 this.value = value;
76 }
77
78
79
80
81
82
83
84
85 protected JTrologTerm(int type, PrologProvider provider, String name, int n) {
86 this(type, provider, new Var(name, n));
87 this.vIndex = n;
88 }
89
90 public final boolean isAtom() {
91 return value instanceof StructAtom;
92 }
93
94 public final boolean isNumber() {
95 return value instanceof Number;
96 }
97
98 public final boolean isFloat() {
99 return value instanceof Float && !isDouble();
100 }
101
102 public final boolean isDouble() {
103 return value instanceof Double;
104 }
105
106 public final boolean isInteger() {
107 return value instanceof Int && !isLong();
108 }
109
110 public final boolean isLong() {
111 return value instanceof Long;
112 }
113
114 public final boolean isVariable() {
115 return value instanceof Var;
116 }
117
118 public final boolean isList() {
119 if (value == Term.emptyList) {
120 return true;
121 } else if (value instanceof Struct) {
122 Struct s = (Struct) value;
123 return (s.name.equals(".") && s.arity == 2);
124 }
125 return false;
126 }
127
128 public final boolean isStructure() {
129 if (!isAtom() && !isList()) {
130 return value instanceof Struct;
131 }
132 return false;
133 }
134
135 public final boolean isNil() {
136 if (!isVariable() && !isNumber()) {
137 return hasIndicator("nil", 0);
138 }
139 return false;
140 }
141
142 public final boolean isEmptyList() {
143 return value == Term.emptyList;
144 }
145
146 public final boolean isEvaluable() {
147 Prolog prolog = new Prolog();
148 Iterator<?> i = prolog.getCurrentOperators();
149 while (i.hasNext()) {
150 Object object = i.next();
151 boolean valueIsStrct = (value instanceof Struct);
152 boolean objectIsStrct = (object instanceof Struct);
153 if (valueIsStrct && objectIsStrct) {
154 Struct op = (Struct) object;
155 Struct vop = (Struct) value;
156 if (op.arity == 3 && ((StructAtom) op.getArg(2)).name.equals(vop.name)) {
157 return true;
158 }
159 }
160 }
161 return false;
162 }
163
164 public final boolean isAtomic() {
165 return !isCompound();
166 }
167
168 public final boolean isCompound() {
169 return !(isEmptyList()) && (isList() || isStructure());
170 }
171
172 public final boolean isTrueType() {
173 return getObject().equals(true);
174 }
175
176 public final boolean isFalseType() {
177 return getObject().equals(false);
178 }
179
180 public final boolean isNullType() {
181 return getObject() == null;
182 }
183
184 public final boolean isVoidType() {
185 return getObject() == void.class;
186 }
187
188 public final boolean isObjectType() {
189 return getType() == OBJECT_TYPE;
190 }
191
192 public final boolean isReference() {
193 return isObjectType();
194 }
195
196 public PrologTerm getTerm() {
197 return this;
198 }
199
200 public final boolean unify(PrologTerm term) {
201 Term otherTerm = fromTerm(term, Term.class);
202 return Prolog.match(value, otherTerm);
203 }
204
205 public final int compareTo(PrologTerm term) {
206 int termType = term.getType();
207
208 if ((type >> 8) < (termType >> 8)) {
209 return -1;
210 } else if ((type >> 8) > (termType >> 8)) {
211 return 1;
212 }
213
214 switch (type) {
215 case NIL_TYPE:
216 case CUT_TYPE:
217 case FAIL_TYPE:
218 case TRUE_TYPE:
219 case FALSE_TYPE:
220 case ATOM_TYPE:
221
222
223 StructAtom atom = (StructAtom) value;
224 int result = atom.name.compareTo(term.getFunctor());
225 if (result < 0) {
226 return -1;
227 } else if (result > 0) {
228 return 1;
229 }
230 break;
231
232 case FLOAT_TYPE:
233
234 float thisFloatValue = ((Number) value).floatValue();
235 float otherFloatValue = ((PrologNumber) term).getFloatValue();
236
237 if (thisFloatValue < otherFloatValue) {
238 return -1;
239 } else if (thisFloatValue > otherFloatValue) {
240 return 1;
241 }
242
243 break;
244
245 case LONG_TYPE:
246
247 long thisLongValue = ((Number) value).longValue();
248 long otherLongValue = ((PrologNumber) term).getLongValue();
249
250 if (thisLongValue < otherLongValue) {
251 return -1;
252 } else if (thisLongValue > otherLongValue) {
253 return 1;
254 }
255
256 break;
257
258 case DOUBLE_TYPE:
259
260 double thisDoubleValue = ((Number) value).doubleValue();
261 double otherDoubleValue = ((PrologNumber) term).getDoubleValue();
262
263 if (thisDoubleValue < otherDoubleValue) {
264 return -1;
265 } else if (thisDoubleValue > otherDoubleValue) {
266 return 1;
267 }
268
269 break;
270
271 case INTEGER_TYPE:
272
273 int thisIntegerValue = ((Number) value).intValue();
274 int otherIntegerValue = ((PrologNumber) term).getIntegerValue();
275
276 if (thisIntegerValue < otherIntegerValue) {
277 return -1;
278 } else if (thisIntegerValue > otherIntegerValue) {
279 return 1;
280 }
281
282 break;
283
284 case LIST_TYPE:
285 case STRUCTURE_TYPE:
286
287 PrologTerm thisCompound = this;
288 PrologTerm otherCompound = term;
289
290
291 if (thisCompound.getArity() < otherCompound.getArity()) {
292 return -1;
293 } else if (thisCompound.getArity() > otherCompound.getArity()) {
294 return 1;
295 }
296
297
298 result = thisCompound.getFunctor().compareTo(otherCompound.getFunctor());
299 if (result < 0) {
300 return -1;
301 } else if (result > 0) {
302 return 1;
303 }
304
305
306 PrologTerm[] thisArguments = thisCompound.getArguments();
307 PrologTerm[] otherArguments = otherCompound.getArguments();
308
309 for (int i = 0; i < thisArguments.length; i++) {
310 PrologTerm thisArgument = thisArguments[i];
311 PrologTerm otherArgument = otherArguments[i];
312 if (thisArgument != null && otherArgument != null) {
313 result = thisArgument.compareTo(otherArgument);
314 if (result != 0) {
315 return result;
316 }
317 }
318 }
319 break;
320
321 case VARIABLE_TYPE:
322
323 PrologTerm thisVariable = this;
324 PrologTerm otherVariable = term;
325 if (thisVariable.hashCode() < otherVariable.hashCode()) {
326 return -1;
327 } else if (thisVariable.hashCode() > otherVariable.hashCode()) {
328 return 1;
329 }
330 break;
331
332 default:
333 return 0;
334
335 }
336
337 return 0;
338 }
339
340 public int hashCode() {
341 final int prime = 31;
342 int result = 1;
343 result = prime * result + type;
344 result = prime * result + ((value == null) ? 0 : value.toString().hashCode());
345 return result;
346 }
347
348 public boolean equals(Object obj) {
349 if (this == obj)
350 return true;
351 if (obj == null)
352 return false;
353 if (!(obj instanceof JTrologTerm))
354 return false;
355 JTrologTerm other = (JTrologTerm) obj;
356 if (value == null) {
357 if (other.value != null)
358 return false;
359 } else if (value.toString().equals(other.value.toString())) {
360 return true;
361 } else if (!Prolog.match(value, other.value)) {
362 return false;
363 }
364 return true;
365 }
366
367 public String toString() {
368 return value.toStringSmall();
369 }
370
371 }