package hu.bme.mit.inf.dslreasoner.viatra2logic import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicProblemBuilder import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Term import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Variable import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem import java.util.LinkedList import java.util.Map import org.eclipse.emf.common.util.Enumerator import org.eclipse.emf.ecore.EAttribute import org.eclipse.emf.ecore.EClass import org.eclipse.emf.ecore.EReference import org.eclipse.emf.ecore.EStructuralFeature import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey import org.eclipse.viatra.query.runtime.emf.types.EStructuralFeatureInstancesKey import org.eclipse.viatra.query.runtime.matchers.aggregators.DoubleSumOperator import org.eclipse.viatra.query.runtime.matchers.aggregators.ExtremumOperator import org.eclipse.viatra.query.runtime.matchers.aggregators.ExtremumOperator.Extreme import org.eclipse.viatra.query.runtime.matchers.aggregators.IntegerSumOperator import org.eclipse.viatra.query.runtime.matchers.aggregators.LongSumOperator import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.AggregatorConstraint import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Equality import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExportedParameter import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.ExpressionEvaluation import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.Inequality import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.PatternMatchCounter import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.TypeFilterConstraint import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.BinaryTransitiveClosure import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.ConstantValue import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* class Constraint2Logic { val extension LogicProblemBuilder builder = new LogicProblemBuilder val Ecore2Logic ecore2Logic val ExpressionEvaluation2Logic expressionEvaliation2Logic = new ExpressionEvaluation2Logic val expressionExtractor = new XExpressionExtractor new(Ecore2Logic ecore2Logic) { this.ecore2Logic = ecore2Logic } def dispatch Term transformConstraint(Equality constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { constraint.who.lookup(variable2Variable) == constraint.withWhom.lookup(variable2Variable) } def dispatch Term transformConstraint(ExportedParameter constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { return null } def dispatch Term transformConstraint(Inequality constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { constraint.who.lookup(variable2Variable) != constraint.withWhom.lookup(variable2Variable) } def dispatch Term transformConstraint(NegativePatternCall constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val parameterSubstitution = new LinkedList for(index : 0.. ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { transitiveClosure( constraint.referredQuery.lookup(viatra2LogicTrace.query2Relation), (constraint.variablesTuple.get(0) as PVariable).lookup(variable2Variable).toTerm, (constraint.variablesTuple.get(1) as PVariable).lookup(variable2Variable).toTerm ) } def dispatch Term transformConstraint(ConstantValue constant, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val tuple = constant.variablesTuple if(tuple.size == 1) { val variable = tuple.get(0) as PVariable //println(variable.name + " == " + constant.supplierKey + "["+constant.supplierKey.class.name+"]") val translatedConstant = transformConstantValue(constant.supplierKey,ecore2LogicTrace,viatra2LogicTrace,config); return variable.lookup(variable2Variable) == translatedConstant } else throw new AssertionError } private def dispatch transformConstantValue( Enumerator enumerator, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Viatra2LogicConfiguration config) { ecore2Logic.Literal(ecore2LogicTrace.trace,enumerator) } private def dispatch transformConstantValue( Integer value, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Viatra2LogicConfiguration config) { return value.asTerm } private def dispatch transformConstantValue( Boolean value, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Viatra2LogicConfiguration config) { return value.asTerm } private def dispatch transformConstantValue( String value, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Viatra2LogicConfiguration config) { return value.asTerm } private def dispatch transformConstantValue( Double value, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Viatra2LogicConfiguration config) { return value.asTerm } private def dispatch transformConstantValue( Float value, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Viatra2LogicConfiguration config) { return value.asTerm } private def dispatch transformConstantValue(Object other, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Viatra2LogicConfiguration config) { throw new UnsupportedOperationException('''Unknown constant «other»:«other.class.name»''') } def dispatch Term transformConstraint(PositivePatternCall constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val parameterSubstitution = new LinkedList for(index : 0.. ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val tuple = constraint.variablesTuple if(tuple.size == 1) { val typeConstraint = constraint.equivalentJudgement.inputKey if(typeConstraint instanceof EClassTransitiveInstancesKey) { val type = typeConstraint.emfKey val variable = tuple.get(0) as PVariable return transformTypeConstraint(type,variable,ecore2LogicTrace,variable2Variable,viatra2LogicTrace) } else if(typeConstraint instanceof EDataTypeInSlotsKey) { // If the type is a primitive type or EEnum, then instanceof is an unnecessary constraint return null } } else if(tuple.size == 2) { val type = (constraint.equivalentJudgement.inputKey as EStructuralFeatureInstancesKey).emfKey val src = tuple.get(0) as PVariable val trg = tuple.get(1) as PVariable return transformPathConstraint(type,src,trg,ecore2LogicTrace,variable2Variable,viatra2LogicTrace) } else throw new IllegalArgumentException('''unknown tuple: «tuple»''') } def Term transformTypeConstraint( EClass type, PVariable variable, TracedOutput ecore2LogicTrace, Map variable2Variable, Viatra2LogicTrace viatra2LogicTrace) { InstanceOf( variable.lookup(variable2Variable), ecore2Logic.TypeofEClass(ecore2LogicTrace.trace,type)) } def Term transformPathConstraint( EStructuralFeature feature, PVariable src, PVariable trg, TracedOutput ecore2LogicTrace, Map variable2Variable, Viatra2LogicTrace viatra2LogicTrace) { if(feature instanceof EReference) { return ecore2Logic.IsInReference(ecore2LogicTrace.trace, src.lookup(variable2Variable), trg.lookup(variable2Variable), feature) } else if(feature instanceof EAttribute) { return ecore2Logic.IsAttributeValue(ecore2LogicTrace.trace, src.lookup(variable2Variable), trg.lookup(variable2Variable), feature) } else { throw new IllegalArgumentException('''Unsupported path expression: «feature.class.name»''') } } def dispatch Term transformConstraint(TypeFilterConstraint constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val tuple = constraint.variablesTuple if(tuple.size == 1) { val typeConstraint = constraint.equivalentJudgement.inputKey if(typeConstraint instanceof EClassTransitiveInstancesKey) { val type = typeConstraint.emfKey val variable = tuple.get(0) as PVariable return transformTypeConstraint(type,variable,ecore2LogicTrace,variable2Variable,viatra2LogicTrace) } else if(typeConstraint instanceof EDataTypeInSlotsKey) { // If the type is a primitive type or EEnum, then instanceof is an unnecessary constraint return null } } else if(tuple.size == 2) { val type = (constraint.equivalentJudgement.inputKey as EStructuralFeatureInstancesKey).emfKey val src = tuple.get(0) as PVariable val trg = tuple.get(1) as PVariable return transformPathConstraint(type,src,trg,ecore2LogicTrace,variable2Variable,viatra2LogicTrace) } else throw new IllegalArgumentException('''unknown tuple: «tuple»''') } def dispatch Term transformConstraint(AggregatorConstraint constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val logicReferred = constraint.referredQuery.lookup(viatra2LogicTrace.query2Relation) val parameterSubstitution = new LinkedList for(index : 0.. ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val logicReferred = constraint.referredQuery.lookup(viatra2LogicTrace.query2Relation) val parameterSubstitution = new LinkedList for(index : 0.. ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { val outputVariable = constraint.outputVariable val expression = expressionExtractor.extractExpression(constraint.evaluator) if(outputVariable === null) { return expressionEvaliation2Logic.transformCheck(expression,variable2Variable) } else { return expressionEvaliation2Logic.transformEval(outputVariable,expression,variable2Variable) } } def dispatch Term transformConstraint(PConstraint constraint, TracedOutput ecore2LogicTrace, Viatra2LogicTrace viatra2LogicTrace, Map variable2Variable, Viatra2LogicConfiguration config) { throw new UnsupportedOperationException('''Unkown constraint type: «constraint.class.name»''') } }