This is an automated email from the ASF dual-hosted git repository.

gitgabrio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git


The following commit(s) were added to refs/heads/main by this push:
     new 0805f07bb0 [incubator-kie-issues#83] Refactor InfixOpNode inside DMN 
core (#5621)
0805f07bb0 is described below

commit 0805f07bb0f3144c4652421d997a8284a736b210
Author: Gabriele Cardosi <[email protected]>
AuthorDate: Wed Dec 13 14:40:59 2023 +0100

    [incubator-kie-issues#83] Refactor InfixOpNode inside DMN core (#5621)
    
    * [incubator-kie-issues#83] WIP - Splitting structur and behaviour. Tests 
failing
    
    * [incubator-kie-issues#83] Working status. Same single test failing as in 
main
    
    * [incubator-kie-issues#83] Cleanup
    
    * [incubator-kie-issues#83] DivExecutor
    
    * [incubator-kie-issues#83] AddExecutor
    
    * [incubator-kie-issues#83] MultExecutor
    
    * [incubator-kie-issues#83] SubExecutor
    
    * [incubator-kie-issues#83] Fix DMNRuntimeListenerTest
    
    * [incubator-kie-issues#83] Fix as per PR review
    
    * [incubator-kie-issues#83] Remove duplicated code
    
    * [incubator-kie-issues#83] Renaming as per PR review
    
    ---------
    
    Co-authored-by: BAMOE CI <[email protected]>
---
 .../feel11/CompiledFEELSemanticMappings.java       |  51 ++-
 .../kie/dmn/feel/codegen/feel11/Expressions.java   |   7 +-
 .../org/kie/dmn/feel/lang/ast/BetweenNode.java     |  51 ++-
 .../org/kie/dmn/feel/lang/ast/InfixOpNode.java     | 427 ++-------------------
 .../org/kie/dmn/feel/lang/ast/InfixOperator.java   |  79 ++++
 .../feel/lang/ast/infixexecutors/AddExecutor.java  | 127 ++++++
 .../feel/lang/ast/infixexecutors/AndExecutor.java  |  58 +++
 .../ast/infixexecutors/ClassIdentifierTuple.java   |  56 +++
 .../feel/lang/ast/infixexecutors/DivExecutor.java  | 102 +++++
 .../feel/lang/ast/infixexecutors/EqExecutor.java   |  46 +++
 .../ast/infixexecutors/EvaluatedParameters.java    |  38 ++
 .../feel/lang/ast/infixexecutors/GtExecutor.java   |  46 +++
 .../feel/lang/ast/infixexecutors/GteExecutor.java  |  49 +++
 .../lang/ast/infixexecutors/InfixExecutor.java     |  30 ++
 .../ast/infixexecutors/InfixExecutorUtils.java     | 165 ++++++++
 .../feel/lang/ast/infixexecutors/LtExecutor.java   |  46 +++
 .../feel/lang/ast/infixexecutors/LteExecutor.java  |  50 +++
 .../feel/lang/ast/infixexecutors/MultExecutor.java |  91 +++++
 .../feel/lang/ast/infixexecutors/NeExecutor.java   |  47 +++
 .../feel/lang/ast/infixexecutors/OrExecutor.java   |  58 +++
 .../feel/lang/ast/infixexecutors/PowExecutor.java  |  50 +++
 .../feel/lang/ast/infixexecutors/SubExecutor.java  | 104 +++++
 .../org/kie/dmn/feel/lang/ast/InfixOpNodeTest.java | 196 ----------
 .../kie/dmn/feel/lang/ast/InfixOperatorTest.java   | 127 ++++++
 .../infixexecutors/ClassidentifierTupleTest.java   |  35 ++
 .../ast/infixexecutors/InfixExecutorUtilsTest.java | 101 +++++
 .../kie/dmn/feel/parser/feel11/FEELParserTest.java |  66 +---
 .../dmn/feel/runtime/FEELNumberCoercionTest.java   |   2 +-
 .../dmn/validation/dtanalysis/DMNDTAnalyser.java   |   2 +-
 29 files changed, 1610 insertions(+), 697 deletions(-)

diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSemanticMappings.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSemanticMappings.java
index 9768f448f9..78326a136f 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSemanticMappings.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/CompiledFEELSemanticMappings.java
@@ -18,18 +18,9 @@
  */
 package org.kie.dmn.feel.codegen.feel11;
 
-import java.math.MathContext;
-import java.time.Period;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Supplier;
-
-import ch.obermuhlner.math.big.BigDecimalMath;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.feel.lang.EvaluationContext;
-import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.lang.ast.InfixOperator;
 import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
 import org.kie.dmn.feel.runtime.Range;
 import org.kie.dmn.feel.runtime.UnaryTest;
@@ -39,6 +30,12 @@ import org.kie.dmn.feel.runtime.impl.RangeImpl;
 import org.kie.dmn.feel.util.EvalHelper;
 import org.kie.dmn.feel.util.Msg;
 
+import java.time.Period;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Supplier;
+
 /**
  * The purpose of this class is to offer import .* methods to compiled FEEL 
classes compiling expressions.
  * Implementing DMN FEEL spec chapter 10.3.2.12 Semantic mappings
@@ -265,12 +262,13 @@ public class CompiledFEELSemanticMappings {
 
     /**
      * FEEL spec Table 38
-     * Delegates to {@link InfixOpNode} except evaluationcontext
+     * Delegates to {@link InfixOperator} except evaluationcontext
+     *
      * @deprecated does not support short-circuit of the operator
      */
     @Deprecated
     public static Boolean and(Object left, Object right) {
-        return (Boolean) InfixOpNode.and(left, right, null);
+        return (Boolean) InfixOperator.AND.evaluate(left, right, null);
     }
 
     public static Boolean and(Boolean left, Supplier<Boolean> right) {
@@ -300,14 +298,15 @@ public class CompiledFEELSemanticMappings {
 
     /**
      * FEEL spec Table 38
-     * Delegates to {@link InfixOpNode} except evaluationcontext
+     * Delegates to {@link InfixOperator} except evaluationcontext
+     *
      * @deprecated does not support short-circuit of the operator
      */
     @Deprecated
     public static Boolean or(Object left, Object right) {
-        return (Boolean) InfixOpNode.or(left, right, null);
+        return (Boolean) InfixOperator.OR.evaluate(left, right, null);
     }
-    
+
     public static Boolean or(Boolean left, Supplier<Boolean> right) {
         if (left != null) {
             if (!left.booleanValue()) {
@@ -335,38 +334,38 @@ public class CompiledFEELSemanticMappings {
 
     /**
      * FEEL spec Table 45
-     * Delegates to {@link InfixOpNode} except evaluationcontext
+     * Delegates to {@link InfixOperator} except evaluationcontext
      */
     public static Object add(final Object left, final Object right, final 
EvaluationContext context) {
-        return InfixOpNode.add(left, right, context);
+        return InfixOperator.ADD.evaluate(left, right, context);
     }
 
     /**
      * FEEL spec Table 45
-     * Delegates to {@link InfixOpNode} except evaluationcontext
+     * Delegates to {@link InfixOperator} except evaluationcontext
      */
     public static Object sub(final Object left, final Object right, final 
EvaluationContext context) {
-        return InfixOpNode.sub(left, right, context);
+        return InfixOperator.SUB.evaluate(left, right, context);
     }
 
     /**
      * FEEL spec Table 45
-     * Delegates to {@link InfixOpNode} except evaluationcontext
+     * Delegates to {@link InfixOperator} except evaluationcontext
      */
     public static Object mult(final Object left, final Object right, final 
EvaluationContext context) {
-        return InfixOpNode.mult(left, right, context);
+        return InfixOperator.MULT.evaluate(left, right, context);
     }
 
     /**
      * FEEL spec Table 45
-     * Delegates to {@link InfixOpNode} except evaluationcontext
+     * Delegates to {@link InfixOperator} except evaluationcontext
      */
     public static Object div(final Object left, final Object right, final 
EvaluationContext context) {
-        return InfixOpNode.div(left, right, context);
+        return InfixOperator.DIV.evaluate(left, right, context);
     }
 
     public static Object pow(final Object left, final Object right, final 
EvaluationContext context) {
-        return InfixOpNode.math(left, right, context, (l, r) -> 
BigDecimalMath.pow(l, r, MathContext.DECIMAL128));
+        return InfixOperator.POW.evaluate(left, right, context);
     }
 
     /**
@@ -375,7 +374,7 @@ public class CompiledFEELSemanticMappings {
      */
     public static Boolean lte(Object left, Object right) {
         return or(lt(left, right),
-                  eq(left, right)); // do not use Java || to avoid potential 
NPE due to FEEL 3vl.
+                eq(left, right)); // do not use Java || to avoid potential NPE 
due to FEEL 3vl.
     }
 
     /**
@@ -392,7 +391,7 @@ public class CompiledFEELSemanticMappings {
      */
     public static Boolean gte(Object left, Object right) {
         return or(gt(left, right),
-                  eq(left, right)); // do not use Java || to avoid potential 
NPE due to FEEL 3vl.
+                eq(left, right)); // do not use Java || to avoid potential NPE 
due to FEEL 3vl.
     }
 
     /**
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/Expressions.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/Expressions.java
index 80d354626d..b2ae13201f 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/Expressions.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/codegen/feel11/Expressions.java
@@ -39,10 +39,7 @@ import com.github.javaparser.ast.stmt.ExpressionStmt;
 import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.ast.type.Type;
 import com.github.javaparser.ast.type.UnknownType;
-import org.kie.dmn.feel.lang.ast.InfixOpNode;
-import org.kie.dmn.feel.lang.ast.QuantifiedExpressionNode;
-import org.kie.dmn.feel.lang.ast.RangeNode;
-import org.kie.dmn.feel.lang.ast.UnaryTestNode;
+import org.kie.dmn.feel.lang.ast.*;
 import org.kie.dmn.feel.lang.impl.MapBackedType;
 import org.kie.dmn.feel.lang.impl.NamedParameter;
 import org.kie.dmn.feel.lang.types.GenFnType;
@@ -110,7 +107,7 @@ public class Expressions {
     }
 
     public static MethodCallExpr binary(
-            InfixOpNode.InfixOperator operator,
+            InfixOperator operator,
             Expression l,
             Expression r) {
         switch (operator) {
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/BetweenNode.java 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/BetweenNode.java
index feb773f595..383c107cb8 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/BetweenNode.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/BetweenNode.java
@@ -22,6 +22,7 @@ import org.antlr.v4.runtime.ParserRuleContext;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
 import org.kie.dmn.feel.lang.EvaluationContext;
 import org.kie.dmn.feel.lang.Type;
+import org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils;
 import org.kie.dmn.feel.lang.types.BuiltInType;
 import org.kie.dmn.feel.util.EvalHelper;
 import org.kie.dmn.feel.util.Msg;
@@ -34,7 +35,7 @@ public class BetweenNode
     private BaseNode end;
 
     public BetweenNode(ParserRuleContext ctx, BaseNode value, BaseNode start, 
BaseNode end) {
-        super( ctx );
+        super(ctx);
         this.value = value;
         this.start = start;
         this.end = end;
@@ -67,34 +68,52 @@ public class BetweenNode
     @Override
     public Object evaluate(EvaluationContext ctx) {
         boolean problem = false;
-        if ( value == null ) { ctx.notifyEvt( astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "value")) ); problem = true; }
-        if ( start == null ) { ctx.notifyEvt( astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "start")) ); problem = true; }
-        if ( end == null )   { ctx.notifyEvt( astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "end")) ); problem = true; }
+        if (value == null) {
+            ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "value")));
+            problem = true;
+        }
+        if (start == null) {
+            ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "start")));
+            problem = true;
+        }
+        if (end == null) {
+            ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "end")));
+            problem = true;
+        }
         if (problem) return null;
 
         Object o_val = value.evaluate(ctx);
         Object o_s = start.evaluate(ctx);
         Object o_e = end.evaluate(ctx);
-        if ( o_val == null ) { ctx.notifyEvt( astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "value")) ); problem = true; }
-        if ( o_s == null ) { ctx.notifyEvt( astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "start")) ); problem = true; }
-        if ( o_e == null )   { ctx.notifyEvt( astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "end")) ); problem = true; }
+        if (o_val == null) {
+            ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "value")));
+            problem = true;
+        }
+        if (o_s == null) {
+            ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "start")));
+            problem = true;
+        }
+        if (o_e == null) {
+            ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.IS_NULL, "end")));
+            problem = true;
+        }
         if (problem) return null;
 
-        Object gte = InfixOpNode.or(EvalHelper.compare(o_val, o_s, ctx, (l, r) 
-> l.compareTo(r) > 0),
-                                   EvalHelper.isEqual(o_val, o_s, ctx),
-                                   ctx); // do not use Java || to avoid 
potential NPE due to FEEL 3vl.
+        Object gte = InfixExecutorUtils.or(EvalHelper.compare(o_val, o_s, ctx, 
(l, r) -> l.compareTo(r) > 0),
+                EvalHelper.isEqual(o_val, o_s, ctx),
+                ctx); // do not use Java || to avoid potential NPE due to FEEL 
3vl.
         if (gte == null) {
             ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.X_TYPE_INCOMPATIBLE_WITH_Y_TYPE, "value", "start")));
         }
 
-        Object lte = InfixOpNode.or(EvalHelper.compare(o_val, o_e, ctx, (l, r) 
-> l.compareTo(r) < 0),
-                                    EvalHelper.isEqual(o_val, o_e, ctx),
-                                    ctx); // do not use Java || to avoid 
potential NPE due to FEEL 3vl.
+        Object lte = InfixExecutorUtils.or(EvalHelper.compare(o_val, o_e, ctx, 
(l, r) -> l.compareTo(r) < 0),
+                EvalHelper.isEqual(o_val, o_e, ctx),
+                ctx); // do not use Java || to avoid potential NPE due to FEEL 
3vl.
         if (lte == null) {
             ctx.notifyEvt(astEvent(Severity.ERROR, 
Msg.createMessage(Msg.X_TYPE_INCOMPATIBLE_WITH_Y_TYPE, "value", "end")));
         }
-        
-        return InfixOpNode.and(gte, lte, ctx); // do not use Java && to avoid 
potential NPE due to FEEL 3vl.
+
+        return InfixExecutorUtils.and(gte, lte, ctx); // do not use Java && to 
avoid potential NPE due to FEEL 3vl.
     }
 
     @Override
@@ -104,7 +123,7 @@ public class BetweenNode
 
     @Override
     public ASTNode[] getChildrenNode() {
-        return new ASTNode[] { value, start, end };
+        return new ASTNode[]{value, start, end};
     }
 
     @Override
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/InfixOpNode.java 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/InfixOpNode.java
index 5c4cc05df7..6932289271 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/InfixOpNode.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/InfixOpNode.java
@@ -18,80 +18,22 @@
  */
 package org.kie.dmn.feel.lang.ast;
 
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.math.RoundingMode;
-import java.time.Duration;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.OffsetDateTime;
-import java.time.OffsetTime;
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-import java.time.chrono.ChronoPeriod;
-import java.time.temporal.ChronoUnit;
-import java.time.temporal.Temporal;
-import java.time.temporal.TemporalAmount;
-import java.util.function.BinaryOperator;
-
-import ch.obermuhlner.math.big.BigDecimalMath;
 import org.antlr.v4.runtime.ParserRuleContext;
-import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.feel.lang.EvaluationContext;
 import org.kie.dmn.feel.lang.Type;
 import org.kie.dmn.feel.lang.types.BuiltInType;
-import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
-import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
-import org.kie.dmn.feel.util.EvalHelper;
-import org.kie.dmn.feel.util.Msg;
 
 public class InfixOpNode
         extends BaseNode {
 
-    public static enum InfixOperator {
-        ADD( "+" ),
-        SUB( "-" ),
-        MULT( "*" ),
-        DIV( "/" ),
-        POW( "**" ),
-        LTE( "<=" ),
-        LT( "<" ),
-        GT( ">" ),
-        GTE( ">=" ),
-        EQ( "=" ),
-        NE( "!=" ),
-        AND( "and" ),
-        OR( "or" );
-
-        public final String symbol;
-
-        InfixOperator(String symbol) {
-            this.symbol = symbol;
-        }
-
-        public static InfixOperator determineOperator(String symbol) {
-            for ( InfixOperator op : InfixOperator.values() ) {
-                if ( op.symbol.equals( symbol ) ) {
-                    return op;
-                }
-            }
-            throw new IllegalArgumentException( "No operator found for symbol 
'" + symbol + "'" );
-        }
-
-        public boolean isBoolean() {
-            return this == LTE || this == LT || this == GT || this == GTE || 
this == EQ || this == NE || this == AND || this == OR;
-        }
-    }
-
     private InfixOperator operator;
-    private BaseNode      left;
-    private BaseNode      right;
+    private BaseNode left;
+    private BaseNode right;
 
     public InfixOpNode(ParserRuleContext ctx, BaseNode left, String op, 
BaseNode right) {
-        super( ctx );
+        super(ctx);
         this.left = left;
-        this.operator = InfixOperator.determineOperator( op );
+        this.operator = InfixOperator.determineOperator(op);
         this.right = right;
     }
 
@@ -126,40 +68,42 @@ public class InfixOpNode
     @Override
     public Type getResultType() {
         // see FEEL spec Table 45.
-        if ( operator.isBoolean() ) { return BuiltInType.BOOLEAN; }
-        switch ( operator ) {
+        if (operator.isBoolean()) {
+            return BuiltInType.BOOLEAN;
+        }
+        switch (operator) {
             case ADD:
             case SUB: {
-                if ( left.getResultType() == BuiltInType.NUMBER && 
right.getResultType() == BuiltInType.NUMBER ) {
+                if (left.getResultType() == BuiltInType.NUMBER && 
right.getResultType() == BuiltInType.NUMBER) {
                     return BuiltInType.NUMBER;
-                } else if ( left.getResultType() == BuiltInType.DATE_TIME && 
right.getResultType() == BuiltInType.DATE_TIME ) {
+                } else if (left.getResultType() == BuiltInType.DATE_TIME && 
right.getResultType() == BuiltInType.DATE_TIME) {
                     return BuiltInType.DATE_TIME;
-                } else if ( left.getResultType() == BuiltInType.TIME && 
right.getResultType() == BuiltInType.TIME ) {
+                } else if (left.getResultType() == BuiltInType.TIME && 
right.getResultType() == BuiltInType.TIME) {
                     return BuiltInType.TIME;
-                } else if ( left.getResultType() == BuiltInType.DURATION || 
right.getResultType() == BuiltInType.DURATION ) {
-                    if ( left.getResultType() == BuiltInType.DATE_TIME || 
right.getResultType() == BuiltInType.DATE_TIME ) {
+                } else if (left.getResultType() == BuiltInType.DURATION || 
right.getResultType() == BuiltInType.DURATION) {
+                    if (left.getResultType() == BuiltInType.DATE_TIME || 
right.getResultType() == BuiltInType.DATE_TIME) {
                         return BuiltInType.DATE_TIME;
-                    } else if ( left.getResultType() == BuiltInType.TIME || 
right.getResultType() == BuiltInType.TIME ) {
+                    } else if (left.getResultType() == BuiltInType.TIME || 
right.getResultType() == BuiltInType.TIME) {
                         return BuiltInType.TIME;
-                    } else if ( left.getResultType() == BuiltInType.DURATION 
&& right.getResultType() == BuiltInType.DURATION ) {
+                    } else if (left.getResultType() == BuiltInType.DURATION && 
right.getResultType() == BuiltInType.DURATION) {
                         return BuiltInType.DURATION;
                     }
-                } else if ( left.getResultType() == BuiltInType.STRING && 
right.getResultType() == BuiltInType.STRING ) {
+                } else if (left.getResultType() == BuiltInType.STRING && 
right.getResultType() == BuiltInType.STRING) {
                     return BuiltInType.STRING;
                 }
             }
             case MULT:
             case DIV: {
-                if ( left.getResultType() == BuiltInType.NUMBER && 
right.getResultType() == BuiltInType.NUMBER ) {
+                if (left.getResultType() == BuiltInType.NUMBER && 
right.getResultType() == BuiltInType.NUMBER) {
                     return BuiltInType.NUMBER;
-                } else if ( left.getResultType() == BuiltInType.DURATION || 
right.getResultType() == BuiltInType.DURATION ) {
-                    if ( left.getResultType() == BuiltInType.NUMBER || 
right.getResultType() == BuiltInType.NUMBER ) {
+                } else if (left.getResultType() == BuiltInType.DURATION || 
right.getResultType() == BuiltInType.DURATION) {
+                    if (left.getResultType() == BuiltInType.NUMBER || 
right.getResultType() == BuiltInType.NUMBER) {
                         return BuiltInType.NUMBER;
                     }
                 }
             }
             case POW: {
-                if ( left.getResultType() == BuiltInType.NUMBER && 
right.getResultType() == BuiltInType.NUMBER ) {
+                if (left.getResultType() == BuiltInType.NUMBER && 
right.getResultType() == BuiltInType.NUMBER) {
                     return BuiltInType.NUMBER;
                 }
             }
@@ -171,267 +115,12 @@ public class InfixOpNode
     @Override
     public Object evaluate(EvaluationContext ctx) {
         if (this.left == null) return null;
-        switch ( operator ) {
-            case ADD:
-                return add(this.left.evaluate(ctx), this.right.evaluate(ctx), 
ctx);
-            case SUB:
-                return sub(this.left.evaluate(ctx), this.right.evaluate(ctx), 
ctx);
-            case MULT:
-                return mult(this.left.evaluate(ctx), this.right.evaluate(ctx), 
ctx);
-            case DIV:
-                return div(this.left.evaluate(ctx), this.right.evaluate(ctx), 
ctx);
-            case POW:
-                return math(this.left.evaluate(ctx), this.right.evaluate(ctx), 
ctx, (l, r) -> BigDecimalMath.pow(l, r, MathContext.DECIMAL128));
-            case AND:
-                Boolean leftAND = 
EvalHelper.getBooleanOrNull(this.left.evaluate(ctx));
-                if (leftAND != null) {
-                    if (leftAND.booleanValue()) {
-                        return 
EvalHelper.getBooleanOrNull(this.right.evaluate(ctx));
-                    } else {
-                        return Boolean.FALSE; //left hand operand is false, we 
do not need to evaluate right side
-                    }
-                } else {
-                    Boolean rightAND = 
EvalHelper.getBooleanOrNull(this.right.evaluate(ctx));
-                    return Boolean.FALSE.equals(rightAND) ? Boolean.FALSE : 
null;
-                }
-            case OR:
-                Boolean leftOR = 
EvalHelper.getBooleanOrNull(this.left.evaluate(ctx));
-                if (leftOR != null) {
-                    if (!leftOR.booleanValue()) {
-                        return 
EvalHelper.getBooleanOrNull(this.right.evaluate(ctx));
-                    } else {
-                        return Boolean.TRUE; //left hand operand is true, we 
do not need to evaluate right side
-                    }
-                } else {
-                    Boolean rightOR = 
EvalHelper.getBooleanOrNull(this.right.evaluate(ctx));
-                    return Boolean.TRUE.equals(rightOR) ? Boolean.TRUE : null;
-                }
-            case LTE:
-                Object leftLTE = this.left.evaluate(ctx);
-                Object rightLTE = this.right.evaluate(ctx);
-                return or(EvalHelper.compare(leftLTE, rightLTE, ctx, (l, r) -> 
l.compareTo(r) < 0),
-                          EvalHelper.isEqual(leftLTE, rightLTE, ctx),
-                          ctx); // do not use Java || to avoid potential NPE 
due to FEEL 3vl.
-            case LT:
-                return EvalHelper.compare(this.left.evaluate(ctx), 
this.right.evaluate(ctx), ctx, (l, r) -> l.compareTo(r) < 0);
-            case GT:
-                return EvalHelper.compare(this.left.evaluate(ctx), 
this.right.evaluate(ctx), ctx, (l, r) -> l.compareTo(r) > 0);
-            case GTE:
-                Object leftGTE = this.left.evaluate(ctx);
-                Object rightGTE = this.right.evaluate(ctx);
-                return or(EvalHelper.compare(leftGTE, rightGTE, ctx, (l, r) -> 
l.compareTo(r) > 0),
-                          EvalHelper.isEqual(leftGTE, rightGTE, ctx),
-                          ctx); // do not use Java || to avoid potential NPE 
due to FEEL 3vl.
-            case EQ:
-                return EvalHelper.isEqual(this.left.evaluate(ctx), 
this.right.evaluate(ctx), ctx);
-            case NE:
-                Boolean result = EvalHelper.isEqual(this.left.evaluate(ctx), 
this.right.evaluate(ctx), ctx);
-                return result != null ? !result : null;
-            default:
-                return null;
-        }
-    }
-
-    public static Object add(Object left, Object right, EvaluationContext ctx) 
{
-        if ( left == null || right == null ) {
-            return null;
-        } else if ( left instanceof String && right instanceof String ) {
-            return left + ((String) right);
-        } else if (left instanceof ChronoPeriod && right instanceof 
ChronoPeriod) {
-            return new ComparablePeriod(((ChronoPeriod) 
left).plus((ChronoPeriod) right));
-        } else if ( left instanceof Duration && right instanceof Duration ) {
-            return ((Duration) left).plus( (Duration) right);
-        } else if (left instanceof ZonedDateTime && right instanceof 
ChronoPeriod) {
-            return ((ZonedDateTime) left).plus((ChronoPeriod) right);
-        } else if (left instanceof OffsetDateTime && right instanceof 
ChronoPeriod) {
-            return ((OffsetDateTime) left).plus((ChronoPeriod) right);
-        } else if (left instanceof LocalDateTime && right instanceof 
ChronoPeriod) {
-            return ((LocalDateTime) left).plus((ChronoPeriod) right);
-        } else if (left instanceof LocalDate && right instanceof ChronoPeriod) 
{
-            return ((LocalDate) left).plus((ChronoPeriod) right);
-        } else if ( left instanceof ZonedDateTime && right instanceof Duration 
) {
-            return ((ZonedDateTime) left).plus( (Duration) right);
-        } else if ( left instanceof OffsetDateTime && right instanceof 
Duration ) {
-            return ((OffsetDateTime) left).plus( (Duration) right);
-        } else if ( left instanceof LocalDateTime && right instanceof Duration 
) {
-            return ((LocalDateTime) left).plus( (Duration) right);
-        } else if ( left instanceof LocalDate && right instanceof Duration ) {
-            return addLocalDateAndDuration((LocalDate) left, (Duration) right);
-        } else if (left instanceof ChronoPeriod && right instanceof 
ZonedDateTime) {
-            return ((ZonedDateTime) right).plus((ChronoPeriod) left);
-        } else if (left instanceof ChronoPeriod && right instanceof 
OffsetDateTime) {
-            return ((OffsetDateTime) right).plus((ChronoPeriod) left);
-        } else if (left instanceof ChronoPeriod && right instanceof 
LocalDateTime) {
-            return ((LocalDateTime) right).plus((ChronoPeriod) left);
-        } else if (left instanceof ChronoPeriod && right instanceof LocalDate) 
{
-            return ((LocalDate) right).plus((ChronoPeriod) left);
-        } else if ( left instanceof Duration && right instanceof ZonedDateTime 
) {
-            return ((ZonedDateTime) right).plus( (Duration) left);
-        } else if ( left instanceof Duration && right instanceof 
OffsetDateTime ) {
-            return ((OffsetDateTime) right).plus( (Duration) left);
-        } else if ( left instanceof Duration && right instanceof LocalDateTime 
) {
-            return ((LocalDateTime) right).plus( (Duration) left);
-        } else if ( left instanceof Duration && right instanceof LocalDate ) {
-            return addLocalDateAndDuration((LocalDate) right, (Duration) left);
-        } else if ( left instanceof LocalTime && right instanceof Duration ) {
-            return ((LocalTime) left).plus( (Duration) right);
-        } else if ( left instanceof Duration && right instanceof LocalTime ) {
-            return ((LocalTime) right).plus( (Duration) left);
-        } else if ( left instanceof OffsetTime && right instanceof Duration ) {
-            return ((OffsetTime) left).plus( (Duration) right);
-        } else if ( left instanceof Duration && right instanceof OffsetTime ) {
-            return ((OffsetTime) right).plus( (Duration) left);
-        } else if ( left instanceof Temporal && right instanceof Temporal ) {
-            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()));
-            return null;
-        } else {
-            return math( left, right, ctx, (l, r) -> l.add( r, 
MathContext.DECIMAL128 ) );
-        }
-    }
-
-    public static Object sub(Object left, Object right, EvaluationContext ctx) 
{
-        if ( left == null || right == null ) {
-            return null;
-        } else if ( left instanceof Temporal && right instanceof Temporal ) {
-            return subtractTemporals((Temporal) left, (Temporal) right, ctx);
-        } else if (left instanceof ChronoPeriod && right instanceof 
ChronoPeriod) {
-            return new ComparablePeriod(((ChronoPeriod) 
left).minus((ChronoPeriod) right));
-        } else if ( left instanceof Duration && right instanceof Duration ) {
-            return ((Duration) left).minus( (Duration) right);
-        } else if (left instanceof ZonedDateTime && right instanceof 
ChronoPeriod) {
-            return ((ZonedDateTime) left).minus((ChronoPeriod) right);
-        } else if (left instanceof OffsetDateTime && right instanceof 
ChronoPeriod) {
-            return ((OffsetDateTime) left).minus((ChronoPeriod) right);
-        } else if (left instanceof LocalDateTime && right instanceof 
ChronoPeriod) {
-            return ((LocalDateTime) left).minus((ChronoPeriod) right);
-        } else if (left instanceof LocalDate && right instanceof ChronoPeriod) 
{
-            return ((LocalDate) left).minus((ChronoPeriod) right);
-        } else if ( left instanceof ZonedDateTime && right instanceof Duration 
) {
-            return ((ZonedDateTime) left).minus( (Duration) right);
-        } else if ( left instanceof OffsetDateTime && right instanceof 
Duration ) {
-            return ((OffsetDateTime) left).minus( (Duration) right);
-        } else if ( left instanceof LocalDateTime && right instanceof Duration 
) {
-            return ((LocalDateTime) left).minus( (Duration) right);
-        } else if ( left instanceof LocalDate && right instanceof Duration ) {
-            LocalDateTime leftLDT = LocalDateTime.of((LocalDate) left, 
LocalTime.MIDNIGHT);
-            LocalDateTime evaluated = leftLDT.minus((Duration) right);
-            return LocalDate.of(evaluated.getYear(), evaluated.getMonth(), 
evaluated.getDayOfMonth());
-        } else if ( left instanceof LocalTime && right instanceof Duration ) {
-            return ((LocalTime) left).minus( (Duration) right);
-        } else if ( left instanceof OffsetTime && right instanceof Duration ) {
-            return ((OffsetTime) left).minus( (Duration) right);
-        } else {
-            return math( left, right, ctx, (l, r) -> l.subtract( r, 
MathContext.DECIMAL128 )  );
-        }
-    }
-
-    public static Object mult(Object left, Object right, EvaluationContext 
ctx) {
-        if ( left == null || right == null ) {
-            return null;
-        } else if (!isAllowedMultiplicationBasedOnSpec(left, right, ctx)) {
-            return null;
-        } else if ( left instanceof Duration && right instanceof Number ) {
-            final BigDecimal durationNumericValue = 
BigDecimal.valueOf(((Duration) left).toNanos());
-            final BigDecimal rightDecimal = BigDecimal.valueOf(((Number) 
right).doubleValue());
-            return 
Duration.ofNanos(durationNumericValue.multiply(rightDecimal).longValue());
-        } else if ( left instanceof Number && right instanceof Duration ) {
-            return Duration.ofSeconds( EvalHelper.getBigDecimalOrNull( left 
).multiply( EvalHelper.getBigDecimalOrNull( ((Duration)right).getSeconds() ), 
MathContext.DECIMAL128 ).longValue() );
-        } else if (left instanceof ChronoPeriod && right instanceof Number) {
-            return 
ComparablePeriod.ofMonths(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 left)).multiply(EvalHelper.getBigDecimalOrNull(right), 
MathContext.DECIMAL128).intValue());
-        } else if (left instanceof Number && right instanceof ChronoPeriod) {
-            return 
ComparablePeriod.ofMonths(EvalHelper.getBigDecimalOrNull(left).multiply(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 right)), MathContext.DECIMAL128).intValue());
-        } else if (left instanceof ChronoPeriod && right instanceof 
ChronoPeriod) {
-            return 
EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) 
left)).multiply(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 right)), MathContext.DECIMAL128);
-        } else {
-            return math( left, right, ctx, (l, r) -> l.multiply( r, 
MathContext.DECIMAL128 ) );
-        }
-    }
-
-    public static Object div(Object left, Object right, EvaluationContext ctx) 
{
-        if ( left == null || right == null ) {
-            return null;
-        } else if ( left instanceof Duration && right instanceof Number ) {
-            final BigDecimal durationNumericValue = 
BigDecimal.valueOf(((Duration) left).toNanos());
-            final BigDecimal rightDecimal = BigDecimal.valueOf(((Number) 
right).doubleValue());
-            return Duration.ofNanos(durationNumericValue.divide(rightDecimal, 
0, RoundingMode.HALF_EVEN).longValue());
-        } else if ( left instanceof Number && right instanceof TemporalAmount) 
{
-            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()));
-            return null;
-        } else if ( left instanceof Duration && right instanceof Duration ) {
-            return EvalHelper.getBigDecimalOrNull( ((Duration) 
left).getSeconds() ).divide( EvalHelper.getBigDecimalOrNull( 
((Duration)right).getSeconds() ), MathContext.DECIMAL128 );
-        } else if (left instanceof ChronoPeriod && right instanceof Number) {
-            final BigDecimal rightDecimal = 
EvalHelper.getBigDecimalOrNull(right);
-            if (rightDecimal.compareTo(BigDecimal.ZERO) == 0) {
-                ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.DIVISION_BY_ZERO.getMask()));
-                return null;
-            } else {
-                return 
ComparablePeriod.ofMonths(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 left)).divide(rightDecimal, MathContext.DECIMAL128).intValue());
-            }
-        } else if (left instanceof ChronoPeriod && right instanceof 
ChronoPeriod) {
-            return 
EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) 
left)).divide(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 right)), MathContext.DECIMAL128);
-        } else {
-            return math( left, right, ctx, (l, r) -> l.divide( r, 
MathContext.DECIMAL128 ) );
-        }
-    }
-
-    public static Object math(Object left, Object right, EvaluationContext 
ctx, BinaryOperator<BigDecimal> op) {
-        BigDecimal l = left instanceof String ? null : 
EvalHelper.getBigDecimalOrNull( left );
-        BigDecimal r = right instanceof String ? null : 
EvalHelper.getBigDecimalOrNull( right );
-        if ( l == null || r == null ) {
-            return null;
-        }
-        try {
-            return op.apply( l, r );
-        } catch ( ArithmeticException e ) {
-            // happens in cases like division by 0
-            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.GENERAL_ARITHMETIC_EXCEPTION, e.getMessage())));
-            return null;
-        }
-    }
-
-    /**
-     * Implements the ternary logic AND operation
-     * @deprecated this variant do not allow short-circuit of the operator
-     */
-    @Deprecated
-    public static Object and(Object left, Object right, EvaluationContext ctx) 
{
-        Boolean l = EvalHelper.getBooleanOrNull( left );
-        Boolean r = EvalHelper.getBooleanOrNull( right );
-        // have to check for all nulls first to avoid NPE
-        if ( (l == null && r == null) || (l == null && r == true) || (r == 
null && l == true) ) {
-            return null;
-        } else if ( l == null || r == null ) {
-            return false;
-        }
-        return l && r;
-    }
-
-    /**
-     * Implements the ternary logic OR operation
-     * @deprecated this variant do not allow short-circuit of the operator
-     */
-    @Deprecated
-    public static Object or(Object left, Object right, EvaluationContext ctx) {
-        Boolean l = EvalHelper.getBooleanOrNull( left );
-        Boolean r = EvalHelper.getBooleanOrNull( right );
-        // have to check for all nulls first to avoid NPE
-        if ( (l == null && r == null) || (l == null && r == false) || (r == 
null && l == false) ) {
-            return null;
-        } else if ( l == null || r == null ) {
-            return true;
-        }
-        return l || r;
-    }
-
-    private static LocalDate addLocalDateAndDuration(LocalDate left, Duration 
right) {
-        LocalDateTime leftLDT = LocalDateTime.of( left, LocalTime.MIDNIGHT);
-        LocalDateTime evaluated = leftLDT.plus(right);
-        return LocalDate.of(evaluated.getYear(), evaluated.getMonth(), 
evaluated.getDayOfMonth());
+        return operator.evaluate(this, ctx);
     }
 
     @Override
     public ASTNode[] getChildrenNode() {
-        return new ASTNode[] { left, right };
+        return new ASTNode[]{left, right};
     }
 
     @Override
@@ -439,76 +128,4 @@ public class InfixOpNode
         return v.visit(this);
     }
 
-    private static Object subtractTemporals(final Temporal left, final 
Temporal right, final EvaluationContext ctx) {
-        // Based on the Table 57 in the spec, if it is only date, convert to 
date and time.
-        final Temporal leftTemporal = getTemporalForSubtraction(left);
-        final Temporal rightTemporal = getTemporalForSubtraction(right);
-
-        if (isAllowedTemporalSubtractionBasedOnSpec(leftTemporal, 
rightTemporal, ctx)) {
-            return Duration.between(rightTemporal, leftTemporal);
-        } else {
-            return null;
-        }
-    }
-
-    private static Temporal getTemporalForSubtraction(final Temporal temporal) 
{
-        if (temporal instanceof LocalDate) {
-            return ZonedDateTime.of((LocalDate) temporal, LocalTime.MIDNIGHT, 
ZoneOffset.UTC);
-        } else {
-            return temporal;
-        }
-    }
-
-    /**
-     * Checks if the multiplication is supported by the DMN specification 
based on the objects specified as parameters.
-     *
-     * @param left Left parameter of the subtraction expression.
-     * @param right Right parameter of the subtraction expression.
-     * @param ctx Context that is used to notify about not allowed set of 
parameters.
-     * @return True, if the parameters are valid for multiplication based on 
the DMN specification.
-     *         False, when multiplication is not defined for the specified set 
of parameters in the DMN spec, or is forbidden: <br>
-     *         - Multiplication of two durations e is not allowed in the 
specification.
-     */
-    static boolean isAllowedMultiplicationBasedOnSpec(final Object left, final 
Object right, final EvaluationContext ctx) {
-        if (left instanceof TemporalAmount && right instanceof TemporalAmount) 
{
-            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.INVALID_PARAMETERS_FOR_OPERATION, "multiplication",
-                                                                               
                        left.getClass().getName(),
-                                                                               
                        right.getClass().getName())));
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Checks if the subtraction is supported by the DMN specification based 
on the temporals specified as parameters.
-     *
-     * @param leftTemporal Left temporal parameter of the subtraction 
expression.
-     * @param rightTemporal Right temporal parameter of the subtraction 
expression.
-     * @param ctx Context that is used to notify about not allowed set of 
parameters.
-     * @return True, if the temporal parameters are valid for subtraction 
based on the DMN specification.
-     *         False, when subtraction is not defined for the specified set of 
parameters in the DMN spec, or is forbidden: <br>
-     *         - Subtraction of a datetime with timezone and a datetime 
without a timezone is not defined in the specification.
-     *         - Subtraction of a time and a datetime is not defined in the 
specification.
-     */
-    private static boolean isAllowedTemporalSubtractionBasedOnSpec(final 
Temporal leftTemporal, final Temporal rightTemporal, final EvaluationContext 
ctx) {
-        // Both datetimes have a timezone or both timezones don't have it. 
Cannot combine timezoned datetime and datetime without a timezone.
-        if ((leftTemporal instanceof ZonedDateTime || leftTemporal instanceof 
OffsetDateTime)
-                && (rightTemporal instanceof LocalDateTime))  {
-            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.DATE_AND_TIME_TIMEZONE_NEEDED, "first", leftTemporal, 
"second", rightTemporal)));
-            return false;
-        } else if ((rightTemporal instanceof ZonedDateTime || rightTemporal 
instanceof OffsetDateTime)
-                && (leftTemporal instanceof LocalDateTime)) {
-            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.DATE_AND_TIME_TIMEZONE_NEEDED, "second", rightTemporal, 
"first", leftTemporal)));
-            return false;
-        }
-
-        // Cannot combine time and date (or datetime) based on the DMN 
specification.
-        if ((!leftTemporal.isSupported(ChronoUnit.DAYS) && 
rightTemporal.isSupported(ChronoUnit.DAYS))
-                || (!rightTemporal.isSupported(ChronoUnit.DAYS) && 
leftTemporal.isSupported(ChronoUnit.DAYS))) {
-            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()));
-            return false;
-        }
-
-        return true;
-    }
 }
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/InfixOperator.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/InfixOperator.java
new file mode 100644
index 0000000000..b881f1925f
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/InfixOperator.java
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.infixexecutors.*;
+
+/**
+ * Enum responsible to execute Infix operations.
+ * Each entry provide
+ * 1. the symbol of the operator
+ * 2. the actual <code>InfixExecutor</code> instance to be executed
+ */
+public enum InfixOperator {
+    ADD("+", AddExecutor.instance()),
+    SUB("-", SubExecutor.instance()),
+    MULT("*", MultExecutor.instance()),
+    DIV("/", DivExecutor.instance()),
+    POW("**", PowExecutor.instance()),
+    LTE("<=", LteExecutor.instance()),
+    LT("<", LtExecutor.instance()),
+    GT(">", GtExecutor.instance()),
+    GTE(">=", GteExecutor.instance()),
+    EQ("=", EqExecutor.instance()),
+    NE("!=", NeExecutor.instance()),
+    AND("and", AndExecutor.instance()),
+    OR("or", OrExecutor.instance());
+
+    public final String symbol;
+    private final InfixExecutor infixExecutor;
+
+    InfixOperator(String symbol,
+                  InfixExecutor infixExecutor) {
+        this.symbol = symbol;
+        this.infixExecutor = infixExecutor;
+    }
+
+    public static InfixOperator determineOperator(String symbol) {
+        for (InfixOperator op : InfixOperator.values()) {
+            if (op.symbol.equals(symbol)) {
+                return op;
+            }
+        }
+        throw new IllegalArgumentException("No operator found for symbol '" + 
symbol + "'");
+    }
+
+    public boolean isBoolean() {
+        return this == LTE || this == LT || this == GT || this == GTE || this 
== EQ || this == NE || this == AND || this == OR;
+    }
+
+    public String getSymbol() {
+        return symbol;
+    }
+
+    public Object evaluate(final Object left, final Object right, 
EvaluationContext ctx) {
+        return infixExecutor.evaluate(left, right, ctx);
+    }
+
+    public Object evaluate(InfixOpNode opNode, EvaluationContext ctx) {
+        return infixExecutor.evaluate(opNode, ctx);
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AddExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AddExecutor.java
new file mode 100644
index 0000000000..3af4d454fa
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AddExecutor.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.kie.dmn.feel.util.Msg;
+
+import java.math.MathContext;
+import java.time.*;
+import java.time.chrono.ChronoPeriod;
+import java.time.temporal.Temporal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static 
org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.addLocalDateAndDuration;
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.math;
+
+public class AddExecutor implements InfixExecutor {
+
+    private static final AddExecutor INSTANCE = new AddExecutor();
+    private final Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> addFunctionsByClassesTuple;
+
+    private AddExecutor() {
+        addFunctionsByClassesTuple = getAddFunctionsByClassesTuple();
+    }
+
+    public static AddExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return evaluate(new EvaluatedParameters(left, right), ctx);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+    private Object evaluate(EvaluatedParameters params, EvaluationContext ctx) 
{
+        if (params.getLeft() == null || params.getRight() == null) {
+            return null;
+        }
+        ClassIdentifierTuple identifierTuple = new 
ClassIdentifierTuple(params.getLeft(), params.getRight());
+        if (addFunctionsByClassesTuple.containsKey(identifierTuple)) {
+            return 
addFunctionsByClassesTuple.get(identifierTuple).apply(params, ctx);
+        } else {
+            return math(params.getLeft(), params.getRight(), ctx, (l, r) -> 
l.add(r, MathContext.DECIMAL128));
+        }
+    }
+
+    private Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> getAddFunctionsByClassesTuple() {
+        Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> toReturn = new HashMap<>();
+        toReturn.put(new ClassIdentifierTuple(String.class, String.class), 
(parameters, ctx) -> parameters.getLeft() + (String) parameters.getRight());
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                new ComparablePeriod(((ChronoPeriod) 
parameters.getLeft()).plus((ChronoPeriod) parameters.getRight())));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, Duration.class), 
(parameters, ctx) ->
+                ((Duration) parameters.getLeft()).plus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(ZonedDateTime.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((ZonedDateTime) parameters.getLeft()).plus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(OffsetDateTime.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((OffsetDateTime) parameters.getLeft()).plus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDateTime.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((LocalDateTime) parameters.getLeft()).plus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDate.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((LocalDate) parameters.getLeft()).plus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(ZonedDateTime.class, 
Duration.class), (parameters, ctx) ->
+                ((ZonedDateTime) parameters.getLeft()).plus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(OffsetDateTime.class, 
Duration.class), (parameters, ctx) ->
+                ((OffsetDateTime) parameters.getLeft()).plus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDateTime.class, 
Duration.class), (parameters, ctx) ->
+                ((LocalDateTime) parameters.getLeft()).plus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDate.class, 
Duration.class), (parameters, ctx) ->
+                addLocalDateAndDuration((LocalDate) parameters.getLeft(), 
(Duration) parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
ZonedDateTime.class), (parameters, ctx) ->
+                ((ZonedDateTime) parameters.getRight()).plus((ChronoPeriod) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
OffsetDateTime.class), (parameters, ctx) ->
+                ((OffsetDateTime) parameters.getRight()).plus((ChronoPeriod) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
LocalDateTime.class), (parameters, ctx) ->
+                ((LocalDateTime) parameters.getRight()).plus((ChronoPeriod) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
LocalDate.class), (parameters, ctx) ->
+                ((LocalDate) parameters.getRight()).plus((ChronoPeriod) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, 
ZonedDateTime.class), (parameters, ctx) ->
+                ((ZonedDateTime) parameters.getRight()).plus((Duration) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, 
OffsetDateTime.class), (parameters, ctx) ->
+                ((OffsetDateTime) parameters.getRight()).plus((Duration) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, 
LocalDateTime.class), (parameters, ctx) ->
+                ((LocalDateTime) parameters.getRight()).plus((Duration) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, 
LocalDate.class), (parameters, ctx) ->
+                addLocalDateAndDuration((LocalDate) parameters.getRight(), 
(Duration) parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(LocalTime.class, 
Duration.class), (parameters, ctx) ->
+                ((LocalTime) parameters.getLeft()).plus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, 
LocalTime.class), (parameters, ctx) ->
+                ((LocalTime) parameters.getRight()).plus((Duration) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(OffsetTime.class, 
Duration.class), (parameters, ctx) ->
+                ((OffsetTime) parameters.getLeft()).plus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, 
OffsetTime.class), (parameters, ctx) ->
+                ((OffsetTime) parameters.getRight()).plus((Duration) 
parameters.getLeft()));
+        toReturn.put(new ClassIdentifierTuple(Temporal.class, Temporal.class), 
(parameters, ctx) -> {
+            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()));
+            return null;
+        });
+        return toReturn;
+    }
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java
new file mode 100644
index 0000000000..766c74ba65
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.and;
+
+public class AndExecutor implements InfixExecutor {
+
+    private static final AndExecutor INSTANCE = new AndExecutor();
+
+    private AndExecutor() {
+    }
+
+    public static AndExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return and(left, right, ctx);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        Boolean leftAND = 
EvalHelper.getBooleanOrNull(infixNode.getLeft().evaluate(ctx));
+        if (leftAND != null) {
+            if (leftAND.booleanValue()) {
+                return 
EvalHelper.getBooleanOrNull(infixNode.getRight().evaluate(ctx));
+            } else {
+                return Boolean.FALSE; //left hand operand is false, we do not 
need to evaluate right side
+            }
+        } else {
+            Boolean rightAND = 
EvalHelper.getBooleanOrNull(infixNode.getRight().evaluate(ctx));
+            return Boolean.FALSE.equals(rightAND) ? Boolean.FALSE : null;
+        }
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/ClassIdentifierTuple.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/ClassIdentifierTuple.java
new file mode 100644
index 0000000000..bbecdbccfb
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/ClassIdentifierTuple.java
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import java.util.Objects;
+
+public class ClassIdentifierTuple {
+
+    private final Class<?> LEFT_TYPE;
+    private final Class<?> RIGHT_TYPE;
+
+
+    public ClassIdentifierTuple(Object leftObject, Object rightObject) {
+        this.LEFT_TYPE = leftObject != null ? leftObject.getClass() : null;
+        this.RIGHT_TYPE = rightObject != null ? rightObject.getClass() : null;
+    }
+
+    public ClassIdentifierTuple(Class<?> leftType, Class<?> rightType) {
+        this.LEFT_TYPE = leftType;
+        this.RIGHT_TYPE = rightType;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ClassIdentifierTuple that = (ClassIdentifierTuple) o;
+        return isEquals(LEFT_TYPE, that.LEFT_TYPE) && isEquals(RIGHT_TYPE, 
that.RIGHT_TYPE);
+    }
+
+    @Override
+    public int hashCode() {
+        return 1;
+    }
+
+    static boolean isEquals(Class<?> thisClass, Class<?> thatClass) {
+        return (thisClass != null && thatClass != null) &&
+                (Objects.equals(thisClass, thatClass) || 
thatClass.isAssignableFrom(thisClass));
+    }
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/DivExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/DivExecutor.java
new file mode 100644
index 0000000000..9a2bb13479
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/DivExecutor.java
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.kie.dmn.feel.util.EvalHelper;
+import org.kie.dmn.feel.util.Msg;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.time.Duration;
+import java.time.chrono.ChronoPeriod;
+import java.time.temporal.TemporalAmount;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.math;
+
+public class DivExecutor implements InfixExecutor {
+
+    private static final DivExecutor INSTANCE = new DivExecutor();
+    private final Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> sumFunctionsByClassesTuple;
+
+    private DivExecutor() {
+        sumFunctionsByClassesTuple = getSumFunctionsByClassesTuple();
+    }
+
+    public static DivExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return evaluate(new EvaluatedParameters(left, right), ctx);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+    private Object evaluate(EvaluatedParameters params, EvaluationContext ctx) 
{
+        if (params.getLeft() == null || params.getRight() == null) {
+            return null;
+        }
+        ClassIdentifierTuple identifierTuple = new 
ClassIdentifierTuple(params.getLeft(), params.getRight());
+        if (sumFunctionsByClassesTuple.containsKey(identifierTuple)) {
+            return 
sumFunctionsByClassesTuple.get(identifierTuple).apply(params, ctx);
+        } else {
+            return math(params.getLeft(), params.getRight(), ctx, (l, r) -> 
l.divide(r, MathContext.DECIMAL128));
+        }
+    }
+
+    private Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> getSumFunctionsByClassesTuple() {
+        Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> toReturn = new HashMap<>();
+        toReturn.put(new ClassIdentifierTuple(Duration.class, Number.class), 
(parameters, ctx) -> {
+            final BigDecimal durationNumericValue = 
BigDecimal.valueOf(((Duration) parameters.getLeft()).toNanos());
+            final BigDecimal rightDecimal = BigDecimal.valueOf(((Number) 
parameters.getRight()).doubleValue());
+            return Duration.ofNanos(durationNumericValue.divide(rightDecimal, 
0, RoundingMode.HALF_EVEN).longValue());
+        });
+        toReturn.put(new ClassIdentifierTuple(Number.class, 
TemporalAmount.class), (parameters, ctx) -> {
+            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()));
+            return null;
+        });
+        toReturn.put(new ClassIdentifierTuple(Duration.class, Duration.class), 
(parameters, ctx) ->
+                EvalHelper.getBigDecimalOrNull(((Duration) 
parameters.getLeft()).getSeconds()).divide(EvalHelper.getBigDecimalOrNull(((Duration)
 parameters.getRight()).getSeconds()), MathContext.DECIMAL128));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
Number.class), (parameters, ctx) -> {
+            final BigDecimal rightDecimal = 
EvalHelper.getBigDecimalOrNull(parameters.getRight());
+            if (rightDecimal.compareTo(BigDecimal.ZERO) == 0) {
+                ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.DIVISION_BY_ZERO.getMask()));
+                return null;
+            } else {
+                return 
ComparablePeriod.ofMonths(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 parameters.getLeft())).divide(rightDecimal, 
MathContext.DECIMAL128).intValue());
+            }
+        });
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                
EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) 
parameters.getLeft())).divide(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 parameters.getRight())), MathContext.DECIMAL128));
+        return toReturn;
+    }
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/EqExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/EqExecutor.java
new file mode 100644
index 0000000000..144d12019f
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/EqExecutor.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+public class EqExecutor implements InfixExecutor {
+
+    private static final EqExecutor INSTANCE = new EqExecutor();
+
+    private EqExecutor() {
+    }
+
+    public static EqExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return EvalHelper.isEqual(left, right, ctx);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/EvaluatedParameters.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/EvaluatedParameters.java
new file mode 100644
index 0000000000..a4f14dfd4b
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/EvaluatedParameters.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+public class EvaluatedParameters {
+
+        private final Object left;
+        private final Object right;
+
+        public EvaluatedParameters(Object leftObject, Object rightObject) {
+            this.left = leftObject;
+            this.right = rightObject;
+        }
+
+        public Object getLeft() {
+            return left;
+        }
+
+        public Object getRight() {
+            return right;
+        }
+    }
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/GtExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/GtExecutor.java
new file mode 100644
index 0000000000..86a289ce5b
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/GtExecutor.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+public class GtExecutor implements InfixExecutor {
+
+    private static final GtExecutor INSTANCE = new GtExecutor();
+
+    private GtExecutor() {
+    }
+
+    public static GtExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return EvalHelper.compare(left, right, ctx, (l, r) -> l.compareTo(r) > 
0);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/GteExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/GteExecutor.java
new file mode 100644
index 0000000000..9a50dd40c2
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/GteExecutor.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.or;
+
+public class GteExecutor implements InfixExecutor {
+
+    private static final GteExecutor INSTANCE = new GteExecutor();
+
+    private GteExecutor() {
+    }
+
+    public static GteExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return or(EvalHelper.compare(left, right, ctx, (l, r) -> 
l.compareTo(r) > 0),
+                EvalHelper.isEqual(left, right, ctx),
+                ctx); // do not use Java || to avoid potential NPE due to FEEL 
3vl.
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutor.java
new file mode 100644
index 0000000000..3a594555c8
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutor.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+
+public interface InfixExecutor {
+
+    Object evaluate(final Object left, final Object right, EvaluationContext 
ctx);
+
+    Object evaluate(InfixOpNode infixNode, EvaluationContext ctx);
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutorUtils.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutorUtils.java
new file mode 100644
index 0000000000..2ebd96768e
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutorUtils.java
@@ -0,0 +1,165 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.kie.dmn.feel.util.EvalHelper;
+import org.kie.dmn.feel.util.Msg;
+
+import java.math.BigDecimal;
+import java.time.*;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAmount;
+import java.util.function.BinaryOperator;
+
+public class InfixExecutorUtils {
+
+    /**
+     * Implements the ternary logic OR operation
+     *
+     * @deprecated this variant do not allow short-circuit of the operator
+     */
+    @Deprecated
+    public static Object or(Object left, Object right, EvaluationContext ctx) {
+        Boolean l = EvalHelper.getBooleanOrNull(left);
+        Boolean r = EvalHelper.getBooleanOrNull(right);
+        // have to check for all nulls first to avoid NPE
+        if ((l == null && r == null) || (l == null && r == false) || (r == 
null && l == false)) {
+            return null;
+        } else if (l == null || r == null) {
+            return true;
+        }
+        return l || r;
+    }
+
+    /**
+     * Implements the ternary logic AND operation
+     *
+     * @deprecated this variant do not allow short-circuit of the operator
+     */
+    @Deprecated
+    public static Object and(Object left, Object right, EvaluationContext ctx) 
{
+        Boolean l = EvalHelper.getBooleanOrNull(left);
+        Boolean r = EvalHelper.getBooleanOrNull(right);
+        // have to check for all nulls first to avoid NPE
+        if ((l == null && r == null) || (l == null && r == true) || (r == null 
&& l == true)) {
+            return null;
+        } else if (l == null || r == null) {
+            return false;
+        }
+        return l && r;
+    }
+
+    static Object math(Object left, Object right, EvaluationContext ctx, 
BinaryOperator<BigDecimal> op) {
+        BigDecimal l = left instanceof String ? null : 
EvalHelper.getBigDecimalOrNull(left);
+        BigDecimal r = right instanceof String ? null : 
EvalHelper.getBigDecimalOrNull(right);
+        if (l == null || r == null) {
+            return null;
+        }
+        try {
+            return op.apply(l, r);
+        } catch (ArithmeticException e) {
+            // happens in cases like division by 0
+            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.GENERAL_ARITHMETIC_EXCEPTION, e.getMessage())));
+            return null;
+        }
+    }
+
+    static LocalDate addLocalDateAndDuration(LocalDate left, Duration right) {
+        LocalDateTime leftLDT = LocalDateTime.of(left, LocalTime.MIDNIGHT);
+        LocalDateTime evaluated = leftLDT.plus(right);
+        return LocalDate.of(evaluated.getYear(), evaluated.getMonth(), 
evaluated.getDayOfMonth());
+    }
+
+    static Object subtractTemporals(final Temporal left, final Temporal right, 
final EvaluationContext ctx) {
+        // Based on the Table 57 in the spec, if it is only date, convert to 
date and time.
+        final Temporal leftTemporal = getTemporalForSubtraction(left);
+        final Temporal rightTemporal = getTemporalForSubtraction(right);
+
+        if (isAllowedTemporalSubtractionBasedOnSpec(leftTemporal, 
rightTemporal, ctx)) {
+            return Duration.between(rightTemporal, leftTemporal);
+        } else {
+            return null;
+        }
+    }
+
+    static Temporal getTemporalForSubtraction(final Temporal temporal) {
+        if (temporal instanceof LocalDate) {
+            return ZonedDateTime.of((LocalDate) temporal, LocalTime.MIDNIGHT, 
ZoneOffset.UTC);
+        } else {
+            return temporal;
+        }
+    }
+
+    /**
+     * Checks if the multiplication is supported by the DMN specification 
based on the objects specified as parameters.
+     *
+     * @param left  Left parameter of the subtraction expression.
+     * @param right Right parameter of the subtraction expression.
+     * @param ctx   Context that is used to notify about not allowed set of 
parameters.
+     * @return True, if the parameters are valid for multiplication based on 
the DMN specification.
+     * False, when multiplication is not defined for the specified set of 
parameters in the DMN spec, or is forbidden: <br>
+     * - Multiplication of two durations e is not allowed in the specification.
+     */
+    static boolean isAllowedMultiplicationBasedOnSpec(final Object left, final 
Object right, final EvaluationContext ctx) {
+        if (left instanceof TemporalAmount && right instanceof TemporalAmount) 
{
+            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.INVALID_PARAMETERS_FOR_OPERATION, "multiplication",
+                    left.getClass().getName(),
+                    right.getClass().getName())));
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the subtraction is supported by the DMN specification based 
on the temporals specified as parameters.
+     *
+     * @param leftTemporal  Left temporal parameter of the subtraction 
expression.
+     * @param rightTemporal Right temporal parameter of the subtraction 
expression.
+     * @param ctx           Context that is used to notify about not allowed 
set of parameters.
+     * @return True, if the temporal parameters are valid for subtraction 
based on the DMN specification.
+     * False, when subtraction is not defined for the specified set of 
parameters in the DMN spec, or is forbidden: <br>
+     * - Subtraction of a datetime with timezone and a datetime without a 
timezone is not defined in the specification.
+     * - Subtraction of a time and a datetime is not defined in the 
specification.
+     */
+    static boolean isAllowedTemporalSubtractionBasedOnSpec(final Temporal 
leftTemporal, final Temporal rightTemporal, final EvaluationContext ctx) {
+        // Both datetimes have a timezone or both timezones don't have it. 
Cannot combine timezoned datetime and datetime without a timezone.
+        if ((leftTemporal instanceof ZonedDateTime || leftTemporal instanceof 
OffsetDateTime)
+                && (rightTemporal instanceof LocalDateTime)) {
+            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.DATE_AND_TIME_TIMEZONE_NEEDED, "first", leftTemporal, 
"second", rightTemporal)));
+            return false;
+        } else if ((rightTemporal instanceof ZonedDateTime || rightTemporal 
instanceof OffsetDateTime)
+                && (leftTemporal instanceof LocalDateTime)) {
+            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.createMessage(Msg.DATE_AND_TIME_TIMEZONE_NEEDED, "second", rightTemporal, 
"first", leftTemporal)));
+            return false;
+        }
+
+        // Cannot combine time and date (or datetime) based on the DMN 
specification.
+        if ((!leftTemporal.isSupported(ChronoUnit.DAYS) && 
rightTemporal.isSupported(ChronoUnit.DAYS))
+                || (!rightTemporal.isSupported(ChronoUnit.DAYS) && 
leftTemporal.isSupported(ChronoUnit.DAYS))) {
+            ctx.notifyEvt(() -> new 
InvalidParametersEvent(FEELEvent.Severity.ERROR, 
Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()));
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/LtExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/LtExecutor.java
new file mode 100644
index 0000000000..0db56818b9
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/LtExecutor.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+public class LtExecutor implements InfixExecutor {
+
+    private static final LtExecutor INSTANCE = new LtExecutor();
+
+    private LtExecutor() {
+    }
+
+    public static LtExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return EvalHelper.compare(left, right, ctx, (l, r) -> l.compareTo(r) < 
0);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/LteExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/LteExecutor.java
new file mode 100644
index 0000000000..d4f9d90886
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/LteExecutor.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.or;
+
+public class LteExecutor implements InfixExecutor {
+
+    private static final LteExecutor INSTANCE = new LteExecutor();
+
+    private LteExecutor() {
+    }
+
+    public static LteExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return or(EvalHelper.compare(left, right, ctx, (l, r) -> 
l.compareTo(r) < 0),
+                EvalHelper.isEqual(left, right, ctx),
+                ctx); // do not use Java || to avoid potential NPE due to FEEL 
3vl.
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/MultExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/MultExecutor.java
new file mode 100644
index 0000000000..3b435ce50b
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/MultExecutor.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.util.EvalHelper;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.time.*;
+import java.time.chrono.ChronoPeriod;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static 
org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.isAllowedMultiplicationBasedOnSpec;
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.math;
+
+public class MultExecutor implements InfixExecutor {
+
+    private static final MultExecutor INSTANCE = new MultExecutor();
+    private final Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> multFunctionsByClassesTuple;
+
+    private MultExecutor() {
+        multFunctionsByClassesTuple = getMultFunctionsByClassesTuple();
+    }
+
+    public static MultExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return evaluate(new EvaluatedParameters(left, right), ctx);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+    private Object evaluate(EvaluatedParameters params, EvaluationContext ctx) 
{
+        if ( params.getLeft() == null || params.getRight() == null ) {
+            return null;
+        } else if (!isAllowedMultiplicationBasedOnSpec(params.getLeft(), 
params.getRight(), ctx)) {
+            return null;
+        }
+        ClassIdentifierTuple identifierTuple = new 
ClassIdentifierTuple(params.getLeft(), params.getRight());
+        if (multFunctionsByClassesTuple.containsKey(identifierTuple)) {
+            return 
multFunctionsByClassesTuple.get(identifierTuple).apply(params, ctx);
+        } else {
+            return math( params.getLeft(), params.getRight(), ctx, (l, r) -> 
l.multiply( r, MathContext.DECIMAL128 ) );
+        }
+    }
+
+    private Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> getMultFunctionsByClassesTuple() {
+        Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> toReturn = new HashMap<>();
+        toReturn.put(new ClassIdentifierTuple(Duration.class, Number.class), 
(parameters, ctx) -> {
+            final BigDecimal durationNumericValue = 
BigDecimal.valueOf(((Duration) parameters.getLeft()).toNanos());
+            final BigDecimal rightDecimal = BigDecimal.valueOf(((Number) 
parameters.getRight()).doubleValue());
+            return 
Duration.ofNanos(durationNumericValue.multiply(rightDecimal).longValue());
+        });
+        toReturn.put(new ClassIdentifierTuple(Number.class, Duration.class), 
(parameters, ctx) ->
+                
Duration.ofSeconds(EvalHelper.getBigDecimalOrNull(parameters.getLeft()).multiply(EvalHelper.getBigDecimalOrNull(((Duration)
 parameters.getRight()).getSeconds()), MathContext.DECIMAL128).longValue()));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
Number.class), (parameters, ctx) ->
+                
ComparablePeriod.ofMonths(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 
parameters.getLeft())).multiply(EvalHelper.getBigDecimalOrNull(parameters.getRight()),
 MathContext.DECIMAL128).intValue()));
+        toReturn.put(new ClassIdentifierTuple(Number.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                
ComparablePeriod.ofMonths(EvalHelper.getBigDecimalOrNull(parameters.getLeft()).multiply(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 parameters.getRight())), MathContext.DECIMAL128).intValue()));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                
EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) 
parameters.getLeft())).multiply(EvalHelper.getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod)
 parameters.getRight())), MathContext.DECIMAL128));
+        return toReturn;
+    }
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/NeExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/NeExecutor.java
new file mode 100644
index 0000000000..4e285dae10
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/NeExecutor.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+public class NeExecutor implements InfixExecutor {
+
+    private static final NeExecutor INSTANCE = new NeExecutor();
+
+    private NeExecutor() {
+    }
+
+    public static NeExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        Boolean result = EvalHelper.isEqual(left, right, ctx);
+        return result != null ? !result : null;
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/OrExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/OrExecutor.java
new file mode 100644
index 0000000000..8c079bd9c9
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/OrExecutor.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.util.EvalHelper;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.or;
+
+public class OrExecutor implements InfixExecutor {
+
+    private static final OrExecutor INSTANCE = new OrExecutor();
+
+    private OrExecutor() {
+    }
+
+    public static OrExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return or(left, right, ctx);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        Boolean leftOR = 
EvalHelper.getBooleanOrNull(infixNode.getLeft().evaluate(ctx));
+        if (leftOR != null) {
+            if (!leftOR.booleanValue()) {
+                return 
EvalHelper.getBooleanOrNull(infixNode.getRight().evaluate(ctx));
+            } else {
+                return Boolean.TRUE; //left hand operand is true, we do not 
need to evaluate right side
+            }
+        } else {
+            Boolean rightOR = 
EvalHelper.getBooleanOrNull(infixNode.getRight().evaluate(ctx));
+            return Boolean.TRUE.equals(rightOR) ? Boolean.TRUE : null;
+        }
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/PowExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/PowExecutor.java
new file mode 100644
index 0000000000..8f0e09cb0c
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/PowExecutor.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import ch.obermuhlner.math.big.BigDecimalMath;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+
+import java.math.MathContext;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.math;
+
+public class PowExecutor implements InfixExecutor {
+
+    private static final PowExecutor INSTANCE = new PowExecutor();
+
+    private PowExecutor() {
+    }
+
+    public static PowExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return math(left, right, ctx, (l, r) -> BigDecimalMath.pow(l, r, 
MathContext.DECIMAL128));
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/SubExecutor.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/SubExecutor.java
new file mode 100644
index 0000000000..2516a3c0db
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/SubExecutor.java
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.ast.InfixOpNode;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+
+import java.math.MathContext;
+import java.time.*;
+import java.time.chrono.ChronoPeriod;
+import java.time.temporal.Temporal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.math;
+import static 
org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.subtractTemporals;
+
+public class SubExecutor implements InfixExecutor {
+
+    private static final SubExecutor INSTANCE = new SubExecutor();
+    private final Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> subFunctionsByClassesTuple;
+
+    private SubExecutor() {
+        subFunctionsByClassesTuple = getSubFunctionsByClassesTuple();
+    }
+
+    public static SubExecutor instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public Object evaluate(Object left, Object right, EvaluationContext ctx) {
+        return evaluate(new EvaluatedParameters(left, right), ctx);
+    }
+
+    @Override
+    public Object evaluate(InfixOpNode infixNode, EvaluationContext ctx) {
+        return evaluate(infixNode.getLeft().evaluate(ctx), 
infixNode.getRight().evaluate(ctx), ctx);
+    }
+
+    private Object evaluate(EvaluatedParameters params, EvaluationContext ctx) 
{
+        if (params.getLeft() == null || params.getRight() == null) {
+            return null;
+        }
+        ClassIdentifierTuple identifierTuple = new 
ClassIdentifierTuple(params.getLeft(), params.getRight());
+        if (subFunctionsByClassesTuple.containsKey(identifierTuple)) {
+            return 
subFunctionsByClassesTuple.get(identifierTuple).apply(params, ctx);
+        } else {
+            return math(params.getLeft(), params.getRight(), ctx, (l, r) -> 
l.subtract(r, MathContext.DECIMAL128));
+        }
+    }
+
+    private Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> getSubFunctionsByClassesTuple() {
+        Map<ClassIdentifierTuple, BiFunction<EvaluatedParameters, 
EvaluationContext, Object>> toReturn = new HashMap<>();
+        toReturn.put(new ClassIdentifierTuple(Temporal.class, Temporal.class), 
(parameters, ctx) ->
+                subtractTemporals((Temporal) parameters.getLeft(), (Temporal) 
parameters.getRight(), ctx));
+        toReturn.put(new ClassIdentifierTuple(ChronoPeriod.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                new ComparablePeriod(((ChronoPeriod) 
parameters.getLeft()).minus((ChronoPeriod) parameters.getRight())));
+        toReturn.put(new ClassIdentifierTuple(Duration.class, Duration.class), 
(parameters, ctx) ->
+                ((Duration) parameters.getLeft()).minus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(ZonedDateTime.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((ZonedDateTime) parameters.getLeft()).minus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(OffsetDateTime.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((OffsetDateTime) parameters.getLeft()).minus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDateTime.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((LocalDateTime) parameters.getLeft()).minus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDate.class, 
ChronoPeriod.class), (parameters, ctx) ->
+                ((LocalDate) parameters.getLeft()).minus((ChronoPeriod) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(ZonedDateTime.class, 
Duration.class), (parameters, ctx) ->
+                ((ZonedDateTime) parameters.getLeft()).minus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(OffsetDateTime.class, 
Duration.class), (parameters, ctx) ->
+                ((OffsetDateTime) parameters.getLeft()).minus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDateTime.class, 
Duration.class), (parameters, ctx) ->
+                ((LocalDateTime) parameters.getLeft()).minus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(LocalDate.class, 
Duration.class), (parameters, ctx) -> {
+            LocalDateTime leftLDT = LocalDateTime.of((LocalDate) 
parameters.getLeft(), LocalTime.MIDNIGHT);
+            LocalDateTime evaluated = leftLDT.minus((Duration) 
parameters.getRight());
+            return LocalDate.of(evaluated.getYear(), evaluated.getMonth(), 
evaluated.getDayOfMonth());
+        });
+        toReturn.put(new ClassIdentifierTuple(LocalTime.class, 
Duration.class), (parameters, ctx) ->
+                ((LocalTime) parameters.getLeft()).minus((Duration) 
parameters.getRight()));
+        toReturn.put(new ClassIdentifierTuple(OffsetTime.class, 
Duration.class), (parameters, ctx) ->
+                ((OffsetTime) parameters.getLeft()).minus((Duration) 
parameters.getRight()));
+        return toReturn;
+    }
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/InfixOpNodeTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/InfixOpNodeTest.java
deleted file mode 100644
index 0d38ae29bc..0000000000
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/InfixOpNodeTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.kie.dmn.feel.lang.ast;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-import java.time.Duration;
-import java.time.LocalDate;
-import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.function.BinaryOperator;
-import java.util.function.Supplier;
-
-import ch.obermuhlner.math.big.BigDecimalMath;
-import org.junit.Before;
-import org.junit.Test;
-import org.kie.dmn.feel.lang.EvaluationContext;
-
-import static java.time.temporal.ChronoUnit.DAYS;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-public class InfixOpNodeTest {
-
-    private static List<BinaryOperator<BigDecimal>> MATH_OPERATORS;
-
-    @Before
-    public void setUp() throws Exception {
-        MATH_OPERATORS = new ArrayList<>();
-        MATH_OPERATORS.add((l, r) -> l.add(r, MathContext.DECIMAL128));
-        MATH_OPERATORS.add((l, r) -> l.subtract(r, MathContext.DECIMAL128));
-        MATH_OPERATORS.add((l, r) -> l.multiply(r, MathContext.DECIMAL128));
-        MATH_OPERATORS.add((l, r) -> l.divide(r, MathContext.DECIMAL128));
-        MATH_OPERATORS.add((l, r) -> BigDecimalMath.pow(l, r, 
MathContext.DECIMAL128));
-    }
-
-    @Test
-    public void math_BothNumbers() {
-        final Random rnd = new Random();
-        MATH_OPERATORS.forEach(operator -> {
-            BigDecimal left = BigDecimal.valueOf(rnd.nextDouble());
-            BigDecimal right = BigDecimal.valueOf(rnd.nextDouble());
-            BigDecimal expected = operator.apply(left, right);
-            Object retrieved = InfixOpNode.math(left, right, null, operator);
-            assertThat(retrieved).isNotNull()
-                    .isInstanceOf(BigDecimal.class)
-                    .isEqualTo(expected);
-        });
-    }
-
-    @Test
-    public void math_NumberAndString() {
-        final Random rnd = new Random();
-        MATH_OPERATORS.forEach(operator -> {
-            BigDecimal left = BigDecimal.valueOf(rnd.nextDouble());
-            String right = String.valueOf(rnd.nextDouble());
-            Object retrieved = InfixOpNode.math(left, right, null, operator);
-            assertThat(retrieved).isNull();
-        });
-    }
-
-    @Test
-    public void addLocalDateAndDuration() {
-        LocalDate left = LocalDate.of(2021, 1, 1);
-        Duration right = Duration.of(-1, ChronoUnit.HOURS);
-        LocalDate retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
-        right = Duration.of(-24, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
-        right = Duration.of(-25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 30));
-        right = Duration.of(1, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
-
-        left = LocalDate.of(2021, 1, 2);
-        right = Duration.of(1, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 2));
-        right = Duration.of(24, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 3));
-        right = Duration.of(25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 3));
-
-        left = LocalDate.of(2021, 1, 3);
-        right = Duration.of(25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 4));
-
-        left = LocalDate.of(2020, 12, 30);
-        right = Duration.of(-25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 28));
-
-        left = LocalDate.of(2020, 12, 31);
-        right = Duration.of(-1, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.add(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 30));
-    }
-
-    @Test
-    public void subLocalDateAndDuration() {
-        LocalDate left = LocalDate.of(2021, 1, 1);
-        Duration right = Duration.of(-1, ChronoUnit.HOURS);
-        LocalDate retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
-        right = Duration.of(-24, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 2));
-        right = Duration.of(-25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 2));
-        right = Duration.of(1, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
-
-        left = LocalDate.of(2021, 1, 2);
-        right = Duration.of(1, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
-        right = Duration.of(24, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
-        right = Duration.of(25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
-
-        left = LocalDate.of(2021, 1, 3);
-        right = Duration.of(25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
-
-        left = LocalDate.of(2020, 12, 30);
-        right = Duration.of(-25, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
-
-        left = LocalDate.of(2020, 12, 31);
-        right = Duration.of(-1, ChronoUnit.HOURS);
-        retrieved = (LocalDate) InfixOpNode.sub(left, right, null);
-        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
-    }
-    @Test
-    public void mulDurationAndDuration() {
-        Object left = Duration.of(5, DAYS);
-        Object right = Duration.of(5, DAYS);
-        assertThat(InfixOpNode.mult(left, right, 
mock(EvaluationContext.class))).isNull();
-    }
-
-
-    @Test
-    public void isAllowedMultiplicationBasedOnSpec() {
-        EvaluationContext evaluationContext = mock(EvaluationContext.class);
-        Object left = 23;
-        Object right = 354.5;
-        assertThat(InfixOpNode.isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isTrue();
-        verify(evaluationContext, never()).notifyEvt(any());
-        right = Duration.of(5, DAYS);
-        assertThat(InfixOpNode.isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isTrue();
-        verify(evaluationContext, never()).notifyEvt(any());
-        left = Duration.of(5, DAYS);
-        right = 354.5;
-        assertThat(InfixOpNode.isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isTrue();
-        verify(evaluationContext, never()).notifyEvt(any());
-        left = Duration.of(5, DAYS);
-        right = Duration.of(5, DAYS);
-        assertThat(InfixOpNode.isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isFalse();
-        verify(evaluationContext, times(1)).notifyEvt(any(Supplier.class));
-    }
-}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/InfixOperatorTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/InfixOperatorTest.java
new file mode 100644
index 0000000000..080ff45e44
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/InfixOperatorTest.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast;
+
+import org.junit.Test;
+import org.kie.dmn.feel.lang.EvaluationContext;
+
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+
+import static java.time.temporal.ChronoUnit.DAYS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class InfixOperatorTest {
+
+    @Test
+    public void addLocalDateAndDuration() {
+        LocalDate left = LocalDate.of(2021, 1, 1);
+        Duration right = Duration.of(-1, ChronoUnit.HOURS);
+        LocalDate retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, 
right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
+        right = Duration.of(-24, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
+        right = Duration.of(-25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 30));
+        right = Duration.of(1, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
+
+        left = LocalDate.of(2021, 1, 2);
+        right = Duration.of(1, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 2));
+        right = Duration.of(24, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 3));
+        right = Duration.of(25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 3));
+
+        left = LocalDate.of(2021, 1, 3);
+        right = Duration.of(25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 4));
+
+        left = LocalDate.of(2020, 12, 30);
+        right = Duration.of(-25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 28));
+
+        left = LocalDate.of(2020, 12, 31);
+        right = Duration.of(-1, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.ADD.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 30));
+    }
+
+    @Test
+    public void subLocalDateAndDuration() {
+        LocalDate left = LocalDate.of(2021, 1, 1);
+        Duration right = Duration.of(-1, ChronoUnit.HOURS);
+        LocalDate retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, 
right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
+        right = Duration.of(-24, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 2));
+        right = Duration.of(-25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 2));
+        right = Duration.of(1, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
+
+        left = LocalDate.of(2021, 1, 2);
+        right = Duration.of(1, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
+        right = Duration.of(24, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
+        right = Duration.of(25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
+
+        left = LocalDate.of(2021, 1, 3);
+        right = Duration.of(25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2021, 1, 1));
+
+        left = LocalDate.of(2020, 12, 30);
+        right = Duration.of(-25, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
+
+        left = LocalDate.of(2020, 12, 31);
+        right = Duration.of(-1, ChronoUnit.HOURS);
+        retrieved = (LocalDate) InfixOperator.SUB.evaluate(left, right, null);
+        assertThat(retrieved).isEqualTo(LocalDate.of(2020, 12, 31));
+    }
+
+    @Test
+    public void mulDurationAndDuration() {
+        Object left = Duration.of(5, DAYS);
+        Object right = Duration.of(5, DAYS);
+        assertThat(InfixOperator.MULT.evaluate(left, right, 
mock(EvaluationContext.class))).isNull();
+    }
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/infixexecutors/ClassidentifierTupleTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/infixexecutors/ClassidentifierTupleTest.java
new file mode 100644
index 0000000000..70ecd6b7d2
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/infixexecutors/ClassidentifierTupleTest.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import org.junit.Test;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+
+import java.time.chrono.ChronoPeriod;
+
+import static org.junit.Assert.assertTrue;
+
+
+public class ClassidentifierTupleTest {
+
+    @Test
+    public void testClassidentifierTuple_isEquals() {
+        assertTrue(ClassIdentifierTuple.isEquals(ComparablePeriod.class, 
ChronoPeriod.class));
+    }
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutorUtilsTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutorUtilsTest.java
new file mode 100644
index 0000000000..cce73e0cd5
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/infixexecutors/InfixExecutorUtilsTest.java
@@ -0,0 +1,101 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.infixexecutors;
+
+import ch.obermuhlner.math.big.BigDecimalMath;
+import org.junit.Before;
+import org.junit.Test;
+import org.kie.dmn.feel.lang.EvaluationContext;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.function.BinaryOperator;
+import java.util.function.Supplier;
+
+import static java.time.temporal.ChronoUnit.DAYS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static 
org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.isAllowedMultiplicationBasedOnSpec;
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.math;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+public class InfixExecutorUtilsTest {
+
+    private static List<BinaryOperator<BigDecimal>> MATH_OPERATORS;
+
+    @Before
+    public void setUp() throws Exception {
+        MATH_OPERATORS = new ArrayList<>();
+        MATH_OPERATORS.add((l, r) -> l.add(r, MathContext.DECIMAL128));
+        MATH_OPERATORS.add((l, r) -> l.subtract(r, MathContext.DECIMAL128));
+        MATH_OPERATORS.add((l, r) -> l.multiply(r, MathContext.DECIMAL128));
+        MATH_OPERATORS.add((l, r) -> l.divide(r, MathContext.DECIMAL128));
+        MATH_OPERATORS.add((l, r) -> BigDecimalMath.pow(l, r, 
MathContext.DECIMAL128));
+    }
+
+    @Test
+    public void math_BothNumbers() {
+        final Random rnd = new Random();
+        MATH_OPERATORS.forEach(operator -> {
+            BigDecimal left = BigDecimal.valueOf(rnd.nextDouble());
+            BigDecimal right = BigDecimal.valueOf(rnd.nextDouble());
+            BigDecimal expected = operator.apply(left, right);
+            Object retrieved = math(left, right, null, operator);
+            assertThat(retrieved).isNotNull()
+                    .isInstanceOf(BigDecimal.class)
+                    .isEqualTo(expected);
+        });
+    }
+
+    @Test
+    public void math_NumberAndString() {
+        final Random rnd = new Random();
+        MATH_OPERATORS.forEach(operator -> {
+            BigDecimal left = BigDecimal.valueOf(rnd.nextDouble());
+            String right = String.valueOf(rnd.nextDouble());
+            Object retrieved = math(left, right, null, operator);
+            assertThat(retrieved).isNull();
+        });
+    }
+
+    @Test
+    public void isAllowedMultiplicationBasedOnSpecTest() {
+        EvaluationContext evaluationContext = mock(EvaluationContext.class);
+        Object left = 23;
+        Object right = 354.5;
+        assertThat(isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isTrue();
+        verify(evaluationContext, never()).notifyEvt(any());
+        right = Duration.of(5, DAYS);
+        assertThat(isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isTrue();
+        verify(evaluationContext, never()).notifyEvt(any());
+        left = Duration.of(5, DAYS);
+        right = 354.5;
+        assertThat(isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isTrue();
+        verify(evaluationContext, never()).notifyEvt(any());
+        left = Duration.of(5, DAYS);
+        right = Duration.of(5, DAYS);
+        assertThat(isAllowedMultiplicationBasedOnSpec(left, right, 
evaluationContext)).isFalse();
+        verify(evaluationContext, times(1)).notifyEvt(any(Supplier.class));
+    }
+
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserTest.java
index 1b65990a72..5206b3d440 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserTest.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/parser/feel11/FEELParserTest.java
@@ -26,35 +26,7 @@ import org.antlr.v4.runtime.tree.ParseTree;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.kie.dmn.feel.lang.Type;
-import org.kie.dmn.feel.lang.ast.ASTNode;
-import org.kie.dmn.feel.lang.ast.AtLiteralNode;
-import org.kie.dmn.feel.lang.ast.BaseNode;
-import org.kie.dmn.feel.lang.ast.BetweenNode;
-import org.kie.dmn.feel.lang.ast.BooleanNode;
-import org.kie.dmn.feel.lang.ast.ContextEntryNode;
-import org.kie.dmn.feel.lang.ast.ContextNode;
-import org.kie.dmn.feel.lang.ast.FilterExpressionNode;
-import org.kie.dmn.feel.lang.ast.ForExpressionNode;
-import org.kie.dmn.feel.lang.ast.FunctionDefNode;
-import org.kie.dmn.feel.lang.ast.FunctionInvocationNode;
-import org.kie.dmn.feel.lang.ast.IfExpressionNode;
-import org.kie.dmn.feel.lang.ast.InNode;
-import org.kie.dmn.feel.lang.ast.InfixOpNode;
-import org.kie.dmn.feel.lang.ast.InstanceOfNode;
-import org.kie.dmn.feel.lang.ast.IterationContextNode;
-import org.kie.dmn.feel.lang.ast.ListNode;
-import org.kie.dmn.feel.lang.ast.NameDefNode;
-import org.kie.dmn.feel.lang.ast.NameRefNode;
-import org.kie.dmn.feel.lang.ast.NamedParameterNode;
-import org.kie.dmn.feel.lang.ast.NullNode;
-import org.kie.dmn.feel.lang.ast.NumberNode;
-import org.kie.dmn.feel.lang.ast.PathExpressionNode;
-import org.kie.dmn.feel.lang.ast.QualifiedNameNode;
-import org.kie.dmn.feel.lang.ast.QuantifiedExpressionNode;
-import org.kie.dmn.feel.lang.ast.RangeNode;
-import org.kie.dmn.feel.lang.ast.SignedUnaryNode;
-import org.kie.dmn.feel.lang.ast.StringNode;
-import org.kie.dmn.feel.lang.ast.TypeNode;
+import org.kie.dmn.feel.lang.ast.*;
 import org.kie.dmn.feel.lang.impl.MapBackedType;
 import org.kie.dmn.feel.lang.types.BuiltInType;
 import org.kie.dmn.feel.util.Msg;
@@ -294,7 +266,7 @@ public class FEELParserTest {
         assertThat( mult.getLeft()).isInstanceOf(NumberNode.class);
         assertThat( mult.getLeft().getText()).isEqualTo("10");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.MULT);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.MULT);
 
         assertThat( mult.getRight()).isInstanceOf(NameRefNode.class);
         assertThat( mult.getRight().getText()).isEqualTo("x");
@@ -317,12 +289,12 @@ public class FEELParserTest {
         assertThat( div.getLeft()).isInstanceOf(NameRefNode.class);
         assertThat( div.getLeft().getText()).isEqualTo("y");
 
-        assertThat( 
div.getOperator()).isEqualTo(InfixOpNode.InfixOperator.DIV);
+        assertThat( div.getOperator()).isEqualTo(InfixOperator.DIV);
 
         assertThat( div.getRight()).isInstanceOf(NumberNode.class);
         assertThat( div.getRight().getText()).isEqualTo("5");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.MULT);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.MULT);
 
         assertThat( mult.getRight()).isInstanceOf(NameRefNode.class);
         assertThat( mult.getRight().getText()).isEqualTo("x");
@@ -341,7 +313,7 @@ public class FEELParserTest {
         assertThat( mult.getLeft()).isInstanceOf(NameRefNode.class);
         assertThat( mult.getLeft().getText()).isEqualTo("y");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.MULT);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.MULT);
 
         assertThat( mult.getRight()).isInstanceOf(InfixOpNode.class);
         assertThat( mult.getRight().getText()).isEqualTo( "5 ** 3");
@@ -350,7 +322,7 @@ public class FEELParserTest {
         assertThat( exp.getLeft()).isInstanceOf(NumberNode.class);
         assertThat( exp.getLeft().getText()).isEqualTo("5");
 
-        assertThat( 
exp.getOperator()).isEqualTo(InfixOpNode.InfixOperator.POW);
+        assertThat( exp.getOperator()).isEqualTo(InfixOperator.POW);
 
         assertThat( exp.getRight()).isInstanceOf(NumberNode.class);
         assertThat( exp.getRight().getText()).isEqualTo("3");
@@ -369,7 +341,7 @@ public class FEELParserTest {
         assertThat( exp.getLeft()).isInstanceOf(InfixOpNode.class);
         assertThat( exp.getLeft().getText()).isEqualTo( "y * 5");
 
-        assertThat( 
exp.getOperator()).isEqualTo(InfixOpNode.InfixOperator.POW);
+        assertThat( exp.getOperator()).isEqualTo(InfixOperator.POW);
 
         assertThat( exp.getRight()).isInstanceOf(NumberNode.class);
         assertThat( exp.getRight().getText()).isEqualTo("3");
@@ -378,7 +350,7 @@ public class FEELParserTest {
         assertThat( mult.getLeft()).isInstanceOf(NameRefNode.class);
         assertThat( mult.getLeft().getText()).isEqualTo("y");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.MULT);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.MULT);
 
         assertThat( mult.getRight()).isInstanceOf(NumberNode.class);
         assertThat( mult.getRight().getText()).isEqualTo("5");
@@ -397,7 +369,7 @@ public class FEELParserTest {
         assertThat( mult.getLeft()).isInstanceOf(InfixOpNode.class);
         assertThat( mult.getLeft().getText()).isEqualTo( "y ** 5");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.MULT);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.MULT);
 
         assertThat( mult.getRight()).isInstanceOf(NumberNode.class);
         assertThat( mult.getRight().getText()).isEqualTo("3");
@@ -406,7 +378,7 @@ public class FEELParserTest {
         assertThat( exp.getLeft()).isInstanceOf(NameRefNode.class);
         assertThat( exp.getLeft().getText()).isEqualTo("y");
 
-        assertThat( 
exp.getOperator()).isEqualTo(InfixOpNode.InfixOperator.POW);
+        assertThat( exp.getOperator()).isEqualTo(InfixOperator.POW);
 
         assertThat( exp.getRight()).isInstanceOf(NumberNode.class);
         assertThat( exp.getRight().getText()).isEqualTo("5");
@@ -425,7 +397,7 @@ public class FEELParserTest {
         assertThat( exp.getLeft()).isInstanceOf(NameRefNode.class);
         assertThat( exp.getLeft().getText()).isEqualTo("y");
 
-        assertThat( 
exp.getOperator()).isEqualTo(InfixOpNode.InfixOperator.POW);
+        assertThat( exp.getOperator()).isEqualTo(InfixOperator.POW);
 
         assertThat( exp.getRight()).isInstanceOf(InfixOpNode.class);
         assertThat( exp.getRight().getText()).isEqualTo( "5 * 3");
@@ -434,7 +406,7 @@ public class FEELParserTest {
         assertThat( mult.getLeft()).isInstanceOf(NumberNode.class);
         assertThat( mult.getLeft().getText()).isEqualTo("5");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.MULT);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.MULT);
 
         assertThat( mult.getRight()).isInstanceOf(NumberNode.class);
         assertThat( mult.getRight().getText()).isEqualTo("3");
@@ -453,7 +425,7 @@ public class FEELParserTest {
         assertThat( add.getLeft()).isInstanceOf(NameRefNode.class);
         assertThat( add.getLeft().getText()).isEqualTo("y");
 
-        assertThat( 
add.getOperator()).isEqualTo(InfixOpNode.InfixOperator.ADD);
+        assertThat( add.getOperator()).isEqualTo(InfixOperator.ADD);
 
         assertThat( add.getRight()).isInstanceOf(InfixOpNode.class);
         assertThat( add.getRight().getText()).isEqualTo( "5 * 3");
@@ -462,7 +434,7 @@ public class FEELParserTest {
         assertThat( mult.getLeft()).isInstanceOf(NumberNode.class);
         assertThat( mult.getLeft().getText()).isEqualTo("5");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.MULT);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.MULT);
 
         assertThat( mult.getRight()).isInstanceOf(NumberNode.class);
         assertThat( mult.getRight().getText()).isEqualTo("3");
@@ -481,7 +453,7 @@ public class FEELParserTest {
         assertThat( sub.getLeft()).isInstanceOf(InfixOpNode.class);
         assertThat( sub.getLeft().getText()).isEqualTo( "y - 5");
 
-        assertThat( 
sub.getOperator()).isEqualTo(InfixOpNode.InfixOperator.POW);
+        assertThat( sub.getOperator()).isEqualTo(InfixOperator.POW);
 
         assertThat( sub.getRight()).isInstanceOf(NumberNode.class);
         assertThat( sub.getRight().getText()).isEqualTo("3");
@@ -490,7 +462,7 @@ public class FEELParserTest {
         assertThat( mult.getLeft()).isInstanceOf(NameRefNode.class);
         assertThat( mult.getLeft().getText()).isEqualTo("y");
 
-        assertThat( 
mult.getOperator()).isEqualTo(InfixOpNode.InfixOperator.SUB);
+        assertThat( mult.getOperator()).isEqualTo(InfixOperator.SUB);
 
         assertThat( mult.getRight()).isInstanceOf(NumberNode.class);
         assertThat( mult.getRight().getText()).isEqualTo("5");
@@ -655,7 +627,7 @@ public class FEELParserTest {
         assertThat( or.getLeft()).isInstanceOf(InfixOpNode.class);
         assertThat( or.getLeft().getText()).isEqualTo( "foo < 10 and bar = 
\"x\"");
 
-        assertThat( or.getOperator()).isEqualTo(InfixOpNode.InfixOperator.OR);
+        assertThat( or.getOperator()).isEqualTo(InfixOperator.OR);
 
         assertThat( or.getRight()).isInstanceOf(NameRefNode.class);
         assertThat( or.getRight().getText()).isEqualTo("baz");
@@ -664,7 +636,7 @@ public class FEELParserTest {
         assertThat( and.getLeft()).isInstanceOf(InfixOpNode.class);
         assertThat( and.getLeft().getText()).isEqualTo( "foo < 10");
 
-        assertThat( 
and.getOperator()).isEqualTo(InfixOpNode.InfixOperator.AND);
+        assertThat( and.getOperator()).isEqualTo(InfixOperator.AND);
 
         assertThat( and.getRight()).isInstanceOf(InfixOpNode.class);
         assertThat( and.getRight().getText()).isEqualTo( "bar = \"x\"");
@@ -1052,7 +1024,7 @@ public class FEELParserTest {
         assertThat( andExpr.getResultType()).isEqualTo(BuiltInType.BOOLEAN);
 
         InfixOpNode and = (InfixOpNode) andExpr;
-        assertThat( 
and.getOperator()).isEqualTo(InfixOpNode.InfixOperator.AND);
+        assertThat( and.getOperator()).isEqualTo(InfixOperator.AND);
         assertThat( and.getLeft()).isInstanceOf(InstanceOfNode.class);
         assertThat( and.getRight()).isInstanceOf(InstanceOfNode.class);
         assertThat( and.getLeft().getText()).isEqualTo( "\"foo\" instance of 
string");
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELNumberCoercionTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELNumberCoercionTest.java
index 6647149ac0..38ac0869c6 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELNumberCoercionTest.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELNumberCoercionTest.java
@@ -25,7 +25,7 @@ import java.util.Map;
 
 import org.junit.Test;
 import org.kie.dmn.feel.FEEL;
-import org.kie.dmn.feel.lang.ast.InfixOpNode.InfixOperator;
+import org.kie.dmn.feel.lang.ast.InfixOperator;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.kie.dmn.feel.util.EvalHelper.getBigDecimalOrNull;
diff --git 
a/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
 
b/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
index 7394fd6781..37521c58ae 100644
--- 
a/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
+++ 
b/kie-dmn/kie-dmn-validation/src/main/java/org/kie/dmn/validation/dtanalysis/DMNDTAnalyser.java
@@ -47,7 +47,7 @@ import org.kie.dmn.feel.lang.SimpleType;
 import org.kie.dmn.feel.lang.ast.BaseNode;
 import org.kie.dmn.feel.lang.ast.DashNode;
 import org.kie.dmn.feel.lang.ast.InfixOpNode;
-import org.kie.dmn.feel.lang.ast.InfixOpNode.InfixOperator;
+import org.kie.dmn.feel.lang.ast.InfixOperator;
 import org.kie.dmn.feel.lang.ast.NameRefNode;
 import org.kie.dmn.feel.lang.ast.NullNode;
 import org.kie.dmn.feel.lang.ast.RangeNode;


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


Reply via email to