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

History | View | Annotate | Download (6.45 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.BaseArguments;
14
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCode;
15
import org.gvsig.tools.script.Script;
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 void addSymbolTable(SymbolTable symbolTable) {
46
            throw new UnsupportedOperationException("Not supported yet.");
47
        }
48

    
49
        @Override
50
        public Function function(String name) {
51
            return this.symbolTable.function(name);
52
        }
53

    
54
        @Override
55
        public boolean exists(String name) {
56
            return false;
57
        }
58

    
59
        @Override
60
        public Object value(String name) {
61
            return null;
62
        }
63

    
64
        @Override
65
        public Collection<String> variables() {
66
            return Collections.EMPTY_LIST;
67
        }
68

    
69
        @Override
70
        public Collection<Function> functions() {
71
            return this.symbolTable.functions();
72
        }
73

    
74
        @Override
75
        public Collection<Script> scripts() {
76
            return this.symbolTable.scripts();
77
        }
78

    
79
        @Override
80
        @SuppressWarnings("CloneDoesntCallSuperClone")
81
        public SymbolTable clone() throws CloneNotSupportedException {
82
            throw new UnsupportedOperationException("Not supported yet.");
83
        }
84

    
85
        @Override
86
        public Iterator<Function> iterator() {
87
            return this.symbolTable.iterator();
88
        }
89

    
90
    }
91

    
92
    private final OptimizerSymbolTable symbolTable;
93
    private Interpreter interpreter;
94
    private CodeBuilder codeBuilder;
95
    
96
    public DefaultOptimizer() {
97
        this.symbolTable = new OptimizerSymbolTable();
98
    }
99

    
100
    public DefaultOptimizer(SymbolTable symbolTable) {
101
        this();
102
        this.symbolTable.setSymbolTable(symbolTable);
103
    }
104

    
105
    @Override
106
    public void setSymbolTable(SymbolTable symbolTable) {
107
        this.symbolTable.setSymbolTable(symbolTable);
108
    }
109

    
110
    private Interpreter getInterpreter() {
111
        if( this.interpreter == null ) {
112
            this.interpreter = new DefaultInterpreter();
113
            this.interpreter.setSymbolTable(this.symbolTable);
114
        }
115
        return this.interpreter;
116
    }
117
    
118
    private CodeBuilder getCodeBuilder() {
119
        if( this.codeBuilder == null ) {
120
            this.codeBuilder = new DefaultCodeBuilder();
121
        }
122
        return this.codeBuilder;
123
    }
124
    
125
    @Override
126
    public Code optimize(Code code) {
127
        this.getInterpreter().link(code);
128
        code = this.doOptimize(code);
129
        return code;
130
    }
131
    
132
    private Code doOptimize(Code code) {
133
        switch (code.code()) {
134
            case Code.CALLER:
135
                Caller caller = (Caller) code;
136
                switch (caller.type()) {
137
                    case Caller.BINARY_OPERATOR: {
138
                        Code op1 = this.doOptimize(caller.args().get(0));
139
                        Code op2 = this.doOptimize(caller.args().get(1));
140
                        if ( caller.function().allowConstantFolding() && 
141
                                op1.code() == Code.CONSTANT && 
142
                                op2.code() == Code.CONSTANT) {
143
                            Object value = this.getInterpreter().run(code);
144
                            Code newCode = this.getCodeBuilder().constant(value);
145
                            return newCode;
146
                        }
147
                        Code newCode = this.getCodeBuilder().operator(caller.name(), op1, op2);
148
                        return newCode;
149
                    }
150
                    
151
                    case Code.Caller.UNARY_OPERATOR: {
152
                        Code op1 = this.doOptimize(caller.args().get(0));
153
                        if ( caller.function().allowConstantFolding() && 
154
                                op1.code() == Code.CONSTANT ) {
155
                            Object value = this.getInterpreter().run(code);
156
                            Code newCode = this.getCodeBuilder().constant(value);
157
                            return newCode;
158
                        }
159
                        return code;
160
                    }
161

    
162
                    case Code.Caller.FUNCTION:
163
                    default: {
164
                        BaseArguments newArgs = null;
165
                        boolean canOptimize = true;
166
                        if( caller.args()!=null ) {
167
                            newArgs = (BaseArguments) this.getCodeBuilder().args();
168
                            for (Code arg : caller.args()) {
169
                                Code newArg = this.doOptimize(arg);
170
                                newArgs.add(newArg);
171
                                if( newArg.code() != Code.CONSTANT ) {
172
                                    canOptimize = false;
173
                                }
174
                            }
175
                        }
176
                        if( canOptimize && caller.function().allowConstantFolding() ) {
177
                            Object value = this.getInterpreter().run(code);
178
                            Code newCode = this.getCodeBuilder().constant(value);
179
                            return newCode;
180
                        }
181
                        Code newCode = this.getCodeBuilder().function(
182
                                caller.name(),
183
                                caller.type(),
184
                                newArgs
185
                        );
186
                        return newCode;
187
                    }
188
                }
189

    
190
            case Code.CONSTANT:
191
            case Code.IDENTIFIER:
192
            case Code.METHOD:
193
            default:
194
                return code;
195
        }
196
    }
197
}