]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / TypeCheckingScheduler.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingScheduler.java
new file mode 100644 (file)
index 0000000..c3fb2dd
--- /dev/null
@@ -0,0 +1,117 @@
+package org.simantics.scl.compiler.compilation;
+
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint;
+import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+
+/**
+ * Schedules the order of type checking.
+ * 
+ * @author Hannu Niemistö
+ */
+public class TypeCheckingScheduler {
+    final ErrorLog errorLog;
+    final Environment environment;
+    
+    ArrayList<TypeInferableDefinition> definitions = new ArrayList<TypeInferableDefinition>();
+    ArrayList<Runnable> postTypeCheckingRunnables = new ArrayList<Runnable>();
+    
+    public TypeCheckingScheduler(ErrorLog errorLog, Environment environment) {
+        this.errorLog = errorLog;
+        this.environment = environment;
+    }
+
+    public void addTypeInferableDefinition(TypeInferableDefinition definition) {
+        definitions.add(definition);
+    }
+    
+    public void addPostTypeCheckingRunnable(Runnable runnable) {
+        postTypeCheckingRunnables.add(runnable);
+    }
+    
+    public void schedule() {
+        final TObjectIntHashMap<Object> allRefs = 
+                new TObjectIntHashMap<Object>(definitions.size(), Constants.DEFAULT_LOAD_FACTOR, -1);
+        
+        for(int i=0;i<definitions.size();++i)
+            for(Object definedObject : definitions.get(i).getDefinedObjects())
+                allRefs.put(definedObject, i);
+        new StronglyConnectedComponents(definitions.size()) {
+            
+            TIntHashSet set = new TIntHashSet();
+            
+            @Override
+            protected void reportComponent(int[] component) {
+                typeCheck(component);
+            }
+
+            @Override
+            protected int[] findDependencies(int u) {
+                definitions.get(u).collectRefs(allRefs, set);
+                int[] result = set.toArray();
+                set.clear();
+                return result;
+            }
+            
+        }.findComponents();
+        
+        for(Runnable runnable : postTypeCheckingRunnables)
+            runnable.run();
+    }
+    
+    private void typeCheck(int[] component) {
+        TypingContext context = new TypingContext(errorLog, environment);
+        context.recursiveValues = new THashSet<SCLValue>();
+        
+        for(int c : component)
+            definitions.get(c).initializeTypeChecking(context);
+        for(int c : component)
+            definitions.get(c).checkType(context);
+        context.solveSubsumptions(definitions.get(component[0]).getLocation());
+        for(int c : component)
+            definitions.get(c).solveConstraints();
+        
+        THashSet<TVar> varSet = new THashSet<TVar>(); 
+        for(int c : component)
+            definitions.get(c).collectFreeTypeVariables(varSet);
+        TVar[] vars = varSet.toArray(new TVar[varSet.size()]);
+        
+        THashSet<TPred> constraintSet = new THashSet<TPred>();
+        for(int c : component)
+            for(Variable evidence : definitions.get(c).getFreeEvidence())
+                constraintSet.add((TPred)evidence.getType());
+        TPred[] constraints = constraintSet.toArray(new TPred[constraintSet.size()]);
+        
+        THashMap<TPred, Constraint> constraintMap = null;
+        for(TPred constraint : constraints)
+            if(constraint.containsMetaVars()) {
+                if(constraintMap == null) {
+                    constraintMap = new THashMap<TPred, Constraint>();
+                    for(int c : component)
+                        for(Constraint cons : definitions.get(c).getUnsolvedConstraints())
+                            constraintMap.put(cons.constraint, cons);
+                }
+                Constraint cons = constraintMap.get(constraint);
+                errorLog.log(cons.getDemandLocation(), 
+                        "Constrain " + constraint + 
+                        " contains free variables not mentioned in the type of the value.");
+            }
+        
+        for(int c : component)
+            definitions.get(c).injectEvidence(vars, constraints);
+    }
+}