1 package org.simantics.scl.compiler.elaboration.expressions;
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
4 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
7 import org.simantics.scl.compiler.errors.ErrorLog;
8 import org.simantics.scl.compiler.errors.Locations;
9 import org.simantics.scl.compiler.types.Skeletons;
10 import org.simantics.scl.compiler.types.TMetaVar;
11 import org.simantics.scl.compiler.types.Type;
12 import org.simantics.scl.compiler.types.Types;
13 import org.simantics.scl.compiler.types.exceptions.MatchException;
14 import org.simantics.scl.compiler.types.exceptions.UnificationException;
15 import org.simantics.scl.compiler.types.util.TypeListener;
16 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
18 import gnu.trove.map.hash.THashMap;
19 import gnu.trove.map.hash.TObjectIntHashMap;
20 import gnu.trove.set.hash.THashSet;
21 import gnu.trove.set.hash.TIntHashSet;
23 public class EAmbiguous extends SimplifiableExpression {
24 public static final boolean DEBUG = false;
26 Alternative[] alternatives;
29 transient TypingContext context;
30 Expression resolvedExpression;
32 public abstract static class Alternative {
33 public abstract Type getType();
34 public abstract Expression realize();
37 public EAmbiguous(Alternative[] alternatives) {
38 this.alternatives = alternatives;
39 this.active = new boolean[alternatives.length];
40 for(int i=0;i<alternatives.length;++i)
41 this.active[i] = true;
42 this.activeCount = alternatives.length;
46 public void collectRefs(TObjectIntHashMap<Object> allRefs,
51 public void collectVars(TObjectIntHashMap<Variable> allVars,
56 public void forVariables(VariableProcedure procedure) {
60 protected void updateType() throws MatchException {
61 throw new InternalCompilerError();
64 private Type getCommonSkeleton() {
65 Type[] types = new Type[activeCount];
66 for(int i=0,j=0;i<alternatives.length;++i)
68 types[j++] = Types.instantiateAndStrip(alternatives[i].getType());
69 return Skeletons.commonSkeleton(context.getEnvironment(), types);
72 private void filterActive() {
73 THashMap<TMetaVar,Type> unifications = new THashMap<TMetaVar,Type>();
74 Type requiredType = getType();
76 System.out.println("EAmbigious.filterActive with " + requiredType);
77 for(int i=0;i<alternatives.length;++i)
80 Type alternativeType = Types.instantiateAndStrip(alternatives[i].getType());
82 System.out.println(" " + alternativeType);
83 if(!Skeletons.areSkeletonsCompatible(unifications, alternativeType, requiredType)) {
89 System.out.println(" activeCount = " + activeCount);
92 private String getNoMatchDescription(Type requiredType) {
93 StringBuilder b = new StringBuilder();
94 b.append("Expected <");
95 requiredType.toString(new TypeUnparsingContext(), b);
96 b.append(">, but no alteratives match the type: ");
97 for(int i=0;i<alternatives.length;++i) {
99 b.append(alternatives[i]);
101 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
107 private String getAmbiguousDescription(Type requiredType) {
108 StringBuilder b = new StringBuilder();
109 b.append("Expected <");
110 requiredType.toString(new TypeUnparsingContext(), b);
111 b.append(">, but multiple values match the type: ");
112 for(int i=0;i<alternatives.length;++i) {
114 b.append(alternatives[i]);
116 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
123 private void resolveTo(int i) {
125 System.out.println("EAmbigious.resolve to " + alternatives[i]);
126 resolvedExpression = context.instantiate(alternatives[i].realize());
127 Type requiredType = getType();
129 Types.unify(resolvedExpression.getType(), requiredType);
130 } catch (UnificationException e) {
131 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
135 private void listenType() {
137 System.out.println("EAmbigious.listenType " + getType());
140 public void notifyAboutChange() {
142 System.out.println("EAmbigious.notifyAboutChange " + getType());
143 Type requiredType = getType();
145 if(activeCount == 0) {
146 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
149 else if(activeCount == 1) {
150 for(int i=0;i<alternatives.length;++i)
156 Type commonType = getCommonSkeleton();
158 Skeletons.unifySkeletons(requiredType, commonType);
160 } catch (UnificationException e) {
161 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
164 }.listenSkeleton(getType());
168 public Expression inferType(TypingContext context) {
169 this.context = context;
170 context.overloadedExpressions.add(this);
171 setType(getCommonSkeleton());
177 public void collectFreeVariables(THashSet<Variable> vars) {
181 public Expression resolve(TranslationContext context) {
182 throw new InternalCompilerError("EAmbiguousConstant should not exist in resolve phase.");
186 public void setLocationDeep(long loc) {
187 if(location == Locations.NO_LOCATION)
192 public void collectEffects(THashSet<Type> effects) {
193 // TODO Auto-generated method stub
197 public void accept(ExpressionVisitor visitor) {
198 // TODO Auto-generated method stub
202 public Expression simplify(SimplificationContext context) {
203 if(resolvedExpression != null)
204 return resolvedExpression;
206 context.getErrorLog().log(location, getAmbiguousDescription(getType()));
211 public void assertResolved(ErrorLog errorLog) {
212 if(resolvedExpression == null)
213 errorLog.log(location, getAmbiguousDescription(getType()));
217 public Expression accept(ExpressionTransformer transformer) {
218 return transformer.transform(this);