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 protected void updateType() throws MatchException {
57 throw new InternalCompilerError();
60 private Type getCommonSkeleton() {
61 Type[] types = new Type[activeCount];
62 for(int i=0,j=0;i<alternatives.length;++i)
64 types[j++] = Types.instantiateAndStrip(alternatives[i].getType());
65 return Skeletons.commonSkeleton(context.getEnvironment(), types);
68 private void filterActive() {
69 THashMap<TMetaVar,Type> unifications = new THashMap<TMetaVar,Type>();
70 Type requiredType = getType();
72 System.out.println("EAmbigious.filterActive with " + requiredType);
73 for(int i=0;i<alternatives.length;++i)
76 Type alternativeType = Types.instantiateAndStrip(alternatives[i].getType());
78 System.out.println(" " + alternativeType);
79 if(!Skeletons.areSkeletonsCompatible(unifications, alternativeType, requiredType)) {
85 System.out.println(" activeCount = " + activeCount);
88 private String getNoMatchDescription(Type requiredType) {
89 StringBuilder b = new StringBuilder();
90 b.append("Expected <");
91 requiredType.toString(new TypeUnparsingContext(), b);
92 b.append(">, but no alteratives match the type: ");
93 for(int i=0;i<alternatives.length;++i) {
95 b.append(alternatives[i]);
97 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
103 private String getAmbiguousDescription(Type requiredType) {
104 StringBuilder b = new StringBuilder();
105 b.append("Expected <");
106 requiredType.toString(new TypeUnparsingContext(), b);
107 b.append(">, but multiple values match the type: ");
108 for(int i=0;i<alternatives.length;++i) {
110 b.append(alternatives[i]);
112 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
119 private void resolveTo(int i) {
121 System.out.println("EAmbigious.resolve to " + alternatives[i]);
122 resolvedExpression = context.instantiate(alternatives[i].realize());
123 Type requiredType = getType();
125 Types.unify(resolvedExpression.getType(), requiredType);
126 } catch (UnificationException e) {
127 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
131 private void listenType() {
133 System.out.println("EAmbigious.listenType " + getType());
136 public void notifyAboutChange() {
138 System.out.println("EAmbigious.notifyAboutChange " + getType());
139 Type requiredType = getType();
141 if(activeCount == 0) {
142 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
145 else if(activeCount == 1) {
146 for(int i=0;i<alternatives.length;++i)
152 Type commonType = getCommonSkeleton();
154 Skeletons.unifySkeletons(requiredType, commonType);
156 } catch (UnificationException e) {
157 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
160 }.listenSkeleton(getType());
164 public Expression inferType(TypingContext context) {
165 this.context = context;
166 context.overloadedExpressions.add(this);
167 setType(getCommonSkeleton());
173 public void collectFreeVariables(THashSet<Variable> vars) {
177 public Expression resolve(TranslationContext context) {
178 throw new InternalCompilerError("EAmbiguousConstant should not exist in resolve phase.");
182 public void setLocationDeep(long loc) {
183 if(location == Locations.NO_LOCATION)
188 public void collectEffects(THashSet<Type> effects) {
189 // TODO Auto-generated method stub
193 public void accept(ExpressionVisitor visitor) {
194 // TODO Auto-generated method stub
198 public Expression simplify(SimplificationContext context) {
199 if(resolvedExpression != null)
200 return resolvedExpression;
202 context.getErrorLog().log(location, getAmbiguousDescription(getType()));
207 public void assertResolved(ErrorLog errorLog) {
208 if(resolvedExpression == null)
209 errorLog.log(location, getAmbiguousDescription(getType()));
213 public Expression accept(ExpressionTransformer transformer) {
214 return transformer.transform(this);