/*
 * 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;

import org.antlr.v4.runtime.ParserRuleContext;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.metron.common.dsl.Context;
import org.apache.metron.common.dsl.Token;
import org.apache.metron.common.dsl.VariableResolver;
import org.apache.metron.common.dsl.functions.resolver.FunctionResolver;
import org.apache.metron.common.stellar.evaluators.ArithmeticEvaluator;
import org.apache.metron.common.stellar.evaluators.ComparisonExpressionWithOperatorEvaluator;
import org.apache.metron.common.stellar.evaluators.NumberLiteralEvaluator;
import org.apache.metron.common.stellar.generated.StellarBaseListener;
import org.apache.metron.common.stellar.generated.StellarParser;
import com.google.common.base.Joiner;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.metron.common.dsl.FunctionMarker;
import org.apache.metron.common.dsl.ParseException;
import org.apache.metron.common.dsl.StellarFunction;
import org.apache.metron.common.utils.ConversionUtils;

import java.io.Serializable;
import java.util.*;

import static java.lang.String.format;

public class StellarCompiler extends StellarBaseListener {
  private static Token<?> EXPRESSION_REFERENCE = new Token<>(null, Object.class);
  private static Token<?> LAMBDA_VARIABLES = new Token<>(null, Object.class);

  private Expression expression;
  private final ArithmeticEvaluator arithmeticEvaluator;
  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;
    VariableResolver variableResolver;
    public ExpressionState(Context context
              , FunctionResolver functionResolver
              , VariableResolver variableResolver
                          ) {
      this.context = context;
      this.variableResolver = variableResolver;
      this.functionResolver = functionResolver;
    }
  }

  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() {
      return tokenDeque;
    }

    public Object apply(ExpressionState state) {
      Deque<Token<?>> instanceDeque = new ArrayDeque<>();
      {
        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);
          }

        }
      }

      if (instanceDeque.isEmpty()) {
        throw new ParseException("Invalid predicate: Empty stack.");
      }
      Token<?> token = instanceDeque.pop();
      if (instanceDeque.isEmpty()) {
        return token.getValue();
      }
      if (instanceDeque.isEmpty()) {
        throw new ParseException("Invalid parse, stack not empty: " + Joiner.on(',').join(instanceDeque));
      } else {
        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 {
    void apply( Deque<Token<?>> tokenDeque
              , ExpressionState state
              );
  }

  public StellarCompiler(
          final ArithmeticEvaluator arithmeticEvaluator,
          final NumberLiteralEvaluator numberLiteralEvaluator,
          final ComparisonExpressionWithOperatorEvaluator comparisonExpressionWithOperatorEvaluator
  ){
    this(new Expression(new ArrayDeque<>()), arithmeticEvaluator, numberLiteralEvaluator, comparisonExpressionWithOperatorEvaluator);
  }

  public StellarCompiler(
          final Expression expression,
          final ArithmeticEvaluator arithmeticEvaluator,
          final NumberLiteralEvaluator numberLiteralEvaluator,
          final ComparisonExpressionWithOperatorEvaluator comparisonExpressionWithOperatorEvaluator
  ){
    this.expression = expression;
    this.arithmeticEvaluator = arithmeticEvaluator;
    this.numberLiteralEvaluator = numberLiteralEvaluator;
    this.comparisonExpressionWithOperatorEvaluator = comparisonExpressionWithOperatorEvaluator;
  }

  @Override
  public void enterTransformation(StellarParser.TransformationContext ctx) {
    expression.clear();
  }

  private boolean handleIn(final Token<?> left, final Token<?> right) {
    Object key = right.getValue();


    if (left.getValue() != null) {
      if (left.getValue() instanceof String && key instanceof String) {
        return ((String) left.getValue()).contains(key.toString());
      }
      else if (left.getValue() instanceof Collection) {
        return ((Collection) left.getValue()).contains(key);
      }
      else if (left.getValue() instanceof Map) {
        return ((Map) left.getValue()).containsKey(key);
      }
      else {
        if (key == null) {
          return key == left.getValue();
        }
        else {
          return key.equals(left.getValue());
        }
      }
    } else {
      return false;
    }
  }

  @Override
  public void exitNullConst(StellarParser.NullConstContext ctx) {
    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(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(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(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(context), p));
    }, DeferredFunction.class, context));
  }

  @SuppressWarnings("unchecked")
  private Pair<Token<? extends Number>, Token<? extends Number>> getArithExpressionPair(Deque<Token<?>> tokenDeque) {
    Token<? extends Number> right = (Token<? extends Number>) popDeque(tokenDeque);
    Token<? extends Number> left = (Token<? extends Number>) popDeque(tokenDeque);
    return Pair.of(left, right);
  }

  @Override
  public void exitIf_expr(StellarParser.If_exprContext ctx) {
    expression.tokenDeque.push(new Token<>(new IfExpr(), IfExpr.class, getArgContext()));
  }

  @Override
  public void enterThen_expr(StellarParser.Then_exprContext ctx) {
    expression.tokenDeque.push(new Token<>(new ThenExpr(), ThenExpr.class, getArgContext()));
  }

  @Override
  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, 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, 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, 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, context));
    }, DeferredFunction.class, context));
    expression.variablesUsed.add(ctx.getText());
  }

  @Override
  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, getArgContext()));
  }

  @Override
  public void exitIntLiteral(StellarParser.IntLiteralContext ctx) {
    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx, getArgContext()));
  }

  @Override
  public void exitDoubleLiteral(StellarParser.DoubleLiteralContext ctx) {
    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx, getArgContext()));
  }

  @Override
  public void exitFloatLiteral(StellarParser.FloatLiteralContext ctx) {
    expression.tokenDeque.push(numberLiteralEvaluator.evaluate(ctx, getArgContext()));
  }

  @Override
  public void exitLongLiteral(StellarParser.LongLiteralContext 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, 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, parentContext));
    }, DeferredFunction.class, context));
    expression.tokenDeque.push(new Token<>(new ShortCircuitFrame(), ShortCircuitFrame.class, context));
  }

  @Override
  public void exitLogicalConst(StellarParser.LogicalConstContext ctx) {
    Boolean b;
    switch (ctx.getText().toUpperCase()) {
      case "TRUE":
        b = true;
        break;
      case "FALSE":
        b = false;
        break;
      default:
        throw new ParseException("Unable to process " + ctx.getText() + " as a boolean constant");
    }
    expression.tokenDeque.push(new Token<>(b, Boolean.class, getArgContext()));
  }

  private boolean booleanOp(final Token<?> left, final Token<?> right, final BooleanOp op, final String opName) {
    Boolean l = ConversionUtils.convert(left.getValue(), Boolean.class);
    Boolean r = ConversionUtils.convert(right.getValue(), Boolean.class);
    if (l == null || r == null) {
      throw new ParseException("Unable to operate on " + left.getValue() + " " + opName + " " + right.getValue() + ", null value");
    }
    return op.op(l, r);
  }


  @Override
  public void enterSingle_lambda_variable(StellarParser.Single_lambda_variableContext ctx) {
    enterLambdaVariables();
  }

  @Override
  public void exitSingle_lambda_variable(StellarParser.Single_lambda_variableContext ctx) {
    exitLambdaVariables();
  }

  @Override
  public void enterLambda_variables(StellarParser.Lambda_variablesContext ctx) {
    enterLambdaVariables();
  }

  @Override
  public void exitLambda_variables(StellarParser.Lambda_variablesContext ctx) {
    exitLambdaVariables();
  }

  @Override
  public void exitLambda_variable(StellarParser.Lambda_variableContext ctx) {
    expression.tokenDeque.push(new Token<>(ctx.getText(), String.class, getArgContext()));
  }

  private void enterLambdaVariables() {
    expression.tokenDeque.push(LAMBDA_VARIABLES);
  }

  private void exitLambdaVariables() {
    Token<?> t = expression.tokenDeque.pop();
    LinkedList<String> variables = new LinkedList<>();
    for(; !expression.tokenDeque.isEmpty() && t != LAMBDA_VARIABLES; t = expression.tokenDeque.pop()) {
      variables.addFirst(t.getValue().toString());
    }
    expression.tokenDeque.push(new Token<>(variables, List.class, getArgContext()));
  }

  private void enterLambda() {
    expression.tokenDeque.push(EXPRESSION_REFERENCE);
  }

  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()) {
      instanceDeque.addLast(t);
    }
    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, context));
    }, DeferredFunction.class, context) );
  }

  @Override
  public void enterLambda_with_args(StellarParser.Lambda_with_argsContext ctx) {
    enterLambda();
  }

  @Override
  public void exitLambda_with_args(StellarParser.Lambda_with_argsContext ctx) {
    exitLambda(true);
  }

  @Override
  public void enterLambda_without_args(StellarParser.Lambda_without_argsContext ctx) {
    enterLambda();
  }

  @Override
  public void exitLambda_without_args(StellarParser.Lambda_without_argsContext ctx) {
    exitLambda(false);
  }

  @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();
      StellarFunction function = resolveFunction(state.functionResolver, functionName);
      initializeFunction(state.context, function, functionName);

      // 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, context));
    }, DeferredFunction.class, context));
  }

  /**
   * Get function arguments.
   * @param token The token containing the function arguments.
   * @return
   */
  @SuppressWarnings("unchecked")
  private List<Object> getFunctionArguments(final Token<?> token) {
    if (token.getUnderlyingType().equals(List.class)) {
      return (List<Object>) token.getValue();

    } else {
      throw new ParseException("Unable to process in clause because " + token.getValue() + " is not a set");
    }
  }

  /**
   * Resolves a function by name.
   * @param funcName
   * @return
   */
  private StellarFunction resolveFunction(FunctionResolver functionResolver, String funcName) {
    try {
      return functionResolver.apply(funcName);

    } catch (Exception e) {
      String valid = Joiner.on(',').join(functionResolver.getFunctions());
      String error = format("Unable to resolve function named '%s'.  Valid functions are %s", funcName, valid);
      throw new ParseException(error, e);
    }
  }

  /**
   * Initialize a Stellar function.
   * @param function The function to initialize.
   * @param functionName The name of the functions.
   */
  private void initializeFunction(Context context, StellarFunction function, String functionName) {
    try {
      if (!function.isInitialized()) {
        function.initialize(context);
      }
    } catch (Throwable t) {
      String error = format("Unable to initialize function '%s'", functionName);
      throw new ParseException(error, t);
    }
  }

  @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, 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, 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) {
        Token<?> token = popDeque(tokenDeque);
        if (token.getUnderlyingType().equals(FunctionMarker.class)) {
          break;
        } else {
          args.addFirst(token.getValue());
        }
      }
      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, 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;
      for (int i = 0; true; i++) {
        Token<?> token = popDeque(tokenDeque);
        if (token.getUnderlyingType().equals(FunctionMarker.class)) {
          break;
        } else {
          if (i % 2 == 0) {
            value = token.getValue();
          } else {
            args.put(token.getValue() + "", value);
          }
        }
      }
      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) {
        Token<?> token = popDeque(tokenDeque);
        if (token.getUnderlyingType().equals(FunctionMarker.class)) {
          break;
        } else {
          args.addFirst(token.getValue());
        }
      }
      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, context));
    }, DeferredFunction.class, context));
  }

  @Override
  public void enterList_entity(StellarParser.List_entityContext ctx) {
    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) {
    if (tokenDeque.isEmpty()) {
      throw new ParseException("Unable to pop an empty stack");
    }
    return tokenDeque.pop();
  }

  public Expression getExpression() {return expression;}

}
