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 }