View Javadoc

1   /*-
2    * #%L
3    * prolobjectlink-jpi
4    * %%
5    * Copyright (C) 2020 - 2021 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 static io.github.prolobjectlink.prolog.PrologTermType.OBJECT_TYPE;
29  
30  public abstract class AbstractCompounds extends AbstractTerm implements PrologTerm {
31  
32  	public AbstractCompounds(int type, PrologProvider provider) {
33  		super(type, provider);
34  	}
35  
36  	public final boolean isAtom() {
37  		return false;
38  	}
39  
40  	public final boolean isNumber() {
41  		return false;
42  	}
43  
44  	public final boolean isFloat() {
45  		return false;
46  	}
47  
48  	public final boolean isInteger() {
49  		return false;
50  	}
51  
52  	public final boolean isDouble() {
53  		return false;
54  	}
55  
56  	public final boolean isLong() {
57  		return false;
58  	}
59  
60  	public boolean isVariable() {
61  		return false;
62  	}
63  
64  	public final boolean isNil() {
65  		return false;
66  	}
67  
68  	public final boolean isAtomic() {
69  		return false;
70  	}
71  
72  	public final boolean isCompound() {
73  		return true;
74  	}
75  
76  	public final boolean isEvaluable() {
77  		return false;
78  	}
79  
80  	public final boolean isTrueType() {
81  		Object object = getObject();
82  		return object != null && object.equals(true);
83  	}
84  
85  	public final boolean isFalseType() {
86  		Object object = getObject();
87  		return object != null && object.equals(false);
88  	}
89  
90  	public final boolean isNullType() {
91  		return isObjectType() && getObject() == null;
92  	}
93  
94  	public final boolean isVoidType() {
95  		return getObject() == void.class;
96  	}
97  
98  	public final boolean isObjectType() {
99  		return getType() == OBJECT_TYPE;
100 	}
101 
102 	public final boolean isReference() {
103 		return isObjectType();
104 	}
105 
106 	public final int compareTo(PrologTerm term) {
107 		PrologTerm thisCompound = this;
108 		PrologTerm otherCompound = term;
109 
110 		if (!otherCompound.isCompound()) {
111 			if (otherCompound.isEmptyList() && thisCompound.isEmptyList()) {
112 				return 0;
113 			}
114 			return 1;
115 		}
116 
117 		if (otherCompound.isEmptyList() && thisCompound.isEmptyList()) {
118 			return 0;
119 		}
120 
121 		// comparison by arity
122 		if (thisCompound.getArity() < otherCompound.getArity()) {
123 			return -1;
124 		} else if (thisCompound.getArity() > otherCompound.getArity()) {
125 			return 1;
126 		}
127 
128 		// alphabetic functor comparison
129 		int result = thisCompound.getFunctor().compareTo(otherCompound.getFunctor());
130 		if (result < 0) {
131 			return -1;
132 		} else if (result > 0) {
133 			return 1;
134 		}
135 
136 		// arguments comparison
137 		PrologTerm[] thisArguments = thisCompound.getArguments();
138 		PrologTerm[] otherArguments = otherCompound.getArguments();
139 
140 		for (int i = 0; i < thisArguments.length; i++) {
141 			PrologTerm thisArgument = thisArguments[i];
142 			PrologTerm otherArgument = otherArguments[i];
143 			if (thisArgument != null && otherArgument != null) {
144 				result = thisArgument.compareTo(otherArgument);
145 				if (result != 0) {
146 					return result;
147 				}
148 			}
149 		}
150 
151 		return 0;
152 	}
153 
154 	public final boolean unify(PrologTerm term) {
155 		PrologTerm thisTerm = this;
156 		PrologTerm otherTerm = term;
157 		if (thisTerm == otherTerm) {
158 			return true;
159 		} else if (thisTerm.isVariable()) {
160 			if (thisTerm == thisTerm.getTerm()) {
161 				return true;
162 			}
163 			return thisTerm.getTerm().unify(otherTerm);
164 		} else if (otherTerm.isVariable()) {
165 			if (otherTerm == otherTerm.getTerm()) {
166 				return true;
167 			}
168 			return otherTerm.getTerm().unify(thisTerm);
169 		} else if (otherTerm.isCompound()) {
170 			int thisArity = thisTerm.getArity();
171 			int otherArity = otherTerm.getArity();
172 			String thisFunctor = thisTerm.getFunctor();
173 			String otherFunctor = otherTerm.getFunctor();
174 			if (thisFunctor.equals(otherFunctor) && thisArity == otherArity) {
175 				PrologTerm[] thisArguments = thisTerm.getArguments();
176 				PrologTerm[] otherArguments = otherTerm.getArguments();
177 				if (thisArguments.length == otherArguments.length) {
178 					for (int i = 0; i < thisArguments.length; i++) {
179 						if (thisArguments[i] != null && otherArguments[i] != null) {
180 							PrologTerm thisArgument = thisArguments[i];
181 							PrologTerm otherArgument = otherArguments[i];
182 							if (!thisArgument.unify(otherArgument)) {
183 								return false;
184 							}
185 						}
186 					}
187 					return true;
188 				}
189 				return false;
190 			}
191 			return false;
192 		}
193 		return false;
194 	}
195 
196 }