]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/kinds/Kinds.java
migrated to svn revision 33108
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / types / kinds / Kinds.java
1 package org.simantics.scl.compiler.types.kinds;
2
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
4 import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
5
6 public class Kinds {
7     public static final KCon STAR = new KCon("*");
8     public static final KCon EFFECT = new KCon("E");
9     public static final Kind STAR_TO_STAR = new KArrow(STAR, STAR);
10     public static final Kind STAR_TO_STAR_TO_STAR = new KArrow(STAR, STAR_TO_STAR);
11     
12     public static KArrow arrow(Kind domain, Kind range) {
13         return new KArrow(domain, range);
14     }
15     
16     public static KMetaVar metaVar() {
17         return new KMetaVar();
18     }
19     
20     public static Kind canonical(Kind a) {
21         while(a instanceof KMetaVar) {
22             KMetaVar mv = (KMetaVar)a;
23             if(mv.ref == null)
24                 return a;
25             a = mv.ref;
26         }
27         return a;
28     }
29     
30     public static void unifyWithStar(Kind a) throws KindUnificationException {
31         a = canonical(a);
32         if(a == STAR)
33             return;
34         if(a instanceof KMetaVar)
35             ((KMetaVar)a).ref = STAR;
36         throw new KindUnificationException();
37     }
38     
39     /**
40      * Tries to unify two kinds by linking matching meta-variables.
41      * @throws KindUnificationException  if unification fails
42      */
43     public static void unify(Kind a, Kind b) throws KindUnificationException {
44         a = canonical(a);
45         b = canonical(b);
46         if(a == b)
47             return;
48         if(a instanceof KMetaVar) {
49             ((KMetaVar)a).setRef(b);
50             return;
51         }
52         if(b instanceof KMetaVar) {
53             ((KMetaVar)b).setRef(a);
54             return;
55         }
56         if(a instanceof KArrow && b instanceof KArrow) {
57             KArrow arrowA = (KArrow)a;
58             KArrow arrowB = (KArrow)b;
59             unify(arrowA.domain, arrowB.domain);
60             unify(arrowA.range, arrowB.range);
61             return;
62         }
63         throw new KindUnificationException();
64     }
65
66     public static boolean equalsCanonical(Kind a, Kind b) {
67         if(a == b)
68             return true;
69         if(!(a instanceof KArrow))
70             return false;
71         if(!(b instanceof KArrow))
72             return false;
73         KArrow arrowA = (KArrow)a;
74         KArrow arrowB = (KArrow)b;
75         return equals(arrowA.domain, arrowB.domain) && 
76                 equals(arrowA.range, arrowB.range);
77     }
78
79     public static boolean equals(Kind a, Kind b) {
80         return equalsCanonical(canonical(a), canonical(b));
81     }
82
83     public static Kind rangeOfArrow(Kind kind) {
84         kind = canonical(kind);
85         if(kind instanceof KArrow)
86             return ((KArrow)kind).range;
87         else if(kind instanceof KMetaVar) {
88             Kind domain = Kinds.metaVar();
89             Kind range = Kinds.metaVar();
90             try {
91                 ((KMetaVar)kind).setRef(arrow(domain, range));
92             } catch (KindUnificationException e) {
93                 // Should not fail because kind is canonical
94                 e.printStackTrace();
95             }
96             return range;
97         }
98         else
99             throw new InternalCompilerError("Assumed arrow kind but encountered " + kind + ".");
100     }    
101 }