]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/references/Val.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 / Val.java
1 package org.simantics.scl.compiler.internal.codegen.references;
2
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
4 import org.simantics.scl.compiler.internal.codegen.types.BTypes;
5 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
6 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
7 import org.simantics.scl.compiler.types.TVar;
8 import org.simantics.scl.compiler.types.Type;
9 import org.simantics.scl.compiler.types.Types;
10 import org.simantics.scl.compiler.types.exceptions.MatchException;
11
12 import gnu.trove.map.hash.THashMap;
13
14
15 public abstract class Val implements IVal {
16     
17     public static final Val[] EMPTY_ARRAY = new Val[0];
18     
19     transient ValRef occurrence;
20     
21     @Override
22     public final ValRef createOccurrence() {
23         return new ValRef(this, Type.EMPTY_ARRAY);
24     }
25     
26     @Override
27     public final ValRef createOccurrence(Type ... parameters) {
28         return new ValRef(this, parameters);
29     }
30     
31     @Override
32     public IVal createSpecialization(Type... parameters) {
33         return new ValSpecialization(this, parameters);
34     }
35     
36     public final void replaceBy(ValRef other) {
37         if(other.parameters.length == 0)
38             replaceBy(other.binding);
39         else
40             replaceBy(other.binding, other.parameters);
41     }
42     
43     public final ValRef getOccurrence() {
44         return occurrence;
45     }
46     
47     public void replaceBy(Val other) {
48         ValRef cur = occurrence;
49         if(cur != null) {
50             while(true) {
51                 //System.out.println("+ " + other + " - " + cur.binding);
52                 if(SCLCompilerConfiguration.DEBUG) {
53                     if(cur.binding != this)
54                         throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + ".");
55                 }                
56                 cur.binding = other;
57                 cur.updateParentEffect();
58                 if(cur.next == null)
59                     break;
60                 else
61                     cur = cur.next;
62             }
63             cur.next = other.occurrence;
64             if(other.occurrence != null)
65                 other.occurrence.prev = cur;
66             other.occurrence = occurrence;
67             occurrence = null;
68         }        
69     }
70     
71     private void replaceBy(Val other, Type[] parameters) {
72         if(other == this || other == null)
73             throw new InternalCompilerError();
74         ValRef cur = occurrence;
75         if(cur != null) {
76             while(true) {
77                 //System.out.println("+ " + other + " - " + cur.binding);
78                 if(SCLCompilerConfiguration.DEBUG) {
79                     if(cur.binding != this)
80                         throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + ".");
81                 }
82                 cur.binding = other;
83                 cur.parameters = Types.concat(parameters, cur.parameters);
84                 cur.updateParentEffect();
85                 if(cur.next == null)
86                     break;
87                 else
88                     cur = cur.next;
89             }
90             cur.next = other.occurrence;
91             if(other.occurrence != null)
92                 other.occurrence.prev = cur;
93             other.occurrence = occurrence;
94             occurrence = null;
95         }
96     }
97     
98     public void replaceBy(Val other, TVar[] from, Type[] to) {
99         if(other == this || other == null)
100             throw new InternalCompilerError();
101         if(from.length == 0)
102             replaceBy(other, to);
103         else {
104             ValRef cur = occurrence;
105             if(cur != null) {
106                 while(true) {
107                     //System.out.println("+ " + other + " - " + cur.binding);
108                     if(SCLCompilerConfiguration.DEBUG) {
109                         if(cur.binding != this)
110                             throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + ".");
111                     }
112                     cur.binding = other;
113                     cur.parameters = Types.replace(to, from, cur.parameters);
114                     cur.updateParentEffect();
115                     if(cur.next == null)
116                         break;
117                     else
118                         cur = cur.next;
119                 }
120                 cur.next = other.occurrence;
121                 if(other.occurrence != null)
122                     other.occurrence.prev = cur;
123                 other.occurrence = occurrence;
124                 occurrence = null;
125             }
126         }        
127     }
128     
129     public abstract Type getType();
130
131     /**
132      * Returns the number of ValRefs of this Val.
133      * @return
134      */
135     public final int occurrenceCount() {
136         int count = 0;
137         for(ValRef ref = occurrence;ref != null;ref=ref.getNext())
138             ++count;
139         return count;
140     }
141     
142
143     public final boolean hasMoreThanOneOccurences() {
144         return occurrence != null && occurrence.getNext() != null;
145     }
146
147     public final boolean hasNoOccurences() {
148         return occurrence == null;
149     }
150
151     public abstract Val copy(THashMap<TVar, TVar> tvarMap);
152     
153     public ValRef[] getOccurences() {
154         int count = occurrenceCount();
155         if(count == 0)
156             return ValRef.EMPTY_ARRAY;
157         ValRef[] result = new ValRef[count];
158         ValRef cur = occurrence;
159         for(int i=0;i<count;++i,cur=cur.getNext())
160             result[i] = cur;
161         return result;
162     }
163
164     public abstract int getEffectiveArity();
165     
166     /**
167      * Applies given values to this constant. Pushes the result to stack and 
168      * returns the type of the result value.
169      */
170     @Override    
171     public Type apply(MethodBuilder mb, Type[] typeParameters, Val ... parameters) {
172         push(mb);
173         if(parameters.length == 0) 
174             return getType();
175         Type returnType;
176         try {
177             returnType = BTypes.matchFunction(getType(), parameters.length)[parameters.length];            
178         } catch (MatchException e) {
179             throw new InternalCompilerError();
180         }
181         mb.pushBoxed(parameters);
182         mb.genericApply(parameters.length); 
183         mb.unbox(returnType);
184         return returnType;
185     }
186     
187     @Override
188     public void setLabel(String label) {   
189     }
190     
191     public void prepare(MethodBuilder mb) {        
192     }
193 }