Revision 44154 trunk/org.gvsig.desktop/org.gvsig.desktop.library/org.gvsig.expressionevaluator/org.gvsig.expressionevaluator.lib/org.gvsig.expressionevaluator.lib.impl/src/main/java/org/gvsig/expressionevaluator/impl/DefaultInterpreter.java
DefaultInterpreter.java | ||
---|---|---|
17 | 17 |
import org.gvsig.expressionevaluator.Codes; |
18 | 18 |
import org.gvsig.expressionevaluator.ExpressionRuntimeException; |
19 | 19 |
import org.gvsig.expressionevaluator.Function; |
20 |
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.RecursionControlSupport; |
|
20 | 21 |
import org.gvsig.expressionevaluator.impl.function.operator.BinaryOperator; |
21 | 22 |
import org.gvsig.expressionevaluator.impl.function.programming.CallMethodFunction; |
22 | 23 |
import org.gvsig.expressionevaluator.impl.function.operator.UnaryOperator; |
... | ... | |
24 | 25 |
|
25 | 26 |
public class DefaultInterpreter implements Interpreter { |
26 | 27 |
|
28 |
public static int DEFAULT_MAX_RECURSION_LIMIT = 20; |
|
29 |
|
|
27 | 30 |
private class DefaultCache implements Cache { |
28 | 31 |
|
29 | 32 |
private Map<Pair<Object,Object>,Pair<Object,Long>> data; |
... | ... | |
83 | 86 |
private Double accuracy; |
84 | 87 |
private Code currentCode; |
85 | 88 |
private Cache cache; |
89 |
private int maxRecursionLimit; |
|
86 | 90 |
|
87 | 91 |
public DefaultInterpreter() { |
88 | 92 |
this.cache = new DefaultCache(); |
93 |
this.maxRecursionLimit = DEFAULT_MAX_RECURSION_LIMIT; |
|
89 | 94 |
} |
90 | 95 |
|
91 | 96 |
@Override |
... | ... | |
95 | 100 |
if( this.symbolTable!=null ) { |
96 | 101 |
other.symbolTable = this.symbolTable.clone(); |
97 | 102 |
} |
98 |
|
|
99 | 103 |
return other; |
100 | 104 |
} |
105 |
|
|
106 |
public int getMaxRecursionLimit() { |
|
107 |
return this.maxRecursionLimit; |
|
108 |
} |
|
101 | 109 |
|
110 |
public void setMaxRecursionLimit(int limit) { |
|
111 |
this.maxRecursionLimit = limit; |
|
112 |
} |
|
113 |
|
|
102 | 114 |
@Override |
103 | 115 |
public Cache getCache() { |
104 | 116 |
return this.cache; |
... | ... | |
159 | 171 |
} |
160 | 172 |
|
161 | 173 |
public Object runCode(Code code) throws Exception { |
174 |
RecursionControlSupport recursionControl = null; |
|
175 |
if( code instanceof RecursionControlSupport ) { |
|
176 |
recursionControl = (RecursionControlSupport) code; |
|
177 |
if( !recursionControl.enterCode(this.maxRecursionLimit) ) { |
|
178 |
recursionControl.resetRecursionState(); |
|
179 |
throw new ExpressionRuntimeException(code, I18N.Maximum_recursion_limit_exceeded()); |
|
180 |
} |
|
181 |
} |
|
182 |
Object value = null; |
|
162 | 183 |
this.currentCode = code; |
163 |
Object value = null;
|
|
164 |
switch( code.code() ) { |
|
165 |
case Code.CONSTANT: |
|
166 |
value = ((Constant) code).value(); |
|
167 |
break; |
|
184 |
try {
|
|
185 |
switch( code.code() ) {
|
|
186 |
case Code.CONSTANT:
|
|
187 |
value = ((Constant) code).value();
|
|
188 |
break;
|
|
168 | 189 |
|
169 |
case Code.IDENTIFIER: |
|
170 |
String name = ((Identifier) code).name(); |
|
171 |
if( !this.getSymbolTable().exists(name) ) { |
|
172 |
throw new ExpressionRuntimeException( |
|
173 |
code, |
|
174 |
I18N.Undefined_variable_XIdentifierX(name), |
|
175 |
I18N.Use_single_quotes_to_enter_literal_strings() |
|
176 |
); |
|
177 |
} |
|
178 |
value = this.getSymbolTable().value(name); |
|
179 |
break; |
|
190 |
case Code.IDENTIFIER:
|
|
191 |
String name = ((Identifier) code).name();
|
|
192 |
if( !this.getSymbolTable().exists(name) ) {
|
|
193 |
throw new ExpressionRuntimeException(
|
|
194 |
code,
|
|
195 |
I18N.Undefined_variable_XIdentifierX(name),
|
|
196 |
I18N.Use_single_quotes_to_enter_literal_strings()
|
|
197 |
);
|
|
198 |
}
|
|
199 |
value = this.getSymbolTable().value(name);
|
|
200 |
break;
|
|
180 | 201 |
|
181 |
case Code.METHOD: { |
|
182 |
Method method = (Method) code; |
|
183 |
Function function = method.function(); |
|
184 |
if( function == null ) { |
|
185 |
Object obj = this.runCode(method.obj()); |
|
186 |
if( obj == null ) { |
|
187 |
throw new NullPointerException("An object pointer was expected to invoke method "+method.methodname()+" and a null was received"); |
|
202 |
case Code.METHOD: { |
|
203 |
Method method = (Method) code; |
|
204 |
Function function = method.function(); |
|
205 |
if( function == null ) { |
|
206 |
Object obj = this.runCode(method.obj()); |
|
207 |
if( obj == null ) { |
|
208 |
throw new NullPointerException("An object pointer was expected to invoke method "+method.methodname()+" and a null was received"); |
|
209 |
} |
|
210 |
method.function(new CallMethodFunction(obj, method.methodname())); |
|
188 | 211 |
} |
189 |
method.function(new CallMethodFunction(obj, method.methodname())); |
|
190 | 212 |
} |
191 |
} |
|
192 |
case Code.CALLER: |
|
193 |
Caller caller = (Caller) code; |
|
194 |
Function function = caller.function(); |
|
195 |
if( function == null ) { |
|
196 |
function = this.getSymbolTable().function(caller.name()); |
|
213 |
case Code.CALLER: |
|
214 |
Caller caller = (Caller) code; |
|
215 |
Function function = caller.function(); |
|
197 | 216 |
if( function == null ) { |
198 |
throw new ExpressionRuntimeException(code, I18N.Undefined_function_XIdentifierX(caller.name())); |
|
217 |
function = this.getSymbolTable().function(caller.name()); |
|
218 |
if( function == null ) { |
|
219 |
throw new ExpressionRuntimeException(code, I18N.Undefined_function_XIdentifierX(caller.name())); |
|
220 |
} |
|
221 |
caller.function(function); |
|
199 | 222 |
} |
200 |
caller.function(function); |
|
201 |
} |
|
202 |
Codes args = caller.args(); |
|
203 |
try { |
|
204 |
switch( caller.type() ) { |
|
205 |
case Caller.UNARY_OPERATOR: |
|
206 |
if( args == null || args.size() != 1 ) { |
|
207 |
throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_1_got_XargcX(function.name(),args==null?0:args.size())); |
|
208 |
} |
|
209 |
value = ((UnaryOperator) function).call(this, runCode(args.get(0))); |
|
210 |
break; |
|
223 |
Codes args = caller.args(); |
|
224 |
try { |
|
225 |
switch( caller.type() ) { |
|
226 |
case Caller.UNARY_OPERATOR: |
|
227 |
if( args == null || args.size() != 1 ) { |
|
228 |
throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_1_got_XargcX(function.name(),args==null?0:args.size())); |
|
229 |
} |
|
230 |
value = ((UnaryOperator) function).call(this, runCode(args.get(0))); |
|
231 |
break; |
|
211 | 232 |
|
212 |
case Caller.BINARY_OPERATOR: |
|
213 |
if( args == null || args.size() != 2 ) { |
|
214 |
throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_2_got_XargcX(function.name(),args==null?0:args.size())); |
|
215 |
} |
|
216 |
value = ((BinaryOperator) function).call(this, runCode(args.get(0)), runCode(args.get(1))); |
|
217 |
break; |
|
233 |
case Caller.BINARY_OPERATOR:
|
|
234 |
if( args == null || args.size() != 2 ) {
|
|
235 |
throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_operator_XIdentifierX_expected_2_got_XargcX(function.name(),args==null?0:args.size()));
|
|
236 |
}
|
|
237 |
value = ((BinaryOperator) function).call(this, runCode(args.get(0)), runCode(args.get(1)));
|
|
238 |
break;
|
|
218 | 239 |
|
219 |
case Caller.FUNCTION: |
|
220 |
int argc = (args == null) ? 0 : args.size(); |
|
221 |
if( !function.argc().contains(argc) ) { |
|
222 |
throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_function_XIdentifierX_expected_XexpectedX_got_XfoundX(function.name(),function.argc(),argc)); |
|
223 |
} |
|
224 |
if( function.useArgumentsInsteadObjects() ) { |
|
225 |
value = function.call(this, args); |
|
226 |
} else { |
|
227 |
Object[] argvalues = new Object[argc]; |
|
228 |
if( args != null ) { |
|
229 |
int i = 0; |
|
230 |
for( Code arg : args ) { |
|
231 |
argvalues[i++] = runCode(arg); |
|
240 |
case Caller.FUNCTION: |
|
241 |
int argc = (args == null) ? 0 : args.size(); |
|
242 |
if( !function.argc().contains(argc) ) { |
|
243 |
throw new ExpressionRuntimeException(code, I18N.Number_of_argument_mistmatch_in_function_XIdentifierX_expected_XexpectedX_got_XfoundX(function.name(),function.argc(),argc)); |
|
244 |
} |
|
245 |
if( function.useArgumentsInsteadObjects() ) { |
|
246 |
value = function.call(this, args); |
|
247 |
} else { |
|
248 |
Object[] argvalues = new Object[argc]; |
|
249 |
if( args != null ) { |
|
250 |
int i = 0; |
|
251 |
for( Code arg : args ) { |
|
252 |
argvalues[i++] = runCode(arg); |
|
253 |
} |
|
232 | 254 |
} |
255 |
value = function.call(this, argvalues); |
|
233 | 256 |
} |
234 |
value = function.call(this, argvalues); |
|
235 | 257 |
} |
258 |
} catch (RuntimeException ex) { |
|
259 |
throw ex; |
|
260 |
} catch (Exception ex) { |
|
261 |
String argsstr = "???"; |
|
262 |
try { |
|
263 |
argsstr = args.toString(); |
|
264 |
} catch(Exception ex2) { |
|
265 |
// Ignore. |
|
266 |
} |
|
267 |
throw new ExpressionRuntimeException(code, I18N.Problems_calling_function_XIdentifierX_with_args_XargsX(function.name(),argsstr)); |
|
236 | 268 |
} |
237 |
} catch (RuntimeException ex) { |
|
238 |
throw ex; |
|
239 |
} catch (Exception ex) { |
|
240 |
String argsstr = "???"; |
|
241 |
try { |
|
242 |
argsstr = args.toString(); |
|
243 |
} catch(Exception ex2) { |
|
244 |
// Ignore. |
|
245 |
} |
|
246 |
throw new ExpressionRuntimeException(code, I18N.Problems_calling_function_XIdentifierX_with_args_XargsX(function.name(),argsstr)); |
|
269 |
break; |
|
270 |
|
|
247 | 271 |
} |
248 |
break; |
|
249 |
|
|
272 |
} finally { |
|
273 |
this.currentCode = null; |
|
274 |
if( recursionControl!=null ) { |
|
275 |
recursionControl.exitCode(); |
|
276 |
} |
|
250 | 277 |
} |
251 |
this.currentCode = null; |
|
252 | 278 |
return value; |
253 | 279 |
} |
254 | 280 |
|
Also available in: Unified diff