1 package org.simantics.scl.compiler.compilation;
3 import gnu.trove.impl.Constants;
4 import gnu.trove.map.hash.THashMap;
5 import gnu.trove.map.hash.TObjectIntHashMap;
6 import gnu.trove.set.hash.THashSet;
7 import gnu.trove.set.hash.TIntHashSet;
9 import java.util.ArrayList;
11 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
12 import org.simantics.scl.compiler.elaboration.expressions.Variable;
13 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
14 import org.simantics.scl.compiler.environment.Environment;
15 import org.simantics.scl.compiler.errors.ErrorLog;
16 import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint;
17 import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
18 import org.simantics.scl.compiler.types.TPred;
19 import org.simantics.scl.compiler.types.TVar;
22 * Schedules the order of type checking.
24 * @author Hannu Niemistö
26 public class TypeCheckingScheduler {
27 final ErrorLog errorLog;
28 final Environment environment;
30 ArrayList<TypeInferableDefinition> definitions = new ArrayList<TypeInferableDefinition>();
31 ArrayList<Runnable> postTypeCheckingRunnables = new ArrayList<Runnable>();
33 public TypeCheckingScheduler(ErrorLog errorLog, Environment environment) {
34 this.errorLog = errorLog;
35 this.environment = environment;
38 public void addTypeInferableDefinition(TypeInferableDefinition definition) {
39 definitions.add(definition);
42 public void addPostTypeCheckingRunnable(Runnable runnable) {
43 postTypeCheckingRunnables.add(runnable);
46 public void schedule() {
47 final TObjectIntHashMap<Object> allRefs =
48 new TObjectIntHashMap<Object>(definitions.size(), Constants.DEFAULT_LOAD_FACTOR, -1);
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()) {
55 TIntHashSet set = new TIntHashSet();
58 protected void reportComponent(int[] component) {
63 protected int[] findDependencies(int u) {
64 definitions.get(u).collectRefs(allRefs, set);
65 int[] result = set.toArray();
72 for(Runnable runnable : postTypeCheckingRunnables)
76 private void typeCheck(int[] component) {
77 TypingContext context = new TypingContext(errorLog, environment);
78 context.recursiveValues = new THashSet<SCLValue>();
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();
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()]);
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()]);
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);
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.");
114 for(int c : component)
115 definitions.get(c).injectEvidence(vars, constraints);