View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-jpl7
4    * %%
5    * Copyright (C) 2019 Prolobjectlink Project
6    * %%
7    * Redistribution and use in source and binary forms, with or without
8    * modification, are permitted provided that the following conditions are met:
9    * 
10   * 1. Redistributions of source code must retain the above copyright notice,
11   *    this list of conditions and the following disclaimer.
12   * 2. Redistributions in binary form must reproduce the above copyright notice,
13   *    this list of conditions and the following disclaimer in the documentation
14   *    and/or other materials provided with the distribution.
15   * 
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26   * POSSIBILITY OF SUCH DAMAGE.
27   * #L%
28   */
29  package io.github.prolobjectlink.prolog.jpl7;
30  
31  import static io.github.prolobjectlink.prolog.PrologTermType.ATOM_TYPE;
32  import static io.github.prolobjectlink.prolog.PrologTermType.CLASS_TYPE;
33  import static io.github.prolobjectlink.prolog.PrologTermType.CUT_TYPE;
34  import static io.github.prolobjectlink.prolog.PrologTermType.DOUBLE_TYPE;
35  import static io.github.prolobjectlink.prolog.PrologTermType.FAIL_TYPE;
36  import static io.github.prolobjectlink.prolog.PrologTermType.FALSE_TYPE;
37  import static io.github.prolobjectlink.prolog.PrologTermType.FIELD_TYPE;
38  import static io.github.prolobjectlink.prolog.PrologTermType.FLOAT_TYPE;
39  import static io.github.prolobjectlink.prolog.PrologTermType.INTEGER_TYPE;
40  import static io.github.prolobjectlink.prolog.PrologTermType.LIST_TYPE;
41  import static io.github.prolobjectlink.prolog.PrologTermType.LONG_TYPE;
42  import static io.github.prolobjectlink.prolog.PrologTermType.MAP_ENTRY_TYPE;
43  import static io.github.prolobjectlink.prolog.PrologTermType.MAP_TYPE;
44  import static io.github.prolobjectlink.prolog.PrologTermType.MIXIN_TYPE;
45  import static io.github.prolobjectlink.prolog.PrologTermType.NIL_TYPE;
46  import static io.github.prolobjectlink.prolog.PrologTermType.OBJECT_TYPE;
47  import static io.github.prolobjectlink.prolog.PrologTermType.PARAMETER_TYPE;
48  import static io.github.prolobjectlink.prolog.PrologTermType.RESULT_TYPE;
49  import static io.github.prolobjectlink.prolog.PrologTermType.STRUCTURE_TYPE;
50  import static io.github.prolobjectlink.prolog.PrologTermType.TRUE_TYPE;
51  import static io.github.prolobjectlink.prolog.PrologTermType.VARIABLE_TYPE;
52  
53  import java.util.ArrayList;
54  import java.util.List;
55  
56  import org.jpl7.Atom;
57  import org.jpl7.Compound;
58  import org.jpl7.Float;
59  import org.jpl7.Integer;
60  import org.jpl7.JPL;
61  import org.jpl7.JPLException;
62  import org.jpl7.JRef;
63  import org.jpl7.Query;
64  import org.jpl7.Term;
65  import org.jpl7.Variable;
66  
67  import io.github.prolobjectlink.prolog.AbstractConverter;
68  import io.github.prolobjectlink.prolog.PrologAtom;
69  import io.github.prolobjectlink.prolog.PrologConverter;
70  import io.github.prolobjectlink.prolog.PrologDouble;
71  import io.github.prolobjectlink.prolog.PrologFloat;
72  import io.github.prolobjectlink.prolog.PrologInteger;
73  import io.github.prolobjectlink.prolog.PrologLong;
74  import io.github.prolobjectlink.prolog.PrologStructure;
75  import io.github.prolobjectlink.prolog.PrologTerm;
76  import io.github.prolobjectlink.prolog.PrologVariable;
77  import io.github.prolobjectlink.prolog.UnknownTermError;
78  
79  /**
80   * @author Jose Zalacain
81   * @since 1.0
82   */
83  public abstract class JplConverter extends AbstractConverter<Term> implements PrologConverter<Term> {
84  
85  	public final PrologTerm toTerm(Term prologTerm) {
86  		if (prologTerm.isAtom()) {
87  			String functor = prologTerm.name();
88  			if (functor.equals("nil")) {
89  				return new JplNil(provider);
90  			} else if (functor.equals("!")) {
91  				return new JplCut(createProvider());
92  			} else if (functor.equals("fail")) {
93  				return new JplFail(provider);
94  			} else if (functor.equals("true")) {
95  				return new JplTrue(provider);
96  			} else if (functor.equals("false")) {
97  				return new JplFalse(provider);
98  			} else if (functor.equals("[]")) {
99  				return new JplEmpty(provider);
100 			}
101 			return new JplAtom(provider, functor);
102 		} else if (prologTerm.isListNil()) {
103 			return new JplEmpty(provider);
104 		} else if (prologTerm.isFloat()) {
105 			return new JplFloat(provider, ((Float) prologTerm).floatValue());
106 		} else if (prologTerm.isBigInteger()) {
107 			return new JplLong(provider, ((Integer) prologTerm).longValue());
108 		} else if (prologTerm.isInteger()) {
109 			try {
110 				return new JplInteger(provider, ((Integer) prologTerm).intValue());
111 			} catch (JPLException e) {
112 				return new JplLong(provider, ((Integer) prologTerm).longValue());
113 			}
114 		} else if (prologTerm.isVariable()) {
115 			String name = ((Variable) prologTerm).name();
116 			PrologVariable variable = sharedVariables.get(name);
117 			if (variable == null) {
118 				variable = new JplVariable(provider, name);
119 				sharedVariables.put(variable.getName(), variable);
120 			}
121 			return variable;
122 		} else if (prologTerm.isListPair()) {
123 			Term[] a = new Term[0];
124 			List<Term> l = new ArrayList<Term>();
125 			Term ptr = prologTerm;
126 			while (ptr.isListPair()) {
127 				l.add(ptr.arg(1));
128 				ptr = ptr.arg(2);
129 			}
130 			return new JplList(provider, l.toArray(a));
131 		} else if (prologTerm.isJRef()) {
132 			JRef jRef = (JRef) prologTerm;
133 			return new JplReference(provider, jRef);
134 		} else if (prologTerm.isCompound()) {
135 			Compound compound = (Compound) prologTerm;
136 			int arity = compound.arity();
137 			String functor = compound.name();
138 			Term[] arguments = new Term[arity];
139 
140 			// expressions
141 			if (arity == 2) {
142 				String key = "LIST";
143 				String opQuery = "findall(OP,current_op(_,_,OP)," + key + ")";
144 				Query query = new Query(opQuery);
145 				if (query.hasSolution()) {
146 
147 					Term term = query.oneSolution().get(key);
148 					Term[] termArray = term.toTermArray();
149 					for (Term termArray1 : termArray) {
150 						if (termArray1.name().equals(functor)) {
151 							Term left = compound.arg(1);
152 							Term right = compound.arg(2);
153 							return new JplStructure(provider, left, functor, right);
154 						}
155 					}
156 
157 				}
158 				query.close();
159 			}
160 
161 			for (int i = 0; i < arity; i++) {
162 				arguments[i] = compound.arg(i + 1);
163 			}
164 			return new JplStructure(provider, functor, arguments);
165 
166 		}
167 
168 		throw new UnknownTermError(prologTerm);
169 	}
170 
171 	public final Term fromTerm(PrologTerm term) {
172 		switch (term.getType()) {
173 		case NIL_TYPE:
174 			return new Atom("nil");
175 		case CUT_TYPE:
176 			return new Atom("!");
177 		case FAIL_TYPE:
178 			return new Atom("fail");
179 		case TRUE_TYPE:
180 			return new Atom("true");
181 		case FALSE_TYPE:
182 			return new Atom("false");
183 		case ATOM_TYPE:
184 			return new Atom(removeQuoted(((PrologAtom) term).getStringValue()));
185 		case FLOAT_TYPE:
186 			return new Float(((PrologFloat) term).getFloatValue());
187 		case INTEGER_TYPE:
188 			return new Integer(((PrologInteger) term).getIntegerValue());
189 		case DOUBLE_TYPE:
190 			return new Float(((PrologDouble) term).getDoubleValue());
191 		case LONG_TYPE:
192 			return new Integer(((PrologLong) term).getLongValue());
193 		case VARIABLE_TYPE:
194 			String name = ((PrologVariable) term).getName();
195 			Term variable = sharedPrologVariables.get(name);
196 			if (variable == null) {
197 				variable = new Variable(name);
198 				sharedPrologVariables.put(name, variable);
199 			}
200 			return variable;
201 		case LIST_TYPE:
202 		case MAP_TYPE:
203 			PrologTerm[] array = term.getArguments();
204 			Term list = JplEmpty.EMPTY;
205 			for (int i = array.length - 1; i >= 0; --i) {
206 				list = new Compound("[|]", new Term[] { fromTerm(array[i]), list });
207 			}
208 			return list;
209 		case STRUCTURE_TYPE:
210 		case MAP_ENTRY_TYPE:
211 			String functor = term.getFunctor();
212 			Term[] arguments = fromTermArray(((PrologStructure) term).getArguments());
213 			return new Compound(functor, arguments);
214 		case OBJECT_TYPE:
215 			return JPL.newJRef(term.getObject());
216 		case PARAMETER_TYPE:
217 		case RESULT_TYPE:
218 		case FIELD_TYPE:
219 			name = ((PrologVariable) term).getName();
220 			variable = sharedPrologVariables.get(name);
221 			if (variable == null) {
222 				variable = new Variable(name);
223 				sharedPrologVariables.put(name, variable);
224 			}
225 			return variable;
226 		case MIXIN_TYPE:
227 		case CLASS_TYPE:
228 			functor = removeQuoted(term.getFunctor());
229 			arguments = fromTermArray(term.getArguments());
230 			return new Compound(functor, arguments);
231 		default:
232 			throw new UnknownTermError(term);
233 		}
234 	}
235 
236 	public final Term[] fromTermArray(PrologTerm[] terms) {
237 		Term[] prologTerms = new Term[terms.length];
238 		for (int i = 0; i < terms.length; i++) {
239 			prologTerms[i] = fromTerm(terms[i]);
240 		}
241 		return prologTerms;
242 	}
243 
244 	public final Term fromTerm(PrologTerm head, PrologTerm[] body) {
245 		Term clauseHead = fromTerm(head);
246 		if (body != null && body.length > 0) {
247 			Term clauseBody = fromTerm(body[body.length - 1]);
248 			for (int i = body.length - 2; i >= 0; --i) {
249 				clauseBody = new Compound(",", new Term[] { fromTerm(body[i]), clauseBody });
250 			}
251 			return new Compound(":-", new Term[] { clauseHead, clauseBody });
252 		}
253 		return clauseHead;
254 	}
255 
256 }