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 2b991ff859 [incubator-kie-issues#1350] Refactor ForExpressionNode to 
allow dynamically-generated iteration contexts (#6041)
2b991ff859 is described below

commit 2b991ff859190ed8dec5edfdb284b7dcdebc5f3c
Author: Gabriele Cardosi <[email protected]>
AuthorDate: Mon Aug 12 14:45:01 2024 +0200

    [incubator-kie-issues#1350] Refactor ForExpressionNode to allow 
dynamically-generated iteration contexts (#6041)
    
    * [incubator-kie-issues#1350] Refactor ForExpressionNode to allow 
dynamically-generated iteration contexts
    
    * [incubator-kie-issues#1350] Fix headers
    
    * [incubator-kie-issues#1350] Minor fix
    
    ---------
    
    Co-authored-by: Gabriele-Cardosi <[email protected]>
---
 .../kie/dmn/feel/lang/ast/ForExpressionNode.java   |  94 ++--
 .../dmn/feel/lang/ast/IterationContextNode.java    |   7 +
 .../ast/forexpressioniterators/ForIteration.java   |   8 +
 .../dmn/feel/lang/impl/EvaluationContextImpl.java  |   7 +
 .../feel/codegen/feel11/DirectCompilerTest.java    | 307 +++++++------
 .../dmn/feel/lang/ast/ForExpressionNodeTest.java   |  89 ++++
 .../org/kie/dmn/feel/runtime/FEELCompilerTest.java | 484 +++++++++++++++++++++
 .../runtime/functions/ListReplaceFunctionTest.java |   8 +-
 .../java/org/kie/dmn/feel/util/CompilerUtils.java  |  48 +-
 9 files changed, 842 insertions(+), 210 deletions(-)

diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
index f25aa0ca56..1229c35445 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/ForExpressionNode.java
@@ -25,6 +25,8 @@ import org.kie.dmn.feel.lang.EvaluationContext;
 import org.kie.dmn.feel.lang.Type;
 import org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIteration;
 import org.kie.dmn.feel.lang.types.BuiltInType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -35,6 +37,7 @@ import static 
org.kie.dmn.feel.lang.ast.forexpressioniterators.ForIterationUtils
 public class ForExpressionNode
         extends BaseNode {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(ForExpressionNode.class);
 
     private List<IterationContextNode> iterationContexts;
     private BaseNode expression;
@@ -74,16 +77,11 @@ public class ForExpressionNode
     public Object evaluate(EvaluationContext ctx) {
         try {
             ctx.enterFrame();
-            List results = new ArrayList();
-            ctx.setValue("partial", results);
-            ForIteration[] ictx = initializeContexts(ctx, iterationContexts);
-
-            while (nextIteration(ctx, ictx)) {
-                Object result = expression.evaluate(ctx);
-                results.add(result);
-                ctx.exitFrame(); // last i-th scope unrolled, see also 
ForExpressionNode.nextIteration(...)
-            }
-            return results;
+            List<Object> toReturn = new ArrayList<>();
+            ctx.setValue("partial", toReturn);
+            populateToReturn(0, ctx, toReturn);
+            LOG.trace("returning {}", toReturn);
+            return toReturn;
         } catch (EndpointOfRangeNotValidTypeException | 
EndpointOfRangeOfDifferentTypeException e) {
             // ast error already reported
             return null;
@@ -92,28 +90,34 @@ public class ForExpressionNode
         }
     }
 
-    public static boolean nextIteration(EvaluationContext ctx, ForIteration[] 
ictx) {
-        int i = ictx.length - 1;
-        while (i >= 0 && i < ictx.length) {
-            if (ictx[i].hasNextValue()) {
-                ctx.enterFrame(); // on first iter, open last scope frame; or 
new ones when prev unrolled
-                setValueIntoContext(ctx, ictx[i]);
-                i++;
-            } else {
-                if (i > 0) {
-                    // end of iter loop for this i-th scope; i-th scope is 
always unrolled as part of the 
-                    // for-loop cycle, so here must unroll the _prev_ scope;
-                    // the if-guard for this code block makes sure NOT to 
unroll bottom one.
-                    ctx.exitFrame();
-                }
-                i--;
+    private void populateToReturn(int k, EvaluationContext ctx, List<Object> 
toPopulate) {
+        LOG.trace("populateToReturn at index {}", k);
+        if (k > iterationContexts.size() - 1) {
+            LOG.trace("Index {} out of range, returning", k);
+            return;
+        }
+        IterationContextNode iterationContextNode = iterationContexts.get(k);
+        ForIteration forIteration = createForIteration(ctx, 
iterationContextNode);
+        while (forIteration.hasNextValue()) {
+            LOG.trace("{} has next value", forIteration);
+            ctx.enterFrame(); // open loop scope frame, for every iter ctx, 
except last one as guarded by if clause
+            // above
+            setValueIntoContext(ctx, forIteration.getName(), 
forIteration.getNextValue());
+            if (k == iterationContexts.size() - 1) {
+                LOG.trace("i == iterationContexts.size() -1: this is the last 
iteration context; evaluating {}",
+                          expression);
+                Object result = expression.evaluate(ctx);
+                LOG.trace("add {} to toReturn", result);
+                toPopulate.add(result);
+            } else if (k < iterationContexts.size() - 1) {
+                populateToReturn(k + 1, ctx, toPopulate);
             }
         }
-        return i >= 0;
+        ctx.exitFrame();
     }
 
-    public static void setValueIntoContext(EvaluationContext ctx, ForIteration 
forIteration) {
-        ctx.setValue(forIteration.getName(), forIteration.getNextValue());
+    static void setValueIntoContext(EvaluationContext ctx, String name, Object 
value) {
+        ctx.setValue(name, value);
     }
 
     @Override
@@ -121,32 +125,19 @@ public class ForExpressionNode
         return BuiltInType.LIST;
     }
 
-    private ForIteration[] initializeContexts(EvaluationContext ctx, 
List<IterationContextNode> iterationContexts) {
-        ForIteration[] ictx = new ForIteration[iterationContexts.size()];
-        int i = 0;
-        for (IterationContextNode icn : iterationContexts) {
-            ictx[i] = createQuantifiedExpressionIterationContext(ctx, icn);
-            if (i < iterationContexts.size() - 1 && ictx[i].hasNextValue()) {
-                ctx.enterFrame(); // open loop scope frame, for every iter 
ctx, except last one as guarded by if clause above
-                setValueIntoContext(ctx, ictx[i]);
-            }
-            i++;
-        }
-        return ictx;
-    }
-
-    private ForIteration 
createQuantifiedExpressionIterationContext(EvaluationContext ctx, 
IterationContextNode icn) {
-        ForIteration fi;
-        String name = icn.evaluateName(ctx);
-        Object result = icn.evaluate(ctx);
-        Object rangeEnd = icn.evaluateRangeEnd(ctx);
+    private ForIteration createForIteration(EvaluationContext ctx, 
IterationContextNode iterationContextNode) {
+        LOG.trace("Creating ForIteration for {}", iterationContextNode);
+        ForIteration toReturn;
+        String name = iterationContextNode.evaluateName(ctx);
+        Object result = iterationContextNode.evaluate(ctx);
+        Object rangeEnd = iterationContextNode.evaluateRangeEnd(ctx);
         if (rangeEnd == null) {
-            Iterable values = result instanceof Iterable ? (Iterable) result : 
Collections.singletonList(result);
-            fi = new ForIteration(name, values);
+            Iterable values = result instanceof Iterable iterable? iterable : 
Collections.singletonList(result);
+            toReturn = new ForIteration(name, values);
         } else {
-            fi = getForIteration(ctx, name, result, rangeEnd);
+            toReturn = getForIteration(ctx, name, result, rangeEnd);
         }
-        return fi;
+        return toReturn;
     }
 
     @Override
@@ -161,5 +152,4 @@ public class ForExpressionNode
     public <T> T accept(Visitor<T> v) {
         return v.visit(this);
     }
-
 }
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/IterationContextNode.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/IterationContextNode.java
index 70cfa00c9f..0c11f2e71a 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/IterationContextNode.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/IterationContextNode.java
@@ -20,10 +20,14 @@ package org.kie.dmn.feel.lang.ast;
 
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.kie.dmn.feel.lang.EvaluationContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class IterationContextNode
         extends BaseNode {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(IterationContextNode.class);
+
     private NameDefNode name;
     private BaseNode    expression;
     private BaseNode    rangeEndExpr = null;
@@ -69,15 +73,18 @@ public class IterationContextNode
     }
 
     public String evaluateName(EvaluationContext ctx) {
+        LOG.trace("evaluateName {}", name);
         return this.name.evaluate(ctx);
     }
 
     @Override
     public Object evaluate(EvaluationContext ctx) {
+        LOG.trace("evaluate {}", expression);
         return expression != null ? expression.evaluate( ctx ) : null;
     }
 
     public Object evaluateRangeEnd(EvaluationContext ctx) {
+        LOG.trace("evaluateRangeEnd {}", rangeEndExpr);
         return rangeEndExpr != null ? rangeEndExpr.evaluate(ctx) : null;
     }
 
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIteration.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIteration.java
index 43f4f576c0..bd8719f2ef 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIteration.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/forexpressioniterators/ForIteration.java
@@ -64,4 +64,12 @@ public class ForIteration {
     public String getName() {
         return name;
     }
+
+    @Override
+    public String toString() {
+        return "ForIteration{" +
+                "values=" + values +
+                ", name='" + name + '\'' +
+                '}';
+    }
 }
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
index 47759d0aef..8e1e75fa77 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
@@ -32,9 +32,13 @@ import org.kie.dmn.api.feel.runtime.events.FEELEventListener;
 import org.kie.dmn.feel.lang.EvaluationContext;
 import org.kie.dmn.feel.lang.FEELDialect;
 import org.kie.dmn.feel.util.NumberEvalHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class EvaluationContextImpl implements EvaluationContext {
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(EvaluationContextImpl.class);
+
     private final FEELEventListenersManager eventsManager;
     private ArrayDeque<ExecutionFrame> stack;
     private DMNRuntime dmnRuntime;
@@ -102,6 +106,7 @@ public class EvaluationContextImpl implements 
EvaluationContext {
 
     @Override
     public void enterFrame() {
+        LOG.trace("Creating new head element in stack");
         push( new ExecutionFrameImpl( peek() /*, symbols, scope*/ ) );
     }
 
@@ -111,11 +116,13 @@ public class EvaluationContextImpl implements 
EvaluationContext {
 
     @Override
     public void exitFrame() {
+        LOG.trace("Removing head element from stack");
         pop();
     }
 
     @Override
     public void setValue(String name, Object value) {
+        LOG.trace("put {} -> {} in head stack element", name, value);
         peek().setValue(name, NumberEvalHelper.coerceNumber(value ) );
     }
     
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/codegen/feel11/DirectCompilerTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/codegen/feel11/DirectCompilerTest.java
index 8cb00e1655..9231a8b1d5 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/codegen/feel11/DirectCompilerTest.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/codegen/feel11/DirectCompilerTest.java
@@ -20,7 +20,9 @@ package org.kie.dmn.feel.codegen.feel11;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 import org.junit.jupiter.api.Test;
 import org.kie.dmn.feel.lang.EvaluationContext;
@@ -33,12 +35,13 @@ import org.kie.dmn.feel.parser.feel11.FEELParserTest;
 import org.kie.dmn.feel.runtime.FEELConditionsAndLoopsTest;
 import org.kie.dmn.feel.runtime.FEELTernaryLogicTest;
 import org.kie.dmn.feel.runtime.functions.CustomFEELFunction;
+import org.kie.dmn.feel.util.CompilerUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.kie.dmn.feel.util.CompilerUtils.parse;
-import static org.kie.dmn.feel.util.CompilerUtils.parseCompileEvaluate;
+import static org.kie.dmn.feel.util.CompilerUtils.parseCodegen;
+import static org.kie.dmn.feel.util.CompilerUtils.parseCodegenCompileEvaluate;
 import static org.kie.dmn.feel.util.DynamicTypeUtils.entry;
 import static org.kie.dmn.feel.util.DynamicTypeUtils.mapOf;
 
@@ -49,47 +52,47 @@ public class DirectCompilerTest {
 
     @Test
     void feel_number() {
-        
assertThat(parseCompileEvaluate("10")).isEqualTo(BigDecimal.valueOf(10));
+        
assertThat(parseCodegenCompileEvaluate("10")).isEqualTo(BigDecimal.valueOf(10));
     }
 
     @Test
     void feel_negative_number() {
-        
assertThat(parseCompileEvaluate("-10")).isEqualTo(BigDecimal.valueOf(-10));
+        
assertThat(parseCodegenCompileEvaluate("-10")).isEqualTo(BigDecimal.valueOf(-10));
     }
 
     @Test
     void feel_drools_2143() {
         // DROOLS-2143: Allow ''--1' expression as per FEEL grammar rule 26 
-        
assertThat(parseCompileEvaluate("--10")).isEqualTo(BigDecimal.valueOf(10));
-        
assertThat(parseCompileEvaluate("---10")).isEqualTo(BigDecimal.valueOf(-10));
-        
assertThat(parseCompileEvaluate("+10")).isEqualTo(BigDecimal.valueOf(10));
+        
assertThat(parseCodegenCompileEvaluate("--10")).isEqualTo(BigDecimal.valueOf(10));
+        
assertThat(parseCodegenCompileEvaluate("---10")).isEqualTo(BigDecimal.valueOf(-10));
+        
assertThat(parseCodegenCompileEvaluate("+10")).isEqualTo(BigDecimal.valueOf(10));
     }
 
     @Test
     void feel_boolean() {
-        assertThat(parseCompileEvaluate("false")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate("true")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("null")).isNull();
+        
assertThat(parseCodegenCompileEvaluate("false")).isEqualTo(Boolean.FALSE);
+        
assertThat(parseCodegenCompileEvaluate("true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("null")).isNull();
     }
 
     @Test
     void feel_null() {
-        assertThat(parseCompileEvaluate("null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("null")).isNull();
     }
 
     @Test
     void feel_string() {
-        assertThat(parseCompileEvaluate("\"some string\"")).isEqualTo("some 
string" );
+        assertThat(parseCodegenCompileEvaluate("\"some 
string\"")).isEqualTo("some string" );
     }
 
     @Test
     void primary_parens() {
-        assertThat(parseCompileEvaluate("(\"some string\")")).isEqualTo("some 
string" );
-        
assertThat(parseCompileEvaluate("(123)")).isEqualTo(BigDecimal.valueOf(123));
-        
assertThat(parseCompileEvaluate("(-123)")).isEqualTo(BigDecimal.valueOf(-123));
-        
assertThat(parseCompileEvaluate("-(123)")).isEqualTo(BigDecimal.valueOf(-123));
-        assertThat(parseCompileEvaluate("(false)")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate("(true)")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("(\"some 
string\")")).isEqualTo("some string" );
+        
assertThat(parseCodegenCompileEvaluate("(123)")).isEqualTo(BigDecimal.valueOf(123));
+        
assertThat(parseCodegenCompileEvaluate("(-123)")).isEqualTo(BigDecimal.valueOf(-123));
+        
assertThat(parseCodegenCompileEvaluate("-(123)")).isEqualTo(BigDecimal.valueOf(-123));
+        
assertThat(parseCodegenCompileEvaluate("(false)")).isEqualTo(Boolean.FALSE);
+        
assertThat(parseCodegenCompileEvaluate("(true)")).isEqualTo(Boolean.TRUE);
     }
 
     /**
@@ -97,29 +100,29 @@ public class DirectCompilerTest {
      */
     @Test
     void ternary_logic() {
-        assertThat(parseCompileEvaluate( "true and 
true")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "true and 
false")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate( "true and null")).isNull();
-        assertThat(parseCompileEvaluate( "false and 
true")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate( "false and 
false")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate( "false and 
null")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate( "null and true")).isNull();
-        assertThat(parseCompileEvaluate( "null and 
false")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate( "null and null")).isNull();
-        assertThat(parseCompileEvaluate( "true or 
true")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "true or 
false")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "true or 
null")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "false or 
true")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "false or 
false")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate( "false or null")).isNull();
-        assertThat(parseCompileEvaluate( "null or 
true")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "null or false")).isNull();
-        assertThat(parseCompileEvaluate( "null or null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("true and 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("true and 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("true and null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("false and 
true")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("false and 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("false and 
null")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("null and true")).isNull();
+        assertThat(parseCodegenCompileEvaluate("null and 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("null and null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("true or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("true or 
false")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("true or 
null")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("false or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("false or 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("false or null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("null or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("null or false")).isNull();
+        assertThat(parseCodegenCompileEvaluate("null or null")).isNull();
         // logical operator priority
-        assertThat(parseCompileEvaluate( "false and false or 
true")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "false and (false or 
true)")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate( "true or false and 
false")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate( "(true or false) and 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("false and false or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("false and (false or 
true)")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("true or false and 
false")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("(true or false) and 
false")).isEqualTo(Boolean.FALSE);
     }
 
     /**
@@ -127,100 +130,100 @@ public class DirectCompilerTest {
      */
     @Test
     void test_if() {
-        assertThat(parseCompileEvaluate( "if true then 15 else 
5")).isEqualTo(BigDecimal.valueOf( 15 ));
-        assertThat(parseCompileEvaluate( "if false then 15 else 
5")).isEqualTo(BigDecimal.valueOf( 5 ));
-        assertThat(parseCompileEvaluate("if null then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5));
-        assertThat(parseCompileEvaluate("if \"hello\" then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5));
+        assertThat(parseCodegenCompileEvaluate("if true then 15 else 
5")).isEqualTo(BigDecimal.valueOf(15 ));
+        assertThat(parseCodegenCompileEvaluate("if false then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5 ));
+        assertThat(parseCodegenCompileEvaluate("if null then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5));
+        assertThat(parseCodegenCompileEvaluate("if \"hello\" then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5));
     }
 
     @Test
     void additive_expression() {
-        assertThat(parseCompileEvaluate( "1 + 
2")).isEqualTo(BigDecimal.valueOf( 3 ));
-        assertThat(parseCompileEvaluate( "1 + null")).isNull();
-        assertThat(parseCompileEvaluate( "1 - 
2")).isEqualTo(BigDecimal.valueOf( -1 ));
-        assertThat(parseCompileEvaluate( "1 - null")).isNull();
-        assertThat(parseCompileEvaluate( "\"Hello, \" + 
\"World\"")).isEqualTo("Hello, World");
+        assertThat(parseCodegenCompileEvaluate("1 + 
2")).isEqualTo(BigDecimal.valueOf(3 ));
+        assertThat(parseCodegenCompileEvaluate("1 + null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("1 - 
2")).isEqualTo(BigDecimal.valueOf(-1 ));
+        assertThat(parseCodegenCompileEvaluate("1 - null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("\"Hello, \" + 
\"World\"")).isEqualTo("Hello, World");
     }
 
     @Test
     void multiplicative_expression() {
-        assertThat(parseCompileEvaluate("3 * 
5")).isEqualTo(BigDecimal.valueOf(15));
-        assertThat(parseCompileEvaluate("3 * null")).isNull();
-        assertThat(parseCompileEvaluate("10 / 
2")).isEqualTo(BigDecimal.valueOf(5));
-        assertThat(parseCompileEvaluate("10 / null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("3 * 
5")).isEqualTo(BigDecimal.valueOf(15));
+        assertThat(parseCodegenCompileEvaluate("3 * null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("10 / 
2")).isEqualTo(BigDecimal.valueOf(5));
+        assertThat(parseCodegenCompileEvaluate("10 / null")).isNull();
     }
 
     @Test
     void exponentiation_expression() {
-        assertThat(parseCompileEvaluate("3 ** 
3")).isEqualTo(BigDecimal.valueOf(27));
-        assertThat(parseCompileEvaluate("3 ** null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("3 ** 
3")).isEqualTo(BigDecimal.valueOf(27));
+        assertThat(parseCodegenCompileEvaluate("3 ** null")).isNull();
     }
 
     @Test
     void logical_negation_expression() {
         // this is all invalid syntax
-        assertThat(parseCompileEvaluate("not true")).isNull();
-        assertThat(parseCompileEvaluate("not false")).isNull();
-        assertThat(parseCompileEvaluate("not null")).isNull();
-        assertThat(parseCompileEvaluate("not 3")).isNull();
+        assertThat(parseCodegenCompileEvaluate("not true")).isNull();
+        assertThat(parseCodegenCompileEvaluate("not false")).isNull();
+        assertThat(parseCodegenCompileEvaluate("not null")).isNull();
+        assertThat(parseCodegenCompileEvaluate("not 3")).isNull();
     }
 
     @Test
     void list_expression() {
-        assertThat(parseCompileEvaluate("[]")).asList().isEmpty();
-        assertThat(parseCompileEvaluate("[ ]")).asList().isEmpty();
-        
assertThat(parseCompileEvaluate("[1]")).asList().containsExactly(BigDecimal.valueOf(1));
-        assertThat(parseCompileEvaluate("[1, 
2,3]")).asList().containsExactly(BigDecimal.valueOf(1), BigDecimal.valueOf(2), 
BigDecimal.valueOf(3));
+        assertThat(parseCodegenCompileEvaluate("[]")).asList().isEmpty();
+        assertThat(parseCodegenCompileEvaluate("[ ]")).asList().isEmpty();
+        
assertThat(parseCodegenCompileEvaluate("[1]")).asList().containsExactly(BigDecimal.valueOf(1));
+        assertThat(parseCodegenCompileEvaluate("[1, 
2,3]")).asList().containsExactly(BigDecimal.valueOf(1), BigDecimal.valueOf(2), 
BigDecimal.valueOf(3));
     }
 
     @Test
     void instance_of_expression() {
-        assertThat(parseCompileEvaluate("123 instance of 
number")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("\"ciao\" instance of 
number")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate("123 instance of 
string")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate("\"ciao\" instance of 
string")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("123 instance of 
number")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("\"ciao\" instance of 
number")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("123 instance of 
string")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("\"ciao\" instance of 
string")).isEqualTo(Boolean.TRUE);
     }
 
     @Test
     void between() {
-        assertThat(parseCompileEvaluate("10 between 5 and 
12")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("10 between 20 and 
30")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate("10 between 5 and \"foo\"")).isNull();
-        assertThat(parseCompileEvaluate("\"foo\" between 5 and 12")).isNull();
-        assertThat(parseCompileEvaluate("\"foo\" between \"bar\" and 
\"zap\"")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("\"foo\" between null and 
\"zap\"")).isNull();
+        assertThat(parseCodegenCompileEvaluate("10 between 5 and 
12")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("10 between 20 and 
30")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("10 between 5 and 
\"foo\"")).isNull();
+        assertThat(parseCodegenCompileEvaluate("\"foo\" between 5 and 
12")).isNull();
+        assertThat(parseCodegenCompileEvaluate("\"foo\" between \"bar\" and 
\"zap\"")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("\"foo\" between null and 
\"zap\"")).isNull();
     }
 
     @Test
     void filter_path() {
         // Filtering by index
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][1]")).isEqualTo("a");
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][2]")).isEqualTo("b");
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][3]")).isEqualTo("c");
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][-1]")).isEqualTo("c");
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][-2]")).isEqualTo("b");
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][-3]")).isEqualTo("a");
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", \"c\"][4]")).isNull();
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][984]")).isNull();
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", \"c\"][-4]")).isNull();
-        assertThat(parseCompileEvaluate("[\"a\", \"b\", 
\"c\"][-984]")).isNull();
-        assertThat(parseCompileEvaluate("\"a\"[1]")).isEqualTo("a");
-        assertThat(parseCompileEvaluate("\"a\"[2]")).isNull();
-        assertThat(parseCompileEvaluate("\"a\"[-1]")).isEqualTo("a");
-        assertThat(parseCompileEvaluate("\"a\"[-2]")).isNull();
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][1]")).isEqualTo("a");
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][2]")).isEqualTo("b");
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][3]")).isEqualTo("c");
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][-1]")).isEqualTo("c");
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][-2]")).isEqualTo("b");
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][-3]")).isEqualTo("a");
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][4]")).isNull();
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][984]")).isNull();
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][-4]")).isNull();
+        assertThat(parseCodegenCompileEvaluate("[\"a\", \"b\", 
\"c\"][-984]")).isNull();
+        assertThat(parseCodegenCompileEvaluate("\"a\"[1]")).isEqualTo("a");
+        assertThat(parseCodegenCompileEvaluate("\"a\"[2]")).isNull();
+        assertThat(parseCodegenCompileEvaluate("\"a\"[-1]")).isEqualTo("a");
+        assertThat(parseCodegenCompileEvaluate("\"a\"[-2]")).isNull();
 
         // Filtering by boolean expression
-        assertThat(parseCompileEvaluate("[1, 2, 3, 4][item = 
4]")).asList().containsExactly(BigDecimal.valueOf(4));
-        assertThat(parseCompileEvaluate("[1, 2, 3, 4][item > 
2]")).asList().containsExactly(BigDecimal.valueOf(3), BigDecimal.valueOf(4));
-        assertThat(parseCompileEvaluate("[1, 2, 3, 4][item > 
5]")).asList().isEmpty();
-        assertThat(parseCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} ][x = 
1]")).asList().containsExactly(mapOf(entry("x", new BigDecimal(1)), entry("y", 
new BigDecimal(2))));
-        assertThat(parseCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} ][x > 
1]")).asList().containsExactly(mapOf(entry("x", new BigDecimal(2)), entry("y", 
new BigDecimal(3))));
-        assertThat(parseCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} ][x = 
0]")).asList().isEmpty();
+        assertThat(parseCodegenCompileEvaluate("[1, 2, 3, 4][item = 
4]")).asList().containsExactly(BigDecimal.valueOf(4));
+        assertThat(parseCodegenCompileEvaluate("[1, 2, 3, 4][item > 
2]")).asList().containsExactly(BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+        assertThat(parseCodegenCompileEvaluate("[1, 2, 3, 4][item > 
5]")).asList().isEmpty();
+        assertThat(parseCodegenCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} ][x = 
1]")).asList().containsExactly(mapOf(entry("x", new BigDecimal(1)), entry("y", 
new BigDecimal(2))));
+        assertThat(parseCodegenCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} ][x > 
1]")).asList().containsExactly(mapOf(entry("x", new BigDecimal(2)), entry("y", 
new BigDecimal(3))));
+        assertThat(parseCodegenCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} ][x = 
0]")).asList().isEmpty();
     }
 
     @Test
     void filter_path_tricky1() {
-        CompiledFEELExpression nameRef = parse( "[ {x:1, y:2}, {x:2, y:3} 
][x]");
+        CompiledFEELExpression nameRef = CompilerUtils.parseCodegen("[ {x:1, 
y:2}, {x:2, y:3} ][x]");
         LOG.debug("{}", nameRef);
         
         EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
@@ -233,7 +236,7 @@ public class DirectCompilerTest {
 
     @Test
     void filter_path_tricky2() {
-        CompiledFEELExpression nameRef = parse("[ {x:1, y:2}, {x:2, y:3} 
][x]");
+        CompiledFEELExpression nameRef = CompilerUtils.parseCodegen("[ {x:1, 
y:2}, {x:2, y:3} ][x]");
         LOG.debug("{}", nameRef);
 
         EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
@@ -247,85 +250,103 @@ public class DirectCompilerTest {
     @Test
     void filter_path_selection() {
         // Selection
-        assertThat(parseCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
].y")).asList().containsExactly(BigDecimal.valueOf(2), BigDecimal.valueOf(3));
-        assertThat(parseCompileEvaluate("[ {x:1, y:2}, {x:2} 
].y")).asList().containsExactly(BigDecimal.valueOf(2), null);
-        assertThat(parseCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
].z")).asList().containsExactly(null, null);
+        assertThat(parseCodegenCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
].y")).asList().containsExactly(BigDecimal.valueOf(2), BigDecimal.valueOf(3));
+        assertThat(parseCodegenCompileEvaluate("[ {x:1, y:2}, {x:2} 
].y")).asList().containsExactly(BigDecimal.valueOf(2), null);
+        assertThat(parseCodegenCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
].z")).asList().containsExactly(null, null);
     }
 
     @Test
     void test_for() {
         // for
-        Object parseCompileEvaluate = parseCompileEvaluate("for x in [ 10, 20, 
30 ], y in [ 1, 2, 3 ] return x * y");
+        Object parseCompileEvaluate = parseCodegenCompileEvaluate("for x in [ 
10, 20, 30 ], y in [ 1, 2, 3 ] return x * y");
                assertThat(parseCompileEvaluate).asList().
                containsExactly(BigDecimal.valueOf(10), BigDecimal.valueOf(20), 
BigDecimal.valueOf(30), BigDecimal.valueOf(20), BigDecimal.valueOf(40), 
BigDecimal.valueOf(60), BigDecimal.valueOf(30), BigDecimal.valueOf(60), 
BigDecimal.valueOf(90));
 
         // normal:
-        assertThat(parseCompileEvaluate("for x in [1, 2, 3] return 
x+1")).asList().
+        assertThat(parseCodegenCompileEvaluate("for x in [1, 2, 3] return 
x+1")).asList().
                containsExactly(BigDecimal.valueOf(2), BigDecimal.valueOf(3), 
BigDecimal.valueOf(4));
         
         // TODO in order to parse correctly the enhanced for loop it is 
required to configure the FEEL Profiles
     }
 
+    @Test
+    void test_nested_for() {
+        List<BigDecimal> firstExpected = Arrays.asList(BigDecimal.ONE, 
BigDecimal.valueOf(2));
+        List<BigDecimal> secondExpected = Arrays.asList(BigDecimal.valueOf(3), 
BigDecimal.valueOf(4));
+        Object parseCompileEvaluate = parseCodegenCompileEvaluate("for x in [ 
[1, 2], [3, 4] ] return x");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(firstExpected, secondExpected);
+        parseCompileEvaluate = parseCodegenCompileEvaluate("for x in [ [1,2], 
[3,4] ] return for y in x return y");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(firstExpected, secondExpected);
+        parseCompileEvaluate = CompilerUtils.parseCodegenCompileEvaluate("for 
x in [ 1, 2, 3, 4 ], y in x return y");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(BigDecimal.ONE, BigDecimal.valueOf(2), 
BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+        parseCompileEvaluate = parseCodegenCompileEvaluate("for x in [ [1,2], 
[3,4] ], y in x return y");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(BigDecimal.ONE, BigDecimal.valueOf(2), 
BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+    }
+
     @Test
     void quantified_expressions() {
         // quantified expressions
-        assertThat(parseCompileEvaluate("some price in [ 80, 11, 110 ] 
satisfies price > 100")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("some price in [ 80, 11, 90 ] 
satisfies price > 100")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate("some x in [ 5, 6, 7 ], y in [ 10, 11, 
6 ] satisfies x > y")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("every price in [ 80, 11, 90 ] 
satisfies price > 10")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("every price in [ 80, 11, 90 ] 
satisfies price > 70")).isEqualTo(Boolean.FALSE);
-        assertThat(parseCompileEvaluate("some x in [ 5, 6, 7 ], y in [ 10, 11, 
12 ] satisfies x < y")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("some price in [ 80, 11, 110 ] 
satisfies price > max(100, 50, 10)")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("some price in [ 80, 11, 110 ] 
satisfies price > 100")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("some price in [ 80, 11, 90 ] 
satisfies price > 100")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("some x in [ 5, 6, 7 ], y in [ 
10, 11, 6 ] satisfies x > y")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("every price in [ 80, 11, 90 ] 
satisfies price > 10")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("every price in [ 80, 11, 90 ] 
satisfies price > 70")).isEqualTo(Boolean.FALSE);
+        assertThat(parseCodegenCompileEvaluate("some x in [ 5, 6, 7 ], y in [ 
10, 11, 12 ] satisfies x < y")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("some price in [ 80, 11, 110 ] 
satisfies price > max(100, 50, 10)")).isEqualTo(Boolean.TRUE);
     }
 
     @Test
     void basic_function_invocation() {
-        assertThat(parseCompileEvaluate("max(1, 2, 3)")).isEqualTo(new 
BigDecimal(3));
+        assertThat(parseCodegenCompileEvaluate("max(1, 2, 3)")).isEqualTo(new 
BigDecimal(3));
     }
 
     @Test
     void basic_function_definition() {
-        assertThat(parseCompileEvaluate("function (a, b) a + 
b")).isInstanceOf(CustomFEELFunction.class);
-        assertThat(parseCompileEvaluate("{ s : function (a, b) a + b, x : 1, y 
: 2, r : s(x,y) }.r")).isEqualTo(new BigDecimal(3));
+        assertThat(parseCodegenCompileEvaluate("function (a, b) a + 
b")).isInstanceOf(CustomFEELFunction.class);
+        assertThat(parseCodegenCompileEvaluate("{ s : function (a, b) a + b, x 
: 1, y : 2, r : s(x,y) }.r")).isEqualTo(new BigDecimal(3));
     }
 
     @Test
     void named_function_invocation() {
-        assertThat(parseCompileEvaluate("substring(start position: 2, string: 
\"FOOBAR\")")).isEqualTo("OOBAR");
-        assertThat(parseCompileEvaluate("ceiling( n : 1.5 )")).isEqualTo(new 
BigDecimal("2"));
+        assertThat(parseCodegenCompileEvaluate("substring(start position: 2, 
string: \"FOOBAR\")")).isEqualTo("OOBAR");
+        assertThat(parseCodegenCompileEvaluate("ceiling( n : 1.5 
)")).isEqualTo(new BigDecimal("2"));
     }
 
     @Test
     void misc_from_original_feelinterpreted_test_suite() {
-        assertThat(parseCompileEvaluate("if null then \"foo\" else 
\"bar\"")).isEqualTo("bar");
-        assertThat(parseCompileEvaluate("{ hello world : function() \"Hello 
World!\", message : hello world() }.message")).isEqualTo("Hello World!");
-        assertThat(parseCompileEvaluate("1 + if true then 1 else 
2")).isEqualTo(new BigDecimal("2"));
-        assertThat(parseCompileEvaluate("\"string with 
\\\"quotes\\\"\"")).isEqualTo("string with \"quotes\"");
-        assertThat(parseCompileEvaluate("date( -0105, 8, 2 
)")).isEqualTo(LocalDate.of(-105, 8, 2));
-        assertThat(parseCompileEvaluate("string(null)")).isNull();
-        assertThat(parseCompileEvaluate("[ null 
]")).asList().containsExactly(new Object[]{null});
-        assertThat(parseCompileEvaluate("[ null, null 
]")).asList().containsExactly(null, null);
-        assertThat(parseCompileEvaluate("[ null, 47, null 
]")).asList().containsExactly(null, BigDecimal.valueOf(47), null);
+        assertThat(parseCodegenCompileEvaluate("if null then \"foo\" else 
\"bar\"")).isEqualTo("bar");
+        assertThat(parseCodegenCompileEvaluate("{ hello world : function() 
\"Hello World!\", message : hello world() }.message")).isEqualTo("Hello 
World!");
+        assertThat(parseCodegenCompileEvaluate("1 + if true then 1 else 
2")).isEqualTo(new BigDecimal("2"));
+        assertThat(parseCodegenCompileEvaluate("\"string with 
\\\"quotes\\\"\"")).isEqualTo("string with \"quotes\"");
+        assertThat(parseCodegenCompileEvaluate("date( -0105, 8, 2 
)")).isEqualTo(LocalDate.of(-105, 8, 2));
+        assertThat(parseCodegenCompileEvaluate("string(null)")).isNull();
+        assertThat(parseCodegenCompileEvaluate("[ null 
]")).asList().containsExactly(new Object[]{null});
+        assertThat(parseCodegenCompileEvaluate("[ null, null 
]")).asList().containsExactly(null, null);
+        assertThat(parseCodegenCompileEvaluate("[ null, 47, null 
]")).asList().containsExactly(null, BigDecimal.valueOf(47), null);
     }
 
     @Test
     void benchmark_feel_expressions() {
-        assertThat(parseCompileEvaluate("{ full name: { first name: \"John\", 
last name: \"Doe\" } }.full name.last name")).isEqualTo("Doe");
-        assertThat(parseCompileEvaluate("some price in [ 80, 11, 110 ] 
satisfies price > 100")).isEqualTo(Boolean.TRUE);
-        assertThat(parseCompileEvaluate("every price in [ 80, 11, 90 ] 
satisfies price > 10")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("{ full name: { first name: 
\"John\", last name: \"Doe\" } }.full name.last name")).isEqualTo("Doe");
+        assertThat(parseCodegenCompileEvaluate("some price in [ 80, 11, 110 ] 
satisfies price > 100")).isEqualTo(Boolean.TRUE);
+        assertThat(parseCodegenCompileEvaluate("every price in [ 80, 11, 90 ] 
satisfies price > 10")).isEqualTo(Boolean.TRUE);
     }
 
     @Test
     void context_expression() {
-        
assertThat(parseCompileEvaluate("{}")).isEqualTo(Collections.emptyMap());
-        assertThat(parseCompileEvaluate("{ 
}")).isEqualTo(Collections.emptyMap());
-        assertThat(parseCompileEvaluate("{ a : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1))));
-        assertThat(parseCompileEvaluate("{ \"a\" : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1))));
-        assertThat(parseCompileEvaluate("{ \" a\" : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)))); // Demonstrating a bad 
practice.
-        assertThat(parseCompileEvaluate("{ a : 1, b : 2, c : 3 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("b", new 
BigDecimal(2)), entry("c", new BigDecimal(3))));
-        assertThat(parseCompileEvaluate("{ a : 1, a name : \"John Doe\" 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("a name", "John 
Doe")));
+        
assertThat(parseCodegenCompileEvaluate("{}")).isEqualTo(Collections.emptyMap());
+        assertThat(parseCodegenCompileEvaluate("{ 
}")).isEqualTo(Collections.emptyMap());
+        assertThat(parseCodegenCompileEvaluate("{ a : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1))));
+        assertThat(parseCodegenCompileEvaluate("{ \"a\" : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1))));
+        assertThat(parseCodegenCompileEvaluate("{ \" a\" : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)))); // Demonstrating a bad 
practice.
+        assertThat(parseCodegenCompileEvaluate("{ a : 1, b : 2, c : 3 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("b", new 
BigDecimal(2)), entry("c", new BigDecimal(3))));
+        assertThat(parseCodegenCompileEvaluate("{ a : 1, a name : \"John Doe\" 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("a name", "John 
Doe")));
 
-        assertThat(parseCompileEvaluate("{ a : 1, b : a 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("b", new 
BigDecimal(1))));
+        assertThat(parseCodegenCompileEvaluate("{ a : 1, b : a 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("b", new 
BigDecimal(1))));
     }
 
     /**
@@ -336,7 +357,7 @@ public class DirectCompilerTest {
         String inputExpression = "{ \"a string key\" : 10," + "\n"
                                + " a non-string key : 11," + "\n"
                                + " a key.with + /' odd chars : 12 }";
-        
assertThat(parseCompileEvaluate(inputExpression)).isEqualTo(mapOf(entry("a 
string key", new BigDecimal(10)), entry("a non-string key", new 
BigDecimal(11)), entry("a key.with + /' odd chars", new BigDecimal(12))));
+        
assertThat(parseCodegenCompileEvaluate(inputExpression)).isEqualTo(mapOf(entry("a
 string key", new BigDecimal(10)), entry("a non-string key", new 
BigDecimal(11)), entry("a key.with + /' odd chars", new BigDecimal(12))));
     }
 
     /**
@@ -356,8 +377,8 @@ public class DirectCompilerTest {
                        + "    xxx: last + name" + "\n"
                        + " } " + "\n"
                        + "}";
-        
assertThat(parseCompileEvaluate(inputExpression)).isEqualTo(mapOf(entry("a 
value", new BigDecimal(10)), 
-                                                                   entry("an 
applicant", mapOf(entry("first name", "Edson"),
+        
assertThat(parseCodegenCompileEvaluate(inputExpression)).isEqualTo(mapOf(entry("a
 value", new BigDecimal(10)),
+                                                                               
  entry("an applicant", mapOf(entry("first name", "Edson"),
                                                                                
                entry("last + name", "Tirelli"),
                                                                                
                entry("full name", "EdsonTirelli"),
                                                                                
                entry("address", mapOf(entry("street", "55 broadway st"),
@@ -378,15 +399,15 @@ public class DirectCompilerTest {
                                 "   },                                         
    \n" +
                                 "   street : an applicant.home address.street 
name \n" +
                                 "}                                             
    ";
-        
assertThat(parseCompileEvaluate(complexContext)).isEqualTo(mapOf(entry("an 
applicant", mapOf(entry("home address", mapOf(entry("street name", "broadway 
st"),
-                                                                               
                                           entry("city", "New York"))))),
-                                                                  
entry("street", "broadway st")));
+        
assertThat(parseCodegenCompileEvaluate(complexContext)).isEqualTo(mapOf(entry("an
 applicant", mapOf(entry("home address", mapOf(entry("street name", "broadway 
st"),
+                                                                               
                                                         entry("city", "New 
York"))))),
+                                                                               
 entry("street", "broadway st")));
     }
 
     @Test
     void nameReference() {
         String inputExpression = "someSimpleName";
-        CompiledFEELExpression nameRef = parse( inputExpression, mapOf( 
entry("someSimpleName", BuiltInType.STRING) ) );
+        CompiledFEELExpression nameRef = parseCodegen(inputExpression, 
mapOf(entry("someSimpleName", BuiltInType.STRING) ) );
         LOG.debug("{}", nameRef);
         
         EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
@@ -401,7 +422,7 @@ public class DirectCompilerTest {
     void qualifiedName() {
         String inputExpression = "My Person.Full Name";
         Type personType = new MapBackedType("Person", mapOf( entry("Full 
Name", BuiltInType.STRING), entry("Age", BuiltInType.NUMBER) ) );
-        CompiledFEELExpression qualRef = parse( inputExpression, mapOf( 
entry("My Person", personType) ) );
+        CompiledFEELExpression qualRef = parseCodegen(inputExpression, 
mapOf(entry("My Person", personType) ) );
         LOG.debug("{}", qualRef);
         
         EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
@@ -412,7 +433,7 @@ public class DirectCompilerTest {
         assertThat(result).isEqualTo("John Doe" );
 
         // check number coercion for qualified name
-        CompiledFEELExpression personAgeExpression = parse("My Person.Age", 
mapOf(entry("My Person", personType)));
+        CompiledFEELExpression personAgeExpression = parseCodegen("My 
Person.Age", mapOf(entry("My Person", personType)));
         LOG.debug("{}", personAgeExpression);
 
         Object resultPersonAge = personAgeExpression.apply(context); // Please 
notice input variable in context is a Map containing and entry value for int 47.
@@ -432,7 +453,7 @@ public class DirectCompilerTest {
     void qualifiedName2() {
         String inputExpression = "My Person.Full Name";
         Type personType = JavaBackedType.of(MyPerson.class);
-        CompiledFEELExpression qualRef = parse( inputExpression, mapOf( 
entry("My Person", personType) ) );
+        CompiledFEELExpression qualRef = parseCodegen(inputExpression, 
mapOf(entry("My Person", personType) ) );
         LOG.debug("{}", qualRef);
         
         EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
@@ -447,7 +468,7 @@ public class DirectCompilerTest {
     void qualifiedName3() {
         String inputExpression = "a date.year";
         Type dateType = BuiltInType.DATE;
-        CompiledFEELExpression qualRef = parse(inputExpression, mapOf(entry("a 
date", dateType)));
+        CompiledFEELExpression qualRef = parseCodegen(inputExpression, 
mapOf(entry("a date", dateType)));
         LOG.debug("{}", qualRef);
         
         EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/ForExpressionNodeTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/ForExpressionNodeTest.java
new file mode 100644
index 0000000000..290abe5132
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/ForExpressionNodeTest.java
@@ -0,0 +1,89 @@
+/**
+ * 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.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+import org.kie.dmn.feel.codegen.feel11.CodegenTestUtil;
+import org.kie.dmn.feel.lang.Type;
+import org.kie.dmn.feel.lang.types.BuiltInType;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ForExpressionNodeTest {
+
+    @Test
+    void evaluateSimpleArray() {
+        IterationContextNode x = getIterationContextNode("x", getListNode("[ 
1, 2, 3, 4 ]", Arrays.asList("1", "2", "3", "4")), "x in [ 1, 2, 3, 4 ]");
+        IterationContextNode y = getIterationContextNode("y", 
getNameRefNode(BuiltInType.UNKNOWN, "x"), "y in x");
+        ForExpressionNode forExpressionNode = new 
ForExpressionNode(Arrays.asList(x, y), getNameRefNode(BuiltInType.UNKNOWN, 
"y"), "for x in [ 1, 2, 3, 4 ], y in x return y");
+        Object retrieved = 
forExpressionNode.evaluate(CodegenTestUtil.newEmptyEvaluationContext());
+        assertThat(retrieved).isInstanceOf(List.class).asList().
+                containsExactly(BigDecimal.ONE, BigDecimal.valueOf(2), 
BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+    }
+
+    @Test
+    void evaluateNestedArray() {
+        Map<String, List<String>> firstIterationContext = new 
LinkedHashMap<>();
+        firstIterationContext.put("1, 2", Arrays.asList("1", "2"));
+        firstIterationContext.put("3, 4", Arrays.asList("3", "4"));
+        IterationContextNode x = getIterationContextNode("x", 
getNestedListNode("[ [1, 2], [3, 4] ]", firstIterationContext), "x in [ [1, 2], 
[3, 4] ]");
+        IterationContextNode y = getIterationContextNode("y", 
getNameRefNode(BuiltInType.UNKNOWN, "x"), "y in x");
+        ForExpressionNode forExpressionNode = new 
ForExpressionNode(Arrays.asList(x, y), getNameRefNode(BuiltInType.UNKNOWN, 
"y"), "for x in [ [1, 2], [3, 4] ], y in x return y");
+        Object retrieved = 
forExpressionNode.evaluate(CodegenTestUtil.newEmptyEvaluationContext());
+        assertThat(retrieved).isInstanceOf(List.class).asList().
+                containsExactly(BigDecimal.ONE, BigDecimal.valueOf(2), 
BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+
+    }
+
+    private IterationContextNode getIterationContextNode(String variableName, 
BaseNode expression, String text) {
+        return new IterationContextNode(getNameDefNode(variableName), 
expression, null, text);
+    }
+
+    private NameDefNode getNameDefNode(String text) {
+       return  new NameDefNode(Collections.singletonList(text), null, text);
+    }
+
+    private NameRefNode getNameRefNode(Type type, String text) {
+        return  new NameRefNode(type, text);
+    }
+
+    private ListNode getNestedListNode(String text,  Map<String, List<String>> 
values) {
+        List<BaseNode> elements = values.entrySet()
+                .stream()
+                .map(entry -> getListNode(entry.getKey(), entry.getValue()))
+                .map(BaseNode.class::cast)
+                .toList();
+        return new ListNode(elements, text);
+    }
+
+    private ListNode getListNode(String text, List<String> values) {
+        List<BaseNode> elements = values.stream()
+                .map(value -> new NumberNode(new BigDecimal(value), value))
+                .map(BaseNode.class::cast)
+                .toList();
+        return new ListNode(elements, text);
+    }
+}
\ No newline at end of file
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELCompilerTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELCompilerTest.java
new file mode 100644
index 0000000000..80502839d7
--- /dev/null
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/FEELCompilerTest.java
@@ -0,0 +1,484 @@
+/**
+ * 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.runtime;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.kie.dmn.feel.codegen.feel11.CodegenTestUtil;
+import org.kie.dmn.feel.codegen.feel11.CompiledFEELExpression;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELProperty;
+import org.kie.dmn.feel.lang.Type;
+import org.kie.dmn.feel.lang.impl.JavaBackedType;
+import org.kie.dmn.feel.lang.impl.MapBackedType;
+import org.kie.dmn.feel.lang.types.BuiltInType;
+import org.kie.dmn.feel.parser.feel11.FEELParserTest;
+import org.kie.dmn.feel.runtime.functions.CustomFEELFunction;
+import org.kie.dmn.feel.util.CompilerUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.kie.dmn.feel.util.CompilerUtils.parseInterpreted;
+import static 
org.kie.dmn.feel.util.CompilerUtils.parseInterpretedCompileEvaluate;
+import static org.kie.dmn.feel.util.DynamicTypeUtils.entry;
+import static org.kie.dmn.feel.util.DynamicTypeUtils.mapOf;
+
+public class FEELCompilerTest {
+
+    public static final Logger LOG = 
LoggerFactory.getLogger(FEELCompilerTest.class);
+
+
+    @Test
+    void feel_number() {
+        
assertThat(parseInterpretedCompileEvaluate("10")).isEqualTo(BigDecimal.valueOf(10));
+    }
+
+    @Test
+    void feel_negative_number() {
+        
assertThat(parseInterpretedCompileEvaluate("-10")).isEqualTo(BigDecimal.valueOf(-10));
+    }
+
+    @Test
+    void feel_drools_2143() {
+        // DROOLS-2143: Allow ''--1' expression as per FEEL grammar rule 26 
+        
assertThat(parseInterpretedCompileEvaluate("--10")).isEqualTo(BigDecimal.valueOf(10));
+        
assertThat(parseInterpretedCompileEvaluate("---10")).isEqualTo(BigDecimal.valueOf(-10));
+        
assertThat(parseInterpretedCompileEvaluate("+10")).isEqualTo(BigDecimal.valueOf(10));
+    }
+
+    @Test
+    void feel_boolean() {
+        
assertThat(parseInterpretedCompileEvaluate("false")).isEqualTo(Boolean.FALSE);
+        
assertThat(parseInterpretedCompileEvaluate("true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("null")).isNull();
+    }
+
+    @Test
+    void feel_null() {
+        assertThat(parseInterpretedCompileEvaluate("null")).isNull();
+    }
+
+    @Test
+    void feel_string() {
+        assertThat(parseInterpretedCompileEvaluate("\"some 
string\"")).isEqualTo("some string" );
+    }
+
+    @Test
+    void primary_parens() {
+        assertThat(parseInterpretedCompileEvaluate("(\"some 
string\")")).isEqualTo("some string" );
+        
assertThat(parseInterpretedCompileEvaluate("(123)")).isEqualTo(BigDecimal.valueOf(123));
+        
assertThat(parseInterpretedCompileEvaluate("(-123)")).isEqualTo(BigDecimal.valueOf(-123));
+        
assertThat(parseInterpretedCompileEvaluate("-(123)")).isEqualTo(BigDecimal.valueOf(-123));
+        
assertThat(parseInterpretedCompileEvaluate("(false)")).isEqualTo(Boolean.FALSE);
+        
assertThat(parseInterpretedCompileEvaluate("(true)")).isEqualTo(Boolean.TRUE);
+    }
+
+    /**
+     * See {@link FEELTernaryLogicTest}
+     */
+    @Test
+    void ternary_logic() {
+        assertThat(parseInterpretedCompileEvaluate("true and 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("true and 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("true and null")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("false and 
true")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("false and 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("false and 
null")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("null and true")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("null and 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("null and null")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("true or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("true or 
false")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("true or 
null")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("false or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("false or 
false")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("false or null")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("null or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("null or false")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("null or null")).isNull();
+        // logical operator priority
+        assertThat(parseInterpretedCompileEvaluate("false and false or 
true")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("false and (false or 
true)")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("true or false and 
false")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("(true or false) and 
false")).isEqualTo(Boolean.FALSE);
+    }
+
+    /**
+     * Partially from {@link FEELConditionsAndLoopsTest}
+     */
+    @Test
+    void test_if() {
+        assertThat(parseInterpretedCompileEvaluate("if true then 15 else 
5")).isEqualTo(BigDecimal.valueOf(15 ));
+        assertThat(parseInterpretedCompileEvaluate("if false then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5 ));
+        assertThat(parseInterpretedCompileEvaluate("if null then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5));
+        assertThat(parseInterpretedCompileEvaluate("if \"hello\" then 15 else 
5")).isEqualTo(BigDecimal.valueOf(5));
+    }
+
+    @Test
+    void additive_expression() {
+        assertThat(parseInterpretedCompileEvaluate("1 + 
2")).isEqualTo(BigDecimal.valueOf(3 ));
+        assertThat(parseInterpretedCompileEvaluate("1 + null")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("1 - 
2")).isEqualTo(BigDecimal.valueOf(-1 ));
+        assertThat(parseInterpretedCompileEvaluate("1 - null")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("\"Hello, \" + 
\"World\"")).isEqualTo("Hello, World");
+    }
+
+    @Test
+    void multiplicative_expression() {
+        assertThat(parseInterpretedCompileEvaluate("3 * 
5")).isEqualTo(BigDecimal.valueOf(15));
+        assertThat(parseInterpretedCompileEvaluate("3 * null")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("10 / 
2")).isEqualTo(BigDecimal.valueOf(5));
+        assertThat(parseInterpretedCompileEvaluate("10 / null")).isNull();
+    }
+
+    @Test
+    void exponentiation_expression() {
+        assertThat(parseInterpretedCompileEvaluate("3 ** 
3")).isEqualTo(BigDecimal.valueOf(27));
+        assertThat(parseInterpretedCompileEvaluate("3 ** null")).isNull();
+    }
+
+    @Test
+    void logical_negation_expression() {
+        // this is all invalid syntax
+        assertThat(parseInterpretedCompileEvaluate("not true")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("not false")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("not null")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("not 3")).isNull();
+    }
+
+    @Test
+    void list_expression() {
+        assertThat(parseInterpretedCompileEvaluate("[]")).asList().isEmpty();
+        assertThat(parseInterpretedCompileEvaluate("[ ]")).asList().isEmpty();
+        
assertThat(parseInterpretedCompileEvaluate("[1]")).asList().containsExactly(BigDecimal.valueOf(1));
+        assertThat(parseInterpretedCompileEvaluate("[1, 
2,3]")).asList().containsExactly(BigDecimal.valueOf(1), BigDecimal.valueOf(2), 
BigDecimal.valueOf(3));
+    }
+
+    @Test
+    void instance_of_expression() {
+        assertThat(parseInterpretedCompileEvaluate("123 instance of 
number")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("\"ciao\" instance of 
number")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("123 instance of 
string")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("\"ciao\" instance of 
string")).isEqualTo(Boolean.TRUE);
+    }
+
+    @Test
+    void between() {
+        assertThat(parseInterpretedCompileEvaluate("10 between 5 and 
12")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("10 between 20 and 
30")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("10 between 5 and 
\"foo\"")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("\"foo\" between 5 and 
12")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("\"foo\" between \"bar\" 
and \"zap\"")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("\"foo\" between null and 
\"zap\"")).isNull();
+    }
+
+    @Test
+    void filter_path() {
+        // Filtering by index
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][1]")).isEqualTo("a");
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][2]")).isEqualTo("b");
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][3]")).isEqualTo("c");
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][-1]")).isEqualTo("c");
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][-2]")).isEqualTo("b");
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][-3]")).isEqualTo("a");
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][4]")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][984]")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][-4]")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("[\"a\", \"b\", 
\"c\"][-984]")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("\"a\"[1]")).isEqualTo("a");
+        assertThat(parseInterpretedCompileEvaluate("\"a\"[2]")).isNull();
+        
assertThat(parseInterpretedCompileEvaluate("\"a\"[-1]")).isEqualTo("a");
+        assertThat(parseInterpretedCompileEvaluate("\"a\"[-2]")).isNull();
+
+        // Filtering by boolean expression
+        assertThat(parseInterpretedCompileEvaluate("[1, 2, 3, 4][item = 
4]")).asList().containsExactly(BigDecimal.valueOf(4));
+        assertThat(parseInterpretedCompileEvaluate("[1, 2, 3, 4][item > 
2]")).asList().containsExactly(BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+        assertThat(parseInterpretedCompileEvaluate("[1, 2, 3, 4][item > 
5]")).asList().isEmpty();
+        assertThat(parseInterpretedCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
][x = 1]")).asList().containsExactly(mapOf(entry("x", new BigDecimal(1)), 
entry("y", new BigDecimal(2))));
+        assertThat(parseInterpretedCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
][x > 1]")).asList().containsExactly(mapOf(entry("x", new BigDecimal(2)), 
entry("y", new BigDecimal(3))));
+        assertThat(parseInterpretedCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
][x = 0]")).asList().isEmpty();
+    }
+
+    @Test
+    void filter_path_tricky1() {
+        CompiledFEELExpression nameRef = CompilerUtils.parseInterpreted("[ 
{x:1, y:2}, {x:2, y:3} ][x]");
+        LOG.debug("{}", nameRef);
+        
+        EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
+        context.setValue("x", 2);
+        Object result = nameRef.apply(context);
+        LOG.debug("{}", result);
+        
+        assertThat(result).isEqualTo(mapOf(entry("x", new BigDecimal(2)), 
entry("y", new BigDecimal(3))));
+    }
+
+    @Test
+    void filter_path_tricky2() {
+        CompiledFEELExpression nameRef = CompilerUtils.parseInterpreted("[ 
{x:1, y:2}, {x:2, y:3} ][x]");
+        LOG.debug("{}", nameRef);
+
+        EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
+        context.setValue("x", false);
+        Object result = nameRef.apply(context);
+        LOG.debug("{}", result);
+
+        assertThat(result).asList().isEmpty();
+    }
+
+    @Test
+    void filter_path_selection() {
+        // Selection
+        assertThat(parseInterpretedCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
].y")).asList().containsExactly(BigDecimal.valueOf(2), BigDecimal.valueOf(3));
+        assertThat(parseInterpretedCompileEvaluate("[ {x:1, y:2}, {x:2} 
].y")).asList().containsExactly(BigDecimal.valueOf(2), null);
+        assertThat(parseInterpretedCompileEvaluate("[ {x:1, y:2}, {x:2, y:3} 
].z")).asList().containsExactly(null, null);
+    }
+
+    @Test
+    void test_for() {
+        // for
+        Object parseCompileEvaluate = parseInterpretedCompileEvaluate("for x 
in [ 10, 20, 30 ], y in [ 1, 2, 3 ] return x * y");
+               assertThat(parseCompileEvaluate).asList().
+               containsExactly(BigDecimal.valueOf(10), BigDecimal.valueOf(20), 
BigDecimal.valueOf(30), BigDecimal.valueOf(20), BigDecimal.valueOf(40), 
BigDecimal.valueOf(60), BigDecimal.valueOf(30), BigDecimal.valueOf(60), 
BigDecimal.valueOf(90));
+
+        // normal:
+        assertThat(parseInterpretedCompileEvaluate("for x in [1, 2, 3] return 
x+1")).asList().
+               containsExactly(BigDecimal.valueOf(2), BigDecimal.valueOf(3), 
BigDecimal.valueOf(4));
+        
+        // TODO in order to parse correctly the enhanced for loop it is 
required to configure the FEEL Profiles
+    }
+
+    @Test
+    void test_nested_for() {
+        List<BigDecimal> firstExpected = Arrays.asList(BigDecimal.ONE, 
BigDecimal.valueOf(2));
+        List<BigDecimal> secondExpected = Arrays.asList(BigDecimal.valueOf(3), 
BigDecimal.valueOf(4));
+        Object parseCompileEvaluate = parseInterpretedCompileEvaluate("for x 
in [ [1, 2], [3, 4] ] return x");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(firstExpected, secondExpected);
+        parseCompileEvaluate = parseInterpretedCompileEvaluate("for x in [ 
[1,2], [3,4] ] return for y in x return y");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(firstExpected, secondExpected);
+        parseCompileEvaluate = 
CompilerUtils.parseInterpretedCompileEvaluate("for x in [ 1, 2, 3, 4 ], y in x 
return y");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(BigDecimal.ONE, BigDecimal.valueOf(2), 
BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+        parseCompileEvaluate = parseInterpretedCompileEvaluate("for x in [ 
[1,2], [3,4] ], y in x return y");
+        assertThat(parseCompileEvaluate).asList().
+                containsExactly(BigDecimal.ONE, BigDecimal.valueOf(2), 
BigDecimal.valueOf(3), BigDecimal.valueOf(4));
+    }
+
+    @Test
+    void quantified_expressions() {
+        // quantified expressions
+        assertThat(parseInterpretedCompileEvaluate("some price in [ 80, 11, 
110 ] satisfies price > 100")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("some price in [ 80, 11, 90 
] satisfies price > 100")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("some x in [ 5, 6, 7 ], y 
in [ 10, 11, 6 ] satisfies x > y")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("every price in [ 80, 11, 
90 ] satisfies price > 10")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("every price in [ 80, 11, 
90 ] satisfies price > 70")).isEqualTo(Boolean.FALSE);
+        assertThat(parseInterpretedCompileEvaluate("some x in [ 5, 6, 7 ], y 
in [ 10, 11, 12 ] satisfies x < y")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("some price in [ 80, 11, 
110 ] satisfies price > max(100, 50, 10)")).isEqualTo(Boolean.TRUE);
+    }
+
+    @Test
+    void basic_function_invocation() {
+        assertThat(parseInterpretedCompileEvaluate("max(1, 2, 
3)")).isEqualTo(new BigDecimal(3));
+    }
+
+    @Test
+    void basic_function_definition() {
+        assertThat(parseInterpretedCompileEvaluate("function (a, b) a + 
b")).isInstanceOf(CustomFEELFunction.class);
+        assertThat(parseInterpretedCompileEvaluate("{ s : function (a, b) a + 
b, x : 1, y : 2, r : s(x,y) }.r")).isEqualTo(new BigDecimal(3));
+    }
+
+    @Test
+    void named_function_invocation() {
+        assertThat(parseInterpretedCompileEvaluate("substring(start position: 
2, string: \"FOOBAR\")")).isEqualTo("OOBAR");
+        assertThat(parseInterpretedCompileEvaluate("ceiling( n : 1.5 
)")).isEqualTo(new BigDecimal("2"));
+    }
+
+    @Test
+    void misc_from_original_feelinterpreted_test_suite() {
+        assertThat(parseInterpretedCompileEvaluate("if null then \"foo\" else 
\"bar\"")).isEqualTo("bar");
+        assertThat(parseInterpretedCompileEvaluate("{ hello world : function() 
\"Hello World!\", message : hello world() }.message")).isEqualTo("Hello 
World!");
+        assertThat(parseInterpretedCompileEvaluate("1 + if true then 1 else 
2")).isEqualTo(new BigDecimal("2"));
+        assertThat(parseInterpretedCompileEvaluate("\"string with 
\\\"quotes\\\"\"")).isEqualTo("string with \"quotes\"");
+        assertThat(parseInterpretedCompileEvaluate("date( -0105, 8, 2 
)")).isEqualTo(LocalDate.of(-105, 8, 2));
+        assertThat(parseInterpretedCompileEvaluate("string(null)")).isNull();
+        assertThat(parseInterpretedCompileEvaluate("[ null 
]")).asList().containsExactly(new Object[]{null});
+        assertThat(parseInterpretedCompileEvaluate("[ null, null 
]")).asList().containsExactly(null, null);
+        assertThat(parseInterpretedCompileEvaluate("[ null, 47, null 
]")).asList().containsExactly(null, BigDecimal.valueOf(47), null);
+    }
+
+    @Test
+    void benchmark_feel_expressions() {
+        assertThat(parseInterpretedCompileEvaluate("{ full name: { first name: 
\"John\", last name: \"Doe\" } }.full name.last name")).isEqualTo("Doe");
+        assertThat(parseInterpretedCompileEvaluate("some price in [ 80, 11, 
110 ] satisfies price > 100")).isEqualTo(Boolean.TRUE);
+        assertThat(parseInterpretedCompileEvaluate("every price in [ 80, 11, 
90 ] satisfies price > 10")).isEqualTo(Boolean.TRUE);
+    }
+
+    @Test
+    void context_expression() {
+        
assertThat(parseInterpretedCompileEvaluate("{}")).isEqualTo(Collections.emptyMap());
+        assertThat(parseInterpretedCompileEvaluate("{ 
}")).isEqualTo(Collections.emptyMap());
+        assertThat(parseInterpretedCompileEvaluate("{ a : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1))));
+        assertThat(parseInterpretedCompileEvaluate("{ \"a\" : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1))));
+        assertThat(parseInterpretedCompileEvaluate("{ \" a\" : 1 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)))); // Demonstrating a bad 
practice.
+        assertThat(parseInterpretedCompileEvaluate("{ a : 1, b : 2, c : 3 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("b", new 
BigDecimal(2)), entry("c", new BigDecimal(3))));
+        assertThat(parseInterpretedCompileEvaluate("{ a : 1, a name : \"John 
Doe\" }")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("a name", "John 
Doe")));
+
+        assertThat(parseInterpretedCompileEvaluate("{ a : 1, b : a 
}")).isEqualTo(mapOf(entry("a", new BigDecimal(1)), entry("b", new 
BigDecimal(1))));
+    }
+
+    /**
+     * See {@link FEELParserTest}
+     */
+    @Test
+    void contextWithMultipleEntries() {
+        String inputExpression = "{ \"a string key\" : 10," + "\n"
+                               + " a non-string key : 11," + "\n"
+                               + " a key.with + /' odd chars : 12 }";
+        
assertThat(parseInterpretedCompileEvaluate(inputExpression)).isEqualTo(mapOf(entry("a
 string key", new BigDecimal(10)), entry("a non-string key", new 
BigDecimal(11)), entry("a key.with + /' odd chars", new BigDecimal(12))));
+    }
+
+    /**
+     * See {@link FEELParserTest}
+     */
+    @Test
+    void nestedContexts() {
+        String inputExpression = "{ a value : 10," + "\n"
+                       + " an applicant : { " + "\n"
+                       + "    first name : \"Edson\", " + "\n"
+                       + "    last + name : \"Tirelli\", " + "\n"
+                       + "    full name : first name + last + name, " + "\n"
+                       + "    address : {" + "\n"
+                       + "        street : \"55 broadway st\"," + "\n"
+                       + "        city : \"New York\" " + "\n"
+                       + "    }, " + "\n"
+                       + "    xxx: last + name" + "\n"
+                       + " } " + "\n"
+                       + "}";
+        
assertThat(parseInterpretedCompileEvaluate(inputExpression)).isEqualTo(mapOf(entry("a
 value", new BigDecimal(10)),
+                                                                               
  entry("an applicant", mapOf(entry("first name", "Edson"),
+                                                                               
                entry("last + name", "Tirelli"),
+                                                                               
                entry("full name", "EdsonTirelli"),
+                                                                               
                entry("address", mapOf(entry("street", "55 broadway st"),
+                                                                               
                                       entry("city", "New York"))),
+                                                                               
                entry("xxx", "Tirelli")))));
+    }
+
+    /**
+     * See {@link FEELParserTest}
+     */
+    @Test
+    void nestedContexts2() {
+        String complexContext = "{ an applicant : {                            
    \n" +
+                                "    home address : {                          
    \n" +
+                                "        street name: \"broadway st\",         
    \n" +
+                                "        city : \"New York\"                   
    \n" +
+                                "    }                                         
    \n" +
+                                "   },                                         
    \n" +
+                                "   street : an applicant.home address.street 
name \n" +
+                                "}                                             
    ";
+        
assertThat(parseInterpretedCompileEvaluate(complexContext)).isEqualTo(mapOf(entry("an
 applicant", mapOf(entry("home address", mapOf(entry("street name", "broadway 
st"),
+                                                                               
                                                         entry("city", "New 
York"))))),
+                                                                               
 entry("street", "broadway st")));
+    }
+
+    @Test
+    void nameReference() {
+        String inputExpression = "someSimpleName";
+        CompiledFEELExpression nameRef = parseInterpreted(inputExpression, 
mapOf(entry("someSimpleName", BuiltInType.STRING) ) );
+        LOG.debug("{}", nameRef);
+        
+        EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
+        context.setValue("someSimpleName", 123L);
+        Object result = nameRef.apply(context);
+        LOG.debug("{}", result);
+        
+        assertThat(result).isEqualTo(BigDecimal.valueOf(123));
+    }
+
+    @Test
+    void qualifiedName() {
+        String inputExpression = "My Person.Full Name";
+        Type personType = new MapBackedType("Person", mapOf( entry("Full 
Name", BuiltInType.STRING), entry("Age", BuiltInType.NUMBER) ) );
+        CompiledFEELExpression qualRef = parseInterpreted(inputExpression, 
mapOf(entry("My Person", personType) ) );
+        LOG.debug("{}", qualRef);
+        
+        EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
+        context.setValue("My Person", mapOf( entry("Full Name", "John Doe"), 
entry("Age", 47) ));
+        Object result = qualRef.apply(context);
+        LOG.debug("{}", result);
+        
+        assertThat(result).isEqualTo("John Doe" );
+
+        // check number coercion for qualified name
+        CompiledFEELExpression personAgeExpression = parseInterpreted("My 
Person.Age", mapOf(entry("My Person", personType)));
+        LOG.debug("{}", personAgeExpression);
+
+        Object resultPersonAge = personAgeExpression.apply(context); // Please 
notice input variable in context is a Map containing and entry value for int 47.
+        LOG.debug("{}", resultPersonAge);
+
+        assertThat(resultPersonAge).isEqualTo(BigDecimal.valueOf(47));
+    }
+    
+    public static class MyPerson {
+        @FEELProperty("Full Name")
+        public String getFullName() {
+            return "John Doe";
+        }
+    }
+
+    @Test
+    void qualifiedName2() {
+        String inputExpression = "My Person.Full Name";
+        Type personType = JavaBackedType.of(MyPerson.class);
+        CompiledFEELExpression qualRef = parseInterpreted(inputExpression, 
mapOf(entry("My Person", personType) ) );
+        LOG.debug("{}", qualRef);
+        
+        EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
+        context.setValue("My Person", new MyPerson());
+        Object result = qualRef.apply(context);
+        LOG.debug("{}", result);
+        
+        assertThat(result).isEqualTo("John Doe" );
+    }
+
+    @Test
+    void qualifiedName3() {
+        String inputExpression = "a date.year";
+        Type dateType = BuiltInType.DATE;
+        CompiledFEELExpression qualRef = parseInterpreted(inputExpression, 
mapOf(entry("a date", dateType)));
+        LOG.debug("{}", qualRef);
+        
+        EvaluationContext context = 
CodegenTestUtil.newEmptyEvaluationContext();
+        context.setValue("a date", LocalDate.of(2016, 8, 2));
+        Object result = qualRef.apply(context);
+        LOG.debug("{}", result);
+        
+        assertThat(result).isEqualTo(BigDecimal.valueOf(2016));
+    }
+
+    
+
+}
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunctionTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunctionTest.java
index 72dfd91742..83091ae306 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunctionTest.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/ListReplaceFunctionTest.java
@@ -30,7 +30,7 @@ import org.junit.jupiter.api.Test;
 import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.kie.dmn.feel.util.CompilerUtils.parseCompileEvaluate;
+import static org.kie.dmn.feel.util.CompilerUtils.parseCodegenCompileEvaluate;
 
 class ListReplaceFunctionTest {
 
@@ -101,7 +101,7 @@ class ListReplaceFunctionTest {
     void invokeMatchInvalid() {
         List list = Arrays.asList(2, 4, 7, 8);
         String validMatchFunction = "function(item, newItem) item + newItem";
-        Object expressionObject = parseCompileEvaluate(validMatchFunction);
+        Object expressionObject = 
parseCodegenCompileEvaluate(validMatchFunction);
         
assertThat(expressionObject).isInstanceOf(AbstractCustomFEELFunction.class);
         FunctionTestUtil.assertResultError(listReplaceFunction.invoke(list, 
(AbstractCustomFEELFunction)expressionObject, 3), InvalidParametersEvent.class);
     }
@@ -112,7 +112,7 @@ class ListReplaceFunctionTest {
         List expected = new ArrayList<>(list);
         expected.set(1, null);
         String validMatchFunction = "function(item, newItem) item = 
\"Element-1\"";
-        Object expressionObject = parseCompileEvaluate(validMatchFunction);
+        Object expressionObject = 
parseCodegenCompileEvaluate(validMatchFunction);
         
assertThat(expressionObject).isInstanceOf(AbstractCustomFEELFunction.class);
         FunctionTestUtil.assertResult(listReplaceFunction.invoke(list, 
(AbstractCustomFEELFunction)expressionObject, null), expected);
     }
@@ -120,7 +120,7 @@ class ListReplaceFunctionTest {
     @Test
     void invokeReplaceByMatchWithNotNull() {
         String validMatchFunction = "function(item, newItem) item < newItem";
-        Object expressionObject = parseCompileEvaluate(validMatchFunction);
+        Object expressionObject = 
parseCodegenCompileEvaluate(validMatchFunction);
         
assertThat(expressionObject).isInstanceOf(AbstractCustomFEELFunction.class);
         List list = Arrays.asList(BigDecimal.valueOf(2), 
BigDecimal.valueOf(4), BigDecimal.valueOf(7), BigDecimal.valueOf(8));
         List expected = new ArrayList<>(list);
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/CompilerUtils.java 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/CompilerUtils.java
index b56bd81798..c201ec39ca 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/CompilerUtils.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/util/CompilerUtils.java
@@ -31,6 +31,8 @@ import org.kie.dmn.feel.codegen.feel11.CompilerBytecodeLoader;
 import org.kie.dmn.feel.lang.EvaluationContext;
 import org.kie.dmn.feel.lang.Type;
 import org.kie.dmn.feel.lang.ast.BaseNode;
+import org.kie.dmn.feel.lang.impl.CompiledExpressionImpl;
+import org.kie.dmn.feel.lang.impl.InterpretedExecutableExpression;
 import org.kie.dmn.feel.parser.feel11.ASTBuilderVisitor;
 import org.kie.dmn.feel.parser.feel11.FEELParser;
 import org.kie.dmn.feel.parser.feel11.FEEL_1_1Parser;
@@ -43,21 +45,17 @@ public class CompilerUtils {
     private static final String TEMPLATE_RESOURCE = 
"/TemplateCompiledFEELExpression.java";
     private static final String TEMPLATE_CLASS = 
"TemplateCompiledFEELExpression";
 
-    public static Object parseCompileEvaluate(String feelLiteralExpression) {
-        CompiledFEELExpression compiledExpression = parse( 
feelLiteralExpression );
-        LOG.debug("{}", compiledExpression);
-
-        EvaluationContext emptyContext = 
CodegenTestUtil.newEmptyEvaluationContext();
-        Object result = compiledExpression.apply(emptyContext);
-        LOG.debug("{}", result);
-        return result;
+    public static Object parseCodegenCompileEvaluate(String 
feelLiteralExpression) {
+        LOG.debug("{}", feelLiteralExpression);
+        CompiledFEELExpression compiledExpression = 
parseCodegen(feelLiteralExpression );
+        return evaluate(compiledExpression);
     }
 
-    public static CompiledFEELExpression parse(String input) {
-        return parse(input, Collections.emptyMap() );
+    public static CompiledFEELExpression parseCodegen(String input) {
+        return parseCodegen(input, Collections.emptyMap() );
     }
 
-    public static CompiledFEELExpression parse(String input, Map<String, Type> 
inputTypes) {
+    public static CompiledFEELExpression parseCodegen(String input, 
Map<String, Type> inputTypes) {
         FEEL_1_1Parser parser = FEELParser.parse(null, input, inputTypes, 
Collections.emptyMap(), Collections.emptyList(), Collections.emptyList(), null);
 
         ParseTree tree = parser.compilation_unit();
@@ -80,4 +78,32 @@ public class CompilerUtils {
         return compilerBytecodeLoader.compileUnit(packageName, TEMPLATE_CLASS, 
cu);
     }
 
+    public static Object parseInterpretedCompileEvaluate(String 
feelLiteralExpression) {
+        LOG.debug("{}", feelLiteralExpression);
+        CompiledFEELExpression compiledExpression = 
parseInterpreted(feelLiteralExpression );
+        return evaluate(compiledExpression);
+    }
+
+    public static CompiledFEELExpression parseInterpreted(String input) {
+        return parseInterpreted(input, Collections.emptyMap() );
+    }
+
+    public static CompiledFEELExpression parseInterpreted(String input, 
Map<String, Type> inputTypes) {
+        FEEL_1_1Parser parser = FEELParser.parse(null, input, inputTypes, 
Collections.emptyMap(), Collections.emptyList(), Collections.emptyList(), null);
+
+        ParseTree tree = parser.compilation_unit();
+
+        ASTBuilderVisitor v = new ASTBuilderVisitor(inputTypes, null);
+        BaseNode ast = tree.accept(v);
+        return new InterpretedExecutableExpression(new 
CompiledExpressionImpl(ast));
+    }
+
+    public static Object evaluate(CompiledFEELExpression compiledExpression) {
+        LOG.debug("{}", compiledExpression);
+        EvaluationContext emptyContext = 
CodegenTestUtil.newEmptyEvaluationContext();
+        Object result = compiledExpression.apply(emptyContext);
+        LOG.debug("{}", result);
+        return result;
+    }
+
 }
\ No newline at end of file


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


Reply via email to