package org.simantics.scl.compiler.elaboration.chr.analysis; import java.util.ArrayList; import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; import org.simantics.scl.compiler.elaboration.chr.CHRRule; import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import gnu.trove.map.hash.THashMap; public class UsageAnalysis { public static void analyzeUsage(CHRRuleset ruleset) { THashMap> headConstraintMap = createHeadConstraintMap(ruleset); //calculateFirstPriorities(ruleset, headConstraintMap); calculateLastPriorities(ruleset, headConstraintMap); if(!ruleset.extensible) for(CHRRule rule : ruleset.rules) determinePassiveLiterals(rule); //printPriorities(ruleset); } /* private static void calculateFirstPriorities(CHRRuleset ruleset, THashMap> headConstraintMap) { for(CHRRule rule : ruleset.rules) rule.firstPriorityExecuted = Integer.MAX_VALUE; for(CHRConstraint constraint : ruleset.constraints) { constraint.firstPriorityAdded = Integer.MAX_VALUE; constraint.firstPriorityRemoved = Integer.MAX_VALUE; } for(CHRRule rule : ruleset.rules) calculateFirstPriority(headConstraintMap, rule); } private static void calculateFirstPriority(THashMap> headConstraintMap, CHRRule rule) { int result = rule.priority; for(CHRLiteral literal : rule.head.literals) if(literal.relation instanceof CHRConstraint) { CHRConstraint constraint = (CHRConstraint)literal.relation; int constraintPriority = constraint.firstPriorityAdded; if(constraintPriority == Integer.MAX_VALUE) return; result = Math.max(result, constraintPriority); } rule.firstPriorityExecuted = result; for(CHRLiteral literal : rule.head.literals) if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) { CHRConstraint constraint = (CHRConstraint)literal.relation; if(constraint.firstPriorityRemoved == Integer.MAX_VALUE) constraint.firstPriorityRemoved = result; } for(CHRLiteral literal : rule.body.literals) if(literal.relation instanceof CHRConstraint) { CHRConstraint constraint = (CHRConstraint)literal.relation; if(constraint.firstPriorityAdded != Integer.MAX_VALUE) continue; constraint.firstPriorityAdded = result; ArrayList list = headConstraintMap.get(constraint); if(list == null) continue; for(CHRRule lowerPriorityRule : list) if(lowerPriorityRule.priority < rule.priority) // We know here that previous call to lowerPriorityRule "failed", // because constraint.firstPriorityAdded was previously Integer.MAX_VALUE calculateFirstPriority(headConstraintMap, lowerPriorityRule); } } */ private static void calculateLastPriorities(CHRRuleset ruleset, THashMap> headConstraintMap) { for(CHRRule rule : ruleset.rules) rule.lastPriorityExecuted = Integer.MIN_VALUE; for(CHRConstraint constraint : headConstraintMap.keySet()) { constraint.lastPriorityAdded = Integer.MIN_VALUE; constraint.lastPriorityRemoved = Integer.MIN_VALUE; } for(int i=ruleset.rules.size()-1;i>=0;--i) { CHRRule rule = ruleset.rules.get(i); if(rule.lastPriorityExecuted == Integer.MIN_VALUE) calculateLastPriority(headConstraintMap, rule, rule.priority); } } private static void calculateLastPriority(THashMap> headConstraintMap, CHRRule rule, int priority) { rule.lastPriorityExecuted = priority; for(CHRLiteral literal : rule.head.literals) if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) { CHRConstraint constraint = (CHRConstraint)literal.relation; if(constraint.lastPriorityRemoved == Integer.MIN_VALUE) constraint.lastPriorityRemoved = priority; } for(CHRLiteral literal : rule.body.literals) if(literal.relation instanceof CHRConstraint) { CHRConstraint constraint = (CHRConstraint)literal.relation; if(constraint.lastPriorityAdded != Integer.MIN_VALUE) continue; constraint.lastPriorityAdded = priority; ArrayList list = headConstraintMap.get(constraint); if(list == null) continue; for(CHRRule lowerPriorityRule : list) if(lowerPriorityRule.lastPriorityExecuted == Integer.MIN_VALUE) calculateLastPriority(headConstraintMap, lowerPriorityRule, priority); } } private static THashMap> createHeadConstraintMap(CHRRuleset ruleset) { THashMap> map = new THashMap>(); for(CHRRule rule : ruleset.rules) for(CHRLiteral literal : rule.head.literals) if(literal.relation instanceof CHRConstraint) { ArrayList list = map.get(literal.relation); if(list == null) { list = new ArrayList(); map.put((CHRConstraint)literal.relation, list); list.add(rule); } else if(list.get(list.size()-1) != rule) list.add(rule); } return map; } /*private static void printPriorities(CHRRuleset ruleset) { System.out.println("-------------------------------"); for(CHRConstraint constraint : ruleset.constraints) { System.out.print(" [" + constraint.firstPriorityAdded + ".." + constraint.lastPriorityAdded + "]"); if(constraint.firstPriorityRemoved != Integer.MAX_VALUE) System.out.print("R[" + constraint.firstPriorityRemoved + ".." + constraint.lastPriorityRemoved + "]"); System.out.print(" "); System.out.println(constraint); } for(CHRRule rule : ruleset.rules) { System.out.print(rule.priority); System.out.print(" [" + rule.firstPriorityExecuted + ".." + rule.lastPriorityExecuted + "] "); System.out.println(rule); } }*/ private static void determinePassiveLiterals(CHRRule rule) { for(CHRLiteral literal : rule.head.literals) { if(literal.passive) continue; CHRConstraint constraint = (CHRConstraint)literal.relation; if(constraint.lastPriorityAdded < rule.priority) literal.passive = true; } } }