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