]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/references/ValRef.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / references / ValRef.java
1 package org.simantics.scl.compiler.internal.codegen.references;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
8 import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;
9 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
10 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
11 import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
12 import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
13 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
14 import org.simantics.scl.compiler.types.TVar;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.scl.compiler.types.Types;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 public final class ValRef implements IVal {
21     private static final Logger LOGGER = LoggerFactory.getLogger(ValRef.class);
22     public static final ValRef[] EMPTY_ARRAY = new ValRef[0];
23
24     Val binding;
25     ValRef prev; // FreeVars with the same binding form a linked list
26     ValRef next;     
27     ValRefBinder parent;
28     Type[] parameters;
29     
30     /**
31      * Just for deserialization
32      */
33     public ValRef(Type[] parameters) {
34         this.parameters = parameters;
35     }
36     
37     ValRef(Val binding, Type[] parameters) {
38         //System.out.println("+ " + bindin g);
39         this.parameters = parameters;        
40         setBinding(binding);
41     }    
42     
43     public void setBinding(Val binding) {
44         this.binding = binding;
45         
46         ValRef head = binding.occurrence;
47         binding.occurrence = this;
48         this.next = head;
49         this.prev = null;
50         if(head != null)
51             head.prev = this;
52     }
53     
54     int removeModiId = -1;
55     public void remove() {
56         //System.out.println("- " + binding);
57         if(prev == null)
58             try {
59                 binding.occurrence = next;
60             } catch(NullPointerException e) {
61                 LOGGER.error("removeModiId = " + removeModiId);
62                 LOGGER.error("current ModiId = " + SSASimplificationContext.modiId, e);
63                 throw new InternalCompilerError("The ValRef has already been removed.");
64             }
65         else
66             prev.next = next;
67         if(next != null)
68             next.prev = prev;
69         if(SCLCompilerConfiguration.DEBUG) {
70             next = null;
71             prev = null;
72             binding = null;
73         }
74         removeModiId = SSASimplificationContext.modiId;
75     }
76     
77     public Val getBinding() {
78         return binding;
79     }
80     
81     public ValRef getNext() {
82         return next;
83     }
84     
85     public static Val[] getBindings(ValRef[] refs) {
86         Val[] result = new Val[refs.length];
87         for(int i=0;i<refs.length;++i)
88             result[i] = refs[i].getBinding();
89         return result;
90     }
91
92     @Override
93     public ValRef createOccurrence() {
94         return binding.createOccurrence(parameters);
95     }
96
97     @Override
98     public ValRef createOccurrence(Type... otherParameters) {
99         return binding.createOccurrence(Types.concat(parameters, otherParameters));
100     }
101     
102     @Override
103     public IVal createSpecialization(Type... otherParameters) {
104         return new ValSpecialization(binding, Types.concat(parameters, otherParameters));
105     }
106
107     public void setParent(ValRefBinder parent) {
108         this.parent = parent;
109     }
110     
111     @Override
112     public Type getType() {
113         if(parameters.length == 0)
114             return binding.getType();
115         else
116             return Types.instantiate(binding.getType(), parameters); 
117     }
118     
119     public static ValRef[] createOccurrences(IVal[] vals) {
120         ValRef[] result = new ValRef[vals.length];
121         for(int i=0;i<vals.length;++i)
122             result[i] = vals[i].createOccurrence();
123         return result;
124     }
125     
126     public static <T extends IVal> ValRef[] createOccurrences(List<T> vals) {
127         ValRef[] result = new ValRef[vals.size()];
128         for(int i=0;i<vals.size();++i)
129             result[i] = vals.get(i).createOccurrence();
130         return result;
131     }
132     
133     public Type[] getTypeParameters() {
134         return parameters;
135     }
136     
137     public Type getTypeParameter(int i) {
138         return parameters[i];
139     }
140
141     public static ValRef[] concat(ValRef[] refs1, ValRef[] refs2) {
142         ValRef[] result = new ValRef[refs1.length + refs2.length];
143         for(int i=0;i<refs1.length;++i)
144             result[i] = refs1[i];
145         for(int i=0;i<refs2.length;++i)
146             result[refs1.length + i] = refs2[i];
147         return result;
148     }
149     
150     @Override
151     public void push(MethodBuilder mb) {
152         binding.push(mb);
153     }
154     
155     public ValRefBinder getParent() {
156         return parent;
157     }
158     
159     public SSAFunction getParentFunction() {
160         return parent.getParentFunction();
161     }
162     
163     public void replace(TVar[] vars, Type[] replacements) {
164         for(int i=0;i<parameters.length;++i) {
165             Type oldType = parameters[i];
166             Type newType = parameters[i].replace(vars, replacements);
167             if(oldType != newType) {
168                 Type[] newParameters = new Type[parameters.length];
169                 for(int j=0;j<i;++j)
170                     newParameters[j] = parameters[j];
171                 newParameters[i] = newType;
172                 for(int j=i+1;j<parameters.length;++j)
173                     newParameters[j] = parameters[j].replace(vars, replacements);
174                 this.parameters = newParameters;
175                 return;
176             }
177             
178         }
179     }
180
181     public void setTypeParameters(Type[] parameters) {
182         this.parameters = parameters;
183     }
184     
185     public static ValRef[] copy(ValRef[] refs) {
186         ValRef[] result = new ValRef[refs.length];
187         for(int i=0;i<refs.length;++i)
188             result[i] = refs[i].copy();
189         return result;
190     }
191
192     public ValRef copy() {
193         return binding.createOccurrence(parameters);
194     }
195
196     public void collectFreeVariables(SSAFunction function,
197             ArrayList<ValRef> vars) {
198         if(binding instanceof BoundVar) {
199             BoundVar var = (BoundVar)binding;
200             if(var.getFunctionParent() != function)
201                 vars.add(this);
202         }
203     }
204
205     public void replaceBy(Val binding) {
206         remove();
207         setBinding(binding);
208     }
209     
210     @Override
211     public Type apply(MethodBuilder mb, Type[] typeParameters,
212             Val... parameters) {
213         return binding.apply(mb, Types.concat(this.parameters, typeParameters), parameters);
214     }
215
216     /**
217      * Replaces this reference with an application
218      */
219     public void replaceByApply(Val function, Val ... parameters) {
220         getParent().replaceByApply(this, function, this.parameters, parameters);
221     }
222     
223     @Override
224     public Object realizeValue(TransientClassBuilder classLoader) {
225         return binding.realizeValue(classLoader); 
226     }
227
228     @Override
229     public void setLabel(String label) {
230     }
231
232     public void updateParentEffect() {
233         if(parent instanceof LetApply) {
234             LetApply apply = (LetApply)parent;
235             if(apply.getFunction() == this)
236                 apply.updateEffect();
237         }
238     }
239 }