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 collectVars(TObjectIntHashMap<Variable> allVars,
51 protected void updateType() throws MatchException {
52 throw new InternalCompilerError();
55 private Type getCommonSkeleton() {
56 Type[] types = new Type[activeCount];
57 for(int i=0,j=0;i<alternatives.length;++i)
59 types[j++] = Types.instantiateAndStrip(alternatives[i].getType());
60 return Skeletons.commonSkeleton(context.getEnvironment(), types);
63 private void filterActive() {
64 THashMap<TMetaVar,Type> unifications = new THashMap<TMetaVar,Type>();
65 Type requiredType = getType();
67 System.out.println("EAmbigious.filterActive with " + requiredType);
68 for(int i=0;i<alternatives.length;++i)
71 Type alternativeType = Types.instantiateAndStrip(alternatives[i].getType());
73 System.out.println(" " + alternativeType);
74 if(!Skeletons.areSkeletonsCompatible(unifications, alternativeType, requiredType)) {
80 System.out.println(" activeCount = " + activeCount);
83 private String getNoMatchDescription(Type requiredType) {
84 StringBuilder b = new StringBuilder();
85 b.append("Expected <");
86 requiredType.toString(new TypeUnparsingContext(), b);
87 b.append(">, but no alteratives match the type: ");
88 for(int i=0;i<alternatives.length;++i) {
90 b.append(alternatives[i]);
92 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
98 private String getAmbiguousDescription(Type requiredType) {
99 StringBuilder b = new StringBuilder();
100 b.append("Expected <");
101 requiredType.toString(new TypeUnparsingContext(), b);
102 b.append(">, but multiple values match the type: ");
103 for(int i=0;i<alternatives.length;++i) {
105 b.append(alternatives[i]);
107 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
114 private void resolveTo(int i) {
116 System.out.println("EAmbigious.resolve to " + alternatives[i]);
117 resolvedExpression = context.instantiate(alternatives[i].realize());
118 Type requiredType = getType();
120 Types.unify(resolvedExpression.getType(), requiredType);
121 } catch (UnificationException e) {
122 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
126 private void listenType() {
128 System.out.println("EAmbigious.listenType " + getType());
131 public void notifyAboutChange() {
133 System.out.println("EAmbigious.notifyAboutChange " + getType());
134 Type requiredType = getType();
136 if(activeCount == 0) {
137 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
140 else if(activeCount == 1) {
141 for(int i=0;i<alternatives.length;++i)
147 Type commonType = getCommonSkeleton();
149 Skeletons.unifySkeletons(requiredType, commonType);
151 } catch (UnificationException e) {
152 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
155 }.listenSkeleton(getType());
159 public Expression inferType(TypingContext context) {
160 this.context = context;
161 context.overloadedExpressions.add(this);
162 setType(getCommonSkeleton());
168 public void collectFreeVariables(THashSet<Variable> vars) {
172 public Expression resolve(TranslationContext context) {
173 throw new InternalCompilerError("EAmbiguousConstant should not exist in resolve phase.");
177 public void setLocationDeep(long loc) {
178 if(location == Locations.NO_LOCATION)
183 public void collectEffects(THashSet<Type> effects) {
184 // TODO Auto-generated method stub
188 public void accept(ExpressionVisitor visitor) {
189 // TODO Auto-generated method stub
193 public Expression simplify(SimplificationContext context) {
194 if(resolvedExpression != null)
195 return resolvedExpression;
197 context.getErrorLog().log(location, getAmbiguousDescription(getType()));
202 public void assertResolved(ErrorLog errorLog) {
203 if(resolvedExpression == null)
204 errorLog.log(location, getAmbiguousDescription(getType()));
208 public Expression accept(ExpressionTransformer transformer) {
209 return transformer.transform(this);