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;
20 public class EAmbiguous extends SimplifiableExpression {
21 public static final boolean DEBUG = false;
23 Alternative[] alternatives;
26 transient TypingContext context;
27 public Expression resolvedExpression;
29 public abstract static class Alternative {
30 public abstract Type getType();
31 public abstract Expression realize();
34 public EAmbiguous(Alternative[] alternatives) {
35 this.alternatives = alternatives;
36 this.active = new boolean[alternatives.length];
37 for(int i=0;i<alternatives.length;++i)
38 this.active[i] = true;
39 this.activeCount = alternatives.length;
43 protected void updateType() throws MatchException {
44 throw new InternalCompilerError();
47 private Type getCommonSkeleton() {
48 Type[] types = new Type[activeCount];
49 for(int i=0,j=0;i<alternatives.length;++i)
51 types[j++] = Types.instantiateAndStrip(alternatives[i].getType());
52 return Skeletons.commonSkeleton(context.getEnvironment(), types);
55 private void filterActive() {
56 THashMap<TMetaVar,Type> unifications = new THashMap<TMetaVar,Type>();
57 Type requiredType = getType();
59 System.out.println("EAmbigious.filterActive with " + requiredType.toStringSkeleton());
60 for(int i=0;i<alternatives.length;++i)
63 Type alternativeType = Types.instantiateAndStrip(alternatives[i].getType());
65 System.out.println(" " + alternativeType);
66 if(!Skeletons.areSkeletonsCompatible(unifications, alternativeType, requiredType)) {
72 System.out.println(" activeCount = " + activeCount);
75 private String getNoMatchDescription(Type requiredType) {
76 StringBuilder b = new StringBuilder();
77 b.append("Expected <");
78 requiredType.toString(new TypeUnparsingContext(), b);
79 b.append(">, but no alternatives match the type: ");
80 for(int i=0;i<alternatives.length;++i) {
82 b.append(alternatives[i]);
84 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
90 private String getAmbiguousDescription(Type requiredType) {
91 StringBuilder b = new StringBuilder();
92 b.append("Expected <");
93 requiredType.toString(new TypeUnparsingContext(), b);
94 b.append(">, but multiple values match the type: ");
95 for(int i=0;i<alternatives.length;++i) {
97 b.append(alternatives[i]);
99 alternatives[i].getType().toString(new TypeUnparsingContext(), b);
106 private void resolveTo(int i) {
108 System.out.println("EAmbigious.resolve to " + alternatives[i]);
109 resolvedExpression = context.instantiate(alternatives[i].realize());
110 Type requiredType = getType();
112 Types.unify(resolvedExpression.getType(), requiredType);
113 } catch (UnificationException e) {
114 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
118 private void listenType() {
120 System.out.println("EAmbigious.listenType " + getType().toStringSkeleton());
123 public void notifyAboutChange() {
125 System.out.println("EAmbigious.notifyAboutChange " + getType().toStringSkeleton());
126 Type requiredType = getType();
128 if(activeCount == 0) {
129 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
132 else if(activeCount == 1) {
133 for(int i=0;i<alternatives.length;++i)
139 Type commonType = getCommonSkeleton();
141 Skeletons.unifySkeletons(requiredType, commonType);
143 } catch (UnificationException e) {
144 context.getErrorLog().log(location, getNoMatchDescription(requiredType));
147 }.listenSkeleton(getType());
151 public Expression inferType(TypingContext context) {
152 this.context = context;
153 context.overloadedExpressions.add(this);
154 setType(getCommonSkeleton());
160 public Expression resolve(TranslationContext context) {
161 throw new InternalCompilerError("EAmbiguousConstant should not exist in resolve phase.");
165 public void setLocationDeep(long loc) {
166 if(location == Locations.NO_LOCATION)
171 public void accept(ExpressionVisitor visitor) {
176 public Expression simplify(SimplificationContext context) {
177 if(resolvedExpression != null)
178 return resolvedExpression;
181 System.out.println("EAmbigious.simplify: error");
182 context.getErrorLog().log(location, getAmbiguousDescription(getType()));
187 public void assertResolved(ErrorLog errorLog) {
188 if(resolvedExpression == null) {
190 System.out.println("EAmbigious.assertResolved: error");
191 errorLog.log(location, getAmbiguousDescription(getType()));
196 public Expression accept(ExpressionTransformer transformer) {
197 return transformer.transform(this);