private int executeOperator(
      int operatorIndex,
      final OperatorType operatorType,
      int operandCount,
      Map<Integer, DelegateTokenType> index2DelegateType) {
    Token<?> token = null;
    operandCount += index2DelegateType.size();
    // check if literal expression can be executed
    boolean canExecute = true;
    // operand count
    int count = 0;
    // operand start index
    int operandStartIndex = -1;
    for (int j = operatorIndex - 1; j >= 0; j--) {
      token = this.tokenList.get(j);
      if (token == null) {
        // we must compact token list and retry executing
        return -1;
      }
      final TokenType tokenType = token.getType();
      // Check if operand is a literal operand
      if (!this.isLiteralOperand(token, tokenType, count + 1, index2DelegateType)) {
        canExecute = false;
        break;
      }
      count++;

      if (count == operandCount) {
        operandStartIndex = j;
        break;
      }
    }

    // if we can execute it on compile
    if (canExecute) {
      // arguments
      AviatorObject[] args = new AviatorObject[operandCount];
      int index = 0;
      for (int j = operandStartIndex; j < operatorIndex; j++) {
        token = this.tokenList.get(j);
        if (token.getType() == TokenType.Delegate) {
          this.tokenList.set(j, null);
          continue;
        }
        args[index++] = this.getAviatorObjectFromToken(token);
        // set argument token to null
        this.tokenList.set(j, null);
      }
      // execute it now
      AviatorObject result = operatorType.eval(args);
      // set result as token to tokenList for next executing
      this.tokenList.set(operatorIndex, this.getTokenFromOperand(result));
      return 1;
    }
    return 0;
  }
 private int execute() {
   int exeCount = 0;
   final int size = this.tokenList.size();
   this.printTokenList();
   for (int i = 0; i < size; i++) {
     Token<?> token = this.tokenList.get(i);
     if (token.getType() == TokenType.Operator) {
       final OperatorToken op = (OperatorToken) token;
       final OperatorType operatorType = op.getOperatorType();
       final int operandCount = operatorType.getOperandCount();
       switch (operatorType) {
         case FUNC:
         case INDEX:
           // Could not optimize function and index call
           break;
         default:
           Map<Integer, DelegateTokenType> index2DelegateType =
               this.getIndex2DelegateTypeMap(operatorType);
           final int result =
               this.executeOperator(i, operatorType, operandCount, index2DelegateType);
           if (result < 0) {
             this.compactTokenList();
             return exeCount;
           }
           exeCount += result;
           break;
       }
     }
   }
   this.compactTokenList();
   return exeCount;
 }
 private AviatorObject getAviatorObjectFromToken(Token<?> lookhead) {
   AviatorObject result = null;
   switch (lookhead.getType()) {
     case Number:
       // load numbers
       NumberToken numberToken = (NumberToken) lookhead;
       if (numberToken.getNumber() instanceof Double) {
         result = AviatorDouble.valueOf(numberToken.getNumber());
       } else {
         result = AviatorLong.valueOf(numberToken.getNumber());
       }
       break;
     case String:
       // load string
       result = new AviatorString((String) lookhead.getValue(null));
       break;
     case Pattern:
       // load pattern
       result = new AviatorPattern((String) lookhead.getValue(null));
       break;
     case Variable:
       if (lookhead == Variable.TRUE) {
         result = AviatorBoolean.TRUE;
       } else if (lookhead == Variable.FALSE) {
         result = AviatorBoolean.FALSE;
       } else if (lookhead == Variable.NIL) {
         result = AviatorNil.NIL;
       }
       break;
     case Char:
       result = new AviatorString(String.valueOf(lookhead.getValue(null)));
       break;
   }
   return result;
 }
 private boolean isLiteralToken(Token<?> token) {
   switch (token.getType()) {
     case Variable:
       return token == Variable.TRUE || token == Variable.FALSE || token == Variable.NIL;
     case Char:
     case Number:
     case Pattern:
     case String:
       return true;
   }
   return false;
 }
  private void callASM(
      Map<String, Integer /* counter */> variables, Map<String, Integer /* counter */> methods) {
    this.asmCodeGenerator.initVariables(variables);
    this.asmCodeGenerator.initMethods(methods);
    this.asmCodeGenerator.start();

    for (int i = 0; i < this.tokenList.size(); i++) {
      Token<?> token = this.tokenList.get(i);
      switch (token.getType()) {
        case Operator:
          OperatorToken op = (OperatorToken) token;

          switch (op.getOperatorType()) {
            case ADD:
              this.asmCodeGenerator.onAdd(token);
              break;
            case SUB:
              this.asmCodeGenerator.onSub(token);
              break;
            case MULT:
              this.asmCodeGenerator.onMult(token);
              break;
            case DIV:
              this.asmCodeGenerator.onDiv(token);
              break;
            case MOD:
              this.asmCodeGenerator.onMod(token);
              break;
            case EQ:
              this.asmCodeGenerator.onEq(token);
              break;
            case NEQ:
              this.asmCodeGenerator.onNeq(token);
              break;
            case LT:
              this.asmCodeGenerator.onLt(token);
              break;
            case LE:
              this.asmCodeGenerator.onLe(token);
              break;
            case GT:
              this.asmCodeGenerator.onGt(token);
              break;
            case GE:
              this.asmCodeGenerator.onGe(token);
              break;
            case NOT:
              this.asmCodeGenerator.onNot(token);
              break;
            case NEG:
              this.asmCodeGenerator.onNeg(token);
              break;
            case AND:
              this.asmCodeGenerator.onAndRight(token);
              break;
            case OR:
              this.asmCodeGenerator.onJoinRight(token);
              break;
            case FUNC:
              this.asmCodeGenerator.onMethodInvoke(token);
              break;
            case INDEX:
              this.asmCodeGenerator.onArrayIndexEnd(token);
              break;
            case MATCH:
              this.asmCodeGenerator.onMatch(token);
              break;
            case TERNARY:
              this.asmCodeGenerator.onTernaryRight(token);
              break;
            case BIT_AND:
              this.asmCodeGenerator.onBitAnd(token);
              break;
            case BIT_OR:
              this.asmCodeGenerator.onBitOr(token);
              break;
            case BIT_XOR:
              this.asmCodeGenerator.onBitXor(token);
              break;
            case BIT_NOT:
              this.asmCodeGenerator.onBitNot(token);
              break;
            case SHIFT_LEFT:
              this.asmCodeGenerator.onShiftLeft(token);
              break;
            case SHIFT_RIGHT:
              this.asmCodeGenerator.onShiftRight(token);
              break;
            case U_SHIFT_RIGHT:
              this.asmCodeGenerator.onUnsignedShiftRight(token);
              break;
          }
          break;
        case Delegate:
          DelegateToken delegateToken = (DelegateToken) token;
          final Token<?> realToken = delegateToken.getToken();
          switch (delegateToken.getDelegateTokenType()) {
            case And_Left:
              this.asmCodeGenerator.onAndLeft(realToken);
              break;
            case Join_Left:
              this.asmCodeGenerator.onJoinLeft(realToken);
              break;
            case Array:
              this.asmCodeGenerator.onArray(realToken);
              break;
            case Index_Start:
              this.asmCodeGenerator.onArrayIndexStart(realToken);
              break;
            case Ternary_Boolean:
              this.asmCodeGenerator.onTernaryBoolean(realToken);
              break;
            case Ternary_Left:
              this.asmCodeGenerator.onTernaryLeft(realToken);
              break;
            case Method_Name:
              this.asmCodeGenerator.onMethodName(realToken);
              break;
            case Method_Param:
              this.asmCodeGenerator.onMethodParameter(realToken);
              break;
          }
          break;

        default:
          this.asmCodeGenerator.onConstant(token);
          break;
      }
    }
  }
  public Expression getResult() {
    // execute literal expression
    while (this.execute() > 0) {;
    }

    Map<String, Integer /* counter */> variables = new LinkedHashMap<String, Integer>();
    Map<String, Integer /* counter */> methods = new HashMap<String, Integer>();
    for (Token<?> token : this.tokenList) {
      switch (token.getType()) {
        case Variable:
          String varName = token.getLexeme();
          if (!variables.containsKey(varName)) {
            variables.put(varName, 1);
          } else {
            variables.put(varName, variables.get(varName) + 1);
          }

          break;
        case Delegate:
          DelegateToken delegateToken = (DelegateToken) token;
          if (delegateToken.getDelegateTokenType() == DelegateTokenType.Method_Name) {
            Token<?> realToken = delegateToken.getToken();
            if (realToken.getType() == TokenType.Variable) {
              String methodName = token.getLexeme();
              if (!methods.containsKey(methodName)) {
                methods.put(methodName, 1);
              } else {
                methods.put(methodName, methods.get(methodName) + 1);
              }
            }
          } else if (delegateToken.getDelegateTokenType() == DelegateTokenType.Array) {
            Token<?> realToken = delegateToken.getToken();
            if (realToken.getType() == TokenType.Variable) {
              varName = token.getLexeme();
              if (!variables.containsKey(varName)) {
                variables.put(varName, 1);
              } else {
                variables.put(varName, variables.get(varName) + 1);
              }
            }
          }
          break;
      }
    }
    // call asm to generate byte codes
    this.callASM(variables, methods);

    // Last token is a literal token,then return a LiteralExpression
    if (this.tokenList.size() <= 1) {
      if (this.tokenList.isEmpty()) {
        return new LiteralExpression(null, new ArrayList<String>(variables.keySet()));
      }
      final Token<?> lastToken = this.tokenList.get(0);
      if (this.isLiteralToken(lastToken)) {
        return new LiteralExpression(
            this.getAviatorObjectFromToken(lastToken).getValue(null),
            new ArrayList<String>(variables.keySet()));
      }
    }

    // get result from asm
    return this.asmCodeGenerator.getResult();
  }