diff options
author | 2023-05-01 02:07:23 +0200 | |
---|---|---|
committer | 2023-05-01 02:42:34 +0200 | |
commit | 4e698774925468062974b990143c1091e23ed63b (patch) | |
tree | 21f2fc38b6b3b5f3be6ecbdee100d385a2e92c05 /subprojects/store-query-viatra/src/main | |
parent | fix(web): editor cursor styling (diff) | |
download | refinery-4e698774925468062974b990143c1091e23ed63b.tar.gz refinery-4e698774925468062974b990143c1091e23ed63b.tar.zst refinery-4e698774925468062974b990143c1091e23ed63b.zip |
feat: query parameter binding validation
* Introduce parameter directions for constraints and DNF
* Introduce variable directions for literals
* Infer and check variable directions in DNF and topologically sort literals by
their input variables
Diffstat (limited to 'subprojects/store-query-viatra/src/main')
3 files changed, 67 insertions, 51 deletions
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java index cf96b7fd..211eacb4 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java | |||
@@ -9,7 +9,6 @@ import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContex | |||
9 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | 9 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; |
10 | import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication; | 10 | import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication; |
11 | import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey; | 11 | import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey; |
12 | import tools.refinery.store.query.term.DataSort; | ||
13 | import tools.refinery.store.query.viatra.internal.pquery.SymbolViewWrapper; | 12 | import tools.refinery.store.query.viatra.internal.pquery.SymbolViewWrapper; |
14 | import tools.refinery.store.query.view.AnySymbolView; | 13 | import tools.refinery.store.query.view.AnySymbolView; |
15 | 14 | ||
@@ -62,14 +61,14 @@ public class RelationalQueryMetaContext extends AbstractQueryMetaContext { | |||
62 | relationViewImplication.impliedIndices())); | 61 | relationViewImplication.impliedIndices())); |
63 | } | 62 | } |
64 | } | 63 | } |
65 | var sorts = symbolView.getSorts(); | 64 | var parameters = symbolView.getParameters(); |
66 | int arity = symbolView.arity(); | 65 | int arity = symbolView.arity(); |
67 | for (int i = 0; i < arity; i++) { | 66 | for (int i = 0; i < arity; i++) { |
68 | var sort = sorts.get(i); | 67 | var parameter = parameters.get(i); |
69 | if (sort instanceof DataSort<?> dataSort) { | 68 | var parameterType = parameter.tryGetType(); |
70 | var javaTransitiveInstancesKey = new JavaTransitiveInstancesKey(dataSort.type()); | 69 | if (parameterType.isPresent()) { |
71 | var javaImplication = new InputKeyImplication(implyingKey, javaTransitiveInstancesKey, | 70 | var javaTransitiveInstancesKey = new JavaTransitiveInstancesKey(parameterType.get()); |
72 | List.of(i)); | 71 | var javaImplication = new InputKeyImplication(implyingKey, javaTransitiveInstancesKey, List.of(i)); |
73 | inputKeyImplications.add(javaImplication); | 72 | inputKeyImplications.add(javaImplication); |
74 | } | 73 | } |
75 | } | 74 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java index b511a5c7..ec880435 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java | |||
@@ -19,11 +19,13 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.Consta | |||
19 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | 19 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; |
20 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; | 20 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; |
21 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 21 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
22 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameterDirection; | ||
22 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; | 23 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; |
23 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | 24 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; |
24 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 25 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
25 | import tools.refinery.store.query.dnf.Dnf; | 26 | import tools.refinery.store.query.dnf.Dnf; |
26 | import tools.refinery.store.query.dnf.DnfClause; | 27 | import tools.refinery.store.query.dnf.DnfClause; |
28 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
27 | import tools.refinery.store.query.literal.*; | 29 | import tools.refinery.store.query.literal.*; |
28 | import tools.refinery.store.query.term.ConstantTerm; | 30 | import tools.refinery.store.query.term.ConstantTerm; |
29 | import tools.refinery.store.query.term.StatefulAggregator; | 31 | import tools.refinery.store.query.term.StatefulAggregator; |
@@ -82,15 +84,20 @@ public class Dnf2PQuery { | |||
82 | var pQuery = new RawPQuery(dnfQuery.getUniqueName()); | 84 | var pQuery = new RawPQuery(dnfQuery.getUniqueName()); |
83 | pQuery.setEvaluationHints(consumeHint(dnfQuery)); | 85 | pQuery.setEvaluationHints(consumeHint(dnfQuery)); |
84 | 86 | ||
85 | Map<Variable, PParameter> parameters = new HashMap<>(); | 87 | Map<SymbolicParameter, PParameter> parameters = new HashMap<>(); |
86 | for (Variable variable : dnfQuery.getParameters()) { | ||
87 | parameters.put(variable, new PParameter(variable.getUniqueName())); | ||
88 | } | ||
89 | |||
90 | List<PParameter> parameterList = new ArrayList<>(); | 88 | List<PParameter> parameterList = new ArrayList<>(); |
91 | for (var param : dnfQuery.getParameters()) { | 89 | for (var parameter : dnfQuery.getSymbolicParameters()) { |
92 | parameterList.add(parameters.get(param)); | 90 | var direction = switch (parameter.getDirection()) { |
91 | case IN_OUT -> PParameterDirection.INOUT; | ||
92 | case OUT -> PParameterDirection.OUT; | ||
93 | case IN -> throw new IllegalArgumentException("Query %s with input parameter %s is not supported" | ||
94 | .formatted(dnfQuery, parameter.getVariable())); | ||
95 | }; | ||
96 | var pParameter = new PParameter(parameter.getVariable().getUniqueName(), null, null, direction); | ||
97 | parameters.put(parameter, pParameter); | ||
98 | parameterList.add(pParameter); | ||
93 | } | 99 | } |
100 | |||
94 | pQuery.setParameters(parameterList); | 101 | pQuery.setParameters(parameterList); |
95 | 102 | ||
96 | for (var functionalDependency : dnfQuery.getFunctionalDependencies()) { | 103 | for (var functionalDependency : dnfQuery.getFunctionalDependencies()) { |
@@ -110,15 +117,15 @@ public class Dnf2PQuery { | |||
110 | synchronized (P_CONSTRAINT_LOCK) { | 117 | synchronized (P_CONSTRAINT_LOCK) { |
111 | for (DnfClause clause : dnfQuery.getClauses()) { | 118 | for (DnfClause clause : dnfQuery.getClauses()) { |
112 | PBody body = new PBody(pQuery); | 119 | PBody body = new PBody(pQuery); |
113 | List<ExportedParameter> symbolicParameters = new ArrayList<>(); | 120 | List<ExportedParameter> parameterExports = new ArrayList<>(); |
114 | for (var param : dnfQuery.getParameters()) { | 121 | for (var parameter : dnfQuery.getSymbolicParameters()) { |
115 | PVariable pVar = body.getOrCreateVariableByName(param.getUniqueName()); | 122 | PVariable pVar = body.getOrCreateVariableByName(parameter.getVariable().getUniqueName()); |
116 | symbolicParameters.add(new ExportedParameter(body, pVar, parameters.get(param))); | 123 | parameterExports.add(new ExportedParameter(body, pVar, parameters.get(parameter))); |
117 | } | 124 | } |
118 | body.setSymbolicParameters(symbolicParameters); | 125 | body.setSymbolicParameters(parameterExports); |
119 | pQuery.addBody(body); | 126 | pQuery.addBody(body); |
120 | for (Literal literal : clause.literals()) { | 127 | for (Literal literal : clause.literals()) { |
121 | translateLiteral(literal, clause, body); | 128 | translateLiteral(literal, body); |
122 | } | 129 | } |
123 | } | 130 | } |
124 | } | 131 | } |
@@ -126,11 +133,11 @@ public class Dnf2PQuery { | |||
126 | return pQuery; | 133 | return pQuery; |
127 | } | 134 | } |
128 | 135 | ||
129 | private void translateLiteral(Literal literal, DnfClause clause, PBody body) { | 136 | private void translateLiteral(Literal literal, PBody body) { |
130 | if (literal instanceof EquivalenceLiteral equivalenceLiteral) { | 137 | if (literal instanceof EquivalenceLiteral equivalenceLiteral) { |
131 | translateEquivalenceLiteral(equivalenceLiteral, body); | 138 | translateEquivalenceLiteral(equivalenceLiteral, body); |
132 | } else if (literal instanceof CallLiteral callLiteral) { | 139 | } else if (literal instanceof CallLiteral callLiteral) { |
133 | translateCallLiteral(callLiteral, clause, body); | 140 | translateCallLiteral(callLiteral, body); |
134 | } else if (literal instanceof ConstantLiteral constantLiteral) { | 141 | } else if (literal instanceof ConstantLiteral constantLiteral) { |
135 | translateConstantLiteral(constantLiteral, body); | 142 | translateConstantLiteral(constantLiteral, body); |
136 | } else if (literal instanceof AssignLiteral<?> assignLiteral) { | 143 | } else if (literal instanceof AssignLiteral<?> assignLiteral) { |
@@ -138,25 +145,25 @@ public class Dnf2PQuery { | |||
138 | } else if (literal instanceof AssumeLiteral assumeLiteral) { | 145 | } else if (literal instanceof AssumeLiteral assumeLiteral) { |
139 | translateAssumeLiteral(assumeLiteral, body); | 146 | translateAssumeLiteral(assumeLiteral, body); |
140 | } else if (literal instanceof CountLiteral countLiteral) { | 147 | } else if (literal instanceof CountLiteral countLiteral) { |
141 | translateCountLiteral(countLiteral, clause, body); | 148 | translateCountLiteral(countLiteral, body); |
142 | } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) { | 149 | } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) { |
143 | translateAggregationLiteral(aggregationLiteral, clause, body); | 150 | translateAggregationLiteral(aggregationLiteral, body); |
144 | } else { | 151 | } else { |
145 | throw new IllegalArgumentException("Unknown literal: " + literal.toString()); | 152 | throw new IllegalArgumentException("Unknown literal: " + literal.toString()); |
146 | } | 153 | } |
147 | } | 154 | } |
148 | 155 | ||
149 | private void translateEquivalenceLiteral(EquivalenceLiteral equivalenceLiteral, PBody body) { | 156 | private void translateEquivalenceLiteral(EquivalenceLiteral equivalenceLiteral, PBody body) { |
150 | PVariable varSource = body.getOrCreateVariableByName(equivalenceLiteral.left().getUniqueName()); | 157 | PVariable varSource = body.getOrCreateVariableByName(equivalenceLiteral.getLeft().getUniqueName()); |
151 | PVariable varTarget = body.getOrCreateVariableByName(equivalenceLiteral.right().getUniqueName()); | 158 | PVariable varTarget = body.getOrCreateVariableByName(equivalenceLiteral.getRight().getUniqueName()); |
152 | if (equivalenceLiteral.positive()) { | 159 | if (equivalenceLiteral.isPositive()) { |
153 | new Equality(body, varSource, varTarget); | 160 | new Equality(body, varSource, varTarget); |
154 | } else { | 161 | } else { |
155 | new Inequality(body, varSource, varTarget); | 162 | new Inequality(body, varSource, varTarget); |
156 | } | 163 | } |
157 | } | 164 | } |
158 | 165 | ||
159 | private void translateCallLiteral(CallLiteral callLiteral, DnfClause clause, PBody body) { | 166 | private void translateCallLiteral(CallLiteral callLiteral, PBody body) { |
160 | var polarity = callLiteral.getPolarity(); | 167 | var polarity = callLiteral.getPolarity(); |
161 | switch (polarity) { | 168 | switch (polarity) { |
162 | case POSITIVE -> { | 169 | case POSITIVE -> { |
@@ -186,7 +193,7 @@ public class Dnf2PQuery { | |||
186 | new BinaryTransitiveClosure(body, substitution, pattern); | 193 | new BinaryTransitiveClosure(body, substitution, pattern); |
187 | } | 194 | } |
188 | case NEGATIVE -> { | 195 | case NEGATIVE -> { |
189 | var wrappedCall = wrapperFactory.maybeWrapConstraint(callLiteral, clause); | 196 | var wrappedCall = wrapperFactory.maybeWrapConstraint(callLiteral); |
190 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); | 197 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); |
191 | var pattern = wrappedCall.pattern(); | 198 | var pattern = wrappedCall.pattern(); |
192 | new NegativePatternCall(body, substitution, pattern); | 199 | new NegativePatternCall(body, substitution, pattern); |
@@ -206,13 +213,13 @@ public class Dnf2PQuery { | |||
206 | } | 213 | } |
207 | 214 | ||
208 | private void translateConstantLiteral(ConstantLiteral constantLiteral, PBody body) { | 215 | private void translateConstantLiteral(ConstantLiteral constantLiteral, PBody body) { |
209 | var variable = body.getOrCreateVariableByName(constantLiteral.variable().getUniqueName()); | 216 | var variable = body.getOrCreateVariableByName(constantLiteral.getVariable().getUniqueName()); |
210 | new ConstantValue(body, variable, constantLiteral.nodeId()); | 217 | new ConstantValue(body, variable, constantLiteral.getNodeId()); |
211 | } | 218 | } |
212 | 219 | ||
213 | private <T> void translateAssignLiteral(AssignLiteral<T> assignLiteral, PBody body) { | 220 | private <T> void translateAssignLiteral(AssignLiteral<T> assignLiteral, PBody body) { |
214 | var variable = body.getOrCreateVariableByName(assignLiteral.variable().getUniqueName()); | 221 | var variable = body.getOrCreateVariableByName(assignLiteral.getTargetVariable().getUniqueName()); |
215 | var term = assignLiteral.term(); | 222 | var term = assignLiteral.getTerm(); |
216 | if (term instanceof ConstantTerm<T> constantTerm) { | 223 | if (term instanceof ConstantTerm<T> constantTerm) { |
217 | new ConstantValue(body, variable, constantTerm.getValue()); | 224 | new ConstantValue(body, variable, constantTerm.getValue()); |
218 | } else { | 225 | } else { |
@@ -222,19 +229,18 @@ public class Dnf2PQuery { | |||
222 | } | 229 | } |
223 | 230 | ||
224 | private void translateAssumeLiteral(AssumeLiteral assumeLiteral, PBody body) { | 231 | private void translateAssumeLiteral(AssumeLiteral assumeLiteral, PBody body) { |
225 | var evaluator = new AssumptionEvaluator(assumeLiteral.term()); | 232 | var evaluator = new AssumptionEvaluator(assumeLiteral.getTerm()); |
226 | new ExpressionEvaluation(body, evaluator, null); | 233 | new ExpressionEvaluation(body, evaluator, null); |
227 | } | 234 | } |
228 | 235 | ||
229 | private void translateCountLiteral(CountLiteral countLiteral, DnfClause clause, PBody body) { | 236 | private void translateCountLiteral(CountLiteral countLiteral, PBody body) { |
230 | var wrappedCall = wrapperFactory.maybeWrapConstraint(countLiteral, clause); | 237 | var wrappedCall = wrapperFactory.maybeWrapConstraint(countLiteral); |
231 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); | 238 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); |
232 | var resultVariable = body.getOrCreateVariableByName(countLiteral.getResultVariable().getUniqueName()); | 239 | var resultVariable = body.getOrCreateVariableByName(countLiteral.getResultVariable().getUniqueName()); |
233 | new PatternMatchCounter(body, substitution, wrappedCall.pattern(), resultVariable); | 240 | new PatternMatchCounter(body, substitution, wrappedCall.pattern(), resultVariable); |
234 | } | 241 | } |
235 | 242 | ||
236 | private <R, T> void translateAggregationLiteral(AggregationLiteral<R, T> aggregationLiteral, DnfClause clause, | 243 | private <R, T> void translateAggregationLiteral(AggregationLiteral<R, T> aggregationLiteral, PBody body) { |
237 | PBody body) { | ||
238 | var aggregator = aggregationLiteral.getAggregator(); | 244 | var aggregator = aggregationLiteral.getAggregator(); |
239 | IMultisetAggregationOperator<T, ?, R> aggregationOperator; | 245 | IMultisetAggregationOperator<T, ?, R> aggregationOperator; |
240 | if (aggregator instanceof StatelessAggregator<R, T> statelessAggregator) { | 246 | if (aggregator instanceof StatelessAggregator<R, T> statelessAggregator) { |
@@ -244,7 +250,7 @@ public class Dnf2PQuery { | |||
244 | } else { | 250 | } else { |
245 | throw new IllegalArgumentException("Unknown aggregator: " + aggregator); | 251 | throw new IllegalArgumentException("Unknown aggregator: " + aggregator); |
246 | } | 252 | } |
247 | var wrappedCall = wrapperFactory.maybeWrapConstraint(aggregationLiteral, clause); | 253 | var wrappedCall = wrapperFactory.maybeWrapConstraint(aggregationLiteral); |
248 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); | 254 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); |
249 | var inputVariable = body.getOrCreateVariableByName(aggregationLiteral.getInputVariable().getUniqueName()); | 255 | var inputVariable = body.getOrCreateVariableByName(aggregationLiteral.getInputVariable().getUniqueName()); |
250 | var aggregatedColumn = substitution.invertIndex().get(inputVariable); | 256 | var aggregatedColumn = substitution.invertIndex().get(inputVariable); |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java index 0d046455..2b7280f2 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java | |||
@@ -14,12 +14,13 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeCo | |||
14 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 14 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
15 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; | 15 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; |
16 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; | 16 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; |
17 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | ||
17 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 18 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
18 | import tools.refinery.store.query.Constraint; | 19 | import tools.refinery.store.query.Constraint; |
19 | import tools.refinery.store.query.dnf.Dnf; | 20 | import tools.refinery.store.query.dnf.Dnf; |
20 | import tools.refinery.store.query.dnf.DnfClause; | ||
21 | import tools.refinery.store.query.dnf.DnfUtils; | 21 | import tools.refinery.store.query.dnf.DnfUtils; |
22 | import tools.refinery.store.query.literal.AbstractCallLiteral; | 22 | import tools.refinery.store.query.literal.AbstractCallLiteral; |
23 | import tools.refinery.store.query.term.ParameterDirection; | ||
23 | import tools.refinery.store.query.term.Variable; | 24 | import tools.refinery.store.query.term.Variable; |
24 | import tools.refinery.store.query.view.AnySymbolView; | 25 | import tools.refinery.store.query.view.AnySymbolView; |
25 | import tools.refinery.store.query.view.SymbolView; | 26 | import tools.refinery.store.query.view.SymbolView; |
@@ -45,21 +46,17 @@ class QueryWrapperFactory { | |||
45 | } | 46 | } |
46 | return maybeWrapConstraint(symbolView, identity); | 47 | return maybeWrapConstraint(symbolView, identity); |
47 | } | 48 | } |
48 | public WrappedCall maybeWrapConstraint(AbstractCallLiteral callLiteral, DnfClause clause) { | 49 | |
50 | public WrappedCall maybeWrapConstraint(AbstractCallLiteral callLiteral) { | ||
49 | var arguments = callLiteral.getArguments(); | 51 | var arguments = callLiteral.getArguments(); |
50 | int arity = arguments.size(); | 52 | int arity = arguments.size(); |
51 | var remappedParameters = new int[arity]; | 53 | var remappedParameters = new int[arity]; |
52 | var boundVariables = clause.boundVariables(); | ||
53 | var unboundVariableIndices = new HashMap<Variable, Integer>(); | 54 | var unboundVariableIndices = new HashMap<Variable, Integer>(); |
54 | var appendVariable = new VariableAppender(); | 55 | var appendVariable = new VariableAppender(); |
55 | for (int i = 0; i < arity; i++) { | 56 | for (int i = 0; i < arity; i++) { |
56 | var variable = arguments.get(i); | 57 | var variable = arguments.get(i); |
57 | if (boundVariables.contains(variable)) { | 58 | // Unify all variables to avoid VIATRA bugs, even if they're bound in the containing clause. |
58 | // Do not join bound variable to make sure that the embedded pattern stays as general as possible. | 59 | remappedParameters[i] = unboundVariableIndices.computeIfAbsent(variable, appendVariable::applyAsInt); |
59 | remappedParameters[i] = appendVariable.applyAsInt(variable); | ||
60 | } else { | ||
61 | remappedParameters[i] = unboundVariableIndices.computeIfAbsent(variable, appendVariable::applyAsInt); | ||
62 | } | ||
63 | } | 60 | } |
64 | var pattern = maybeWrapConstraint(callLiteral.getTarget(), remappedParameters); | 61 | var pattern = maybeWrapConstraint(callLiteral.getTarget(), remappedParameters); |
65 | return new WrappedCall(pattern, appendVariable.getRemappedArguments()); | 62 | return new WrappedCall(pattern, appendVariable.getRemappedArguments()); |
@@ -89,6 +86,8 @@ class QueryWrapperFactory { | |||
89 | var constraint = remappedConstraint.constraint(); | 86 | var constraint = remappedConstraint.constraint(); |
90 | var remappedParameters = remappedConstraint.remappedParameters(); | 87 | var remappedParameters = remappedConstraint.remappedParameters(); |
91 | 88 | ||
89 | checkNoInputParameters(constraint); | ||
90 | |||
92 | var embeddedPQuery = new RawPQuery(DnfUtils.generateUniqueName(constraint.name()), PVisibility.EMBEDDED); | 91 | var embeddedPQuery = new RawPQuery(DnfUtils.generateUniqueName(constraint.name()), PVisibility.EMBEDDED); |
93 | var body = new PBody(embeddedPQuery); | 92 | var body = new PBody(embeddedPQuery); |
94 | int arity = Arrays.stream(remappedParameters).max().orElse(-1) + 1; | 93 | int arity = Arrays.stream(remappedParameters).max().orElse(-1) + 1; |
@@ -112,6 +111,21 @@ class QueryWrapperFactory { | |||
112 | } | 111 | } |
113 | var argumentTuple = Tuples.flatTupleOf(arguments); | 112 | var argumentTuple = Tuples.flatTupleOf(arguments); |
114 | 113 | ||
114 | addPositiveConstraint(constraint, body, argumentTuple); | ||
115 | embeddedPQuery.addBody(body); | ||
116 | return embeddedPQuery; | ||
117 | } | ||
118 | |||
119 | private static void checkNoInputParameters(Constraint constraint) { | ||
120 | for (var constraintParameter : constraint.getParameters()) { | ||
121 | if (constraintParameter.getDirection() == ParameterDirection.IN) { | ||
122 | throw new IllegalArgumentException("Input parameter %s of %s is not supported" | ||
123 | .formatted(constraintParameter, constraint)); | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | private void addPositiveConstraint(Constraint constraint, PBody body, Tuple argumentTuple) { | ||
115 | if (constraint instanceof SymbolView<?> view) { | 129 | if (constraint instanceof SymbolView<?> view) { |
116 | new TypeConstraint(body, argumentTuple, getInputKey(view)); | 130 | new TypeConstraint(body, argumentTuple, getInputKey(view)); |
117 | } else if (constraint instanceof Dnf dnf) { | 131 | } else if (constraint instanceof Dnf dnf) { |
@@ -120,9 +134,6 @@ class QueryWrapperFactory { | |||
120 | } else { | 134 | } else { |
121 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); | 135 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); |
122 | } | 136 | } |
123 | |||
124 | embeddedPQuery.addBody(body); | ||
125 | return embeddedPQuery; | ||
126 | } | 137 | } |
127 | 138 | ||
128 | public IInputKey getInputKey(AnySymbolView symbolView) { | 139 | public IInputKey getInputKey(AnySymbolView symbolView) { |