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

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