View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-jtrolog
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.jtrolog;
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.Iterator;
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.PrologProvider;
57  import io.github.prolobjectlink.prolog.PrologStructure;
58  import io.github.prolobjectlink.prolog.PrologTerm;
59  import io.github.prolobjectlink.prolog.PrologVariable;
60  import io.github.prolobjectlink.prolog.UnknownTermError;
61  import jTrolog.terms.Double;
62  import jTrolog.terms.Float;
63  import jTrolog.terms.Int;
64  import jTrolog.terms.Long;
65  import jTrolog.terms.Struct;
66  import jTrolog.terms.StructAtom;
67  import jTrolog.terms.Term;
68  import jTrolog.terms.Var;
69  
70  /**
71   * 
72   * @author Jose Zalacain
73   * @since 1.0
74   */
75  final class JTrologConverter extends AbstractConverter<Term> implements PrologConverter<Term> {
76  
77  	private static final JTrologOperatorSet OPERATORS = new JTrologOperatorSet();
78  
79  	public PrologTerm toTerm(Term prologTerm) {
80  		if (prologTerm.equals(Term.TRUE)) {
81  			return new JTrologTrue(provider);
82  		} else if (prologTerm.equals(Term.FALSE)) {
83  			return new JTrologFalse(provider);
84  		}
85  
86  		// long extend integer and double extend float
87  		// be careful with instance check order
88  
89  		else if (prologTerm instanceof Double) { // double always before float
90  			return new JTrologDouble(provider, ((Double) prologTerm).doubleValue());
91  		} else if (prologTerm instanceof Float) { // float always after double
92  			return new JTrologFloat(provider, ((Float) prologTerm).floatValue());
93  		} else if (prologTerm instanceof Long) { // long always before integer
94  			return new JTrologLong(provider, ((Long) prologTerm).longValue());
95  		} else if (prologTerm instanceof Int) { // integer always after long
96  			return new JTrologInteger(provider, ((Int) prologTerm).intValue());
97  		} else if (prologTerm instanceof Var) {
98  			Var var = (Var) prologTerm;
99  			String name = var.toString();
100 			PrologVariable v = sharedVariables.get(name);
101 			if (v == null) {
102 				v = new JTrologVariable(provider, name, var.nrInStruct);
103 				sharedVariables.put(v.toString(), v);
104 			}
105 			return v;
106 		} else if (prologTerm instanceof Struct) {
107 
108 			Struct struct = (Struct) prologTerm;
109 			int arity = struct.arity;
110 			String functor = struct.name;
111 			Term[] arguments = new Term[arity];
112 
113 			if (struct == Term.emptyList) {
114 				return new JTrologEmpty(provider);
115 			}
116 
117 			// atom and constants
118 			else if (prologTerm instanceof StructAtom) {
119 				if (functor.equals("nil")) {
120 					return new JTrologNil(provider);
121 				} else if (functor.equals("!")) {
122 					return new JTrologCut(provider);
123 				} else if (functor.equals("fail")) {
124 					return new JTrologFail(provider);
125 				} else {
126 					return new JTrologAtom(provider, functor);
127 				}
128 			}
129 
130 			// list
131 			else if (struct.name.equals(".") && struct.arity == 2) {
132 				ArrayList<Term> args = new ArrayList<Term>();
133 				Iterator<?> i = Struct.iterator(struct);
134 				while (i.hasNext()) {
135 					Term term = (Term) i.next();
136 					args.add(term);
137 				}
138 				return new JTrologList(provider, args.toArray(arguments));
139 			}
140 
141 			// expression
142 			else if (arity == 2 && OPERATORS.currentOp(functor)) {
143 				Term left = struct.getArg(0);
144 				Term right = struct.getArg(1);
145 				return new JTrologStructure(provider, left, functor, right);
146 			}
147 
148 			// structure
149 			else {
150 				for (int i = 0; i < arity; i++) {
151 					arguments[i] = struct.getArg(i);
152 				}
153 				return new JTrologStructure(provider, functor, arguments);
154 			}
155 
156 		} else {
157 			throw new UnknownTermError(prologTerm);
158 		}
159 	}
160 
161 	public Term fromTerm(PrologTerm term) {
162 		switch (term.getType()) {
163 		case NIL_TYPE:
164 			return new StructAtom("nil");
165 		case CUT_TYPE:
166 			return new StructAtom("!");
167 		case FAIL_TYPE:
168 			return new StructAtom("fail");
169 		case TRUE_TYPE:
170 			return Term.TRUE;
171 		case FALSE_TYPE:
172 			return Term.FALSE;
173 		case ATOM_TYPE:
174 			return new StructAtom(removeQuoted(((PrologAtom) term).getStringValue()));
175 		case FLOAT_TYPE:
176 			return new Float(((PrologFloat) term).getFloatValue());
177 		case INTEGER_TYPE:
178 			return new Int(((PrologInteger) term).getIntegerValue());
179 		case DOUBLE_TYPE:
180 			return new Double(((PrologDouble) term).getDoubleValue());
181 		case LONG_TYPE:
182 			return new Long(((PrologLong) term).getLongValue());
183 		case VARIABLE_TYPE:
184 			PrologVariable v = (PrologVariable) term;
185 			String name = v.getName();
186 			Term variable = sharedPrologVariables.get(name);
187 			if (variable == null) {
188 				variable = new Var(name, v.getPosition());
189 				sharedPrologVariables.put(name, variable);
190 			}
191 			return variable;
192 		case LIST_TYPE:
193 		case MAP_TYPE:
194 			PrologTerm[] elements = term.getArguments();
195 			if (elements != null && elements.length > 0) {
196 				Term list = Term.emptyList;
197 				int offset = elements[elements.length - 1].isEmptyList() ? 2 : 1;
198 				for (int i = elements.length - offset; i >= 0; --i) {
199 					list = new Struct(".", new Term[] { fromTerm(elements[i], Term.class), list });
200 				}
201 				return list;
202 			}
203 			return Term.emptyList;
204 		case STRUCTURE_TYPE:
205 		case MAP_ENTRY_TYPE:
206 			String functor = term.getFunctor();
207 			if (term.getArity() < 1) {
208 				if (!functor.matches(SIMPLE_ATOM_REGEX)) {
209 					return new StructAtom("'" + functor + "'");
210 				} else {
211 					return new StructAtom(functor);
212 				}
213 			}
214 			Term[] arguments = fromTermArray(((PrologStructure) term).getArguments());
215 			return new Struct(functor, arguments);
216 		case OBJECT_TYPE:
217 			return new Struct("'@'", new Term[] { new StructAtom("'" + term.getObject() + "'") });
218 		case PARAMETER_TYPE:
219 		case RESULT_TYPE:
220 		case FIELD_TYPE:
221 			name = ((PrologVariable) term).getName();
222 			int position = ((PrologVariable) term).getPosition();
223 			return new Var(name, position);
224 		case MIXIN_TYPE:
225 		case CLASS_TYPE:
226 			functor = removeQuoted(term.getFunctor());
227 			arguments = fromTermArray(term.getArguments());
228 			return new Struct(functor, arguments);
229 		default:
230 			throw new UnknownTermError(term);
231 		}
232 	}
233 
234 	public Term[] fromTermArray(PrologTerm[] terms) {
235 		Term[] prologTerms = new Term[terms.length];
236 		for (int i = 0; i < terms.length; i++) {
237 			prologTerms[i] = fromTerm(terms[i]);
238 		}
239 		return prologTerms;
240 	}
241 
242 	public Term fromTerm(PrologTerm head, PrologTerm[] body) {
243 		Term h = fromTerm(head);
244 		if (body != null && body.length > 0) {
245 			Term b = fromTerm(body[body.length - 1]);
246 			for (int i = body.length - 2; i >= 0; --i) {
247 				b = new Struct(",", new Term[] { fromTerm(body[i]), b });
248 			}
249 			return new Struct(":-", new Term[] { h, b });
250 		}
251 		return new Struct(":-", new Term[] { h, Term.TRUE });
252 	}
253 
254 	public PrologProvider createProvider() {
255 		return new JTrolog(this);
256 	}
257 
258 	@Override
259 	public String toString() {
260 		return "JTrologConverter";
261 	}
262 
263 }