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

History | View | Annotate | Download (8.18 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.ExpressionEvaluatorManager;
11
import org.gvsig.expressionevaluator.Function;
12
import org.gvsig.expressionevaluator.Interpreter;
13
import org.gvsig.expressionevaluator.SymbolTable;
14
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
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
        public boolean addSymbolTable(SymbolTable symbolTable) {
45
            throw new UnsupportedOperationException("Not supported yet.");
46
        }
47

    
48
        @Override
49
        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
        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
        public boolean isSQLCompatible(String name) {
75
            return false;
76
        }
77

    
78
        @Override
79
        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
        public Collection<Function> localfunctions() {
90
            return this.symbolTable.functions();
91
        }
92
        
93
//        @Override
94
//        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
        @Override
110
        public Collection<String> localvariables() {
111
            return null;
112
        }
113

    
114
    }
115

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

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

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

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

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

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

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

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

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

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

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

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