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
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
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
14

    
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
        public boolean addSymbolTable(SymbolTable symbolTable) {
44
            throw new UnsupportedOperationException("Not supported yet.");
45
        }
46

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

    
77
        @Override
78
        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
        public Collection<Function> localfunctions() {
89
            return this.symbolTable.functions();
90
        }
91
        
92
//        @Override
93
//        public Collection<Script> scripts() {
94
//            return this.symbolTable.scripts();
95
//        }
96
//
97
        @Override
98
        @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
        @Override
109
        public Collection<String> localvariables() {
110
            return null;
111
        }
112

    
113
    }
114

    
115
    private final OptimizerSymbolTable symbolTable;
116
    private Interpreter interpreter;
117
    private CodeBuilder codeBuilder;
118

    
119
    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
    @Override
134
    public SymbolTable getSymbolTable() {
135
        return this.symbolTable;
136
    }
137

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

    
147
    @Override
148
    public CodeBuilder getCodeBuilder() {
149
        if (this.codeBuilder == null) {
150
            this.codeBuilder = new DefaultCodeBuilder();
151
        }
152
        return this.codeBuilder;
153
    }
154

    
155
    @Override
156
    public Code optimize(SymbolTable symbolTable, Code code) {
157
        this.setSymbolTable(symbolTable);
158
        return this.optimize(code);
159
    }
160

    
161
    @Override
162
    public Code optimize(Code code) {
163
        code = this.doOptimize(code);
164
        return code;
165
    }
166

    
167
    private Code doOptimize(Code code) {
168
        switch (code.code()) {
169
            case Code.CALLER:
170
                Caller caller = (Caller) code;
171
                Function function = caller.function();
172
                if ( function == null) {
173
                    // resolve and link function
174
                    function = this.getSymbolTable().function(caller.name());
175
                    caller.function(function);
176
                }
177
                if (function instanceof FunctionOptimizer) {
178
                    return ((FunctionOptimizer) caller.function()).optimize(this, caller);
179
                } else {
180
                    switch (caller.type()) {
181
                        case Caller.BINARY_OPERATOR: {
182
                            Code op1 = this.doOptimize(caller.parameters().get(0));
183
                            Code op2 = this.doOptimize(caller.parameters().get(1));
184
                            if ( function.allowConstantFolding()) {
185
                                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
                        }
194

    
195
                        case Code.Caller.UNARY_OPERATOR: {
196
                            Code op1 = this.doOptimize(caller.parameters().get(0));
197
                            if (function.allowConstantFolding()
198
                                    && 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
                        }
205

    
206
                        case Code.Caller.FUNCTION:
207
                        default: {
208
                            BaseCodes newArgs = null;
209
                            boolean canOptimize = true;
210
                            if (caller.parameters() != null) {
211
                                newArgs = (BaseCodes) this.getCodeBuilder().args();
212
                                for (Code arg : caller.parameters()) {
213
                                    Code newArg = this.doOptimize(arg);
214
                                    newArgs.add(newArg);
215
                                    if (newArg.code() != Code.CONSTANT) {
216
                                        canOptimize = false;
217
                                    }
218
                                }
219
                            }
220
                            if (canOptimize && function!=null && function.allowConstantFolding()) {
221
                                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
                            return newCode;
231
                        }
232
                    }
233
                }
234
                
235
            case Code.CONSTANT:
236
            case Code.IDENTIFIER:
237
            case Code.METHOD:
238
            default:
239
                return code;
240
        }
241
    }
242
}