]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / TypeCheckingScheduler.java
1 package org.simantics.scl.compiler.compilation;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
6 import org.simantics.scl.compiler.elaboration.expressions.Variable;
7 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
8 import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint;
9 import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
10 import org.simantics.scl.compiler.types.TPred;
11 import org.simantics.scl.compiler.types.TVar;
12
13 import gnu.trove.impl.Constants;
14 import gnu.trove.map.hash.THashMap;
15 import gnu.trove.map.hash.TObjectIntHashMap;
16 import gnu.trove.set.hash.THashSet;
17 import gnu.trove.set.hash.TIntHashSet;
18
19 /**
20  * Schedules the order of type checking.
21  * 
22  * @author Hannu Niemistö
23  */
24 public class TypeCheckingScheduler {
25     private final CompilationContext compilationContext;
26     
27     private final ArrayList<TypeInferableDefinition> definitions = new ArrayList<TypeInferableDefinition>();
28     private final ArrayList<Runnable> postTypeCheckingRunnables = new ArrayList<Runnable>();
29     
30     public TypeCheckingScheduler(CompilationContext compilationContext) {
31         this.compilationContext = compilationContext;
32     }
33
34     public void addTypeInferableDefinition(TypeInferableDefinition definition) {
35         definitions.add(definition);
36     }
37     
38     public void addPostTypeCheckingRunnable(Runnable runnable) {
39         postTypeCheckingRunnables.add(runnable);
40     }
41     
42     public void schedule() {
43         final TObjectIntHashMap<Object> allRefs = 
44                 new TObjectIntHashMap<Object>(definitions.size(), Constants.DEFAULT_LOAD_FACTOR, -1);
45         
46         for(int i=0;i<definitions.size();++i)
47             for(Object definedObject : definitions.get(i).getDefinedObjects())
48                 allRefs.put(definedObject, i);
49         new StronglyConnectedComponents(definitions.size()) {
50             
51             TIntHashSet set = new TIntHashSet();
52             
53             @Override
54             protected void reportComponent(int[] component) {
55                 typeCheck(component);
56             }
57
58             @Override
59             protected int[] findDependencies(int u) {
60                 definitions.get(u).collectRefs(allRefs, set);
61                 int[] result = set.toArray();
62                 set.clear();
63                 return result;
64             }
65             
66         }.findComponents();
67         
68         for(Runnable runnable : postTypeCheckingRunnables)
69             runnable.run();
70     }
71     
72     private void typeCheck(int[] component) {
73         TypingContext context = new TypingContext(compilationContext);
74         context.recursiveValues = new THashSet<SCLValue>();
75         
76         for(int c : component)
77             definitions.get(c).initializeTypeChecking(context);
78         for(int c : component)
79             definitions.get(c).checkType(context);
80         context.solveSubsumptions(definitions.get(component[0]).getLocation());
81         for(int c : component)
82             definitions.get(c).solveConstraints();
83         
84         THashSet<TVar> varSet = new THashSet<TVar>(); 
85         for(int c : component)
86             definitions.get(c).collectFreeTypeVariables(varSet);
87         TVar[] vars = varSet.toArray(new TVar[varSet.size()]);
88         
89         THashSet<TPred> constraintSet = new THashSet<TPred>();
90         for(int c : component)
91             for(Variable evidence : definitions.get(c).getFreeEvidence())
92                 constraintSet.add((TPred)evidence.getType());
93         TPred[] constraints = constraintSet.toArray(new TPred[constraintSet.size()]);
94         
95         THashMap<TPred, Constraint> constraintMap = null;
96         for(TPred constraint : constraints)
97             if(constraint.containsMetaVars()) {
98                 if(constraintMap == null) {
99                     constraintMap = new THashMap<TPred, Constraint>();
100                     for(int c : component)
101                         for(Constraint cons : definitions.get(c).getUnsolvedConstraints())
102                             constraintMap.put(cons.constraint, cons);
103                 }
104                 Constraint cons = constraintMap.get(constraint);
105                 compilationContext.errorLog.log(cons.getDemandLocation(), 
106                         "Constrain " + constraint + 
107                         " contains free variables not mentioned in the type of the value.");
108             }
109         
110         for(int c : component)
111             definitions.get(c).injectEvidence(vars, constraints);
112     }
113 }