View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-jpl
4    * %%
5    * Copyright (C) 2019 Prolobjectlink Project
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as
9    * published by the Free Software Foundation, either version 2.1 of the
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-2.1.html>.
20   * #L%
21   */
22  package io.github.prolobjectlink.prolog.jpl;
23  
24  import static io.github.prolobjectlink.prolog.PrologTermType.ATOM_TYPE;
25  import static io.github.prolobjectlink.prolog.PrologTermType.CLASS_TYPE;
26  import static io.github.prolobjectlink.prolog.PrologTermType.CUT_TYPE;
27  import static io.github.prolobjectlink.prolog.PrologTermType.DOUBLE_TYPE;
28  import static io.github.prolobjectlink.prolog.PrologTermType.FAIL_TYPE;
29  import static io.github.prolobjectlink.prolog.PrologTermType.FALSE_TYPE;
30  import static io.github.prolobjectlink.prolog.PrologTermType.FIELD_TYPE;
31  import static io.github.prolobjectlink.prolog.PrologTermType.FLOAT_TYPE;
32  import static io.github.prolobjectlink.prolog.PrologTermType.INTEGER_TYPE;
33  import static io.github.prolobjectlink.prolog.PrologTermType.LIST_TYPE;
34  import static io.github.prolobjectlink.prolog.PrologTermType.LONG_TYPE;
35  import static io.github.prolobjectlink.prolog.PrologTermType.MAP_ENTRY_TYPE;
36  import static io.github.prolobjectlink.prolog.PrologTermType.MAP_TYPE;
37  import static io.github.prolobjectlink.prolog.PrologTermType.MIXIN_TYPE;
38  import static io.github.prolobjectlink.prolog.PrologTermType.NIL_TYPE;
39  import static io.github.prolobjectlink.prolog.PrologTermType.OBJECT_TYPE;
40  import static io.github.prolobjectlink.prolog.PrologTermType.PARAMETER_TYPE;
41  import static io.github.prolobjectlink.prolog.PrologTermType.RESULT_TYPE;
42  import static io.github.prolobjectlink.prolog.PrologTermType.STRUCTURE_TYPE;
43  import static io.github.prolobjectlink.prolog.PrologTermType.TRUE_TYPE;
44  import static io.github.prolobjectlink.prolog.PrologTermType.VARIABLE_TYPE;
45  
46  import java.util.ArrayList;
47  import java.util.List;
48  
49  import io.github.prolobjectlink.prolog.AbstractConverter;
50  import io.github.prolobjectlink.prolog.PrologAtom;
51  import io.github.prolobjectlink.prolog.PrologConverter;
52  import io.github.prolobjectlink.prolog.PrologDouble;
53  import io.github.prolobjectlink.prolog.PrologFloat;
54  import io.github.prolobjectlink.prolog.PrologInteger;
55  import io.github.prolobjectlink.prolog.PrologLong;
56  import io.github.prolobjectlink.prolog.PrologStructure;
57  import io.github.prolobjectlink.prolog.PrologTerm;
58  import io.github.prolobjectlink.prolog.PrologVariable;
59  import io.github.prolobjectlink.prolog.UnknownTermError;
60  import jpl.Atom;
61  import jpl.Compound;
62  import jpl.Float;
63  import jpl.Integer;
64  import jpl.JPL;
65  import jpl.JPLException;
66  import jpl.Query;
67  import jpl.Term;
68  import jpl.Variable;
69  
70  /**
71   * @author Jose Zalacain
72   * @since 1.0
73   */
74  public abstract class JplConverter extends AbstractConverter<Term> implements PrologConverter<Term> {
75  
76  	public final PrologTerm toTerm(Term prologTerm) {
77  		if (prologTerm.isAtom()) {
78  			String functor = prologTerm.name();
79  			if (functor.equals("nil")) {
80  				return new JplNil(provider);
81  			} else if (functor.equals("!")) {
82  				return new JplCut(createProvider());
83  			} else if (functor.equals("fail")) {
84  				return new JplFail(provider);
85  			} else if (functor.equals("true")) {
86  				return new JplTrue(provider);
87  			} else if (functor.equals("false")) {
88  				return new JplFalse(provider);
89  			} else if (functor.equals("[]")) {
90  				return new JplEmpty(provider);
91  			}
92  			return new JplAtom(provider, functor);
93  		} else if (prologTerm.equals(JplList.EMPTY)) {
94  			return new JplEmpty(provider);
95  		} else if (prologTerm.isFloat()) {
96  			return new JplFloat(provider, ((Float) prologTerm).floatValue());
97  		} else if (prologTerm.isInteger()) {
98  			try {
99  				return new JplInteger(provider, ((Integer) prologTerm).intValue());
100 			} catch (JPLException e) {
101 				return new JplLong(provider, ((Integer) prologTerm).longValue());
102 			}
103 		} else if (prologTerm.isVariable()) {
104 			String name = ((Variable) prologTerm).name();
105 			PrologVariable variable = sharedVariables.get(name);
106 			if (variable == null) {
107 				variable = new JplVariable(provider, name);
108 				sharedVariables.put(variable.getName(), variable);
109 			}
110 			return variable;
111 		} else if (prologTerm.hasFunctor(".", 2)) {
112 			Term[] a = new Term[0];
113 			List<Term> l = new ArrayList<Term>();
114 			Term ptr = prologTerm;
115 			while (!ptr.isVariable() && ptr.hasFunctor(".", 2)) {
116 				l.add(ptr.arg(1));
117 				ptr = ptr.arg(2);
118 			}
119 			return new JplList(provider, l.toArray(a));
120 		} else if (prologTerm.isCompound()) {
121 
122 			Compound compound = (Compound) prologTerm;
123 			int arity = compound.arity();
124 			String functor = compound.name();
125 			Term[] arguments = new Term[arity];
126 
127 			// object reference
128 			if (functor.equals("@") && arity == 1) {
129 				return new JplReference(provider, compound);
130 			}
131 
132 			// expressions
133 			else if (arity == 2) {
134 				String key = "LIST";
135 				String opQuery = "findall(OP,current_op(_,_,OP)," + key + ")";
136 				Query query = new Query(opQuery);
137 				if (query.hasSolution()) {
138 
139 					Term term = (Term) query.oneSolution().get(key);
140 					Term[] termArray = term.toTermArray();
141 					for (Term termArray1 : termArray) {
142 						if (termArray1.name().equals(functor)) {
143 							Term left = compound.arg(1);
144 							Term right = compound.arg(2);
145 							return new JplStructure(provider, left, functor, right);
146 						}
147 					}
148 
149 				}
150 				query.close();
151 			}
152 
153 			for (int i = 0; i < arity; i++) {
154 				arguments[i] = compound.arg(i + 1);
155 			}
156 			return new JplStructure(provider, functor, arguments);
157 
158 		}
159 
160 		throw new UnknownTermError(prologTerm);
161 	}
162 
163 	public final Term fromTerm(PrologTerm term) {
164 		switch (term.getType()) {
165 		case NIL_TYPE:
166 			return new Atom("nil");
167 		case CUT_TYPE:
168 			return new Atom("!");
169 		case FAIL_TYPE:
170 			return new Atom("fail");
171 		case TRUE_TYPE:
172 			return new Atom("true");
173 		case FALSE_TYPE:
174 			return new Atom("false");
175 		case ATOM_TYPE:
176 			return new Atom(removeQuoted(((PrologAtom) term).getStringValue()));
177 		case FLOAT_TYPE:
178 			return new Float(((PrologFloat) term).getFloatValue());
179 		case INTEGER_TYPE:
180 			return new Integer(((PrologInteger) term).getIntegerValue());
181 		case DOUBLE_TYPE:
182 			return new Float(((PrologDouble) term).getDoubleValue());
183 		case LONG_TYPE:
184 			return new Integer(((PrologLong) term).getLongValue());
185 		case VARIABLE_TYPE:
186 			String name = ((PrologVariable) term).getName();
187 			Term variable = sharedPrologVariables.get(name);
188 			if (variable == null) {
189 				variable = new Variable(name);
190 				sharedPrologVariables.put(name, variable);
191 			}
192 			return variable;
193 		case LIST_TYPE:
194 		case MAP_TYPE:
195 			PrologTerm[] array = term.getArguments();
196 			Term list = JplEmpty.EMPTY;
197 			for (int i = array.length - 1; i >= 0; --i) {
198 				list = new Compound(".", new Term[] { fromTerm(array[i]), list });
199 			}
200 			return list;
201 		case STRUCTURE_TYPE:
202 		case MAP_ENTRY_TYPE:
203 			String functor = term.getFunctor();
204 			Term[] arguments = fromTermArray(((PrologStructure) term).getArguments());
205 			return new Compound(functor, arguments);
206 		case OBJECT_TYPE:
207 			return JPL.newJRef(term.getObject());
208 		case PARAMETER_TYPE:
209 		case RESULT_TYPE:
210 		case FIELD_TYPE:
211 			name = ((PrologVariable) term).getName();
212 			variable = sharedPrologVariables.get(name);
213 			if (variable == null) {
214 				variable = new Variable(name);
215 				sharedPrologVariables.put(name, variable);
216 			}
217 			return variable;
218 		case MIXIN_TYPE:
219 		case CLASS_TYPE:
220 			functor = removeQuoted(term.getFunctor());
221 			arguments = fromTermArray(term.getArguments());
222 			return new Compound(functor, arguments);
223 		default:
224 			throw new UnknownTermError(term);
225 		}
226 	}
227 
228 	public final Term[] fromTermArray(PrologTerm[] terms) {
229 		Term[] prologTerms = new Term[terms.length];
230 		for (int i = 0; i < terms.length; i++) {
231 			prologTerms[i] = fromTerm(terms[i]);
232 		}
233 		return prologTerms;
234 	}
235 
236 	public final Term fromTerm(PrologTerm head, PrologTerm[] body) {
237 		Term clauseHead = fromTerm(head);
238 		if (body != null && body.length > 0) {
239 			Term clauseBody = fromTerm(body[body.length - 1]);
240 			for (int i = body.length - 2; i >= 0; --i) {
241 				clauseBody = new Compound(",", new Term[] { fromTerm(body[i]), clauseBody });
242 			}
243 			return new Compound(":-", new Term[] { clauseHead, clauseBody });
244 		}
245 		return clauseHead;
246 	}
247 
248 }