package org.overture.interpreter.utilities.pattern; import java.util.LinkedList; import org.overture.ast.analysis.AnalysisException; import org.overture.ast.analysis.AnswerAdaptor; import org.overture.ast.node.INode; import org.overture.ast.patterns.AConcatenationPattern; import org.overture.ast.patterns.AIdentifierPattern; import org.overture.ast.patterns.AIgnorePattern; import org.overture.ast.patterns.AMapPattern; import org.overture.ast.patterns.AMapUnionPattern; import org.overture.ast.patterns.AMapletPatternMaplet; import org.overture.ast.patterns.ANamePatternPair; import org.overture.ast.patterns.AObjectPattern; import org.overture.ast.patterns.ARecordPattern; import org.overture.ast.patterns.ASeqPattern; import org.overture.ast.patterns.ASetPattern; import org.overture.ast.patterns.ATuplePattern; import org.overture.ast.patterns.AUnionPattern; import org.overture.ast.patterns.PPattern; import org.overture.interpreter.assistant.IInterpreterAssistantFactory; public class ConstrainedPatternChecker extends AnswerAdaptor<Boolean> { protected IInterpreterAssistantFactory af; public ConstrainedPatternChecker(IInterpreterAssistantFactory af) { this.af = af; } @Override public Boolean caseAConcatenationPattern(AConcatenationPattern pattern) throws AnalysisException { return pattern.getLeft().apply(THIS) || pattern.getRight().apply(THIS); } @Override public Boolean caseAIdentifierPattern(AIdentifierPattern pattern) throws AnalysisException { return pattern.getConstrained(); // The variable may be constrained to be the same as another occurrence } @Override public Boolean caseAIgnorePattern(AIgnorePattern pattern) throws AnalysisException { return false; } @Override public Boolean caseAMapPattern(AMapPattern pattern) throws AnalysisException { for (AMapletPatternMaplet p : pattern.getMaplets()) { if (p.apply(THIS)) { return true; } } return false; } @Override public Boolean caseAMapUnionPattern(AMapUnionPattern pattern) throws AnalysisException { return pattern.getLeft().apply(THIS) || pattern.getRight().apply(THIS); } @Override public Boolean caseARecordPattern(ARecordPattern pattern) throws AnalysisException { return isConstrained(pattern.getPlist()); } @Override public Boolean caseASeqPattern(ASeqPattern pattern) throws AnalysisException { return isConstrained(pattern.getPlist()); } @Override public Boolean caseASetPattern(ASetPattern pattern) throws AnalysisException { if (af.createPTypeAssistant().isUnion(af.createPPatternListAssistant().getPossibleType(pattern.getPlist(), pattern.getLocation()))) { return true; // Set types are various, so we must permute } // Check that lengths of the members are the same int length = 0; for (PPattern p: pattern.getPlist()) { if (length == 0) { length = p.apply(af.getLengthFinder()); } else { if (p.apply(af.getLengthFinder()) != length) { return true; // Patterns are different sizes, so permute them } } } return isConstrained(pattern.getPlist()); } @Override public Boolean caseATuplePattern(ATuplePattern pattern) throws AnalysisException { return isConstrained(pattern.getPlist()); } @Override public Boolean caseAUnionPattern(AUnionPattern pattern) throws AnalysisException { return pattern.getLeft().apply(THIS) || pattern.getRight().apply(THIS); } @Override public Boolean caseAObjectPattern(AObjectPattern pattern) throws AnalysisException { LinkedList<PPattern> list = new LinkedList<PPattern>(); for (ANamePatternPair npp: pattern.getFields()) { list.add(npp.getPattern()); } return isConstrained(list); } @Override public Boolean defaultPPattern(PPattern node) throws AnalysisException { return true; } @Override public Boolean createNewReturnValue(INode node) throws AnalysisException { // TODO Auto-generated method stub return true; } @Override public Boolean createNewReturnValue(Object node) throws AnalysisException { // TODO Auto-generated method stub return true; } public boolean isConstrained(LinkedList<PPattern> plist) { for (PPattern p : plist) { if (af.createPPatternAssistant().isConstrained(p)) { return true; // NB. OR } } return false; } }