Statistics
| Revision:

svn-gvsig-desktop / 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 / DefaultCodeBuilder.java @ 46050

History | View | Annotate | Download (29.3 KB)

1 43512 jjdelcerro
package org.gvsig.expressionevaluator.impl;
2
3
import java.util.ArrayList;
4 44139 jjdelcerro
import java.util.Collections;
5 43512 jjdelcerro
import java.util.Iterator;
6
import java.util.List;
7 45025 jjdelcerro
import java.util.Map;
8 45983 jjdelcerro
import java.util.function.Predicate;
9 43512 jjdelcerro
import org.gvsig.expressionevaluator.Code;
10
import static org.gvsig.expressionevaluator.Code.CONSTANT;
11 44006 jjdelcerro
import static org.gvsig.expressionevaluator.Code.IDENTIFIER;
12
import static org.gvsig.expressionevaluator.Code.UNDEFINED;
13 44198 jjdelcerro
import static org.gvsig.expressionevaluator.Code.CODES;
14 43512 jjdelcerro
import org.gvsig.expressionevaluator.Code.Constant;
15 44198 jjdelcerro
import static org.gvsig.expressionevaluator.Code.EMPTY_FORMATTER;
16 43512 jjdelcerro
import org.gvsig.expressionevaluator.Code.Identifier;
17 43939 jjdelcerro
import org.gvsig.expressionevaluator.Code.Method;
18 44243 jjdelcerro
//import org.gvsig.expressionevaluator.Code.Method;
19 43512 jjdelcerro
import org.gvsig.expressionevaluator.CodeBuilder;
20 44139 jjdelcerro
import org.gvsig.expressionevaluator.Codes;
21 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder;
22 44750 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_TUPLE;
23 44207 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ADD;
24
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_AND;
25
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_CONCAT;
26
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_DIV;
27
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_EQ;
28
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GE;
29
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_GT;
30
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_ILIKE;
31
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_IS;
32
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LE;
33
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LIKE;
34
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_LT;
35
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_MULT;
36
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NE;
37
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NEGATE;
38
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_NOT;
39
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_OR;
40
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_REGEXP;
41
import static org.gvsig.expressionevaluator.ExpressionBuilder.OPERATOR_SUBST;
42 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder.Value;
43 44644 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
44 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionUtils;
45
import org.gvsig.expressionevaluator.Formatter;
46 43512 jjdelcerro
import org.gvsig.expressionevaluator.Function;
47 43521 jjdelcerro
import org.gvsig.expressionevaluator.Interpreter;
48 44198 jjdelcerro
import org.gvsig.expressionevaluator.SymbolTable;
49 44389 jjdelcerro
import org.gvsig.tools.dynobject.DynObject;
50
import org.gvsig.tools.dynobject.exception.DynMethodNotSupportedException;
51 43512 jjdelcerro
import org.gvsig.tools.exception.BaseException;
52
import org.gvsig.tools.visitor.Visitor;
53 44752 jjdelcerro
import static org.gvsig.expressionevaluator.Code.CALLABLE;
54
import org.gvsig.expressionevaluator.Code.Callable;
55 45025 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_DICT;
56 45011 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_GETITEM;
57 45153 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_LET;
58 44885 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_MOD;
59 45983 jjdelcerro
import org.gvsig.tools.visitor.FilteredVisitable;
60 43512 jjdelcerro
61 44009 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
62 44198 jjdelcerro
public class DefaultCodeBuilder implements CodeBuilder {
63 43512 jjdelcerro
64 45115 jjdelcerro
    public static abstract class BaseCode implements Code {
65 43512 jjdelcerro
66
        @Override
67
        public int code() {
68
            return UNDEFINED;
69
        }
70
71
        @Override
72 45115 jjdelcerro
        public Code clone() throws CloneNotSupportedException {
73
            BaseCode x = (BaseCode) super.clone();
74
            return x;
75
        }
76
77
        @Override
78 43512 jjdelcerro
        public void accept(Visitor visitor) throws BaseException {
79
            visitor.visit(this);
80
        }
81
82 44198 jjdelcerro
        @Override
83 45983 jjdelcerro
        public void accept(Visitor visitor, Predicate<FilteredVisitable> exclude) throws BaseException {
84
            if( !exclude.test(this) ) {
85
                visitor.visit(this);
86
            }
87
        }
88
89
        @Override
90 44198 jjdelcerro
        public Value toValue(ExpressionBuilder builder) {
91
            return null;
92
        }
93
94
        @Override
95
        public Value toValue() {
96
            ExpressionBuilder builder = ExpressionUtils.createExpressionBuilder();
97
            return this.toValue(builder);
98
        }
99
100
        @Override
101
        public void link(SymbolTable symbolTable) {
102 44752 jjdelcerro
            if( this.code() == Code.CALLABLE ) {
103
                Callable caller = (Callable) this;
104 44620 jjdelcerro
                Function fn = symbolTable.function(caller.name());
105
                if( fn != null ) {
106
                    caller.function(fn);
107 44198 jjdelcerro
                }
108
                if( caller.parameters() != null ) {
109
                    for( Code arg : caller.parameters() ) {
110 44738 jjdelcerro
                        if( arg!=null ) {
111
                          arg.link(symbolTable);
112
                        }
113 44198 jjdelcerro
                    }
114
                }
115
            }
116
        }
117 44750 jjdelcerro
118
        @Override
119
        public void replace(Code target, Code replacement) {
120
        }
121
122
123 43512 jjdelcerro
    }
124
125 45115 jjdelcerro
    static class BaseConstant extends BaseCode implements Constant {
126 43512 jjdelcerro
127 44211 jjdelcerro
        private Object value;
128 45115 jjdelcerro
        private final ExpressionEvaluatorManager manager;
129 43512 jjdelcerro
130 45115 jjdelcerro
        public BaseConstant(ExpressionEvaluatorManager manager, Object value) {
131
            this.manager = manager;
132 43512 jjdelcerro
            this.value = value;
133
        }
134
135
        @Override
136 45115 jjdelcerro
        public Code clone() throws CloneNotSupportedException {
137
            return (Code) super.clone();
138
        }
139
140
        @Override
141 43512 jjdelcerro
        public int code() {
142
            return CONSTANT;
143
        }
144
145
        @Override
146
        public Object value() {
147
            return this.value;
148
        }
149
150 44211 jjdelcerro
        public void value(Object v) {
151
            this.value = v;
152
        }
153
154 43521 jjdelcerro
        @Override
155 44198 jjdelcerro
        public Value toValue(ExpressionBuilder builder) {
156 46050 omartinez
            ExpressionBuilder.Constant v = builder.constant(this.value);
157
            v.copyPropertiesFrom(builder);
158
            return v;
159 44198 jjdelcerro
        }
160
161
        @Override
162 43521 jjdelcerro
        public String toString() {
163 44198 jjdelcerro
            return this.toString(EMPTY_FORMATTER);
164
        }
165
166
        @Override
167
        public String toString(Formatter<Code> formatter) {
168
            if( formatter.canApply(this) ) {
169
                return formatter.format(this);
170
            }
171 43521 jjdelcerro
            Object v = this.value();
172 44644 jjdelcerro
            return manager.getReprMethod(v).repr(v);
173 43521 jjdelcerro
        }
174
175 43512 jjdelcerro
    }
176
177 44154 jjdelcerro
    public interface RecursionControlSupport {
178
179
        public boolean enterCode(int max);
180
181
        public void exitCode();
182
183
        public void resetRecursionState();
184
    }
185
186 45115 jjdelcerro
    private static class RecursionSupport implements RecursionControlSupport, Cloneable {
187 44154 jjdelcerro
188
        private int counter;
189
190
        public RecursionSupport() {
191
            this.counter = 0;
192
        }
193 43512 jjdelcerro
194 44154 jjdelcerro
        @Override
195 45115 jjdelcerro
        public RecursionControlSupport clone() throws CloneNotSupportedException {
196
            RecursionControlSupport x = (RecursionControlSupport) super.clone();
197
            return x;
198
        }
199
200
        @Override
201 44154 jjdelcerro
        public boolean enterCode(int max) {
202
            this.counter += 1;
203
            return this.counter < max;
204
        }
205 43512 jjdelcerro
206 44154 jjdelcerro
        @Override
207
        public void exitCode() {
208
            this.counter -= 1;
209
        }
210
211
        @Override
212
        public void resetRecursionState() {
213
            this.counter = 0;
214
        }
215
216
    }
217
218 45115 jjdelcerro
    public static class BaseIdentifier extends BaseCode implements Identifier, RecursionControlSupport {
219 44154 jjdelcerro
220 44198 jjdelcerro
        private final String name;
221
        private final RecursionSupport recursionSupport;
222 44154 jjdelcerro
223 43512 jjdelcerro
        public BaseIdentifier(String name) {
224
            this.name = name;
225 44154 jjdelcerro
            this.recursionSupport = new RecursionSupport();
226 43512 jjdelcerro
        }
227
228
        @Override
229 45115 jjdelcerro
        public Code clone() throws CloneNotSupportedException {
230
            return (Code) super.clone();
231
        }
232
233
        @Override
234 43512 jjdelcerro
        public int code() {
235
            return IDENTIFIER;
236
        }
237
238
        @Override
239
        public String name() {
240
            return this.name;
241
        }
242
243 43521 jjdelcerro
        @Override
244 44198 jjdelcerro
        public Value toValue(ExpressionBuilder builder) {
245 46050 omartinez
            ExpressionBuilder.Variable v = builder.variable(this.name);
246
            v.copyPropertiesFrom(builder);
247
            return v;
248 44198 jjdelcerro
        }
249
250
        @Override
251 43521 jjdelcerro
        public String toString() {
252 44198 jjdelcerro
            return this.toString(EMPTY_FORMATTER);
253
        }
254
255
        @Override
256
        public String toString(Formatter<Code> formatter) {
257
            if( formatter.canApply(this) ) {
258
                return formatter.format(this);
259
            }
260 43521 jjdelcerro
            StringBuilder builder = new StringBuilder();
261 44006 jjdelcerro
            builder.append("\"");
262 43521 jjdelcerro
            builder.append(this.name());
263 44006 jjdelcerro
            builder.append("\"");
264 43521 jjdelcerro
            return builder.toString();
265
        }
266
267 44154 jjdelcerro
        @Override
268
        public boolean enterCode(int max) {
269
            return this.recursionSupport.enterCode(max);
270
        }
271
272
        @Override
273
        public void exitCode() {
274
            this.recursionSupport.exitCode();
275
        }
276
277
        @Override
278
        public void resetRecursionState() {
279
            this.recursionSupport.resetRecursionState();
280
        }
281
282 43512 jjdelcerro
    }
283
284 45115 jjdelcerro
    public static class BaseCodes implements Codes {
285 43512 jjdelcerro
286 45118 jjdelcerro
        private List<Code> codes;
287 43512 jjdelcerro
288 44139 jjdelcerro
        public BaseCodes() {
289
            this.codes = new ArrayList<>();
290 43512 jjdelcerro
        }
291
292
        @Override
293 45115 jjdelcerro
        public Codes clone() throws CloneNotSupportedException {
294
            BaseCodes x = (BaseCodes)super.clone();
295 45118 jjdelcerro
            x.codes = new ArrayList<>();
296
            for (int i = 0; i < this.codes.size(); i++) {
297
                x.add(this.codes.get(i).clone());
298 45115 jjdelcerro
            }
299
            return x;
300
        }
301
302
        @Override
303 44198 jjdelcerro
        public int code() {
304
            return CODES;
305
        }
306
307
        @Override
308 44139 jjdelcerro
        public int size() {
309
            if( codes == null ) {
310 43512 jjdelcerro
                return 0;
311
            }
312 44139 jjdelcerro
            return this.codes.size();
313 43512 jjdelcerro
        }
314
315 44750 jjdelcerro
        public void add(Code arg) {
316
            this.codes.add(arg);
317 44738 jjdelcerro
        }
318
319 44750 jjdelcerro
        public void set(int pos, Code arg) {
320
            this.codes.set(pos, arg);
321 43512 jjdelcerro
        }
322
323 44243 jjdelcerro
        public void insert(int pos, Code arg) {
324 44750 jjdelcerro
            this.codes.add(pos, arg);
325 44243 jjdelcerro
        }
326
327 43512 jjdelcerro
        @Override
328
        public Iterator<Code> iterator() {
329 44750 jjdelcerro
          final Iterator<Code> it = this.codes.iterator();
330
          return it;
331 43512 jjdelcerro
        }
332
333
        @Override
334
        public Code get(int n) {
335 44750 jjdelcerro
            return this.codes.get(n);
336 43512 jjdelcerro
        }
337
338
        @Override
339 44139 jjdelcerro
        public boolean isEmpty() {
340
            return this.codes.isEmpty();
341
        }
342
343
        @Override
344
        public List<Code> toList() {
345 44750 jjdelcerro
            return Collections.unmodifiableList(this.codes);
346 44139 jjdelcerro
        }
347
348
        @Override
349 43512 jjdelcerro
        public void accept(Visitor visitor) throws BaseException {
350 44750 jjdelcerro
            for( Code arg : this.codes ) {
351 45166 omartinez
                if(arg!=null) {
352
                    arg.accept(visitor);
353
                }
354 43512 jjdelcerro
            }
355
        }
356
357 45983 jjdelcerro
        public void accept(Visitor visitor, Predicate<FilteredVisitable> exclude) throws BaseException {
358
            if( !exclude.test(this) ) {
359
                for( Code arg : this.codes ) {
360
                    if(arg!=null) {
361
                        arg.accept(visitor, exclude);
362
                    }
363
                }
364
            }
365
        }
366
367 43521 jjdelcerro
        @Override
368
        public String toString() {
369 44198 jjdelcerro
            return this.toString(EMPTY_FORMATTER);
370
        }
371
372
        @Override
373
        public Value toValue(ExpressionBuilder builder) {
374
            throw new UnsupportedOperationException();
375
        }
376
377
        @Override
378
        public Value toValue() {
379
            throw new UnsupportedOperationException();
380
        }
381
382
        @Override
383
        public String toString(Formatter<Code> formatter) {
384
            if( formatter.canApply(this) ) {
385
                return formatter.format(this);
386
            }
387 44139 jjdelcerro
            if( codes != null ) {
388 43521 jjdelcerro
                StringBuilder builder = new StringBuilder();
389
                boolean skipcoma = true;
390 44750 jjdelcerro
                for( Code arg : codes ) {
391 44738 jjdelcerro
                    if( arg == null ) {
392
                      continue;
393
                    }
394 43521 jjdelcerro
                    if( skipcoma ) {
395
                        skipcoma = false;
396
                    } else {
397
                        builder.append(", ");
398
                    }
399 44750 jjdelcerro
                    builder.append(arg.toString(formatter));
400 43521 jjdelcerro
                }
401
                return builder.toString();
402
            }
403
            return "";
404
        }
405
406 44198 jjdelcerro
        @Override
407
        public void link(SymbolTable symbolTable) {
408 44750 jjdelcerro
            for (Code arg : this.codes) {
409
                arg.link(symbolTable);
410 44198 jjdelcerro
            }
411
        }
412
413 44750 jjdelcerro
        @Override
414
        public void replace(Code target, Code replacement) {
415
            for (int i = 0; i < this.codes.size(); i++) {
416
                Code code = this.codes.get(i);
417
                if( code == target ) {
418
                    codes.set(i, replacement);
419
                } else {
420
                    code.replace(target, replacement);
421
                }
422
            }
423
        }
424
425 43512 jjdelcerro
    }
426
427 44752 jjdelcerro
    public class BaseCaller extends BaseCode implements Callable, RecursionControlSupport {
428 43512 jjdelcerro
429
        private final String name;
430 45115 jjdelcerro
        private Codes args;
431 43512 jjdelcerro
        private Function function;
432
        private final int type;
433 45115 jjdelcerro
        private RecursionSupport recursionSupport;
434 43512 jjdelcerro
435 44139 jjdelcerro
        public BaseCaller(String name, int type, Codes args) {
436 43512 jjdelcerro
            this.name = name;
437
            this.args = args;
438
            this.type = type;
439
            this.function = null;
440 44154 jjdelcerro
            this.recursionSupport = new RecursionSupport();
441 43512 jjdelcerro
        }
442
443
        @Override
444 45115 jjdelcerro
        public Code clone() throws CloneNotSupportedException {
445
            BaseCaller x = (BaseCaller) super.clone();
446
            x.recursionSupport = (RecursionSupport) this.recursionSupport.clone();
447 45537 jolivas
            if (this.args!=null){
448
                x.args = this.args.clone();
449
            }
450 45115 jjdelcerro
            return x;
451
        }
452
453
        @Override
454 43512 jjdelcerro
        public int code() {
455 44752 jjdelcerro
            return CALLABLE;
456 43512 jjdelcerro
        }
457
458
        @Override
459 44750 jjdelcerro
        public void replace(Code target, Code replacement) {
460
            this.args.replace(target, replacement);
461
        }
462
463
        @Override
464 43521 jjdelcerro
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
465
            return this.function.call(interpreter, args);
466 43512 jjdelcerro
        }
467
468
        @Override
469
        public String name() {
470
            return this.name;
471
        }
472
473
        @Override
474
        public Function function() {
475
            return this.function;
476
        }
477
478
        @Override
479
        public Function function(Function function) {
480
            this.function = function;
481
            return this.function;
482
        }
483
484
        @Override
485 44198 jjdelcerro
        public Codes parameters() {
486 43512 jjdelcerro
            return this.args;
487
        }
488
489
        @Override
490
        public int type() {
491
            return this.type;
492
        }
493
494
        @Override
495
        public void accept(Visitor visitor) throws BaseException {
496
            visitor.visit(this);
497 44052 omartinez
            if(this.args!=null) {
498
                this.args.accept(visitor);
499
            }
500 43512 jjdelcerro
        }
501
502 43521 jjdelcerro
        @Override
503 45983 jjdelcerro
        public void accept(Visitor visitor, Predicate<FilteredVisitable> exclude) throws BaseException {
504
            if( !exclude.test(this) ) {
505
                visitor.visit(this);
506
                if(this.args!=null) {
507
                    this.args.accept(visitor, exclude);
508
                }
509
            }
510
        }
511
512
        @Override
513 44198 jjdelcerro
        public Value toValue(ExpressionBuilder builder) {
514 46050 omartinez
            ExpressionBuilder.Value value;
515 44198 jjdelcerro
            switch(this.type) {
516
                case UNARY_OPERATOR:
517 46050 omartinez
                    value = builder.function(
518 44207 jjdelcerro
                            OPERATOR_NEGATE.equalsIgnoreCase(this.name())?
519 46050 omartinez
                                    "-" :
520
                                    this.name(),
521 44198 jjdelcerro
                            this.parameters().get(0).toValue(builder)
522
                    );
523 46050 omartinez
                    break;
524
525 44198 jjdelcerro
                case BINARY_OPERATOR:
526 46050 omartinez
                    value =  builder.binaryOperator(
527 44198 jjdelcerro
                            this.name(),
528
                            this.parameters().get(0).toValue(builder),
529
                            this.parameters().get(1).toValue(builder)
530
                    );
531 46050 omartinez
                    break;
532 44198 jjdelcerro
                case FUNCTION:
533
                default:
534
                    ExpressionBuilder.Function f = builder.function(this.name());
535
                    if( this.parameters()!=null ) {
536
                        for (Code parameter : this.parameters()) {
537 45166 omartinez
                            if (parameter==null) {
538
                                f.parameter(null);
539
                            } else {
540
                                f.parameter(parameter.toValue(builder));
541
                            }
542 44750 jjdelcerro
                        }
543 44198 jjdelcerro
                    }
544 46050 omartinez
                    value = f;
545
                    break;
546 44198 jjdelcerro
547
            }
548 46050 omartinez
            value.copyPropertiesFrom(builder);
549
            return value;
550 44198 jjdelcerro
        }
551
552
        @Override
553 43521 jjdelcerro
        public String toString() {
554 44198 jjdelcerro
            return this.toString(EMPTY_FORMATTER);
555
        }
556
557
        @Override
558
        public String toString(Formatter<Code> formatter) {
559
            if( formatter.canApply(this) ) {
560
                return formatter.format(this);
561
            }
562 44379 jjdelcerro
            Code code;
563 43521 jjdelcerro
            StringBuilder builder = new StringBuilder();
564 44198 jjdelcerro
            switch(this.type) {
565
                case UNARY_OPERATOR:
566 44207 jjdelcerro
                    if( OPERATOR_NEGATE.equalsIgnoreCase(this.name()) ) {
567 44198 jjdelcerro
                        builder.append("-");
568
                    } else {
569
                        builder.append(this.name());
570
                    }
571
                    builder.append("(");
572
                    builder.append(this.parameters().get(0).toString(formatter));
573
                    builder.append(")");
574
                    break;
575
                case BINARY_OPERATOR:
576
                    builder.append("(");
577 44379 jjdelcerro
                    code = this.parameters().get(0);
578
                    if( code == null ) {
579
                        builder.append("?NULL?");
580
                    } else {
581
                        builder.append(code.toString(formatter));
582
                    }
583 44198 jjdelcerro
                    builder.append(" ");
584
                    builder.append(this.name());
585
                    builder.append(" ");
586 44379 jjdelcerro
                    code = this.parameters().get(1);
587
                    if( code == null ) {
588
                        builder.append("?NULL?");
589
                    } else {
590
                        builder.append(code.toString(formatter));
591
                    }
592 44198 jjdelcerro
                    builder.append(")");
593
                    break;
594
                case FUNCTION:
595
                default:
596 45011 jjdelcerro
                    String s = null;
597
                    if( this.function()!=null ) {
598
                        s = this.function().toString(args, formatter);
599
                    }
600
                    if( s == null ) {
601 44738 jjdelcerro
                        builder.append(this.name());
602
                        builder.append("(");
603 45011 jjdelcerro
                        if( this.parameters()!=null ) {
604
                            builder.append(this.parameters().toString(formatter));
605
                        }
606 44738 jjdelcerro
                        builder.append(")");
607
                    } else {
608 45011 jjdelcerro
                        builder.append(s);
609 44198 jjdelcerro
                    }
610 43521 jjdelcerro
            }
611
            return builder.toString();
612
        }
613
614 44154 jjdelcerro
        @Override
615
        public boolean enterCode(int max) {
616
            return this.recursionSupport.enterCode(max);
617
        }
618
619
        @Override
620
        public void exitCode() {
621
            this.recursionSupport.exitCode();
622
        }
623
624
        @Override
625
        public void resetRecursionState() {
626
            this.recursionSupport.resetRecursionState();
627
        }
628 43512 jjdelcerro
    }
629
630 45115 jjdelcerro
    public static class BaseMethod extends BaseCode implements Method {
631 43939 jjdelcerro
632 44750 jjdelcerro
        private Code instance;
633 43939 jjdelcerro
        private final String methodname;
634 45115 jjdelcerro
        private Codes args;
635 43939 jjdelcerro
636 44243 jjdelcerro
        public BaseMethod(Code instance, String methodname, Codes args) {
637
            this.instance = instance;
638 43939 jjdelcerro
            this.methodname = methodname;
639 44243 jjdelcerro
            this.args = args;
640 43939 jjdelcerro
        }
641
642
        @Override
643 45983 jjdelcerro
        public void accept(Visitor visitor) throws BaseException {
644
            visitor.visit(this);
645
            if(this.instance!=null) {
646
                this.instance.accept(visitor);
647
            }
648
            if(this.args!=null) {
649
                this.args.accept(visitor);
650
            }
651
        }
652
653
        @Override
654
        public void accept(Visitor visitor, Predicate<FilteredVisitable> exclude) throws BaseException {
655
            if( !exclude.test(this) ) {
656
                visitor.visit(this);
657
                if(this.instance!=null) {
658
                    this.instance.accept(visitor, exclude);
659
                }
660
                if(this.args!=null) {
661
                    this.args.accept(visitor, exclude);
662
                }
663
            }
664
        }
665
666
        @Override
667 45115 jjdelcerro
        public Code clone() throws CloneNotSupportedException {
668
            BaseMethod x = (BaseMethod) super.clone();
669
            x.args = this.args.clone();
670
            return x;
671
        }
672
673
        @Override
674 43939 jjdelcerro
        public int code() {
675
            return METHOD;
676
        }
677
678
        @Override
679 44750 jjdelcerro
        public void replace(Code target, Code replacement) {
680
            if( target == this.instance ) {
681
              this.instance = replacement;
682
            }
683
            this.args.replace(target, replacement);
684
        }
685
686
        @Override
687 43939 jjdelcerro
        public String methodname() {
688
            return this.methodname;
689
        }
690
691
        @Override
692 44243 jjdelcerro
        public Code instance() {
693
            return this.instance;
694 43939 jjdelcerro
        }
695
696
        @Override
697 44243 jjdelcerro
        public Codes parameters() {
698
            return this.args;
699
        }
700
701
        @Override
702
        public Object call(Interpreter interpreter, Object[] args) throws Exception {
703
            Object theInstance = interpreter.run(instance);
704 44389 jjdelcerro
            if( theInstance instanceof SimpleScript ) {
705
                try {
706
                    return ((SimpleScript)theInstance).invokeFunction(methodname, args);
707
                } catch(NoSuchMethodException ex) {
708
                    // Ignore... continue calling instance method
709
                }
710
            } else if( theInstance instanceof DynObject ) {
711
                DynObject dynobj = (DynObject) theInstance;
712
                try {
713
                    return dynobj.invokeDynMethod(methodname, args);
714
                } catch(DynMethodNotSupportedException ex) {
715
                    // Ignore... continue calling instance method
716
                }
717
            }
718 44243 jjdelcerro
            return InstanceUtils.callmethod(theInstance, methodname, args);
719
        }
720
721
        @Override
722 43939 jjdelcerro
        public String toString() {
723 44198 jjdelcerro
            return this.toString(EMPTY_FORMATTER);
724
        }
725
726
        @Override
727
        public Value toValue(ExpressionBuilder builder) {
728 44243 jjdelcerro
            ExpressionBuilder.Method m = builder.method(this.instance.toValue(builder), this.methodname);
729 44198 jjdelcerro
            if( this.parameters()!=null ) {
730
                for (Code parameter : this.parameters()) {
731
                    m.parameter(parameter.toValue(builder));
732
                }
733
            }
734 46050 omartinez
            m.copyPropertiesFrom(builder);
735 44198 jjdelcerro
            return m;
736
        }
737
738
        @Override
739
        public String toString(Formatter<Code> formatter) {
740
            if( formatter.canApply(this) ) {
741
                return formatter.format(this);
742
            }
743 43939 jjdelcerro
            StringBuilder builder = new StringBuilder();
744 44243 jjdelcerro
            builder.append(this.instance.toString(formatter));
745 46010 jjdelcerro
            builder.append(".");
746 43939 jjdelcerro
            builder.append(this.methodname());
747
            builder.append("(");
748 44198 jjdelcerro
            if( this.parameters()!=null ) {
749
                builder.append(this.parameters().toString(formatter));
750 43939 jjdelcerro
            }
751
            builder.append(")");
752
            return builder.toString();
753
        }
754 45245 omartinez
755
        @Override
756
        public String name() {
757
            return this.methodname();
758
        }
759
760
        @Override
761
        public Function function() {
762
            return null;
763
        }
764
765
        @Override
766
        public Function function(Function function) {
767
            return null;
768
        }
769
770
        @Override
771
        public int type() {
772
            return Code.METHOD;
773
        }
774 44243 jjdelcerro
775
776 43939 jjdelcerro
    }
777 44644 jjdelcerro
778
    protected ExpressionEvaluatorManager manager;
779 43939 jjdelcerro
780 44644 jjdelcerro
    public DefaultCodeBuilder(ExpressionEvaluatorManager manager) {
781
        this.manager = manager;
782
    }
783
784 43512 jjdelcerro
    @Override
785 43809 jjdelcerro
    public CodeBuilder clone() throws CloneNotSupportedException {
786
        // This implementation of CodeBuilder does not maintain state, so
787
        // we only call the super class.
788
        DefaultCodeBuilder other = (DefaultCodeBuilder) super.clone();
789
        return other;
790
    }
791
792
    @Override
793 43512 jjdelcerro
    public Constant constant(Object value) {
794 45115 jjdelcerro
        return new BaseConstant(this.manager, value);
795 43512 jjdelcerro
    }
796
797
    @Override
798
    public Identifier identifier(String name) {
799
        return new BaseIdentifier(name);
800
    }
801
802
    @Override
803 44139 jjdelcerro
    public BaseCodes args() {
804
        return new BaseCodes();
805 43512 jjdelcerro
    }
806
807
    @Override
808 44752 jjdelcerro
    public Callable tuple() {
809 44750 jjdelcerro
      BaseCodes args = this.args();
810
      return function(FUNCTION_TUPLE, args);
811
    }
812
813
    @Override
814 44752 jjdelcerro
    public Callable tuple(Codes args) {
815 44750 jjdelcerro
      if( args == null ) {
816
        args = this.args();
817
      }
818
      return function(FUNCTION_TUPLE, args);
819
    }
820
821
    @Override
822 44752 jjdelcerro
    public Callable function(String name, int type, Codes args) {
823 43512 jjdelcerro
        return new BaseCaller(name, type, args);
824
    }
825
826
    @Override
827 44752 jjdelcerro
    public Callable function(String name, Codes args) {
828
        return function(name, Callable.FUNCTION, args);
829 43512 jjdelcerro
    }
830 43939 jjdelcerro
831 43512 jjdelcerro
    @Override
832 44243 jjdelcerro
    public Code method(Code instance, String methodname, Codes methodargs) {
833
        Method m = new BaseMethod(instance, methodname, methodargs);
834 43939 jjdelcerro
        return m;
835
    }
836
837
    @Override
838 44752 jjdelcerro
    public Callable operator(String name, Code arg1) {
839 44139 jjdelcerro
        BaseCodes args = args();
840
        args.add(arg1);
841 44752 jjdelcerro
        return function(name, Callable.UNARY_OPERATOR, args);
842 43512 jjdelcerro
    }
843
844
    @Override
845 44752 jjdelcerro
    public Callable operator(String name, Code arg1, Code arg2) {
846 44139 jjdelcerro
        BaseCodes args = args();
847
        args.add(arg1);
848
        args.add(arg2);
849 44752 jjdelcerro
        return function(name, Callable.BINARY_OPERATOR, args);
850 43512 jjdelcerro
    }
851 44198 jjdelcerro
852 43512 jjdelcerro
    @Override
853
    public Code not(Code op1) {
854 44207 jjdelcerro
        return operator(OPERATOR_NOT, op1);
855 43512 jjdelcerro
    }
856
857
    @Override
858 44098 jjdelcerro
    public Code negate(Code op1) {
859 44207 jjdelcerro
        return operator(OPERATOR_NEGATE, op1);
860 44098 jjdelcerro
    }
861
862
    @Override
863 44139 jjdelcerro
    public Code concat(Code op1, Code op2) {
864 44207 jjdelcerro
        return operator(OPERATOR_CONCAT, op1, op2);
865 44139 jjdelcerro
    }
866
867
    @Override
868 45153 jjdelcerro
    public Code let(String identifier, Code value) {
869
        BaseCodes args = args();
870
        args.add(this.constant(identifier));
871
        args.add(value);
872
        return function(FUNCTION_LET, Callable.FUNCTION, args);
873
    }
874
875
    @Override
876 43512 jjdelcerro
    public Code add(Code op1, Code op2) {
877 44207 jjdelcerro
        return operator(OPERATOR_ADD, op1, op2);
878 43512 jjdelcerro
    }
879
880
    @Override
881
    public Code subst(Code op1, Code op2) {
882 44207 jjdelcerro
        return operator(OPERATOR_SUBST, op1, op2);
883 43512 jjdelcerro
    }
884
885
    @Override
886
    public Code mult(Code op1, Code op2) {
887 44207 jjdelcerro
        return operator(OPERATOR_MULT, op1, op2);
888 43512 jjdelcerro
    }
889
890
    @Override
891
    public Code div(Code op1, Code op2) {
892 44207 jjdelcerro
        return operator(OPERATOR_DIV, op1, op2);
893 43512 jjdelcerro
    }
894
895
    @Override
896
    public Code mod(Code op1, Code op2) {
897 44885 jjdelcerro
        BaseCodes args = args();
898
        args.add(op1);
899
        args.add(op2);
900
        return function(FUNCTION_MOD, args);
901 43512 jjdelcerro
    }
902
903
    @Override
904
    public Code or(Code op1, Code op2) {
905 44207 jjdelcerro
        return operator(OPERATOR_OR, op1, op2);
906 43512 jjdelcerro
    }
907
908
    @Override
909
    public Code and(Code op1, Code op2) {
910 44207 jjdelcerro
        return operator(OPERATOR_AND, op1, op2);
911 43512 jjdelcerro
    }
912
913
    @Override
914
    public Code like(Code op1, Code op2) {
915 44207 jjdelcerro
        return operator(OPERATOR_LIKE, op1, op2);
916 43512 jjdelcerro
    }
917
918
    @Override
919
    public Code ilike(Code op1, Code op2) {
920 44207 jjdelcerro
        return operator(OPERATOR_ILIKE, op1, op2);
921 43512 jjdelcerro
    }
922
923
    @Override
924 43532 jjdelcerro
    public Code regexp(Code op1, Code op2) {
925 44207 jjdelcerro
        return operator(OPERATOR_REGEXP, op1, op2);
926 43532 jjdelcerro
    }
927
928
    @Override
929 43512 jjdelcerro
    public Code lt(Code op1, Code op2) {
930 44207 jjdelcerro
        return operator(OPERATOR_LT, op1, op2);
931 43512 jjdelcerro
    }
932
933
    @Override
934
    public Code gt(Code op1, Code op2) {
935 44207 jjdelcerro
        return operator(OPERATOR_GT, op1, op2);
936 43512 jjdelcerro
    }
937
938
    @Override
939
    public Code le(Code op1, Code op2) {
940 44207 jjdelcerro
        return operator(OPERATOR_LE, op1, op2);
941 43512 jjdelcerro
    }
942
943
    @Override
944
    public Code ge(Code op1, Code op2) {
945 44207 jjdelcerro
        return operator(OPERATOR_GE, op1, op2);
946 43512 jjdelcerro
    }
947
948
    @Override
949
    public Code eq(Code op1, Code op2) {
950 44207 jjdelcerro
        return operator(OPERATOR_EQ, op1, op2);
951 43512 jjdelcerro
    }
952
953
    @Override
954
    public Code ne(Code op1, Code op2) {
955 44207 jjdelcerro
        return operator(OPERATOR_NE, op1, op2);
956 43512 jjdelcerro
    }
957
958
    @Override
959
    public Code is(Code op1, Code op2) {
960 44207 jjdelcerro
        return operator(OPERATOR_IS, op1, op2);
961 43512 jjdelcerro
    }
962
963 43939 jjdelcerro
    @Override
964
    public Code getattr(Code obj, String attrname) {
965 44139 jjdelcerro
        BaseCodes args = args();
966
        args.add(obj);
967 44855 jjdelcerro
        args.add(constant(attrname));
968 44748 jjdelcerro
        return function(ExpressionBuilder.FUNCTION_GETATTR, args);
969 43939 jjdelcerro
    }
970
971 44139 jjdelcerro
    @Override
972
    public Code getitem(Code obj, Code index) {
973
        BaseCodes args = args();
974
        args.add(obj);
975
        args.add(index);
976 45011 jjdelcerro
        return function(FUNCTION_GETITEM, args);
977 44139 jjdelcerro
    }
978
979 45025 jjdelcerro
    @Override
980
    public Code dict(Map<String,Code>map ) {
981
        BaseCodes args = args();
982
        for (Map.Entry<String, Code> entry : map.entrySet()) {
983
            String key = entry.getKey();
984
            Code value = entry.getValue();
985
            args.add(constant(key));
986
            args.add(value);
987
        }
988
        return function(FUNCTION_DICT, args);
989
    }
990 44139 jjdelcerro
991 43512 jjdelcerro
}