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