METRON-980: Short circuit operations for Stellar closes apache/metron#606

Project: http://git-wip-us.apache.org/repos/asf/metron/repo
Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/30d0e2a6
Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/30d0e2a6
Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/30d0e2a6

Branch: refs/heads/master
Commit: 30d0e2a6faa1c1205522758e5fd15f35ebc9fcbb
Parents: 7d6121b
Author: cstella <ceste...@gmail.com>
Authored: Fri Jun 9 11:48:27 2017 -0400
Committer: cstella <ceste...@gmail.com>
Committed: Fri Jun 9 11:48:27 2017 -0400

----------------------------------------------------------------------
 .../profiler/client/window/WindowProcessor.java |   2 +-
 metron-platform/metron-common/README.md         |   1 +
 .../metron/common/stellar/generated/Stellar.g4  |  16 +-
 .../org/apache/metron/common/dsl/Token.java     |  14 +
 .../common/stellar/BaseStellarProcessor.java    |   1 +
 .../metron/common/stellar/FrameContext.java     |  45 ++
 .../metron/common/stellar/StellarCompiler.java  | 287 +++++--
 .../stellar/evaluators/ArithmeticEvaluator.java |  42 +-
 ...mparisonExpressionWithOperatorEvaluator.java |   9 +-
 .../evaluators/DoubleLiteralEvaluator.java      |   5 +-
 .../evaluators/FloatLiteralEvaluator.java       |   5 +-
 .../stellar/evaluators/IntLiteralEvaluator.java |   5 +-
 .../evaluators/LongLiteralEvaluator.java        |   5 +-
 .../stellar/evaluators/NumberEvaluator.java     |   3 +-
 .../evaluators/NumberLiteralEvaluator.java      |   8 +-
 .../stellar/generated/StellarBaseListener.java  |  36 +
 .../stellar/generated/StellarListener.java      |  30 +
 .../common/stellar/generated/StellarParser.java | 774 +++++++++++--------
 .../dsl/functions/FunctionalFunctionsTest.java  |  17 +
 .../common/stellar/StellarInterpreterTest.java  |  24 +-
 .../metron/common/stellar/StellarTest.java      | 101 ++-
 .../evaluators/ArithmeticEvaluatorTest.java     |  58 +-
 ...isonExpressionWithOperatorEvaluatorTest.java |  10 +-
 .../evaluators/DoubleLiteralEvaluatorTest.java  |   8 +-
 .../evaluators/FloatLiteralEvaluatorTest.java   |   8 +-
 .../evaluators/IntLiteralEvaluatorTest.java     |   8 +-
 .../evaluators/LongLiteralEvaluatorTest.java    |   8 +-
 .../evaluators/NumberLiteralEvaluatorTest.java  |  18 +-
 28 files changed, 1029 insertions(+), 519 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/window/WindowProcessor.java
----------------------------------------------------------------------
diff --git 
a/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/window/WindowProcessor.java
 
b/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/window/WindowProcessor.java
index 16a7513..1ae4aaf 100644
--- 
a/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/window/WindowProcessor.java
+++ 
b/metron-analytics/metron-profiler-client/src/main/java/org/apache/metron/profiler/client/window/WindowProcessor.java
@@ -89,7 +89,7 @@ public class WindowProcessor extends WindowBaseListener {
     if(checkForException(ctx)) {
       return;
     }
-    stack.push(new Token<>(ctx.getText().substring(1), String.class));
+    stack.push(new Token<>(ctx.getText().substring(1), String.class ));
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/README.md
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/README.md 
b/metron-platform/metron-common/README.md
index 9e1de7a..95f59ba 100644
--- a/metron-platform/metron-common/README.md
+++ b/metron-platform/metron-common/README.md
@@ -26,6 +26,7 @@ The query language supports the following:
   * The literal `"\"foo\""` would represent `"foo"`
   * The literal `'foo \\ bar'` would represent `foo \ bar`
 * Simple boolean operations: `and`, `not`, `or`
+  * Boolean expressions are short-circuited (e.g. `true or FUNC()` would never 
execute `FUNC`)
 * Simple arithmetic operations: `*`, `/`, `+`, `-` on real numbers or integers
 * Simple comparison operations `<`, `>`, `<=`, `>=`
 * Simple equality comparison operations `==`, `!=`

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/antlr4/org/apache/metron/common/stellar/generated/Stellar.g4
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/antlr4/org/apache/metron/common/stellar/generated/Stellar.g4
 
b/metron-platform/metron-common/src/main/antlr4/org/apache/metron/common/stellar/generated/Stellar.g4
index 8602fde..3577377 100644
--- 
a/metron-platform/metron-common/src/main/antlr4/org/apache/metron/common/stellar/generated/Stellar.g4
+++ 
b/metron-platform/metron-common/src/main/antlr4/org/apache/metron/common/stellar/generated/Stellar.g4
@@ -139,9 +139,21 @@ transformation_expr:
   | in_expr #InExpression
   ;
 
+if_expr:
+  logical_expr
+  ;
+
+then_expr:
+  transformation_expr
+  ;
+
+else_expr:
+  transformation_expr
+  ;
+
 conditional_expr :
-  logical_expr QUESTION transformation_expr COLON transformation_expr 
#TernaryFuncWithoutIf
-  | IF logical_expr THEN transformation_expr ELSE transformation_expr 
#TernaryFuncWithIf
+  if_expr QUESTION then_expr COLON else_expr #TernaryFuncWithoutIf
+  | IF if_expr THEN then_expr ELSE else_expr #TernaryFuncWithIf
   ;
 
 logical_expr:

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/Token.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/Token.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/Token.java
index 4c94be0..cf168a4 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/Token.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/dsl/Token.java
@@ -18,13 +18,27 @@
 
 package org.apache.metron.common.dsl;
 
+import org.apache.metron.common.stellar.FrameContext;
+
 public class Token<T> {
   T value;
   Class<T> underlyingType;
+  FrameContext.Context multiArgContext;
+
   public Token(T value, Class<T> clazz) {
+    this(value, clazz, null);
+  }
+
+  public Token(T value, Class<T> clazz, FrameContext.Context multiArgContext) {
     this.value = value;
     this.underlyingType = clazz;
+    this.multiArgContext = multiArgContext;
   }
+
+  public FrameContext.Context getMultiArgContext() {
+    return multiArgContext;
+  }
+
   public T getValue() {
     return value;
   }

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
index 8f4af93..5bf4a64 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/BaseStellarProcessor.java
@@ -24,6 +24,7 @@ import com.google.common.cache.CacheLoader;
 import com.google.common.util.concurrent.UncheckedExecutionException;
 import org.antlr.v4.runtime.ANTLRInputStream;
 import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.TokenStream;
 
 import java.util.HashSet;

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/FrameContext.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/FrameContext.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/FrameContext.java
new file mode 100644
index 0000000..16bc07a
--- /dev/null
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/FrameContext.java
@@ -0,0 +1,45 @@
+/**
+ * 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.apache.metron.common.stellar;
+
+public enum FrameContext {
+  BOOLEAN_AND,
+  BOOLEAN_OR;
+
+  public static class Context {
+    private FrameContext variety;
+    public Context(FrameContext variety) {
+      this.variety = variety;
+    }
+
+    public FrameContext getVariety() {
+      return variety;
+    }
+
+    @Override
+    public String toString() {
+      return "Context{" +
+              "variety=" + variety +
+              '}';
+    }
+  }
+
+  public Context create() {
+    return new Context(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
index b289f48..136728d 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/StellarCompiler.java
@@ -48,6 +48,15 @@ public class StellarCompiler extends StellarBaseListener {
   private final NumberLiteralEvaluator numberLiteralEvaluator;
   private final ComparisonExpressionWithOperatorEvaluator 
comparisonExpressionWithOperatorEvaluator;
 
+  public interface ShortCircuitOp {}
+
+  public static class ShortCircuitFrame {}
+  public static class BooleanArg implements ShortCircuitOp {}
+  public static class IfExpr implements ShortCircuitOp {}
+  public static class ThenExpr implements ShortCircuitOp {}
+  public static class ElseExpr implements ShortCircuitOp {}
+  public static class EndConditional implements ShortCircuitOp {}
+
   public static class ExpressionState {
     Context context;
     FunctionResolver functionResolver;
@@ -64,10 +73,18 @@ public class StellarCompiler extends StellarBaseListener {
 
   public static class Expression implements Serializable {
     final Deque<Token<?>> tokenDeque;
+    final Deque<FrameContext.Context> multiArgumentState;
     final Set<String> variablesUsed;
     public Expression(Deque<Token<?>> tokenDeque) {
       this.tokenDeque = tokenDeque;
       this.variablesUsed = new HashSet<>();
+      this.multiArgumentState = new ArrayDeque<>();
+    }
+
+    public void clear() {
+      tokenDeque.clear();
+      variablesUsed.clear();
+      multiArgumentState.clear();
     }
 
     public Deque<Token<?>> getTokenDeque() {
@@ -76,14 +93,77 @@ public class StellarCompiler extends StellarBaseListener {
 
     public Object apply(ExpressionState state) {
       Deque<Token<?>> instanceDeque = new ArrayDeque<>();
-      for(Iterator<Token<?>> it = 
getTokenDeque().descendingIterator();it.hasNext();) {
-        Token<?> token = it.next();
-        if(token.getUnderlyingType() == DeferredFunction.class) {
-          DeferredFunction func = (DeferredFunction) token.getValue();
-          func.apply(instanceDeque, state);
-        }
-        else {
-          instanceDeque.push(token);
+      {
+        boolean skipElse = false;
+        Token<?> token = null;
+        for (Iterator<Token<?>> it = getTokenDeque().descendingIterator(); 
it.hasNext(); ) {
+          token = it.next();
+          //if we've skipped an else previously, then we need to skip the 
deferred tokens associated with the else.
+          if(skipElse && token.getUnderlyingType() == ElseExpr.class) {
+            while(it.hasNext()) {
+              token = it.next();
+              if(token.getUnderlyingType() == EndConditional.class) {
+                break;
+              }
+            }
+            skipElse = false;
+          }
+          /*
+          curr is the current value on the stack.  This is the non-deferred 
actual evaluation for this expression
+          and with the current context.
+           */
+          Token<?> curr = instanceDeque.peek();
+          if( curr != null
+           && curr.getValue() != null && curr.getValue() instanceof Boolean
+           && ShortCircuitOp.class.isAssignableFrom(token.getUnderlyingType())
+                  ) {
+            //if we have a boolean as the current value and the next 
non-contextual token is a short circuit op
+            //then we need to short circuit possibly
+            if(token.getUnderlyingType() == BooleanArg.class) {
+              if (curr.getMultiArgContext() != null
+                      && curr.getMultiArgContext().getVariety() == 
FrameContext.BOOLEAN_OR
+                      && (Boolean) (curr.getValue())
+                      ) {
+                //short circuit the or
+                FrameContext.Context context = curr.getMultiArgContext();
+                shortCircuit(it, context);
+              } else if (curr.getMultiArgContext() != null
+                      && curr.getMultiArgContext().getVariety() == 
FrameContext.BOOLEAN_AND
+                      && !(Boolean) (curr.getValue())
+                      ) {
+                //short circuit the and
+                FrameContext.Context context = curr.getMultiArgContext();
+                shortCircuit(it, context);
+              }
+            }
+            else if(token.getUnderlyingType() == IfExpr.class) {
+              //short circuit the if/then/else
+              instanceDeque.pop();
+              if((Boolean)curr.getValue()) {
+                //choose then
+                skipElse = true;
+              }
+              else {
+                //choose else
+                while(it.hasNext()) {
+                  Token<?> t = it.next();
+                  if(t.getUnderlyingType() == ElseExpr.class) {
+                    break;
+                  }
+                }
+              }
+            }
+          }
+          if (token.getUnderlyingType() == DeferredFunction.class) {
+            DeferredFunction func = (DeferredFunction) token.getValue();
+            func.apply(instanceDeque, state);
+          }
+          else if(token.getUnderlyingType() != ShortCircuitFrame.class
+               && 
!ShortCircuitOp.class.isAssignableFrom(token.getUnderlyingType())
+                  ) {
+            instanceDeque.push(token);
+          }
+
         }
       }
 
@@ -100,6 +180,15 @@ public class StellarCompiler extends StellarBaseListener {
         throw new ParseException("Invalid parse, found " + token);
       }
     }
+
+    public void shortCircuit(Iterator<Token<?>> it, FrameContext.Context 
context) {
+      while (it.hasNext()) {
+        Token<?> token = it.next();
+        if (token.getUnderlyingType() == ShortCircuitFrame.class && 
token.getMultiArgContext() == context) {
+          break;
+        }
+      }
+    }
   }
 
   interface DeferredFunction {
@@ -130,7 +219,7 @@ public class StellarCompiler extends StellarBaseListener {
 
   @Override
   public void enterTransformation(StellarParser.TransformationContext ctx) {
-    expression.tokenDeque.clear();
+    expression.clear();
   }
 
   private boolean handleIn(final Token<?> left, final Token<?> right) {
@@ -162,39 +251,43 @@ public class StellarCompiler extends StellarBaseListener {
 
   @Override
   public void exitNullConst(StellarParser.NullConstContext ctx) {
-    expression.tokenDeque.push(new Token<>(null, Object.class));
+    expression.tokenDeque.push(new Token<>(null, Object.class, 
getArgContext()));
   }
 
   @Override
   public void exitArithExpr_plus(StellarParser.ArithExpr_plusContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>((tokenDeque, state) -> {
       Pair<Token<? extends Number>, Token<? extends Number>> p = 
getArithExpressionPair(tokenDeque);
-      
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(),
 p));
-    }, DeferredFunction.class));
+      
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.addition(context),
 p));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void exitArithExpr_minus(StellarParser.ArithExpr_minusContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Pair<Token<? extends Number>, Token<? extends Number>> p = 
getArithExpressionPair(tokenDeque);
-    
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(),
 p));
-    }, DeferredFunction.class));
+    
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.subtraction(context),
 p));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void exitArithExpr_div(StellarParser.ArithExpr_divContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Pair<Token<? extends Number>, Token<? extends Number>> p = 
getArithExpressionPair(tokenDeque);
-    
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(),
 p));
-    }, DeferredFunction.class));
+    
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.division(context),
 p));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void exitArithExpr_mul(StellarParser.ArithExpr_mulContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Pair<Token<? extends Number>, Token<? extends Number>> p = 
getArithExpressionPair(tokenDeque);
-    
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(),
 p));
-    }, DeferredFunction.class));
+    
tokenDeque.push(arithmeticEvaluator.evaluate(ArithmeticEvaluator.ArithmeticEvaluatorFunctions.multiplication(context),
 p));
+    }, DeferredFunction.class, context));
   }
 
   @SuppressWarnings("unchecked")
@@ -204,61 +297,62 @@ public class StellarCompiler extends StellarBaseListener {
     return Pair.of(left, right);
   }
 
-  private void handleConditional() {
-    expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
-      Token<?> elseExpr = popDeque(tokenDeque);
-      Token<?> thenExpr = popDeque(tokenDeque);
-      Token<?> ifExpr = popDeque(tokenDeque);
-      @SuppressWarnings("unchecked") boolean b = ((Token<Boolean>) 
ifExpr).getValue();
-      if (b) {
-        tokenDeque.push(thenExpr);
-      } else {
-        tokenDeque.push(elseExpr);
-      }
-    }, DeferredFunction.class));
+  @Override
+  public void exitIf_expr(StellarParser.If_exprContext ctx) {
+    expression.tokenDeque.push(new Token<>(new IfExpr(), IfExpr.class, 
getArgContext()));
   }
 
   @Override
-  public void 
exitTernaryFuncWithoutIf(StellarParser.TernaryFuncWithoutIfContext ctx) {
-    handleConditional();
+  public void enterThen_expr(StellarParser.Then_exprContext ctx) {
+    expression.tokenDeque.push(new Token<>(new ThenExpr(), ThenExpr.class, 
getArgContext()));
   }
 
   @Override
-  public void exitTernaryFuncWithIf(StellarParser.TernaryFuncWithIfContext 
ctx) {
-    handleConditional();
+  public void enterElse_expr(StellarParser.Else_exprContext ctx) {
+    expression.tokenDeque.push(new Token<>(new ElseExpr(), ElseExpr.class, 
getArgContext()));
+  }
+
+  @Override
+  public void exitElse_expr(StellarParser.Else_exprContext ctx) {
+    expression.tokenDeque.push(new Token<>(new EndConditional(), 
EndConditional.class, getArgContext()));
   }
 
   @Override
   public void 
exitInExpressionStatement(StellarParser.InExpressionStatementContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Token<?> left = popDeque(tokenDeque);
     Token<?> right = popDeque(tokenDeque);
-    tokenDeque.push(new Token<>(handleIn(left, right), Boolean.class));
-    }, DeferredFunction.class));
+    tokenDeque.push(new Token<>(handleIn(left, right), Boolean.class, 
context));
+    }, DeferredFunction.class, context));
   }
 
+
   @Override
   public void 
exitNInExpressionStatement(StellarParser.NInExpressionStatementContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Token<?> left = popDeque(tokenDeque);
     Token<?> right = popDeque(tokenDeque);
-    tokenDeque.push(new Token<>(!handleIn(left, right), Boolean.class));
-    }, DeferredFunction.class));
+    tokenDeque.push(new Token<>(!handleIn(left, right), Boolean.class, 
context));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void exitNotFunc(StellarParser.NotFuncContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Token<Boolean> arg = (Token<Boolean>) popDeque(tokenDeque);
-    tokenDeque.push(new Token<>(!arg.getValue(), Boolean.class));
-    }, DeferredFunction.class));
+    tokenDeque.push(new Token<>(!arg.getValue(), Boolean.class, context));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void exitVariable(StellarParser.VariableContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
-      tokenDeque.push(new 
Token<>(state.variableResolver.resolve(ctx.getText()), Object.class));
-    }, DeferredFunction.class));
+      tokenDeque.push(new 
Token<>(state.variableResolver.resolve(ctx.getText()), Object.class, context));
+    }, DeferredFunction.class, context));
     expression.variablesUsed.add(ctx.getText());
   }
 
@@ -266,46 +360,77 @@ public class StellarCompiler extends StellarBaseListener {
   public void exitStringLiteral(StellarParser.StringLiteralContext ctx) {
     String rawToken = ctx.getText();
     String literal = StringEscapeUtils.UNESCAPE_JSON.translate(rawToken);
-    expression.tokenDeque.push(new Token<>(literal.substring(1, 
literal.length()-1), String.class));
+    expression.tokenDeque.push(new Token<>(literal.substring(1, 
literal.length()-1), String.class, getArgContext()));
   }
 
   @Override
   public void exitIntLiteral(StellarParser.IntLiteralContext ctx) {
-    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx));
+    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx, 
getArgContext()));
   }
 
   @Override
   public void exitDoubleLiteral(StellarParser.DoubleLiteralContext ctx) {
-    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx));
+    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx, 
getArgContext()));
   }
 
   @Override
   public void exitFloatLiteral(StellarParser.FloatLiteralContext ctx) {
-    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx));
+    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx, 
getArgContext()));
   }
 
   @Override
   public void exitLongLiteral(StellarParser.LongLiteralContext ctx) {
-    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx));
+    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx, 
getArgContext()));
+  }
+
+  @Override
+  public void enterB_expr(StellarParser.B_exprContext ctx) {
+    //Enter is not guaranteed to be called by Antlr for logical labels, so we 
need to
+    //emulate it like this.  See  https://github.com/antlr/antlr4/issues/802
+    if(ctx.getParent() instanceof StellarParser.LogicalExpressionOrContext) {
+      expression.multiArgumentState.push(FrameContext.BOOLEAN_OR.create());
+    }
+    else if(ctx.getParent() instanceof 
StellarParser.LogicalExpressionAndContext) {
+      expression.multiArgumentState.push(FrameContext.BOOLEAN_AND.create());
+    }
+  }
+
+  @Override
+  public void exitB_expr(StellarParser.B_exprContext ctx) {
+    if(ctx.getParent() instanceof StellarParser.LogicalExpressionOrContext
+    || ctx.getParent() instanceof StellarParser.LogicalExpressionAndContext
+      )
+    {
+      //we want to know when the argument to the boolean expression is complete
+      expression.tokenDeque.push(new Token<>(new BooleanArg(), 
BooleanArg.class, getArgContext()));
+    }
   }
 
   @Override
   public void 
exitLogicalExpressionAnd(StellarParser.LogicalExpressionAndContext ctx) {
+    final FrameContext.Context context = getArgContext();
+    popArgContext();
+    final FrameContext.Context parentContext = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Token<?> left = popDeque(tokenDeque);
     Token<?> right = popDeque(tokenDeque);
-    tokenDeque.push(new Token<>(booleanOp(left, right, (l, r) -> l && r, 
"&&"), Boolean.class));
-    }, DeferredFunction.class));
+    tokenDeque.push(new Token<>(booleanOp(left, right, (l, r) -> l && r, 
"&&"), Boolean.class, parentContext));
+    }, DeferredFunction.class, context));
+    expression.tokenDeque.push(new Token<>(new ShortCircuitFrame(), 
ShortCircuitFrame.class, context));
   }
 
   @Override
   public void exitLogicalExpressionOr(StellarParser.LogicalExpressionOrContext 
ctx) {
+    final FrameContext.Context context = getArgContext();
+    popArgContext();
+    final FrameContext.Context parentContext = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
     Token<?> left = popDeque(tokenDeque);
     Token<?> right = popDeque(tokenDeque);
 
-    tokenDeque.push(new Token<>(booleanOp(left, right, (l, r) -> l || r, 
"||"), Boolean.class));
-    }, DeferredFunction.class));
+    tokenDeque.push(new Token<>(booleanOp(left, right, (l, r) -> l || r, 
"||"), Boolean.class, parentContext));
+    }, DeferredFunction.class, context));
+    expression.tokenDeque.push(new Token<>(new ShortCircuitFrame(), 
ShortCircuitFrame.class, context));
   }
 
   @Override
@@ -321,7 +446,7 @@ public class StellarCompiler extends StellarBaseListener {
       default:
         throw new ParseException("Unable to process " + ctx.getText() + " as a 
boolean constant");
     }
-    expression.tokenDeque.push(new Token<>(b, Boolean.class));
+    expression.tokenDeque.push(new Token<>(b, Boolean.class, getArgContext()));
   }
 
   private boolean booleanOp(final Token<?> left, final Token<?> right, final 
BooleanOp op, final String opName) {
@@ -356,7 +481,7 @@ public class StellarCompiler extends StellarBaseListener {
 
   @Override
   public void exitLambda_variable(StellarParser.Lambda_variableContext ctx) {
-    expression.tokenDeque.push(new Token<>(ctx.getText(), String.class));
+    expression.tokenDeque.push(new Token<>(ctx.getText(), String.class, 
getArgContext()));
   }
 
   private void enterLambdaVariables() {
@@ -369,7 +494,7 @@ public class StellarCompiler extends StellarBaseListener {
     for(; !expression.tokenDeque.isEmpty() && t != LAMBDA_VARIABLES; t = 
expression.tokenDeque.pop()) {
       variables.addFirst(t.getValue().toString());
     }
-    expression.tokenDeque.push(new Token<>(variables, List.class));
+    expression.tokenDeque.push(new Token<>(variables, List.class, 
getArgContext()));
   }
 
   private void enterLambda() {
@@ -377,6 +502,7 @@ public class StellarCompiler extends StellarBaseListener {
   }
 
   private void exitLambda(boolean hasArgs) {
+    final FrameContext.Context context = getArgContext();
     Token<?> t = expression.tokenDeque.pop();
     final Deque<Token<?>> instanceDeque = new ArrayDeque<>();
     for(; !expression.tokenDeque.isEmpty() && t != EXPRESSION_REFERENCE; t = 
expression.tokenDeque.pop()) {
@@ -385,8 +511,8 @@ public class StellarCompiler extends StellarBaseListener {
     final List<String> variables = hasArgs? (List<String>) 
instanceDeque.removeLast().getValue() :new ArrayList<>();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
       LambdaExpression expr = new LambdaExpression(variables, instanceDeque, 
state);
-      tokenDeque.push(new Token<>(expr, Object.class));
-    }, DeferredFunction.class) );
+      tokenDeque.push(new Token<>(expr, Object.class, context));
+    }, DeferredFunction.class, context) );
   }
 
   @Override
@@ -411,7 +537,7 @@ public class StellarCompiler extends StellarBaseListener {
 
   @Override
   public void exitTransformationFunc(StellarParser.TransformationFuncContext 
ctx) {
-
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
       // resolve and initialize the function
       String functionName = ctx.getChild(0).getText();
@@ -421,8 +547,8 @@ public class StellarCompiler extends StellarBaseListener {
       // fetch the args, execute, and push result onto the stack
       List<Object> args = getFunctionArguments(popDeque(tokenDeque));
       Object result = function.apply(args, state.context);
-      tokenDeque.push(new Token<>(result, Object.class));
-    }, DeferredFunction.class));
+      tokenDeque.push(new Token<>(result, Object.class, context));
+    }, DeferredFunction.class, context));
   }
 
   /**
@@ -474,22 +600,24 @@ public class StellarCompiler extends StellarBaseListener {
 
   @Override
   public void exitExistsFunc(StellarParser.ExistsFuncContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
       String variable = ctx.getChild(2).getText();
       boolean exists = state.variableResolver.resolve(variable) != null;
-      tokenDeque.push(new Token<>(exists, Boolean.class));
-    }, DeferredFunction.class));
+      tokenDeque.push(new Token<>(exists, Boolean.class, context));
+    }, DeferredFunction.class, context));
     String variable = ctx.getChild(2).getText();
     expression.variablesUsed.add(variable);
   }
 
   @Override
   public void enterFunc_args(StellarParser.Func_argsContext ctx) {
-    expression.tokenDeque.push(new Token<>(new FunctionMarker(), 
FunctionMarker.class));
+    expression.tokenDeque.push(new Token<>(new FunctionMarker(), 
FunctionMarker.class, getArgContext()));
   }
 
   @Override
   public void exitFunc_args(StellarParser.Func_argsContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>((tokenDeque, state) -> {
       LinkedList<Object> args = new LinkedList<>();
       while (true) {
@@ -500,17 +628,18 @@ public class StellarCompiler extends StellarBaseListener {
           args.addFirst(token.getValue());
         }
       }
-      tokenDeque.push(new Token<>(args, List.class));
-    }, DeferredFunction.class));
+      tokenDeque.push(new Token<>(args, List.class, context));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void enterMap_entity(StellarParser.Map_entityContext ctx) {
-    expression.tokenDeque.push(new Token<>(new FunctionMarker(), 
FunctionMarker.class));
+    expression.tokenDeque.push(new Token<>(new FunctionMarker(), 
FunctionMarker.class, getArgContext()));
   }
 
   @Override
   public void exitMap_entity(StellarParser.Map_entityContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
       HashMap<String, Object> args = new HashMap<>();
       Object value = null;
@@ -526,12 +655,13 @@ public class StellarCompiler extends StellarBaseListener {
           }
         }
       }
-      tokenDeque.push(new Token<>(args, Map.class));
-    }, DeferredFunction.class));
+      tokenDeque.push(new Token<>(args, Map.class, context));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void exitList_entity(StellarParser.List_entityContext ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
       LinkedList<Object> args = new LinkedList<>();
       while (true) {
@@ -542,24 +672,37 @@ public class StellarCompiler extends StellarBaseListener {
           args.addFirst(token.getValue());
         }
       }
-      tokenDeque.push(new Token<>(args, List.class));
-    }, DeferredFunction.class));
+      tokenDeque.push(new Token<>(args, List.class, context));
+    }, DeferredFunction.class, context));
   }
 
+
+
   @Override
   public void 
exitComparisonExpressionWithOperator(StellarParser.ComparisonExpressionWithOperatorContext
 ctx) {
+    final FrameContext.Context context = getArgContext();
     expression.tokenDeque.push(new Token<>( (tokenDeque, state) -> {
       StellarParser.Comp_operatorContext op = ctx.comp_operator();
       Token<?> right = popDeque(tokenDeque);
       Token<?> left = popDeque(tokenDeque);
 
-      tokenDeque.push(comparisonExpressionWithOperatorEvaluator.evaluate(left, 
right, (StellarParser.ComparisonOpContext) op));
-    }, DeferredFunction.class));
+      tokenDeque.push(comparisonExpressionWithOperatorEvaluator.evaluate(left, 
right, (StellarParser.ComparisonOpContext) op, context));
+    }, DeferredFunction.class, context));
   }
 
   @Override
   public void enterList_entity(StellarParser.List_entityContext ctx) {
-    expression.tokenDeque.push(new Token<>(new FunctionMarker(), 
FunctionMarker.class));
+    expression.tokenDeque.push(new Token<>(new FunctionMarker(), 
FunctionMarker.class, getArgContext()));
+  }
+
+  private void popArgContext() {
+    if(!expression.multiArgumentState.isEmpty()) {
+      expression.multiArgumentState.pop();
+    }
+  }
+
+  private FrameContext.Context getArgContext() {
+    return 
expression.multiArgumentState.isEmpty()?null:expression.multiArgumentState.peek();
   }
 
   private Token<?> popDeque(Deque<Token<?>> tokenDeque) {

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ArithmeticEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ArithmeticEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ArithmeticEvaluator.java
index f1264e2..b458f9c 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ArithmeticEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ArithmeticEvaluator.java
@@ -19,8 +19,8 @@
 package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.metron.common.dsl.ParseException;
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 
 import java.util.function.BiFunction;
 
@@ -44,58 +44,58 @@ public enum ArithmeticEvaluator {
    * types is taken for the Java spec: 
http://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.6.2
    */
   public static final class ArithmeticEvaluatorFunctions {
-    public static BiFunction<Number, Number, Token<? extends Number>> 
addition() {
+    public static BiFunction<Number, Number, Token<? extends Number>> 
addition(final FrameContext.Context context) {
       return (Number l, Number r) -> {
         if (l instanceof Double || r instanceof Double) {
-          return new Token<>(l.doubleValue() + r.doubleValue(), Double.class);
+          return new Token<>(l.doubleValue() + r.doubleValue(), Double.class, 
context);
         } else if (l instanceof Float || r instanceof Float) {
-          return new Token<>(l.floatValue() + r.floatValue(), Float.class);
+          return new Token<>(l.floatValue() + r.floatValue(), Float.class, 
context);
         } else if (l instanceof Long || r instanceof Long) {
-          return new Token<>(l.longValue() + r.longValue(), Long.class);
+          return new Token<>(l.longValue() + r.longValue(), Long.class, 
context);
         } else {
-          return new Token<>(l.intValue() + r.intValue(), Integer.class);
+          return new Token<>(l.intValue() + r.intValue(), Integer.class, 
context);
         }
       };
     }
 
-    public static BiFunction<Number, Number, Token<? extends Number>> 
multiplication() {
+    public static BiFunction<Number, Number, Token<? extends Number>> 
multiplication(final FrameContext.Context context) {
       return (Number l, Number r) -> {
         if (l instanceof Double || r instanceof Double) {
-          return new Token<>(l.doubleValue() * r.doubleValue(), Double.class);
+          return new Token<>(l.doubleValue() * r.doubleValue(), Double.class, 
context);
         } else if (l instanceof Float || r instanceof Float) {
-          return new Token<>(l.floatValue() * r.floatValue(), Float.class);
+          return new Token<>(l.floatValue() * r.floatValue(), Float.class, 
context);
         } else if (l instanceof Long || r instanceof Long) {
-          return new Token<>(l.longValue() * r.longValue(), Long.class);
+          return new Token<>(l.longValue() * r.longValue(), Long.class, 
context);
         } else {
-          return new Token<>(l.intValue() * r.intValue(), Integer.class);
+          return new Token<>(l.intValue() * r.intValue(), Integer.class, 
context);
         }
       };
     }
 
-    public static BiFunction<Number, Number, Token<? extends Number>> 
subtraction() {
+    public static BiFunction<Number, Number, Token<? extends Number>> 
subtraction(final FrameContext.Context context) {
       return (Number l, Number r) -> {
         if (l instanceof Double || r instanceof Double) {
-          return new Token<>(l.doubleValue() - r.doubleValue(), Double.class);
+          return new Token<>(l.doubleValue() - r.doubleValue(), Double.class, 
context);
         } else if (l instanceof Float || r instanceof Float) {
-          return new Token<>(l.floatValue() - r.floatValue(), Float.class);
+          return new Token<>(l.floatValue() - r.floatValue(), Float.class, 
context);
         } else if (l instanceof Long || r instanceof Long) {
-          return new Token<>(l.longValue() - r.longValue(), Long.class);
+          return new Token<>(l.longValue() - r.longValue(), Long.class, 
context);
         } else {
-          return new Token<>(l.intValue() - r.intValue(), Integer.class);
+          return new Token<>(l.intValue() - r.intValue(), Integer.class, 
context);
         }
       };
     }
 
-    public static BiFunction<Number, Number, Token<? extends Number>> 
division() {
+    public static BiFunction<Number, Number, Token<? extends Number>> 
division(FrameContext.Context context) {
       return (Number l, Number r) -> {
         if (l instanceof Double || r instanceof Double) {
-          return new Token<>(l.doubleValue() / r.doubleValue(), Double.class);
+          return new Token<>(l.doubleValue() / r.doubleValue(), Double.class, 
context);
         } else if (l instanceof Float || r instanceof Float) {
-          return new Token<>(l.floatValue() / r.floatValue(), Float.class);
+          return new Token<>(l.floatValue() / r.floatValue(), Float.class, 
context);
         } else if (l instanceof Long || r instanceof Long) {
-          return new Token<>(l.longValue() / r.longValue(), Long.class);
+          return new Token<>(l.longValue() / r.longValue(), Long.class, 
context);
         } else {
-          return new Token<>(l.intValue() / r.intValue(), Integer.class);
+          return new Token<>(l.intValue() / r.intValue(), Integer.class, 
context);
         }
       };
     }

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ComparisonExpressionWithOperatorEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ComparisonExpressionWithOperatorEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ComparisonExpressionWithOperatorEvaluator.java
index 4862684..e213eb5 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ComparisonExpressionWithOperatorEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/ComparisonExpressionWithOperatorEvaluator.java
@@ -20,6 +20,7 @@ package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.metron.common.dsl.ParseException;
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
 /**
@@ -81,13 +82,13 @@ public enum ComparisonExpressionWithOperatorEvaluator {
    * @param op The operator in the Stellar expression.
    * @return A token with type boolean. This is based on the comparison of the 
{@code right} and {@code left} values.
    */
-  public Token<Boolean> evaluate(final Token<?> left, final Token<?> right, 
final StellarParser.ComparisonOpContext op) {
+  public Token<Boolean> evaluate(final Token<?> left, final Token<?> right, 
final StellarParser.ComparisonOpContext op, FrameContext.Context context) {
     if (op.EQ() != null) {
-      return new 
Token<>(Strategy.EQUALITY_OPERATORS.evaluator().evaluate(left, right, op), 
Boolean.class);
+      return new 
Token<>(Strategy.EQUALITY_OPERATORS.evaluator().evaluate(left, right, op), 
Boolean.class, context);
     } else if (op.NEQ() != null) {
-      return new 
Token<>(!Strategy.EQUALITY_OPERATORS.evaluator().evaluate(left, right, op), 
Boolean.class);
+      return new 
Token<>(!Strategy.EQUALITY_OPERATORS.evaluator().evaluate(left, right, op), 
Boolean.class, context);
     } else if (op.LT() != null || op.GT() != null || op.LTE() != null || 
op.GTE() != null) {
-      return new 
Token<>(Strategy.COMPARISON_OPERATORS.evaluator().evaluate(left, right, op), 
Boolean.class);
+      return new 
Token<>(Strategy.COMPARISON_OPERATORS.evaluator().evaluate(left, right, op), 
Boolean.class, context);
     }
 
     throw new ParseException("Unsupported operations. The following expression 
is invalid: " + left.getValue() + op.getText() + right.getValue());

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/DoubleLiteralEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/DoubleLiteralEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/DoubleLiteralEvaluator.java
index 1bd1a49..653b56c 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/DoubleLiteralEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/DoubleLiteralEvaluator.java
@@ -19,15 +19,16 @@
 package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
 public class DoubleLiteralEvaluator implements 
NumberEvaluator<StellarParser.DoubleLiteralContext> {
   @Override
-  public Token<Double> evaluate(StellarParser.DoubleLiteralContext context) {
+  public Token<Double> evaluate(StellarParser.DoubleLiteralContext context, 
FrameContext.Context contextVariety) {
     if (context == null) {
       throw new IllegalArgumentException("Cannot evaluate a context that is 
null.");
     }
 
-    return new Token<>(Double.parseDouble(context.getText()), Double.class);
+    return new Token<>(Double.parseDouble(context.getText()), Double.class, 
contextVariety);
   }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/FloatLiteralEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/FloatLiteralEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/FloatLiteralEvaluator.java
index 60b312b..4489d30 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/FloatLiteralEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/FloatLiteralEvaluator.java
@@ -19,15 +19,16 @@
 package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
 public class FloatLiteralEvaluator implements 
NumberEvaluator<StellarParser.FloatLiteralContext> {
   @Override
-  public Token<Float> evaluate(StellarParser.FloatLiteralContext context) {
+  public Token<Float> evaluate(StellarParser.FloatLiteralContext context, 
FrameContext.Context contextVariety) {
     if (context == null) {
       throw new IllegalArgumentException("Cannot evaluate a context that is 
null.");
     }
 
-    return new Token<>(Float.parseFloat(context.getText()), Float.class);
+    return new Token<>(Float.parseFloat(context.getText()), Float.class, 
contextVariety);
   }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/IntLiteralEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/IntLiteralEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/IntLiteralEvaluator.java
index c928a9a..00e62e6 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/IntLiteralEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/IntLiteralEvaluator.java
@@ -19,15 +19,16 @@
 package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
 public class IntLiteralEvaluator implements 
NumberEvaluator<StellarParser.IntLiteralContext> {
   @Override
-  public Token<Integer> evaluate(StellarParser.IntLiteralContext context) {
+  public Token<Integer> evaluate(StellarParser.IntLiteralContext context, 
FrameContext.Context contextVariety) {
     if (context == null) {
       throw new IllegalArgumentException("Cannot evaluate a context that is 
null.");
     }
 
-    return new Token<>(Integer.parseInt(context.getText()), Integer.class);
+    return new Token<>(Integer.parseInt(context.getText()), Integer.class, 
contextVariety);
   }
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/LongLiteralEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/LongLiteralEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/LongLiteralEvaluator.java
index 05ee162..338adc4 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/LongLiteralEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/LongLiteralEvaluator.java
@@ -20,11 +20,12 @@ package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.metron.common.dsl.ParseException;
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
 public class LongLiteralEvaluator implements 
NumberEvaluator<StellarParser.LongLiteralContext> {
   @Override
-  public Token<Long> evaluate(StellarParser.LongLiteralContext context) {
+  public Token<Long> evaluate(StellarParser.LongLiteralContext context, 
FrameContext.Context contextVariety) {
     if (context == null) {
       throw new IllegalArgumentException("Cannot evaluate a context that is 
null.");
     }
@@ -32,7 +33,7 @@ public class LongLiteralEvaluator implements 
NumberEvaluator<StellarParser.LongL
     String value = context.getText();
     if (value.endsWith("l") || value.endsWith("L")) {
       value = value.substring(0, value.length() - 1); // Drop the 'L' or 'l'. 
Long.parseLong does not accept a string with either of these.
-      return new Token<>(Long.parseLong(value), Long.class);
+      return new Token<>(Long.parseLong(value), Long.class, contextVariety);
     } else {
       // Technically this should never happen, but just being safe.
       throw new ParseException("Invalid format for long. Failed trying to 
parse a long with the following value: " + value);

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberEvaluator.java
index 0007b72..2c18f9d 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberEvaluator.java
@@ -19,8 +19,9 @@
 package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
 public interface NumberEvaluator<T extends 
StellarParser.Arithmetic_operandsContext> {
-  Token<? extends Number> evaluate(T context);
+  Token<? extends Number> evaluate(T context, FrameContext.Context 
contextVariety);
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberLiteralEvaluator.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberLiteralEvaluator.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberLiteralEvaluator.java
index 83d795f..0ec3859 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberLiteralEvaluator.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/evaluators/NumberLiteralEvaluator.java
@@ -20,6 +20,7 @@ package org.apache.metron.common.stellar.evaluators;
 
 import org.apache.metron.common.dsl.ParseException;
 import org.apache.metron.common.dsl.Token;
+import org.apache.metron.common.stellar.FrameContext;
 import org.apache.metron.common.stellar.generated.StellarParser;
 
 import java.util.HashMap;
@@ -53,17 +54,18 @@ public enum NumberLiteralEvaluator {
 
   Token<? extends Number> evaluate(StellarParser.Arithmetic_operandsContext 
context
                                          , Map<Class<? extends 
StellarParser.Arithmetic_operandsContext>, NumberEvaluator> instanceMap
+                                         , FrameContext.Context contextVariety
                                          )
   {
     NumberEvaluator evaluator = instanceMap.get(context.getClass());
     if(evaluator == null) {
       throw new ParseException("Does not support evaluation for type " + 
context.getClass());
     }
-    return evaluator.evaluate(context);
+    return evaluator.evaluate(context, contextVariety);
   }
 
-  public Token<? extends Number> 
evaluate(StellarParser.Arithmetic_operandsContext context) {
-    return evaluate(context, Strategy.strategyMap);
+  public Token<? extends Number> 
evaluate(StellarParser.Arithmetic_operandsContext context, FrameContext.Context 
contextVariety) {
+    return evaluate(context, Strategy.strategyMap, contextVariety);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
index 2be710b..3ca1daa 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarBaseListener.java
@@ -133,6 +133,42 @@ public class StellarBaseListener implements 
StellarListener {
         *
         * <p>The default implementation does nothing.</p>
         */
+       @Override public void enterIf_expr(StellarParser.If_exprContext ctx) { }
+       /**
+        * {@inheritDoc}
+        *
+        * <p>The default implementation does nothing.</p>
+        */
+       @Override public void exitIf_expr(StellarParser.If_exprContext ctx) { }
+       /**
+        * {@inheritDoc}
+        *
+        * <p>The default implementation does nothing.</p>
+        */
+       @Override public void enterThen_expr(StellarParser.Then_exprContext 
ctx) { }
+       /**
+        * {@inheritDoc}
+        *
+        * <p>The default implementation does nothing.</p>
+        */
+       @Override public void exitThen_expr(StellarParser.Then_exprContext ctx) 
{ }
+       /**
+        * {@inheritDoc}
+        *
+        * <p>The default implementation does nothing.</p>
+        */
+       @Override public void enterElse_expr(StellarParser.Else_exprContext 
ctx) { }
+       /**
+        * {@inheritDoc}
+        *
+        * <p>The default implementation does nothing.</p>
+        */
+       @Override public void exitElse_expr(StellarParser.Else_exprContext ctx) 
{ }
+       /**
+        * {@inheritDoc}
+        *
+        * <p>The default implementation does nothing.</p>
+        */
        @Override public void 
enterTernaryFuncWithoutIf(StellarParser.TernaryFuncWithoutIfContext ctx) { }
        /**
         * {@inheritDoc}

http://git-wip-us.apache.org/repos/asf/metron/blob/30d0e2a6/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarListener.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarListener.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarListener.java
index 66493f7..6c00691 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarListener.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/stellar/generated/StellarListener.java
@@ -123,6 +123,36 @@ public interface StellarListener extends ParseTreeListener 
{
         */
        void exitInExpression(StellarParser.InExpressionContext ctx);
        /**
+        * Enter a parse tree produced by {@link StellarParser#if_expr}.
+        * @param ctx the parse tree
+        */
+       void enterIf_expr(StellarParser.If_exprContext ctx);
+       /**
+        * Exit a parse tree produced by {@link StellarParser#if_expr}.
+        * @param ctx the parse tree
+        */
+       void exitIf_expr(StellarParser.If_exprContext ctx);
+       /**
+        * Enter a parse tree produced by {@link StellarParser#then_expr}.
+        * @param ctx the parse tree
+        */
+       void enterThen_expr(StellarParser.Then_exprContext ctx);
+       /**
+        * Exit a parse tree produced by {@link StellarParser#then_expr}.
+        * @param ctx the parse tree
+        */
+       void exitThen_expr(StellarParser.Then_exprContext ctx);
+       /**
+        * Enter a parse tree produced by {@link StellarParser#else_expr}.
+        * @param ctx the parse tree
+        */
+       void enterElse_expr(StellarParser.Else_exprContext ctx);
+       /**
+        * Exit a parse tree produced by {@link StellarParser#else_expr}.
+        * @param ctx the parse tree
+        */
+       void exitElse_expr(StellarParser.Else_exprContext ctx);
+       /**
         * Enter a parse tree produced by the {@code TernaryFuncWithoutIf}
         * labeled alternative in {@link StellarParser#conditional_expr}.
         * @param ctx the parse tree

Reply via email to