diff options
Diffstat (limited to 'Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend')
-rw-r--r-- | Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend | 335 |
1 files changed, 69 insertions, 266 deletions
diff --git a/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend b/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend index 3b828170..74e03f71 100644 --- a/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend +++ b/Framework/hu.bme.mit.inf.dslreasoner.viatra2logic/src/hu/bme/mit/inf/dslreasoner/viatra2logic/Viatra2Logic.xtend | |||
@@ -4,48 +4,36 @@ import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic | |||
4 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace | 4 | import hu.bme.mit.inf.dslreasoner.ecore2logic.Ecore2Logic_Trace |
5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicProblemBuilder | 5 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.LogicProblemBuilder |
6 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput | 6 | import hu.bme.mit.inf.dslreasoner.logic.model.builder.TracedOutput |
7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.ComplexTypeReference | ||
8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.PrimitiveTypeReference | ||
9 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition | 7 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.RelationDefinition |
10 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Type | ||
11 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.TypeReference | ||
12 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Variable | 8 | import hu.bme.mit.inf.dslreasoner.logic.model.logiclanguage.Variable |
13 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem | 9 | import hu.bme.mit.inf.dslreasoner.logic.model.logicproblem.LogicProblem |
14 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery | 10 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.TransfomedViatraQuery |
15 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Viatra2LogicAnnotationsFactory | 11 | import hu.bme.mit.inf.dslreasoner.viatra2logic.viatra2logicannotations.Viatra2LogicAnnotationsFactory |
16 | import java.util.ArrayList | 12 | import java.util.ArrayList |
17 | import java.util.HashMap | 13 | import java.util.HashMap |
18 | import java.util.HashSet | ||
19 | import java.util.LinkedList | 14 | import java.util.LinkedList |
20 | import java.util.List | 15 | import java.util.List |
21 | import java.util.Map | 16 | import java.util.Map |
22 | import java.util.Set | 17 | import java.util.Set |
23 | import org.eclipse.emf.ecore.EAttribute | 18 | import org.eclipse.emf.ecore.EAttribute |
24 | import org.eclipse.emf.ecore.EClassifier | ||
25 | import org.eclipse.emf.ecore.EEnum | ||
26 | import org.eclipse.emf.ecore.EReference | 19 | import org.eclipse.emf.ecore.EReference |
27 | import org.eclipse.emf.ecore.EStructuralFeature | 20 | import org.eclipse.emf.ecore.EStructuralFeature |
28 | import org.eclipse.emf.ecore.EcorePackage | 21 | import org.eclipse.emf.ecore.util.EcoreUtil |
29 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification | 22 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification |
30 | import org.eclipse.viatra.query.runtime.emf.EMFQueryMetaContext | 23 | import org.eclipse.viatra.query.runtime.emf.EMFQueryMetaContext |
31 | import org.eclipse.viatra.query.runtime.emf.types.BaseEMFTypeKey | ||
32 | import org.eclipse.viatra.query.runtime.emf.types.EClassTransitiveInstancesKey | ||
33 | import org.eclipse.viatra.query.runtime.emf.types.EDataTypeInSlotsKey | ||
34 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey | ||
35 | import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey | ||
36 | import org.eclipse.viatra.query.runtime.matchers.planning.helpers.TypeHelper | ||
37 | import org.eclipse.viatra.query.runtime.matchers.psystem.PBody | 24 | import org.eclipse.viatra.query.runtime.matchers.psystem.PBody |
25 | import org.eclipse.viatra.query.runtime.matchers.psystem.PConstraint | ||
38 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable | 26 | import org.eclipse.viatra.query.runtime.matchers.psystem.PVariable |
27 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.AggregatorConstraint | ||
39 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall | 28 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.NegativePatternCall |
29 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicdeferred.PatternMatchCounter | ||
30 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction | ||
40 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter | 31 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter |
41 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery | 32 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery |
42 | import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyNormalizer | 33 | import org.eclipse.viatra.query.runtime.matchers.psystem.rewriters.PBodyNormalizer |
43 | import org.eclipse.xtend.lib.annotations.Data | 34 | import org.eclipse.xtend.lib.annotations.Data |
44 | 35 | ||
45 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* | 36 | import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.* |
46 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PDisjunction | ||
47 | import org.eclipse.emf.ecore.util.EcoreUtil | ||
48 | import org.eclipse.viatra.query.runtime.emf.types.EClassUnscopedTransitiveInstancesKey | ||
49 | 37 | ||
50 | @Data class ViatraQuerySetDescriptor { | 38 | @Data class ViatraQuerySetDescriptor { |
51 | val List<? extends IQuerySpecification<?>> patterns | 39 | val List<? extends IQuerySpecification<?>> patterns |
@@ -57,24 +45,24 @@ class Viatra2LogicTrace { | |||
57 | public val Map<PQuery, RelationDefinition> query2Relation = new HashMap | 45 | public val Map<PQuery, RelationDefinition> query2Relation = new HashMap |
58 | public val Map<PQuery, TransfomedViatraQuery> query2Annotation = new HashMap | 46 | public val Map<PQuery, TransfomedViatraQuery> query2Annotation = new HashMap |
59 | public val Map<Pair<PQuery,PParameter>, Variable> parameter2Variable = new HashMap | 47 | public val Map<Pair<PQuery,PParameter>, Variable> parameter2Variable = new HashMap |
60 | //public val Map<PVariable, Variable> variable2Variable = new HashMap | ||
61 | } | 48 | } |
62 | class Viatra2LogicConfiguration { | 49 | class Viatra2LogicConfiguration { |
63 | public var normalize = true | 50 | public var normalize = true |
64 | public var transitiveClosureDepth = 3 | ||
65 | } | 51 | } |
66 | 52 | ||
67 | class Viatra2Logic { | 53 | class Viatra2Logic { |
68 | val extension LogicProblemBuilder builder = new LogicProblemBuilder | 54 | val extension LogicProblemBuilder builder = new LogicProblemBuilder |
69 | val extension Viatra2LogicAnnotationsFactory factory = Viatra2LogicAnnotationsFactory.eINSTANCE | 55 | val extension Viatra2LogicAnnotationsFactory factory = Viatra2LogicAnnotationsFactory.eINSTANCE |
70 | val normalizer = new PBodyNormalizer(EMFQueryMetaContext.DEFAULT) | 56 | val normalizer = new PBodyNormalizer(EMFQueryMetaContext.DEFAULT) |
57 | val Viatra2LogicTypeInferer typeInferer | ||
71 | 58 | ||
72 | val Ecore2Logic ecore2Logic | 59 | val Ecore2Logic ecore2Logic |
73 | Constraint2Logic constraint2Logic | 60 | Constraint2Logic constraint2Logic |
74 | 61 | ||
75 | new(Ecore2Logic ecore2Logic) { | 62 | new(Ecore2Logic ecore2Logic) { |
76 | this.ecore2Logic = ecore2Logic | 63 | this.ecore2Logic = ecore2Logic |
77 | constraint2Logic = new Constraint2Logic(ecore2Logic) | 64 | this.typeInferer = new Viatra2LogicTypeInferer(ecore2Logic) |
65 | this.constraint2Logic = new Constraint2Logic(ecore2Logic) | ||
78 | } | 66 | } |
79 | 67 | ||
80 | def TracedOutput<LogicProblem,Viatra2LogicTrace> transformQueries( | 68 | def TracedOutput<LogicProblem,Viatra2LogicTrace> transformQueries( |
@@ -82,65 +70,55 @@ class Viatra2Logic { | |||
82 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, | 70 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, |
83 | Viatra2LogicConfiguration config) | 71 | Viatra2LogicConfiguration config) |
84 | { | 72 | { |
73 | // Create trace | ||
85 | val viatra2LogicTrace = new Viatra2LogicTrace | 74 | val viatra2LogicTrace = new Viatra2LogicTrace |
86 | val typeAlanysis = new HashMap | 75 | |
76 | // Translation works on PQueries. QuerySpecification -> PQuery. | ||
87 | val pQueries = queries.patterns.map[it.internalQueryRepresentation] | 77 | val pQueries = queries.patterns.map[it.internalQueryRepresentation] |
88 | 78 | ||
89 | for(query: pQueries) { | 79 | // If requested, the queries are normalized |
90 | val disjunction = normalizer.rewrite(query) | 80 | for(query: pQueries) { |
81 | val disjunction = normalizer.rewrite(query) | ||
91 | viatra2LogicTrace.query2Disjunction.put(query,disjunction) | 82 | viatra2LogicTrace.query2Disjunction.put(query,disjunction) |
92 | } | 83 | } |
93 | 84 | ||
94 | for(query: pQueries) { | 85 | // The types are calculated |
95 | val types = query.lookup(viatra2LogicTrace.query2Disjunction).bodies.toInvertedMap[ | 86 | val types = typeInferer.inferTypes(pQueries,ecore2LogicTrace,viatra2LogicTrace) |
96 | TypeHelper::inferUnaryTypesFor(it.uniqueVariables,it.constraints,EMFQueryMetaContext.DEFAULT) | ||
97 | ] | ||
98 | // for(m : types.values) { | ||
99 | // for(n: m.entrySet) { | ||
100 | // val variable = n.key | ||
101 | // println(''' - «variable.name»''') | ||
102 | // for(type : n.value) { | ||
103 | // println('''«variable.name» - «type»''') | ||
104 | // } | ||
105 | // } | ||
106 | // | ||
107 | // } | ||
108 | |||
109 | typeAlanysis.put(query,types) | ||
110 | } | ||
111 | 87 | ||
88 | // First, the signature of the queries are translated, ... | ||
112 | for(query: pQueries) { | 89 | for(query: pQueries) { |
113 | try { | 90 | try { |
114 | this.transformQueryHeader(query,query.lookup(typeAlanysis),ecore2LogicTrace,viatra2LogicTrace,config) | 91 | this.transformQueryHeader(query,types,ecore2LogicTrace,viatra2LogicTrace,config) |
115 | } catch(IllegalArgumentException e) { | 92 | } catch(IllegalArgumentException e) { |
116 | throw new IllegalArgumentException(''' | 93 | throw new IllegalArgumentException(''' |
117 | Unable to translate query "«query.fullyQualifiedName»". | 94 | Unable to translate query "«query.fullyQualifiedName»". |
118 | Reason: «e.class.simpleName», «e.message»''',e) | 95 | Reason: «e.class.simpleName», «e.message»''',e) |
119 | } | 96 | } |
120 | } | 97 | } |
98 | |||
99 | // ...then the bodies, ... | ||
121 | for(query: pQueries) { | 100 | for(query: pQueries) { |
122 | try { | 101 | try { |
123 | this.transformQuerySpecification(query,query.lookup(typeAlanysis),ecore2LogicTrace,viatra2LogicTrace,config) | 102 | this.transformQuerySpecification(query,types,ecore2LogicTrace,viatra2LogicTrace,config) |
124 | } catch (IllegalArgumentException e){ | 103 | } catch (IllegalArgumentException e){ |
125 | throw new IllegalArgumentException(''' | 104 | throw new IllegalArgumentException(''' |
126 | Unable to translate query "«query.fullyQualifiedName»". | 105 | Unable to translate query "«query.fullyQualifiedName»". |
127 | Reason: «e.class.simpleName», «e.message»''',e) | 106 | Reason: «e.class.simpleName», «e.message»''',e) |
128 | } | 107 | } |
129 | } | 108 | } |
130 | /*for(d : viatra2LogicTrace.query2Relation.values) { | ||
131 | checkDefinition(d) | ||
132 | }*/ | ||
133 | 109 | ||
110 | // ... and finally, the annotations. | ||
134 | transformQueryConstraints( | 111 | transformQueryConstraints( |
135 | queries.validationPatterns.map[internalQueryRepresentation], | 112 | queries.validationPatterns.map[internalQueryRepresentation], |
136 | queries.derivedFeatures, | 113 | queries.derivedFeatures, |
137 | ecore2LogicTrace,viatra2LogicTrace) | 114 | ecore2LogicTrace,viatra2LogicTrace) |
115 | |||
138 | return new TracedOutput(ecore2LogicTrace.output,viatra2LogicTrace) | 116 | return new TracedOutput(ecore2LogicTrace.output,viatra2LogicTrace) |
139 | } | 117 | } |
140 | 118 | ||
141 | def protected transformQueryHeader( | 119 | def protected transformQueryHeader( |
142 | PQuery pquery, | 120 | PQuery pquery, |
143 | Map<PBody, Map<PVariable, Set<IInputKey>>> types, | 121 | Viatra2LogicTypeResult types, |
144 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, | 122 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, |
145 | Viatra2LogicTrace viatra2LogicTrace, | 123 | Viatra2LogicTrace viatra2LogicTrace, |
146 | Viatra2LogicConfiguration config) | 124 | Viatra2LogicConfiguration config) |
@@ -149,7 +127,7 @@ class Viatra2Logic { | |||
149 | val parameters = new ArrayList<Variable>(pquery.parameters.size) | 127 | val parameters = new ArrayList<Variable>(pquery.parameters.size) |
150 | for(vParam: pquery.parameters) { | 128 | for(vParam: pquery.parameters) { |
151 | val parameterName = '''parameter «vParam.name»''' | 129 | val parameterName = '''parameter «vParam.name»''' |
152 | val parameterType = getType(vParam,types,ecore2LogicTrace) | 130 | val parameterType = types.getType(pquery,vParam) |
153 | if(parameterType === null) { | 131 | if(parameterType === null) { |
154 | throw new AssertionError('''null type for parameter «vParam.name» in pattern «pquery.fullyQualifiedName»''') | 132 | throw new AssertionError('''null type for parameter «vParam.name» in pattern «pquery.fullyQualifiedName»''') |
155 | } | 133 | } |
@@ -166,6 +144,7 @@ class Viatra2Logic { | |||
166 | it.target = lRelation | 144 | it.target = lRelation |
167 | it.patternFullyQualifiedName = pquery.fullyQualifiedName | 145 | it.patternFullyQualifiedName = pquery.fullyQualifiedName |
168 | it.patternPQuery = pquery | 146 | it.patternPQuery = pquery |
147 | it.optimizedDisjunction = viatra2LogicTrace.query2Disjunction.get(pquery) | ||
169 | ] | 148 | ] |
170 | viatra2LogicTrace.query2Annotation.put(pquery,annotation) | 149 | viatra2LogicTrace.query2Annotation.put(pquery,annotation) |
171 | ecore2LogicTrace.output.annotations += annotation | 150 | ecore2LogicTrace.output.annotations += annotation |
@@ -175,7 +154,7 @@ class Viatra2Logic { | |||
175 | 154 | ||
176 | def protected transformQuerySpecification( | 155 | def protected transformQuerySpecification( |
177 | PQuery pquery, | 156 | PQuery pquery, |
178 | Map<PBody, Map<PVariable, Set<IInputKey>>> types, | 157 | Viatra2LogicTypeResult types, |
179 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, | 158 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, |
180 | Viatra2LogicTrace viatra2LogicTrace, | 159 | Viatra2LogicTrace viatra2LogicTrace, |
181 | Viatra2LogicConfiguration config) | 160 | Viatra2LogicConfiguration config) |
@@ -233,7 +212,7 @@ class Viatra2Logic { | |||
233 | } | 212 | } |
234 | 213 | ||
235 | def transformBody(PBody body, | 214 | def transformBody(PBody body, |
236 | Map<PBody, Map<PVariable, Set<IInputKey>>> types, | 215 | Viatra2LogicTypeResult types, |
237 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, | 216 | TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace, |
238 | Viatra2LogicTrace viatra2LogicTrace, | 217 | Viatra2LogicTrace viatra2LogicTrace, |
239 | Viatra2LogicConfiguration config) | 218 | Viatra2LogicConfiguration config) |
@@ -248,19 +227,33 @@ class Viatra2Logic { | |||
248 | // Inner Variables | 227 | // Inner Variables |
249 | val innerPositiveVariables = new LinkedList | 228 | val innerPositiveVariables = new LinkedList |
250 | val innerNegativeVariables = new LinkedList | 229 | val innerNegativeVariables = new LinkedList |
230 | val innerAggreatedVariables = new LinkedList | ||
231 | //println(body.uniqueVariables) | ||
251 | for(innerVariable : body.uniqueVariables) { | 232 | for(innerVariable : body.uniqueVariables) { |
252 | 233 | ||
253 | if(!variable2Variable.containsKey(innerVariable)) { | 234 | if(!variable2Variable.containsKey(innerVariable)) { |
254 | val name = '''variable «innerVariable.name.normalizeName»''' | 235 | if(innerVariable.aggregateOnly) { |
255 | //println(body.pattern.fullyQualifiedName + "-") | 236 | // do not create variable |
256 | val logicType = getType(innerVariable,types,ecore2LogicTrace) | 237 | innerAggreatedVariables.add(innerVariable) |
257 | val logicVariable = createVar(name,logicType) | 238 | variable2Variable.put(innerVariable,null) |
258 | if(innerVariable.isPositiveVariable) { | ||
259 | innerPositiveVariables += logicVariable | ||
260 | } else { | 239 | } else { |
261 | innerNegativeVariables += logicVariable | 240 | val name = '''variable «innerVariable.name.normalizeName»''' |
241 | val logicType = types.getType(body,innerVariable) | ||
242 | if(logicType === null) { | ||
243 | throw new IllegalArgumentException('''Variable «innerVariable.name.normalizeName» has no type!''') | ||
244 | } | ||
245 | val logicVariable = createVar(name,logicType) | ||
246 | if(innerVariable.negativeOnly) { | ||
247 | innerNegativeVariables += logicVariable | ||
248 | } else { | ||
249 | innerPositiveVariables += logicVariable | ||
250 | } | ||
251 | variable2Variable.put(innerVariable,logicVariable) | ||
252 | body.pattern.lookup(viatra2LogicTrace.query2Annotation).variableTrace += createVariableMapping=>[ | ||
253 | it.sourcePVariable = innerVariable | ||
254 | it.targetLogicVariable = logicVariable | ||
255 | ] | ||
262 | } | 256 | } |
263 | variable2Variable.put(innerVariable,logicVariable) | ||
264 | } | 257 | } |
265 | } | 258 | } |
266 | 259 | ||
@@ -279,229 +272,39 @@ class Viatra2Logic { | |||
279 | } else { | 272 | } else { |
280 | Exists(innerPositiveVariables,allNegativeVariablesAreSatisfied); | 273 | Exists(innerPositiveVariables,allNegativeVariablesAreSatisfied); |
281 | } | 274 | } |
282 | 275 | ||
283 | return allVariablesAreExisting | 276 | return allVariablesAreExisting |
284 | } | 277 | } |
285 | // def toTypeJudgement(PVariable v, IInputKey key) { | ||
286 | // new TypeJudgement(key,new Tuple1) | ||
287 | // } | ||
288 | 278 | ||
289 | def private normalizeName(String variableName) { | 279 | def private normalizeName(String variableName) { |
290 | return variableName.replaceAll("[\\W]|_", "") | 280 | return variableName.replaceAll("[\\W]|_", "") |
291 | } | 281 | } |
292 | |||
293 | /** | ||
294 | * Translates the type of a parameter variable in a pattern | ||
295 | */ | ||
296 | def TypeReference getType(PParameter v, Map<PBody, Map<PVariable, Set<IInputKey>>> types, TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) { | ||
297 | // If parameter type is specified then the specified type is used | ||
298 | if(v.declaredUnaryType !== null) { | ||
299 | val res = transformTypeReference(v.declaredUnaryType,ecore2LogicTrace) | ||
300 | if(res === null) { | ||
301 | throw new AssertionError(''' | ||
302 | Unable to translate declared type «v.declaredUnaryType». | ||
303 | ''') | ||
304 | } else { | ||
305 | return res | ||
306 | } | ||
307 | } | ||
308 | // Otherwise, calculate the type based on the type of the variable in the bodies | ||
309 | else { | ||
310 | val bodies = types.keySet | ||
311 | val typesFromBodies = new ArrayList(bodies.size) | ||
312 | for(body : bodies) { | ||
313 | // collect the variable in the body | ||
314 | val exported = body.symbolicParameters.filter[it.patternParameter === v] | ||
315 | if(exported.size !== 1) { | ||
316 | throw new AssertionError('''Parameter «v.name» has no reference in body!''') | ||
317 | } | ||
318 | val variable = exported.head.parameterVariable | ||
319 | typesFromBodies+=variable.getType(types,ecore2LogicTrace) | ||
320 | } | ||
321 | return typesFromBodies.calculateCommonSupertype | ||
322 | } | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * Translates the type of a variable in a pattern body | ||
327 | */ | ||
328 | def TypeReference getType(PVariable v, Map<PBody, Map<PVariable, Set<IInputKey>>> types ,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) { | ||
329 | if (v.isPositiveVariable) { | ||
330 | val keys = getTypesFromCollection(v,types) | ||
331 | val logicTypes = keys.map[transformTypeReference(it,ecore2LogicTrace)].filterNull | ||
332 | return logicTypes.calculateCommonSubtype | ||
333 | } else { | ||
334 | val onlyConstraint = v.referringConstraints.head as NegativePatternCall | ||
335 | val indexOfVariable = v.lookup(onlyConstraint.actualParametersTuple.invertIndex) | ||
336 | val parameter = onlyConstraint.referredQuery.parameters.get(indexOfVariable) | ||
337 | val declaredUnaryType = parameter.declaredUnaryType as BaseEMFTypeKey<? extends EClassifier> | ||
338 | if (declaredUnaryType === null) { | ||
339 | throw new UnsupportedOperationException( | ||
340 | '''parameter «parameter.name» in pattern «onlyConstraint.referredQuery.fullyQualifiedName» does not have type!''') | ||
341 | } else | ||
342 | return declaredUnaryType.transformTypeReference(ecore2LogicTrace) | ||
343 | } | ||
344 | } | ||
345 | |||
346 | def getTypesFromCollection(PVariable v, Map<PBody, Map<PVariable, Set<IInputKey>>> types) { | ||
347 | for(entry : types.entrySet) { | ||
348 | if(entry.key.uniqueVariables.contains(v)) { | ||
349 | return v.lookup(entry.value) | ||
350 | } | ||
351 | } | ||
352 | throw new IllegalArgumentException('''Variable «v.name» is not present in neither of the bodies!''') | ||
353 | } | ||
354 | |||
355 | 282 | ||
356 | def TypeReference calculateCommonSubtype(Iterable<TypeReference> types) { | 283 | def isNegativeOnly(PVariable variable) { |
357 | val primitiveTypeReferences = types.filter(PrimitiveTypeReference) | 284 | if(variable.referringConstraints.size == 1) { |
358 | val complexTypeReferences = types.filter(ComplexTypeReference) | 285 | val PConstraint onlyConstraint = variable.referringConstraints.head |
359 | if(complexTypeReferences.isEmpty) { | 286 | if(onlyConstraint instanceof NegativePatternCall) { |
360 | val head = primitiveTypeReferences.head | 287 | return true |
361 | if(primitiveTypeReferences.exists[it.eClass !== head.eClass]) { | 288 | } else { |
362 | throw new IllegalArgumentException('''Inconsistent types: «primitiveTypeReferences.map[eClass.name].toSet.toList»''') | 289 | return false |
363 | } | ||
364 | return head | ||
365 | } else if(primitiveTypeReferences.isEmpty) { | ||
366 | val complexTypes = complexTypeReferences.map[it.referred].toSet | ||
367 | if(complexTypes.size === 1) { | ||
368 | return builder.toTypeReference(complexTypes.head) | ||
369 | } | ||
370 | // Collect possible subtypes | ||
371 | val subtypeSets = complexTypes.map[it.transitiveClosureStar[it.subtypes].toSet] | ||
372 | val commonTypeSet = new HashSet(subtypeSets.head) | ||
373 | val otherSets = subtypeSets.tail | ||
374 | for(otherSet : otherSets) { | ||
375 | commonTypeSet.retainAll(otherSet) | ||
376 | } | ||
377 | if(commonTypeSet.empty) { | ||
378 | throw new IllegalArgumentException('''Inconsistent types: «complexTypes.map[name].toList»''') | ||
379 | } | ||
380 | |||
381 | return calculateCommonComplexSupertype(commonTypeSet) | ||
382 | |||
383 | } else { | ||
384 | throw new IllegalArgumentException(''' | ||
385 | Inconsistent types, mixing primitive and complex types: | ||
386 | «primitiveTypeReferences.map[eClass.name].toSet.toList» | ||
387 | and | ||
388 | «complexTypeReferences.map[it.referred].toSet.map[name].toList»''') | ||
389 | |||
390 | } | ||
391 | } | ||
392 | def TypeReference calculateCommonSupertype(Iterable<TypeReference> types) { | ||
393 | val primitiveTypeReferences = types.filter(PrimitiveTypeReference) | ||
394 | val complexTypeReferences = types.filter(ComplexTypeReference) | ||
395 | if(complexTypeReferences.isEmpty) { | ||
396 | val head = primitiveTypeReferences.head | ||
397 | if(primitiveTypeReferences.exists[it.eClass !== head.eClass]) { | ||
398 | throw new IllegalArgumentException('''Inconsistent types: «primitiveTypeReferences.map[eClass.name].toSet.toList»''') | ||
399 | } | ||
400 | return head | ||
401 | } else if(primitiveTypeReferences.isEmpty) { | ||
402 | val complexTypes = complexTypeReferences.map[it.referred].toSet | ||
403 | return calculateCommonComplexSupertype(complexTypes) | ||
404 | |||
405 | } else { | ||
406 | throw new IllegalArgumentException(''' | ||
407 | Inconsistent types, mixing primitive and complex types: | ||
408 | «primitiveTypeReferences.map[eClass.name].toSet.toList» | ||
409 | and | ||
410 | «complexTypeReferences.map[it.referred].toSet.map[name].toList»''') | ||
411 | |||
412 | } | ||
413 | } | ||
414 | def TypeReference calculateCommonComplexSupertype(Set<Type> complexTypes) { | ||
415 | if(complexTypes.size === 1) { | ||
416 | return builder.toTypeReference(complexTypes.head) | ||
417 | } | ||
418 | // Collect possible supertypes | ||
419 | val supertypeSets = complexTypes.map[it.transitiveClosureStar[it.supertypes].toSet] | ||
420 | val commonTypeSet = new HashSet(supertypeSets.head) | ||
421 | val otherSets = supertypeSets.tail | ||
422 | for(otherSet : otherSets) { | ||
423 | commonTypeSet.retainAll(otherSet) | ||
424 | } | ||
425 | if(commonTypeSet.empty) { | ||
426 | throw new IllegalArgumentException('''Inconsistent types: «complexTypes.map[name].toList»''') | ||
427 | } | ||
428 | // Remove type that already have covered | ||
429 | val coveredTypes = commonTypeSet.map[it.supertypes].flatten | ||
430 | commonTypeSet.removeAll(coveredTypes) | ||
431 | return builder.toTypeReference(commonTypeSet.head) | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * Transforms a Viatra type reference to a logic type. | ||
436 | */ | ||
437 | def dispatch TypeReference transformTypeReference(EDataTypeInSlotsKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) { | ||
438 | val w = k.wrappedKey | ||
439 | if(w == EcorePackage.Literals.EINT || w == EcorePackage.Literals.ESHORT || w == EcorePackage.Literals.ELONG) { | ||
440 | return builder.LogicInt | ||
441 | } else if(w == EcorePackage.Literals.EDOUBLE || w == EcorePackage.Literals.EFLOAT) { | ||
442 | return builder.LogicReal | ||
443 | } else if(w == EcorePackage.Literals.EBOOLEAN) { | ||
444 | return builder.LogicBool | ||
445 | } else if(w == EcorePackage.Literals.ESTRING) { | ||
446 | return builder.LogicString | ||
447 | } else if(w instanceof EEnum) { | ||
448 | val c = this.ecore2Logic.TypeofEEnum(ecore2LogicTrace.trace,w) | ||
449 | return builder.toTypeReference(c); | ||
450 | } else throw new UnsupportedOperationException('''Unknown reference type «w.class.name»''') | ||
451 | } | ||
452 | def dispatch TypeReference transformTypeReference(JavaTransitiveInstancesKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) { | ||
453 | val c = k.wrapperInstanceClass | ||
454 | if(c == Integer || c == Long || c == Short) { | ||
455 | return LogicInt | ||
456 | } else if(c == Float || c == Double) { | ||
457 | return LogicReal | ||
458 | } else if(c == Boolean) { | ||
459 | return LogicBool | ||
460 | } else if(c == String) { | ||
461 | return LogicString | ||
462 | } else if(c.superclass == java.lang.Enum){ | ||
463 | val enums = ecore2Logic.allEnumsInScope(ecore2LogicTrace.trace) | ||
464 | for(enum : enums) { | ||
465 | if(c == enum.instanceClass) { | ||
466 | return builder.toTypeReference(ecore2Logic.TypeofEEnum(ecore2LogicTrace.trace,enum)) | ||
467 | } | ||
468 | } | 290 | } |
469 | throw new IllegalArgumentException('''Enum type «c.simpleName» is not mapped to logic!''') | ||
470 | } | ||
471 | return null | ||
472 | } | ||
473 | def dispatch TypeReference transformTypeReference(EClassTransitiveInstancesKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) { | ||
474 | val c = k.wrappedKey | ||
475 | |||
476 | if(this.ecore2Logic.allClassesInScope(ecore2LogicTrace.trace).toList.contains(c)) { | ||
477 | return builder.toTypeReference(this.ecore2Logic.TypeofEClass(ecore2LogicTrace.trace,k.wrappedKey)) | ||
478 | } else { | 291 | } else { |
479 | return null | 292 | return false |
480 | } | 293 | } |
481 | } | 294 | } |
482 | def dispatch TypeReference transformTypeReference(EClassUnscopedTransitiveInstancesKey k, TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) { | ||
483 | val c = k.wrappedKey | ||
484 | |||
485 | if(this.ecore2Logic.allClassesInScope(ecore2LogicTrace.trace).toList.contains(c)) { | ||
486 | return builder.toTypeReference(this.ecore2Logic.TypeofEClass(ecore2LogicTrace.trace,k.wrappedKey)) | ||
487 | } else { | ||
488 | return null | ||
489 | } | ||
490 | } | ||
491 | |||
492 | def dispatch TypeReference transformTypeReference(IInputKey k,TracedOutput<LogicProblem, Ecore2Logic_Trace> ecore2LogicTrace) { | ||
493 | //println(k) | ||
494 | throw new IllegalArgumentException('''Unsupported type: «k.class.simpleName»''') | ||
495 | } | ||
496 | 295 | ||
497 | def boolean isPositiveVariable(PVariable v) { | 296 | def isAggregateOnly(PVariable variable) { |
498 | val constraints = v.referringConstraints | 297 | if(variable.referringConstraints.size == 1) { |
499 | if(constraints.size == 1) { | 298 | val PConstraint onlyConstraint = variable.referringConstraints.head |
500 | val onlyConstraint = constraints.head | 299 | if(onlyConstraint instanceof AggregatorConstraint) { |
501 | if(onlyConstraint instanceof NegativePatternCall) { | 300 | return true |
301 | } else if(onlyConstraint instanceof PatternMatchCounter) { | ||
302 | return true | ||
303 | } else { | ||
502 | return false | 304 | return false |
503 | } | 305 | } |
306 | } else { | ||
307 | return false | ||
504 | } | 308 | } |
505 | return true | ||
506 | } | 309 | } |
507 | } \ No newline at end of file | 310 | } \ No newline at end of file |