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