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

View differences:

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