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.TIntHashSet;
22 public class EAmbiguous extends SimplifiableExpression {
23 public static final boolean DEBUG = false;
25 Alternative[] alternatives;
28 transient TypingContext context;
29 public Expression resolvedExpression;
31 public abstract static class Alternative {
32 public abstract Type getType();
33 public abstract Expression realize();
36 public EAmbiguous(Alternative[] alternatives) {
37 this.alternatives = alternatives;
38 this.active = new boolean[alternatives.length];
39 for(int i=0;i<alternatives.length;++i)
40 this.active[i] = true;
41 this.activeCount = alternatives.length;
45 public void collectVars(TObjectIntHashMap<Variable> allVars,
50 protected void updateType() throws MatchException {
51 throw new InternalCompilerError();
54 private Type getCommonSkeleton() {
55 Type[] types = new Type[activeCount];
56 for(int i=0,j=0;i<alternatives.length;++i)
58 types[j++] = Types.instantiateAndStrip(alternatives[i].getType());
59 return Skeletons.commonSkeleton(context.getEnvironment(), types);
62 private void filterActive() {
63 THashMap<TMetaVar,Type> unifications = new THashMap<TMetaVar,Type>();
64 Type requiredType = getType();
66 System.out.println("EAmbigious.filterActive with " + requiredType);
67 for(int i=0;i<alternatives.length;++i)
70 Type alternativeType = Types.instantiateAndStrip(alternatives[i].getType());
72 System.out.println(" " + alternativeType);
73 if(!Skeletons.areSkeletonsCompatible(unifications, alternativeType, requiredType)) {
79 System.out.println(" activeCount = " + activeCount);
82 private String getNoMatchDescription(Type requiredType) {
83 StringBuilder b = new StringBuilder();
84 b.append("Expected <");
85 requiredType.toString(new TypeUnparsingContext(), b);
86 b.append(">, but no alteratives match the type: ");
87 for(int i=0;i<alternatives.length;++i) {
89 b.append(alternatives[i]);
91 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
97 private String getAmbiguousDescription(Type requiredType) {
98 StringBuilder b = new StringBuilder();
99 b.append("Expected <");
100 requiredType.toString(new TypeUnparsingContext(), b);
101 b.append(">, but multiple values match the type: ");
102 for(int i=0;i<alternatives.length;++i) {
104 b.append(alternatives[i]);
106 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
113 private void resolveTo(int i) {
115 System.out.println("EAmbigious.resolve to " + alternatives[i]);
116 resolvedExpression = context.instantiate(alternatives[i].realize());
117 Type requiredType = getType();
119 Types.unify(resolvedExpression.getType(), requiredType);
120 } catch (UnificationException e) {
121 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
125 private void listenType() {
127 System.out.println("EAmbigious.listenType " + getType());
130 public void notifyAboutChange() {
132 System.out.println("EAmbigious.notifyAboutChange " + getType());
133 Type requiredType = getType();
135 if(activeCount == 0) {
136 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
139 else if(activeCount == 1) {
140 for(int i=0;i<alternatives.length;++i)
146 Type commonType = getCommonSkeleton();
148 Skeletons.unifySkeletons(requiredType, commonType);
150 } catch (UnificationException e) {
151 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
154 }.listenSkeleton(getType());
158 public Expression inferType(TypingContext context) {
159 this.context = context;
160 context.overloadedExpressions.add(this);
161 setType(getCommonSkeleton());
167 public Expression resolve(TranslationContext context) {
168 throw new InternalCompilerError("EAmbiguousConstant should not exist in resolve phase.");
172 public void setLocationDeep(long loc) {
173 if(location == Locations.NO_LOCATION)
178 public void accept(ExpressionVisitor visitor) {
183 public Expression simplify(SimplificationContext context) {
184 if(resolvedExpression != null)
185 return resolvedExpression;
187 context.getErrorLog().log(location, getAmbiguousDescription(getType()));
192 public void assertResolved(ErrorLog errorLog) {
193 if(resolvedExpression == null)
194 errorLog.log(location, getAmbiguousDescription(getType()));
198 public Expression accept(ExpressionTransformer transformer) {
199 return transformer.transform(this);