]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingOld.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / TypeCheckingOld.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingOld.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/TypeCheckingOld.java
new file mode 100644 (file)
index 0000000..c5ef573
--- /dev/null
@@ -0,0 +1,349 @@
+package org.simantics.scl.compiler.compilation;
+
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.applyTypes;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.lambda;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.vars;
+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.EPlaceholder;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
+import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.elaboration.constraints.Constraint;
+import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintEnvironment;
+import org.simantics.scl.compiler.internal.elaboration.constraints.ConstraintSolver;
+import org.simantics.scl.compiler.internal.elaboration.constraints.ExpressionAugmentation;
+import org.simantics.scl.compiler.internal.elaboration.constraints.ReducedConstraints;
+import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
+import org.simantics.scl.compiler.module.ConcreteModule;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.simantics.scl.compiler.types.util.Polarity;
+
+public class TypeCheckingOld {
+    public static final boolean PRINT_VALUES = false;
+    
+    ErrorLog errorLog;
+    Environment environment;
+    ConcreteModule module;
+    
+    ConstraintEnvironment ce;
+    ArrayList<SCLValue[]> valuesWithoutTypeAnnotation = new ArrayList<SCLValue[]>(); 
+    ArrayList<SCLValue> valuesWithTypeAnnotation = new ArrayList<SCLValue>();
+    
+    public TypeCheckingOld(ErrorLog errorLog, Environment environment,
+            ConcreteModule module) {
+        this.errorLog = errorLog;
+        this.environment = environment;
+        this.module = module;
+    }
+    
+    public void typeCheck() {
+        ce = new ConstraintEnvironment(environment);
+        groupValueDefinitionsByDependency();
+        typeCheckValuesWithoutTypeAnnotations();
+        typeCheckValuesWithTypeAnnotations();
+        typeCheckRules();
+    }
+
+    private void groupValueDefinitionsByDependency() {
+        // Collect all untyped names
+        final ArrayList<SCLValue> values = new ArrayList<SCLValue>();
+        for(SCLValue value : module.getValues()) {
+            if(value.getExpression() != null) {
+                if(value.getType() == null)
+                    values.add(value);
+                else
+                    valuesWithTypeAnnotation.add(value);   
+            }            
+        }
+        
+        // Create inverse
+        final TObjectIntHashMap<Object> allRefs = 
+                new TObjectIntHashMap<Object>(values.size()*2, 0.5f, -1);
+        for(int i=0;i<values.size();++i)
+            allRefs.put(values.get(i), i);
+        
+        // Create groups       
+        new StronglyConnectedComponents(values.size()) {
+            
+            TIntHashSet set = new TIntHashSet();
+            
+            @Override
+            protected void reportComponent(int[] component) {
+                SCLValue[] valueComponent = new SCLValue[component.length];
+                for(int i=0;i<component.length;++i)
+                    valueComponent[i] = values.get(component[i]);
+                valuesWithoutTypeAnnotation.add(valueComponent);
+            }
+            
+            @Override
+            protected int[] findDependencies(int u) {
+                Expression expression = values.get(u).getExpression();
+                expression.collectRefs(allRefs, set);
+                
+                int[] result = set.toArray();
+                set.clear();
+                
+                return result;
+            }
+            
+        }.findComponents();
+    }
+    
+    private void typeCheckValuesWithoutTypeAnnotations() {
+        for(SCLValue[] group : valuesWithoutTypeAnnotation) {
+            if(PRINT_VALUES) {
+                System.out.println("---------------------------------------------");
+                System.out.print("---");
+                for(SCLValue value : group)
+                    System.out.print(" " + value.getName());
+                System.out.println();
+            }
+            
+            for(int i=0;i<group.length;++i)
+                group[i].setType(Types.metaVar(Kinds.STAR));
+            
+            TypingContext context = new TypingContext(errorLog, environment);
+            context.recursiveValues = new THashSet<SCLValue>();
+            for(SCLValue value : group)
+                context.recursiveValues.add(value);
+                    
+            @SuppressWarnings("unchecked")
+            ArrayList<EVariable>[] constraintDemands = new ArrayList[group.length];
+            
+            @SuppressWarnings("unchecked")
+            ArrayList<EPlaceholder>[] recursiveReferences = new ArrayList[group.length];
+            for(int i=0;i<group.length;++i) {
+                context.recursiveReferences = new ArrayList<EPlaceholder>();
+                
+                SCLValue value = group[i];
+                Expression expression = value.getExpression();
+                expression = expression.checkType(context, value.getType());
+                value.setExpression(expression);
+                
+                ArrayList<EVariable> constraintDemand = context.getConstraintDemand();
+                if(!constraintDemand.isEmpty()) {
+                    constraintDemands[i] = constraintDemand;
+                    context.resetConstraintDemand();
+                }
+                
+                recursiveReferences[i] = context.recursiveReferences;
+            }
+
+            for(Type type : Types.getTypes(group))
+                type.addPolarity(Polarity.POSITIVE);
+            context.solveSubsumptions(group[0].getExpression().getLocation());
+            ArrayList<Constraint> allUnsolvedConstraints = new ArrayList<Constraint>(); 
+            
+            @SuppressWarnings("unchecked")
+            ArrayList<Variable>[] freeEvidence = new ArrayList[group.length];  
+            for(int i=0;i<group.length;++i) {
+                if(constraintDemands[i] != null) {
+                    SCLValue value = group[i];
+                    Expression expression = value.getExpression();
+                    
+                    ReducedConstraints red = ConstraintSolver.solve(
+                            ce, new ArrayList<TPred>(0), constraintDemands[i],
+                            true /*!Types.isFunction(expression.getType())*/);                                        
+                    
+                    expression = ExpressionAugmentation.augmentSolved(
+                            red.solvedConstraints, 
+                            expression);
+                    value.setExpression(expression);
+                    value.setType(expression.getType());
+                    
+                    for(Constraint c : red.unsolvedConstraints)
+                        if(c.constraint.isGround()) {
+                            errorLog.log(c.getDemandLocation(), "There is no instance for <"+c.constraint+">.");
+                        }          
+                    
+                    ArrayList<Variable> fe = new ArrayList<Variable>(red.unsolvedConstraints.size());
+                    for(Constraint c : red.unsolvedConstraints) {
+                        allUnsolvedConstraints.add(c);
+                        fe.add(c.evidence);
+                    }
+                    freeEvidence[i] = fe;
+                }
+                else {
+                    group[i].setExpression(group[i].getExpression().decomposeMatching());
+                    freeEvidence[i] = new ArrayList<Variable>(0);
+                }
+            }
+
+            THashSet<TVar> varSet = new THashSet<TVar>(); 
+            for(int i=0;i<group.length;++i) {
+                SCLValue value = group[i];
+                Type type = value.getType();
+                type = type.convertMetaVarsToVars();
+                value.setType(type);
+                varSet.addAll(Types.freeVars(type));
+            }
+            
+            TVar[] vars = varSet.toArray(new TVar[varSet.size()]);
+            
+            // Collect all constraints needed in the group
+            THashSet<TPred> constraintSet = new THashSet<TPred>();
+            for(int i=0;i<group.length;++i) {
+                for(Variable evidence : freeEvidence[i]) {
+                    constraintSet.add((TPred)evidence.getType());
+                }
+            }
+            TPred[] constraints = constraintSet.toArray(new TPred[constraintSet.size()]);
+            for(TPred constraint : constraints)
+                if(constraint.containsMetaVars()) {
+                    for(Constraint c : allUnsolvedConstraints) {
+                        if(Types.equals(c.constraint, constraint)) {
+                            errorLog.log(c.getDemandLocation(), 
+                                    "Constrain " + constraint + 
+                                    " contains free variables not mentioned in the type of the value.");
+                            break;
+                        }
+                    }
+                }
+
+
+            // TODO copy to TypeChecking2 from this onwards
+            for(int i=0;i<group.length;++i) {                
+                // Create evidence array of every value in the group that has the variables
+                // in the same array as in the shared array
+                ArrayList<Variable> fe = freeEvidence[i];
+                THashMap<TPred, Variable> indexedEvidence = new THashMap<TPred, Variable>(fe.size());
+                for(Variable v : fe)
+                    indexedEvidence.put((TPred)v.getType(), v);
+                fe.clear();
+                for(TPred c : constraints) {
+                    Variable var = indexedEvidence.get(c);
+                    if(var == null) {
+                        // These are variables that are not directly needed in 
+                        // this definition but in the definitions that are
+                        // recursively called
+                        var = new Variable("evX");
+                        var.setType(c);
+                        fe.add(var);
+                    }
+                    fe.add(var);
+                }
+                
+                // Add evidence parameters to the functions
+                SCLValue value = group[i];
+                value.setExpression(lambda(Types.NO_EFFECTS, fe, value.getExpression())
+                        .closure(vars));
+                value.setType(Types.forAll(vars, 
+                        Types.constrained(constraints, value.getType())));
+                
+                // Add evidence parameters to recursive calls
+                for(EPlaceholder ref : recursiveReferences[i]) {
+                    ref.expression = loc(ref.expression.location, apply(
+                            Types.NO_EFFECTS,
+                            applyTypes(ref.expression, vars),
+                            vars(fe)));
+                }
+            }
+        }
+    }
+    
+    private void typeCheckValuesWithTypeAnnotations() {
+        ArrayList<TPred> givenConstraints = new ArrayList<TPred>();
+        for(SCLValue value : valuesWithTypeAnnotation) {            
+            Type type = value.getType();
+            if(type != null) {
+                if(PRINT_VALUES) {
+                    System.out.println("---------------------------------------------");
+                    System.out.println("--- " + value.getName() + " :: " + type);
+                }
+                Expression expression = value.getExpression();
+                ArrayList<TVar> vars = new ArrayList<TVar>();
+                type = Types.removeForAll(type, vars);                
+                type = Types.removePred(type, givenConstraints);
+                
+                /*System.out.println("---------------------------------------------");
+                TypeUnparsingContext tuc = new TypeUnparsingContext();
+                System.out.println("--- " + value.getName() + " :: " + type.toString(tuc));
+                for(TPred t : givenConstraints)
+                    System.out.println(">>> " + t.toString(tuc));
+                */
+                TypingContext context = new TypingContext(errorLog, environment);
+                //System.out.println(expression);
+                expression = expression.checkType(context, type);
+                //System.out.println(expression);
+                expression.getType().addPolarity(Polarity.POSITIVE);
+                context.solveSubsumptions(expression.getLocation());
+                ArrayList<EVariable> demands = context.getConstraintDemand();
+                if(!demands.isEmpty() || !givenConstraints.isEmpty()) {
+                    ReducedConstraints red = 
+                            ConstraintSolver.solve(ce, givenConstraints, demands, true);    
+                    givenConstraints.clear();
+                    for(Constraint c :  red.unsolvedConstraints) {
+                        errorLog.log(c.getDemandLocation(), 
+                                "Constraint <"+c.constraint+"> is not given and cannot be derived.");
+                    }
+                    if(errorLog.isEmpty()) { // To prevent exceptions
+                        expression = ExpressionAugmentation.augmentSolved(
+                                red.solvedConstraints,
+                                expression);
+                        expression = ExpressionAugmentation.augmentUnsolved(
+                                red.givenConstraints, 
+                                expression); 
+                    }
+                }
+                else {
+                    if(errorLog.isEmpty()) // To prevent exceptions
+                        expression = expression.decomposeMatching();
+                }
+                expression = expression.closure(vars.toArray(new TVar[vars.size()]));
+                value.setExpression(expression);
+            }
+        }
+    }
+
+    public void typeCheckRules() {
+        TypingContext context = new TypingContext(errorLog, environment);
+        for(TransformationRule rule : module.getRules()) {
+            context.pushEffectUpperBound(rule.location, Types.metaVar(Kinds.EFFECT));
+            rule.checkType(context);
+            rule.setEffect(Types.canonical(context.popEffectUpperBound()));
+        }
+        context.solveSubsumptions(Locations.NO_LOCATION);
+        
+        ArrayList<EVariable> demands = context.getConstraintDemand();
+        if(!demands.isEmpty()) {
+            ReducedConstraints red = 
+                    ConstraintSolver.solve(ce, new ArrayList<TPred>(), demands, true);
+            for(Constraint c :  red.unsolvedConstraints) {
+                errorLog.log(c.getDemandLocation(), 
+                        "Constraint <"+c.constraint+"> is not given and cannot be derived.");
+            }
+        }
+        
+        for(MappingRelation mappingRelation : module.getMappingRelations())
+            for(Type parameterType : mappingRelation.parameterTypes)
+                if(!parameterType.isGround()) {
+                    errorLog.log(mappingRelation.location, "Parameter types of the mapping relation are not completely determined.");
+                    break;
+                }
+        
+        /*for(Rule rule : module.getRules()) {
+            System.out.println(rule.name);
+            for(Variable variable : rule.variables)
+                System.out.println("    " + variable.getName() + " :: " + variable.getType());
+        }*/
+    }
+}