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 @ 44622

History | View | Annotate | Download (7.95 KB)

1 44009 jjdelcerro
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.Function;
11
import org.gvsig.expressionevaluator.Interpreter;
12
import org.gvsig.expressionevaluator.SymbolTable;
13 44139 jjdelcerro
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
14 44009 jjdelcerro
15
/**
16
 *
17
 * @author jjdelcerro
18
 */
19
public class DefaultOptimizer implements Optimizer {
20
21
    private static class OptimizerSymbolTable implements SymbolTable {
22
23
        private SymbolTable symbolTable;
24
25
        public OptimizerSymbolTable() {
26
27
        }
28
29
        public SymbolTable getSymbolTable() {
30
            return this.symbolTable;
31
        }
32
33
        public void setSymbolTable(SymbolTable symbolTable) {
34
            this.symbolTable = symbolTable;
35
        }
36
37
        @Override
38
        public String getName() {
39
            return "Optimizer";
40
        }
41
42
        @Override
43 44215 jjdelcerro
        public boolean addSymbolTable(SymbolTable symbolTable) {
44 44009 jjdelcerro
            throw new UnsupportedOperationException("Not supported yet.");
45
        }
46
47
        @Override
48 44215 jjdelcerro
        public boolean containsSymbolTable(SymbolTable symbolTable) {
49
            throw new UnsupportedOperationException("Not supported yet.");
50
        }
51
52
        @Override
53
        public boolean removeSymbolTable(SymbolTable symbolTable) {
54
            throw new UnsupportedOperationException("Not supported yet.");
55
        }
56
57
        @Override
58 44009 jjdelcerro
        public Function function(String name) {
59
            return this.symbolTable.function(name);
60
        }
61
62
        @Override
63
        public boolean exists(String name) {
64
            return false;
65
        }
66
67
        @Override
68
        public Object value(String name) {
69
            return null;
70
        }
71
72
        @Override
73 44205 jjdelcerro
        public boolean isSQLCompatible(String name) {
74
            return false;
75
        }
76
77
        @Override
78 44009 jjdelcerro
        public Collection<String> variables() {
79
            return Collections.EMPTY_LIST;
80
        }
81
82
        @Override
83
        public Collection<Function> functions() {
84
            return this.symbolTable.functions();
85
        }
86
87
        @Override
88 44338 jjdelcerro
        public Collection<Function> localfunctions() {
89
            return this.symbolTable.functions();
90
        }
91
92 44533 jjdelcerro
//        @Override
93
//        public Collection<Script> scripts() {
94
//            return this.symbolTable.scripts();
95
//        }
96
//
97 44338 jjdelcerro
        @Override
98 44009 jjdelcerro
        @SuppressWarnings("CloneDoesntCallSuperClone")
99
        public SymbolTable clone() throws CloneNotSupportedException {
100
            throw new UnsupportedOperationException("Not supported yet.");
101
        }
102
103
        @Override
104
        public Iterator<Function> iterator() {
105
            return this.symbolTable.iterator();
106
        }
107
108 44340 jjdelcerro
        @Override
109
        public Collection<String> localvariables() {
110
            return null;
111
        }
112
113 44009 jjdelcerro
    }
114
115
    private final OptimizerSymbolTable symbolTable;
116
    private Interpreter interpreter;
117
    private CodeBuilder codeBuilder;
118 44010 jjdelcerro
119 44009 jjdelcerro
    public DefaultOptimizer() {
120
        this.symbolTable = new OptimizerSymbolTable();
121
    }
122
123
    public DefaultOptimizer(SymbolTable symbolTable) {
124
        this();
125
        this.symbolTable.setSymbolTable(symbolTable);
126
    }
127
128
    @Override
129
    public void setSymbolTable(SymbolTable symbolTable) {
130
        this.symbolTable.setSymbolTable(symbolTable);
131
    }
132
133 44010 jjdelcerro
    @Override
134
    public SymbolTable getSymbolTable() {
135
        return this.symbolTable;
136
    }
137
138
    @Override
139
    public Interpreter getInterpreter() {
140
        if (this.interpreter == null) {
141 44009 jjdelcerro
            this.interpreter = new DefaultInterpreter();
142
            this.interpreter.setSymbolTable(this.symbolTable);
143
        }
144
        return this.interpreter;
145
    }
146 44010 jjdelcerro
147
    @Override
148
    public CodeBuilder getCodeBuilder() {
149
        if (this.codeBuilder == null) {
150 44009 jjdelcerro
            this.codeBuilder = new DefaultCodeBuilder();
151
        }
152
        return this.codeBuilder;
153
    }
154 44010 jjdelcerro
155 44009 jjdelcerro
    @Override
156 44019 jjdelcerro
    public Code optimize(SymbolTable symbolTable, Code code) {
157
        this.setSymbolTable(symbolTable);
158
        return this.optimize(code);
159
    }
160
161
    @Override
162 44009 jjdelcerro
    public Code optimize(Code code) {
163
        code = this.doOptimize(code);
164
        return code;
165
    }
166 44010 jjdelcerro
167 44009 jjdelcerro
    private Code doOptimize(Code code) {
168
        switch (code.code()) {
169
            case Code.CALLER:
170
                Caller caller = (Caller) code;
171 44622 jjdelcerro
                Function function = caller.function();
172
                if ( function == null) {
173 44010 jjdelcerro
                    // resolve and link function
174 44622 jjdelcerro
                    function = this.getSymbolTable().function(caller.name());
175
                    caller.function(function);
176 44010 jjdelcerro
                }
177 44622 jjdelcerro
                if (function instanceof FunctionOptimizer) {
178 44010 jjdelcerro
                    return ((FunctionOptimizer) caller.function()).optimize(this, caller);
179
                } else {
180
                    switch (caller.type()) {
181
                        case Caller.BINARY_OPERATOR: {
182 44198 jjdelcerro
                            Code op1 = this.doOptimize(caller.parameters().get(0));
183
                            Code op2 = this.doOptimize(caller.parameters().get(1));
184 44622 jjdelcerro
                            if ( function.allowConstantFolding()) {
185 44010 jjdelcerro
                                if (op1.code() == Code.CONSTANT && op2.code() == Code.CONSTANT) {
186
                                    Object value = this.getInterpreter().run(code);
187
                                    Code newCode = this.getCodeBuilder().constant(value);
188
                                    return newCode;
189
                                }
190
                                Code newCode = this.getCodeBuilder().operator(caller.name(), op1, op2);
191
                                return newCode;
192
                            }
193 44009 jjdelcerro
                        }
194 44010 jjdelcerro
195
                        case Code.Caller.UNARY_OPERATOR: {
196 44198 jjdelcerro
                            Code op1 = this.doOptimize(caller.parameters().get(0));
197 44622 jjdelcerro
                            if (function.allowConstantFolding()
198 44010 jjdelcerro
                                    && op1.code() == Code.CONSTANT) {
199
                                Object value = this.getInterpreter().run(code);
200
                                Code newCode = this.getCodeBuilder().constant(value);
201
                                return newCode;
202
                            }
203
                            return code;
204 44009 jjdelcerro
                        }
205
206 44010 jjdelcerro
                        case Code.Caller.FUNCTION:
207
                        default: {
208 44139 jjdelcerro
                            BaseCodes newArgs = null;
209 44010 jjdelcerro
                            boolean canOptimize = true;
210 44198 jjdelcerro
                            if (caller.parameters() != null) {
211 44139 jjdelcerro
                                newArgs = (BaseCodes) this.getCodeBuilder().args();
212 44198 jjdelcerro
                                for (Code arg : caller.parameters()) {
213 44010 jjdelcerro
                                    Code newArg = this.doOptimize(arg);
214
                                    newArgs.add(newArg);
215
                                    if (newArg.code() != Code.CONSTANT) {
216
                                        canOptimize = false;
217
                                    }
218 44009 jjdelcerro
                                }
219
                            }
220 44622 jjdelcerro
                            if (canOptimize && function!=null && function.allowConstantFolding()) {
221 44010 jjdelcerro
                                Object value = this.getInterpreter().run(code);
222
                                Code newCode = this.getCodeBuilder().constant(value);
223
                                return newCode;
224
                            }
225
                            Code newCode = this.getCodeBuilder().function(
226
                                    caller.name(),
227
                                    caller.type(),
228
                                    newArgs
229
                            );
230 44009 jjdelcerro
                            return newCode;
231
                        }
232
                    }
233
                }
234 44010 jjdelcerro
235 44009 jjdelcerro
            case Code.CONSTANT:
236
            case Code.IDENTIFIER:
237
            case Code.METHOD:
238
            default:
239
                return code;
240
        }
241
    }
242
}