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