View Javadoc

1   /*
2    * #%L
3    * prolobjectlink-jpi-tuprolog
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.tuprolog;
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.Iterator;
47  
48  import alice.tuprolog.Double;
49  import alice.tuprolog.Float;
50  import alice.tuprolog.Int;
51  import alice.tuprolog.Long;
52  import alice.tuprolog.Struct;
53  import alice.tuprolog.Term;
54  import alice.tuprolog.Var;
55  import io.github.prolobjectlink.prolog.AbstractConverter;
56  import io.github.prolobjectlink.prolog.PrologAtom;
57  import io.github.prolobjectlink.prolog.PrologConverter;
58  import io.github.prolobjectlink.prolog.PrologDouble;
59  import io.github.prolobjectlink.prolog.PrologFloat;
60  import io.github.prolobjectlink.prolog.PrologInteger;
61  import io.github.prolobjectlink.prolog.PrologLong;
62  import io.github.prolobjectlink.prolog.PrologProvider;
63  import io.github.prolobjectlink.prolog.PrologTerm;
64  import io.github.prolobjectlink.prolog.PrologVariable;
65  import io.github.prolobjectlink.prolog.UnknownTermError;
66  
67  /**
68   * 
69   * @author Jose Zalacain
70   * @since 1.0
71   */
72  final class TuPrologConverter extends AbstractConverter<Term> implements PrologConverter<Term> {
73  
74  	private static final TuPrologOperatorSet OPERATORS = new TuPrologOperatorSet();
75  
76  	public PrologTerm toTerm(Term prologTerm) {
77  		if (prologTerm.equals(Term.TRUE)) {
78  			return new TuPrologTrue(provider);
79  		} else if (prologTerm.equals(Term.FALSE)) {
80  			return new TuPrologFalse(provider);
81  		} else if (prologTerm instanceof Float) {
82  			return new TuPrologFloat(provider, ((Float) prologTerm).floatValue());
83  		} else if (prologTerm instanceof Int) {
84  			return new TuPrologInteger(provider, ((Int) prologTerm).intValue());
85  		} else if (prologTerm instanceof Double) {
86  			return new TuPrologDouble(provider, ((Double) prologTerm).doubleValue());
87  		} else if (prologTerm instanceof Long) {
88  			return new TuPrologLong(provider, ((Long) prologTerm).longValue());
89  		} else if (prologTerm instanceof Var) {
90  			String name = ((Var) prologTerm).getName();
91  			PrologVariable variable = sharedVariables.get(name);
92  			if (variable == null) {
93  				variable = new TuPrologVariable(provider, name);
94  				sharedVariables.put(variable.getName(), variable);
95  			}
96  			return variable;
97  		} else if (prologTerm instanceof Struct) {
98  
99  			Struct struct = (Struct) prologTerm;
100 			int arity = struct.getArity();
101 			String functor = struct.getName();
102 			Term[] arguments = new Term[arity];
103 
104 			if (struct.isEmptyList()) {
105 				return new TuPrologEmpty(provider);
106 			}
107 
108 			// atom and constants
109 			else if (prologTerm.isAtom()) {
110 				if (functor.equals("nil")) {
111 					return new TuPrologNil(provider);
112 				} else if (functor.equals("!")) {
113 					return new TuPrologCut(provider);
114 				} else if (functor.equals("fail")) {
115 					return new TuPrologFail(provider);
116 				} else {
117 					return new TuPrologAtom(provider, functor);
118 				}
119 			}
120 
121 			// list
122 			else if (struct.isList()) {
123 				int index = 0;
124 				arguments = new Term[struct.listSize()];
125 				Iterator<? extends Term> i = struct.listIterator();
126 				while (i.hasNext()) {
127 					Term term = i.next();
128 					arguments[index++] = term;
129 				}
130 				return new TuPrologList(provider, arguments);
131 			}
132 
133 			// expression
134 			else if (arity == 2 && OPERATORS.currentOp(functor)) {
135 				Term left = struct.getArg(0);
136 				Term right = struct.getArg(1);
137 				return new TuPrologStructure(provider, left, functor, right);
138 			}
139 
140 			// structure
141 			else {
142 				for (int i = 0; i < arity; i++) {
143 					arguments[i] = struct.getArg(i);
144 				}
145 				return new TuPrologStructure(provider, functor, arguments);
146 			}
147 
148 		} else {
149 			throw new UnknownTermError(prologTerm);
150 		}
151 	}
152 
153 	public Term fromTerm(PrologTerm term) {
154 		switch (term.getType()) {
155 		case NIL_TYPE:
156 			return new Struct("nil");
157 		case CUT_TYPE:
158 			return new Struct("!");
159 		case FAIL_TYPE:
160 			return new Struct("fail");
161 		case TRUE_TYPE:
162 			return Term.TRUE;
163 		case FALSE_TYPE:
164 			return Term.FALSE;
165 		case ATOM_TYPE:
166 			return new Struct(removeQuoted(((PrologAtom) term).getStringValue()));
167 		case FLOAT_TYPE:
168 			return new Float(((PrologFloat) term).getFloatValue());
169 		case INTEGER_TYPE:
170 			return new Int(((PrologInteger) term).getIntegerValue());
171 		case DOUBLE_TYPE:
172 			return new Double(((PrologDouble) term).getDoubleValue());
173 		case LONG_TYPE:
174 			return new Long(((PrologLong) term).getLongValue());
175 		case VARIABLE_TYPE:
176 			String name = ((PrologVariable) term).getName();
177 			Term variable = sharedPrologVariables.get(name);
178 			if (variable == null) {
179 				variable = new Var(name);
180 				sharedPrologVariables.put(name, variable);
181 			}
182 			return variable;
183 		case MAP_TYPE:
184 		case LIST_TYPE:
185 			return new Struct(fromTermArray(term.getArguments()));
186 		case STRUCTURE_TYPE:
187 		case MAP_ENTRY_TYPE:
188 			String functor = term.getFunctor();
189 			Term[] arguments = fromTermArray(term.getArguments());
190 			return new Struct(functor, arguments);
191 		case OBJECT_TYPE:
192 			return TuPrologReference.set(term.getObject());
193 		case PARAMETER_TYPE:
194 		case RESULT_TYPE:
195 		case FIELD_TYPE:
196 			name = ((PrologVariable) term).getName();
197 			return new Var(name);
198 		case MIXIN_TYPE:
199 		case CLASS_TYPE:
200 			functor = removeQuoted(term.getFunctor());
201 			arguments = fromTermArray(term.getArguments());
202 			return new Struct(functor, arguments);
203 		default:
204 			throw new UnknownTermError(term);
205 		}
206 	}
207 
208 	public Term[] fromTermArray(PrologTerm[] terms) {
209 		Term[] prologTerms = new Term[terms.length];
210 		for (int i = 0; i < terms.length; i++) {
211 			prologTerms[i] = fromTerm(terms[i]);
212 		}
213 		return prologTerms;
214 	}
215 
216 	public Term fromTerm(PrologTerm head, PrologTerm[] body) {
217 		Term clauseHead = fromTerm(head);
218 		if (body != null && body.length > 0) {
219 			Term clauseBody = fromTerm(body[body.length - 1]);
220 			for (int i = body.length - 2; i >= 0; --i) {
221 				clauseBody = new Struct(",", new Term[] { fromTerm(body[i]), clauseBody });
222 			}
223 			return new Struct(":-", clauseHead, clauseBody);
224 		}
225 		return clauseHead;
226 	}
227 
228 	public PrologProvider createProvider() {
229 		return new TuProlog(this);
230 	}
231 
232 	@Override
233 	public String toString() {
234 		return "TuPrologConverter";
235 	}
236 
237 }