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.internal.elaboration.utils.ExpressionDecorator;
10 import org.simantics.scl.compiler.types.Skeletons;
11 import org.simantics.scl.compiler.types.TMetaVar;
12 import org.simantics.scl.compiler.types.Type;
13 import org.simantics.scl.compiler.types.Types;
14 import org.simantics.scl.compiler.types.exceptions.MatchException;
15 import org.simantics.scl.compiler.types.exceptions.UnificationException;
16 import org.simantics.scl.compiler.types.util.TypeListener;
17 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
19 import gnu.trove.map.hash.THashMap;
20 import gnu.trove.map.hash.TObjectIntHashMap;
21 import gnu.trove.set.hash.THashSet;
22 import gnu.trove.set.hash.TIntHashSet;
24 public class EAmbiguous extends SimplifiableExpression {
25 public static final boolean DEBUG = false;
27 Alternative[] alternatives;
30 transient TypingContext context;
31 Expression resolvedExpression;
33 public abstract static class Alternative {
34 public abstract Type getType();
35 public abstract Expression realize();
38 public EAmbiguous(Alternative[] alternatives) {
39 this.alternatives = alternatives;
40 this.active = new boolean[alternatives.length];
41 for(int i=0;i<alternatives.length;++i)
42 this.active[i] = true;
43 this.activeCount = alternatives.length;
47 public void collectRefs(TObjectIntHashMap<Object> allRefs,
52 public void collectVars(TObjectIntHashMap<Variable> allVars,
57 public void forVariables(VariableProcedure procedure) {
61 protected void updateType() throws MatchException {
62 throw new InternalCompilerError();
65 private Type getCommonSkeleton() {
66 Type[] types = new Type[activeCount];
67 for(int i=0,j=0;i<alternatives.length;++i)
69 types[j++] = Types.instantiateAndStrip(alternatives[i].getType());
70 return Skeletons.commonSkeleton(context.getEnvironment(), types);
73 private void filterActive() {
74 THashMap<TMetaVar,Type> unifications = new THashMap<TMetaVar,Type>();
75 Type requiredType = getType();
77 System.out.println("EAmbigious.filterActive with " + requiredType);
78 for(int i=0;i<alternatives.length;++i)
81 Type alternativeType = Types.instantiateAndStrip(alternatives[i].getType());
83 System.out.println(" " + alternativeType);
84 if(!Skeletons.areSkeletonsCompatible(unifications, alternativeType, requiredType)) {
90 System.out.println(" activeCount = " + activeCount);
93 private String getNoMatchDescription(Type requiredType) {
94 StringBuilder b = new StringBuilder();
95 b.append("Expected <");
96 requiredType.toString(new TypeUnparsingContext(), b);
97 b.append(">, but no alteratives match the type: ");
98 for(int i=0;i<alternatives.length;++i) {
100 b.append(alternatives[i]);
102 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
108 private String getAmbiguousDescription(Type requiredType) {
109 StringBuilder b = new StringBuilder();
110 b.append("Expected <");
111 requiredType.toString(new TypeUnparsingContext(), b);
112 b.append(">, but multiple values match the type: ");
113 for(int i=0;i<alternatives.length;++i) {
115 b.append(alternatives[i]);
117 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
124 private void resolveTo(int i) {
126 System.out.println("EAmbigious.resolve to " + alternatives[i]);
127 resolvedExpression = context.instantiate(alternatives[i].realize());
128 Type requiredType = getType();
130 Types.unify(resolvedExpression.getType(), requiredType);
131 } catch (UnificationException e) {
132 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
136 private void listenType() {
138 System.out.println("EAmbigious.listenType " + getType());
141 public void notifyAboutChange() {
143 System.out.println("EAmbigious.notifyAboutChange " + getType());
144 Type requiredType = getType();
146 if(activeCount == 0) {
147 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
150 else if(activeCount == 1) {
151 for(int i=0;i<alternatives.length;++i)
157 Type commonType = getCommonSkeleton();
159 Skeletons.unifySkeletons(requiredType, commonType);
161 } catch (UnificationException e) {
162 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
165 }.listenSkeleton(getType());
169 public Expression inferType(TypingContext context) {
170 this.context = context;
171 context.overloadedExpressions.add(this);
172 setType(getCommonSkeleton());
178 public void collectFreeVariables(THashSet<Variable> vars) {
182 public Expression resolve(TranslationContext context) {
183 throw new InternalCompilerError("EAmbiguousConstant should not exist in resolve phase.");
187 public void setLocationDeep(long loc) {
188 if(location == Locations.NO_LOCATION)
193 public Expression decorate(ExpressionDecorator decorator) {
198 public void collectEffects(THashSet<Type> effects) {
199 // TODO Auto-generated method stub
203 public void accept(ExpressionVisitor visitor) {
204 // TODO Auto-generated method stub
208 public Expression simplify(SimplificationContext context) {
209 if(resolvedExpression != null)
210 return resolvedExpression;
212 context.getErrorLog().log(location, getAmbiguousDescription(getType()));
217 public void assertResolved(ErrorLog errorLog) {
218 if(resolvedExpression == null)
219 errorLog.log(location, getAmbiguousDescription(getType()));
223 public Expression accept(ExpressionTransformer transformer) {
224 return transformer.transform(this);