1 /*
2 * #%L
3 * prolobjectlink-jpi
4 * %%
5 * Copyright (C) 2019 Prolobjectlink Project
6 * %%
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 * #L%
25 */
26 package io.github.prolobjectlink.prolog;
27
28 import java.util.Map;
29
30 /**
31 * <p>
32 * Ancestor prolog data type. All Prolog data types {@link PrologAtom},
33 * {@link PrologNumber}, {@link PrologList}, {@link PrologStructure} and
34 * {@link PrologVariable} are derived from this class. All before mentioned
35 * classes extends from this class the commons responsibilities. Extends from
36 * {@link Comparable} to compare the current term with another term based on
37 * Standard Order.
38 * </p>
39 *
40 * <p>
41 * The Prolog Provider is the mechanism to create a new Prolog terms invoking
42 * the correspondent methods. {@link PrologProvider#newAtom(String)} for atoms,
43 * {@link PrologProvider#newStructure(String, PrologTerm...)} for structures,
44 * {@link PrologProvider#newVariable(String, int)} for variables and so on.
45 * </p>
46 *
47 * <p>
48 * With {@link #getType()} the term type can be retrieve. Every term have a type
49 * defined in {@link PrologTermType}. The prolog type have by definition one
50 * order (Standard Order) where Variables < Atoms < Numbers <
51 * Compounds. This order is usable to compare two terms.
52 * </p>
53 *
54 * <p>
55 * Prolog terms have two specials properties, the functor and the arity. Functor
56 * is the compound term or atom name and arity is the number of arguments
57 * present in the compound terms. Variable and Number don't have this
58 * properties. This properties are accessible from {@link #getArity()} and
59 * {@link #getFunctor()} methods. Variable and Number raise an
60 * {@link ArityError} and {@link FunctorError} respectively. Based on functor
61 * and arity atoms and compound terms have a predicate indicator that is the
62 * signature for the term. The term indicator is an string formed by the
63 * concatenation of {@link #getFunctor()} and {@link #getArity()} separated by
64 * slash.
65 * </p>
66 *
67 * <p>
68 * The methods {@link #getArguments()} and {@link #getArgument(int)} allow
69 * retrieve the arguments and the some specific arguments for compounds terms
70 * respectively. For atomics terms {@link #getArguments()} return an empty term
71 * array and {@link #getArgument(int)} raise a
72 * {@link ArrayIndexOutOfBoundsException} because don't have arguments. For this
73 * cases is a good practice check compound terms before invoke this methods.
74 * </p>
75 *
76 * <pre>
77 * if (t.isCompound()) {
78 * PrologTerm x = t.getArgument(i);
79 * System.out.println(x);
80 * }
81 * </pre>
82 *
83 * Prolog unification is the process that involves one or more variables such
84 * that they are instantiated with the necessary terms in order to make two
85 * terms are identical. The prolog term interface provide
86 * {@link #unify(PrologTerm)} method to check that the current term unify with
87 * the given term. Prolog unification algorithm is based on three principals
88 * rules:
89 * <ul>
90 * <li>If x and y are atomics constants then x and y unify only if they are same
91 * object.</li>
92 * <li>If x is a variable and y is anything then they unify and x is
93 * instantiated to y. Conversely, if y is a variable then this is instantiated
94 * to x.</li>
95 * <li>If x and y are structured terms then unify only if they match (equals
96 * funtor and arity) and all their correspondents arguments unify.</li>
97 * </ul>
98 *
99 * <pre>
100 * PrologAtom atom = provider.newAtom("smith");
101 * PrologAtom atom1 = provider.newAtom("doe");
102 * // true because the atoms are equals
103 * assertTrue(atom.unify(atom));
104 * // false because the atoms are different
105 * assertFalse(atom.unify(atom1));
106 * PrologVariable variable = provider.newVariable("X", 0);
107 * // true because atom and variable unify
108 * assertTrue(atom.unify(variable));
109 * </pre>
110 *
111 * @author Jose Zalacain
112 * @since 1.0
113 */
114 public interface PrologTerm extends Comparable<PrologTerm>, PrologElement {
115
116 /**
117 * Gets the term indicator represented by one string with the format
118 * functor/arity. More formally the indicator string is formed by the
119 * concatenation of {@link #getFunctor()} and {@link #getArity()} separated by
120 * slash.
121 *
122 * @return term indicator
123 * @since 1.0
124 */
125 public String getIndicator();
126
127 /**
128 * True if term has an indicator with the format functor/arity that match with
129 * the given functor and arity.
130 *
131 * @param functor term functor
132 * @param arity term arity
133 * @return True if term has an indicator functor/arity.
134 * @since 1.0
135 */
136 public boolean hasIndicator(String functor, int arity);
137
138 /**
139 * Get the term type.
140 *
141 * @return term type.
142 * @since 1.0
143 */
144 public int getType();
145
146 /**
147 * True if this term is an atom
148 *
149 * @return whether this Term represents an atom, false in other case
150 * @since 1.0
151 */
152 public boolean isAtom();
153
154 /**
155 * True if this term is an number
156 *
157 * @return whether this Term represents an number, false in other case
158 * @since 1.0
159 */
160 public boolean isNumber();
161
162 /**
163 * True if this Term is a single precision floating point number, false in other
164 * case
165 *
166 * @return whether this Term represents a single precision floating point
167 * number, false in other case
168 * @since 1.0
169 */
170 public boolean isFloat();
171
172 /**
173 * True if this Term is an integer number, false in other case
174 *
175 * @return whether this Term represents an integer number
176 * @since 1.0
177 */
178 public boolean isInteger();
179
180 /**
181 * True if this Term is a double precision floating point number, false in other
182 * case
183 *
184 * @return whether this Term represents a double precision floating point
185 * number, false in other case
186 * @since 1.0
187 */
188 public boolean isDouble();
189
190 /**
191 * True if this Term is a large integer number, false in other case
192 *
193 * @return whether this Term represents a large integer number, false in other
194 * case
195 * @since 1.0
196 */
197 public boolean isLong();
198
199 /**
200 * True if this Term is a variable, false in other case
201 *
202 * @return whether this Term is a variable
203 * @since 1.0
204 */
205 public boolean isVariable();
206
207 /**
208 * True if this Term is a instanced variable, false in other case
209 *
210 * @return whether this Term is a instanced variable
211 * @since 1.1
212 */
213 public boolean isVariableBound();
214
215 /**
216 * True if this Term is a not instanced variable, false in other case
217 *
218 * @return whether this Term is a not instanced variable
219 * @since 1.1
220 */
221 public boolean isVariableNotBound();
222
223 /**
224 * True if this Term is a list, false in other case
225 *
226 * @return whether this Term is a list
227 * @since 1.0
228 */
229 public boolean isList();
230
231 /**
232 * True if this Term is a structured term, false in other case
233 *
234 * @return whether this Term is a structured term
235 * @since 1.0
236 */
237 public boolean isStructure();
238
239 /**
240 * True if this Term is a nil term (null term for prolog), false in other case
241 *
242 * @return whether this Term is a nil term
243 * @since 1.0
244 */
245 public boolean isNil();
246
247 /**
248 * True if this Term is a empty list term ([]), false in other case
249 *
250 * @return whether this Term is a empty list term
251 * @since 1.0
252 */
253 public boolean isEmptyList();
254
255 /**
256 * True if this Term is a atomic term, false in other case
257 *
258 * @return whether this Term is a atomic term
259 * @since 1.0
260 */
261 public boolean isAtomic();
262
263 /**
264 * True if this Term is a compound term, false in other case
265 *
266 * @return whether this Term is a compound term
267 * @since 1.0
268 */
269 public boolean isCompound();
270
271 /**
272 * Check if the current term is a compound term and have like functor an
273 * operator.
274 *
275 * @return true if current term have like functor an operator.
276 * @since 1.0
277 */
278 public boolean isEvaluable();
279
280 /**
281 * Check if the current term is a reference term and the referenced object is an
282 * instance of java true value. Most formally check if the reference term
283 * is @(true) structure.
284 *
285 * @return true if current term have like referenced object an instance of java
286 * true value.
287 * @since 1.0
288 */
289 public boolean isTrueType();
290
291 /**
292 * Check if the current term is a reference term and the referenced object is an
293 * instance of java false value. Most formally check if the reference term
294 * is @(false) structure.
295 *
296 * @return true if current term have like referenced object an instance of java
297 * false value.
298 * @since 1.0
299 */
300 public boolean isFalseType();
301
302 /**
303 * Check if the current term is a reference term and the referenced object is a
304 * java null value. Most formally check if the reference term is @(null)
305 * structure.
306 *
307 * @return true if current term have like referenced object a java null value.
308 * @since 1.0
309 */
310 public boolean isNullType();
311
312 /**
313 * Check if the current term is a reference term for java void type. Most
314 * formally check if the reference term is @(void) structure.
315 *
316 * @return true if current term is a referenced to java void type.
317 * @since 1.0
318 */
319 public boolean isVoidType();
320
321 /**
322 * Check if the current term is a reference term for some java object instance.
323 * Most formally check if the reference term is an structure
324 * like @(J#00000000000000000425).
325 *
326 *
327 *
328 * @return true if current term is a referenced for some java object instance.
329 * @since 1.0
330 */
331 public boolean isObjectType();
332
333 /**
334 * Check if the current term is a reference term for some java object instance
335 * or is a reference term and the referenced object is a java null value.
336 *
337 * @return true if current term is a reference term for object instance or java
338 * null value.
339 * @since 1.0
340 */
341 public boolean isReference();
342
343 /**
344 * True if this Term is a Entry, false in other case
345 *
346 * @return whether this Term is a entry
347 * @since 1.1
348 */
349 public boolean isEntry();
350
351 /**
352 * True if this Term is a Map, false in other case
353 *
354 * @return whether this Term is a map
355 * @since 1.1
356 */
357 public boolean isMap();
358
359 /**
360 * True if this Term is a Field, false in other case
361 *
362 * @return whether this Term is a field
363 * @since 1.1
364 */
365 @Deprecated
366 public boolean isField();
367
368 /**
369 * True if this Term is a Result, false in other case
370 *
371 * @return whether this Term is a result
372 * @since 1.1
373 */
374 @Deprecated
375 public boolean isResult();
376
377 /**
378 * True if this Term is a Parameter, false in other case
379 *
380 * @return whether this Term is a parameter
381 * @since 1.1
382 */
383 @Deprecated
384 public boolean isParameter();
385
386 /**
387 * True if this Term is a Mixin, false in other case
388 *
389 * @return whether this Term is a mixin
390 * @since 1.1
391 */
392 @Deprecated
393 public boolean isMixin();
394
395 /**
396 * True if this Term is a Class, false in other case
397 *
398 * @return whether this Term is a class
399 * @since 1.1
400 */
401 @Deprecated
402 public boolean isClass();
403
404 /**
405 * For references terms return the referenced object.
406 *
407 * @return the referenced object if the current term is a reference prolog term
408 * @since 1.0
409 */
410 public Object getObject();
411
412 /**
413 * Return current term instance if current term is not a variable or is a free
414 * variable term. If current term is a variable bound term then return the
415 * linked term hold by this variable after dereferencing.
416 *
417 * @return return a dereferencing term if current term is bound variable,
418 * current term in otherwise
419 * @since 1.0
420 */
421 public PrologTerm getTerm();
422
423 /**
424 * Term arity. The arity of a term is a argument number for compound terms. If a
425 * the current term is not a compound term, then an exception is raised
426 * indicating a violation.
427 *
428 * @return term arity for compound terms or an exception is raised if the term
429 * is not a compound term.
430 * @since 1.0
431 */
432 public int getArity();
433
434 /**
435 * Term functor.The functor of a term is a name for compound terms. If a the
436 * current term is not a compound term, then an exception is raised indicating a
437 * violation.
438 *
439 * @return term functor for compound terms or an exception is raised if the term
440 * is not a compound term.
441 * @since 1.0
442 */
443 public String getFunctor();
444
445 /**
446 * Term arguments if the current term is a compound term. Compound terms are
447 * Structures and List data types. They are compoused by a PrologTerm[] array.
448 * Atoms, Variables and Numbers return an empty term array.
449 *
450 * @return Term arguments if the current term is a compound term.
451 * @since 1.0
452 */
453 public PrologTerm[] getArguments();
454
455 /**
456 * Term located at some given index position in the current term arguments if
457 * current term is a compound term. If the current term is not compound term an
458 * {@link ArrayIndexOutOfBoundsException} exception is raised.
459 *
460 * @param index position to retrieve the correspondent term.
461 * @return Term located at some given index position.
462 * @throws ArrayIndexOutOfBoundsException if the index value is out of term
463 * array bound.
464 * @since 1.0
465 */
466 public PrologTerm getArgument(int index);
467
468 /**
469 * Check that the current term unify with the given term. Prolog unification
470 * algorithm is based on three principals rules:
471 * <ul>
472 * <li>If x and y are atomics constants then x and y unify only if they are same
473 * object.</li>
474 * <li>If x is a variable and y is anything then they unify and x is
475 * instantiated to y. Conversely, if y is a variable then this is instantiated
476 * to x.</li>
477 * <li>If x and y are structured terms then unify only if they match (equals
478 * funtor and arity) and all their correspondents arguments unify.</li>
479 * </ul>
480 *
481 *
482 * @param term the term to unify with the current term
483 * @return true if the specified term unify whit the current term, false if not
484 * @since 1.0
485 */
486 public boolean unify(PrologTerm term);
487
488 /**
489 * Match to other term returning list of substitutions.
490 *
491 * @param term - term to match check
492 * @return list of substitutions.
493 * @since 1.1
494 */
495 public Map<String, PrologTerm> match(PrologTerm term);
496
497 /**
498 * Prolog provider associated to the current term.
499 *
500 * @return Prolog provider associated to the current term.
501 * @since 1.0
502 */
503 public PrologProvider getProvider();
504
505 /**
506 * Casts the current PrologTerm to the class or interface represented by this
507 * {@code Class} object.
508 *
509 * @return the PrologTerm after casting, or null if term is null
510 *
511 * @throws ClassCastException if the object is not null and is not assignable to
512 * the type T.
513 * @since 1.1
514 */
515 public <T extends PrologTerm> T cast();
516
517 }