Copilot commented on code in PR #7160:
URL: https://github.com/apache/incubator-kie/pull/7160#discussion_r4167963447


##########
drools-base/src/main/java/org/drools/base/reteoo/sequencing/signalprocessors/LogicGate.java:
##########
@@ -97,19 +118,24 @@ public void resetPrior(SequenceMemory memory, 
ValueResolver valueResolver) {
             gate.reset(memory, valueResolver);
         }
 
-        memory.resetLogicGateMemory(gateIndex, valueResolver);
+        if (!statusCanRevert) {
+            memory.resetLogicGateMemory(gateIndex, valueResolver);
+        }
     }
 
     public void reset(SequenceMemory memory, ValueResolver valueResolver) {
         resetPrior(memory, valueResolver);
         output.reset(memory, valueResolver);
     }
 
-    public void activate(SequenceMemory memory) {
+    public void activate(SequenceMemory memory, ValueResolver valueResolver) {
         for (int i = 0; i < filterIndexes.length; i++) {
             memory.activateSignalAdapter(filterIndexes[i], this, 
signalAdapterIndexes[i], i + 1); // bit indexes start at 1
         }
-
+        if (predicate.test(0L, allMatched)) {

Review Comment:
   Activation evaluates the gate as if no child had matched, but child gates 
are activated before their parents and zero-state gates can already signal the 
parent. For example, in `xnor(xnor(a, b), c)` the inner XNOR sets one outer 
input bit; the outer activation still evaluates `0` and incorrectly propagates 
a match. Evaluate the gate's actual memory so nested XNOR state is respected.



##########
drools-base/src/main/java/org/drools/base/reteoo/sequencing/signalprocessors/LogicGateOutputSignalProcessor.java:
##########
@@ -46,4 +46,10 @@ protected void reset(SequenceMemory memory, ValueResolver 
valueResolver) {
         // by each downstream LogicGate resetting itself via resetPrior(). 
There is no
         // state held here that needs clearing.
     }
+
+    public void clearParentBit(SequenceMemory memory) {
+        long[] gateMemory = memory.getLogicGateMemory();
+        gateMemory[gate.getGateIndex()] = gateMemory[gate.getGateIndex()] & 
~(1L << (index - 1));
+        memory.setLogicGateMatched(gate.getGateIndex(), false);

Review Comment:
   This clears only the immediate parent's state. If that parent already 
propagated to a grandparent, the grandparent retains a stale match bit. For 
example, with `and(and(xor(a, b), c), d)`, matching `a` and `c`, then matching 
`b` reverts the XOR but leaves the outer AND's inner-AND bit set, so `d` 
incorrectly completes the step. Reversion needs to re-evaluate the parent and 
propagate the transition recursively through the circuit.



##########
drools-model/drools-canonical-model/src/main/java/org/drools/model/DSL.java:
##########
@@ -555,7 +555,7 @@ public static FixedValueItem expr( String exprId, boolean 
value ) {
 
     // -- Existential operator --
 
-    public static ExprViewItem not( ViewItemBuilder<?> expression, 
ViewItemBuilder<?>... expressions) {
+    public static ExistentialExprViewItem not( ViewItemBuilder<?> expression, 
ViewItemBuilder<?>... expressions) {

Review Comment:
   Changing this public static method's return type changes its JVM descriptor, 
so clients compiled against the previous `ExprViewItem not(...)` signature will 
fail with `NoSuchMethodError` even though source recompilation succeeds. 
Preserve the existing descriptor and expose sequence-step typing through a 
binary-compatible API design.



##########
drools-model/drools-canonical-model/src/main/java/org/drools/model/impl/ViewPatternBuilder.java:
##########
@@ -194,6 +221,50 @@ public static Condition ruleItem2Condition(RuleItem 
ruleItem) {
         throw new UnsupportedOperationException( "Unknown " + ruleItem );
     }
 
+    /**
+     * Rewrites bare xor()/xnor() steps in a sequence by folding each such step
+     * with the immediately following positive step into an and(xor(...), 
next) pair.
+     * <p>
+     * {@code sequence(xor(a, b), c)} is legal sugar for {@code 
sequence(and(xor(a, b), c))}.
+     * The trailing-XOR check in the caller will catch {@code sequence(xor(a, 
b))} (no following step).
+     */
+    private static org.drools.model.SequenceStep[] 
rewriteXorSteps(org.drools.model.SequenceStep[] steps) {
+        boolean hasXor = false;
+        for (int i = 0; i < steps.length; i++) {
+            org.drools.model.SequenceStep step = steps[i];
+            if (step instanceof CombinedExprViewItem) {
+                Condition.Type t = ((CombinedExprViewItem) step).getType();
+                if ((t == Condition.Type.XOR || t == Condition.Type.XNOR) && i 
+ 1 < steps.length) {
+                    hasXor = true;
+                    break;
+                }
+            }
+        }
+        if (!hasXor) {
+            return steps;
+        }
+        List<org.drools.model.SequenceStep> result = new ArrayList<>();
+        for (int i = 0; i < steps.length; i++) {
+            org.drools.model.SequenceStep step = steps[i];
+            if (step instanceof CombinedExprViewItem) {
+                Condition.Type t = ((CombinedExprViewItem) step).getType();
+                if ((t == Condition.Type.XOR || t == Condition.Type.XNOR) && i 
+ 1 < steps.length) {
+                    // Wrap: and(xor/xnor(...), nextStep)
+                    CombinedExprViewItem wrapped = new CombinedExprViewItem(
+                            Condition.Type.AND,
+                            new ViewItem[]{(ViewItem) step, (ViewItem) steps[i 
+ 1]});
+                    result.add(wrapped);
+                    i++; // consume the following step

Review Comment:
   The rewrite consumes any following step, not necessarily the required 
positive step. Thus `sequence(xor(a,b), xor(c,d), e)` becomes 
`sequence(and(xor(a,b), xor(c,d)), e)`: the second XOR is no longer folded with 
`e`, and the first step can advance before `e`. Validate the next step as 
positive or normalize chained absence/reverting gates without consuming their 
intended trigger.



##########
drools-model/drools-canonical-model/src/main/java/org/drools/model/impl/ViewPatternBuilder.java:
##########
@@ -185,7 +185,34 @@ public static Condition ruleItem2Condition(RuleItem 
ruleItem) {
 
         if (ruleItem instanceof SequenceViewItem) {
             SequenceViewItem sv = (SequenceViewItem) ruleItem;
-            List<Condition> steps = Arrays.stream(sv.getSteps())
+            org.drools.model.SequenceStep[] rawSteps = 
rewriteXorSteps(sv.getSteps());
+            if (rawSteps.length > 0) {
+                org.drools.model.SequenceStep last = rawSteps[rawSteps.length 
- 1];
+                if (last instanceof ExistentialExprViewItem) {
+                    ExistentialExprViewItem ex = (ExistentialExprViewItem) 
last;
+                    if (ex.getType() == Condition.Type.NOT) {
+                        throw new IllegalArgumentException(
+                            "sequence(): trailing not() or nor() requires a 
following positive step " +
+                            "or a completeWithin(...) deadline. " +
+                            "Trailing absence with completeWithin is planned 
but not yet implemented. " +
+                            "See ADR 0002.");
+                    }
+                }
+                if (last instanceof CombinedExprViewItem) {
+                    CombinedExprViewItem comb = (CombinedExprViewItem) last;
+                    if (comb.getType() == Condition.Type.NOT
+                            || comb.getType() == Condition.Type.NOR
+                            || comb.getType() == Condition.Type.XOR
+                            || comb.getType() == Condition.Type.XNOR) {

Review Comment:
   The trailing-gate guard only checks the outer node, so wrapping a reverting 
gate bypasses it. `sequence(and(xor(a, b)))` is accepted, then terminates as 
soon as the first child matches; the second child can never revert it, 
defeating the exactly-one-before-a-positive-trigger contract. Validate the 
effective condition tree and require a genuine positive trigger rather than 
relying on the top-level type.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to