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 valuesWithoutTypeAnnotation = new ArrayList(); ArrayList valuesWithTypeAnnotation = new ArrayList(); 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 values = new ArrayList(); for(SCLValue value : module.getValues()) { if(value.getExpression() != null) { if(value.getType() == null) values.add(value); else valuesWithTypeAnnotation.add(value); } } // Create inverse final TObjectIntHashMap allRefs = new TObjectIntHashMap(values.size()*2, 0.5f, -1); for(int i=0;i(); for(SCLValue value : group) context.recursiveValues.add(value); @SuppressWarnings("unchecked") ArrayList[] constraintDemands = new ArrayList[group.length]; @SuppressWarnings("unchecked") ArrayList[] recursiveReferences = new ArrayList[group.length]; for(int i=0;i(); SCLValue value = group[i]; Expression expression = value.getExpression(); expression = expression.checkType(context, value.getType()); value.setExpression(expression); ArrayList 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 allUnsolvedConstraints = new ArrayList(); @SuppressWarnings("unchecked") ArrayList[] freeEvidence = new ArrayList[group.length]; for(int i=0;i(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 fe = new ArrayList(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(0); } } THashSet varSet = new THashSet(); for(int i=0;i constraintSet = new THashSet(); for(int i=0;i fe = freeEvidence[i]; THashMap indexedEvidence = new THashMap(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 givenConstraints = new ArrayList(); 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 vars = new ArrayList(); 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 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 demands = context.getConstraintDemand(); if(!demands.isEmpty()) { ReducedConstraints red = ConstraintSolver.solve(ce, new ArrayList(), 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()); }*/ } }