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 / DefaultOptimizer.java @ 44750

History | View | Annotate | Download (8.37 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import org.gvsig.expressionevaluator.Optimizer;
4
import java.util.Collection;
5
import java.util.Collections;
6
import java.util.Iterator;
7
import org.gvsig.expressionevaluator.Code;
8
import org.gvsig.expressionevaluator.Code.Caller;
9
import org.gvsig.expressionevaluator.CodeBuilder;
10
import org.gvsig.expressionevaluator.Codes;
11
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
12
import org.gvsig.expressionevaluator.Function;
13
import org.gvsig.expressionevaluator.Interpreter;
14
import org.gvsig.expressionevaluator.SymbolTable;
15
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
16

    
17
/**
18
 *
19
 * @author jjdelcerro
20
 */
21
public class DefaultOptimizer implements Optimizer {
22

    
23
    private static class OptimizerSymbolTable implements SymbolTable {
24

    
25
        private SymbolTable symbolTable;
26

    
27
        public OptimizerSymbolTable() {
28

    
29
        }
30

    
31
        public SymbolTable getSymbolTable() {
32
            return this.symbolTable;
33
        }
34

    
35
        public void setSymbolTable(SymbolTable symbolTable) {
36
            this.symbolTable = symbolTable;
37
        }
38

    
39
        @Override
40
        public String getName() {
41
            return "Optimizer";
42
        }
43

    
44
        @Override
45
        public boolean addSymbolTable(SymbolTable symbolTable) {
46
            throw new UnsupportedOperationException("Not supported yet.");
47
        }
48

    
49
        @Override
50
        public boolean containsSymbolTable(SymbolTable symbolTable) {
51
            throw new UnsupportedOperationException("Not supported yet.");
52
        }
53

    
54
        @Override
55
        public boolean removeSymbolTable(SymbolTable symbolTable) {
56
            throw new UnsupportedOperationException("Not supported yet.");
57
        }
58

    
59
        @Override
60
        public Function function(String name) {
61
            return this.symbolTable.function(name);
62
        }
63

    
64
        @Override
65
        public boolean exists(String name) {
66
            return false;
67
        }
68

    
69
        @Override
70
        public Object value(String name) {
71
            return null;
72
        }
73

    
74
        @Override
75
        public boolean isSQLCompatible(String name) {
76
            return false;
77
        }
78

    
79
        @Override
80
        public Collection<String> variables() {
81
            return Collections.EMPTY_LIST;
82
        }
83

    
84
        @Override
85
        public Collection<Function> functions() {
86
            return this.symbolTable.functions();
87
        }
88

    
89
        @Override
90
        public Collection<Function> localfunctions() {
91
            return this.symbolTable.functions();
92
        }
93
        
94
//        @Override
95
//        public Collection<Script> scripts() {
96
//            return this.symbolTable.scripts();
97
//        }
98
//
99
        @Override
100
        @SuppressWarnings("CloneDoesntCallSuperClone")
101
        public SymbolTable clone() throws CloneNotSupportedException {
102
            throw new UnsupportedOperationException("Not supported yet.");
103
        }
104

    
105
        @Override
106
        public Iterator<Function> iterator() {
107
            return this.symbolTable.iterator();
108
        }
109

    
110
        @Override
111
        public Collection<String> localvariables() {
112
            return null;
113
        }
114

    
115
    }
116

    
117
    private final OptimizerSymbolTable symbolTable;
118
    private Interpreter interpreter;
119
    private CodeBuilder codeBuilder;
120
    protected ExpressionEvaluatorManager manager;
121

    
122
    public DefaultOptimizer(ExpressionEvaluatorManager manager) {
123
        this.manager = manager;
124
        this.symbolTable = new OptimizerSymbolTable();
125
    }
126

    
127
    public DefaultOptimizer(ExpressionEvaluatorManager manager, SymbolTable symbolTable) {
128
        this(manager);
129
        this.symbolTable.setSymbolTable(symbolTable);
130
    }
131

    
132
    @Override
133
    public void setSymbolTable(SymbolTable symbolTable) {
134
        this.symbolTable.setSymbolTable(symbolTable);
135
    }
136

    
137
    @Override
138
    public SymbolTable getSymbolTable() {
139
        return this.symbolTable;
140
    }
141

    
142
    @Override
143
    public Interpreter getInterpreter() {
144
        if (this.interpreter == null) {
145
            this.interpreter = new DefaultInterpreter();
146
            this.interpreter.setSymbolTable(this.symbolTable);
147
        }
148
        return this.interpreter;
149
    }
150

    
151
    @Override
152
    public CodeBuilder getCodeBuilder() {
153
        if (this.codeBuilder == null) {
154
            this.codeBuilder = new DefaultCodeBuilder(this.manager);
155
        }
156
        return this.codeBuilder;
157
    }
158

    
159
    @Override
160
    public Code optimize(SymbolTable symbolTable, Code code) {
161
        this.setSymbolTable(symbolTable);
162
        return this.optimize(code);
163
    }
164

    
165
    @Override
166
    public Code optimize(Code code) {
167
        code = this.doOptimize(code);
168
        return code;
169
    }
170

    
171
    private Code doOptimize(Code code) {
172
        switch (code.code()) {
173
            case Code.CALLER:
174
                Caller caller = (Caller) code;
175
                Function function = caller.function();
176
                if ( function == null) {
177
                    // resolve and link function
178
                    function = this.getSymbolTable().function(caller.name());
179
                    caller.function(function);
180
                }
181
                if (function instanceof FunctionOptimizer) {
182
                    return ((FunctionOptimizer) caller.function()).optimize(this, caller);
183
                } else {
184
                    switch (caller.type()) {
185
                        case Caller.BINARY_OPERATOR: {
186
                            Code op1 = this.doOptimize(caller.parameters().get(0));
187
                            Code op2 = this.doOptimize(caller.parameters().get(1));
188
                            if ( function.allowConstantFolding()) {
189
                                if (op1.code() == Code.CONSTANT && op2.code() == Code.CONSTANT) {
190
                                    Object value = this.getInterpreter().run(code);
191
                                    Code newCode = this.getCodeBuilder().constant(value);
192
                                    return newCode;
193
                                }
194
                                Code newCode = this.getCodeBuilder().operator(caller.name(), op1, op2);
195
                                return newCode;
196
                            }
197
                        }
198

    
199
                        case Code.Caller.UNARY_OPERATOR: {
200
                            Code op1 = this.doOptimize(caller.parameters().get(0));
201
                            if (function.allowConstantFolding()
202
                                    && op1.code() == Code.CONSTANT) {
203
                                Object value = this.getInterpreter().run(code);
204
                                Code newCode = this.getCodeBuilder().constant(value);
205
                                return newCode;
206
                            }
207
                            return code;
208
                        }
209

    
210
                        case Code.Caller.FUNCTION:
211
                        default: {
212
                            BaseCodes newArgs = null;
213
                            boolean canOptimize = true;
214
                            if (caller.parameters() != null) {
215
                                newArgs = (BaseCodes) this.getCodeBuilder().args();
216
                                Codes parameters = caller.parameters();
217
                                for (int i = 0; i < parameters.size(); i++) {
218
                                    Code arg = parameters.get(i);
219
                                    Code newArg = this.doOptimize(arg);
220
                                    newArgs.add(newArg);
221
                                    if (newArg.code() != Code.CONSTANT) {
222
                                        canOptimize = false;
223
                                    }
224
                                }
225
                            }
226
                            if (canOptimize && function!=null && function.allowConstantFolding()) {
227
                                Object value = this.getInterpreter().run(code);
228
                                Code newCode = this.getCodeBuilder().constant(value);
229
                                return newCode;
230
                            }
231
                            Code newCode = this.getCodeBuilder().function(
232
                                    caller.name(),
233
                                    caller.type(),
234
                                    newArgs
235
                            );
236
                            return newCode;
237
                        }
238
                    }
239
                }
240
                
241
            case Code.CONSTANT:
242
            case Code.IDENTIFIER:
243
            case Code.METHOD:
244
            default:
245
                return code;
246
        }
247
    }
248
}