All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.libra.expr.compiler.syntax.operator.BinOperator Maven / Gradle / Ivy

The newest version!
/*
 * MIT License
 *
 * Copyright (c) 2018 Alibaba Group
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.libra.expr.compiler.syntax.operator;

import com.libra.Log;

import com.libra.TextUtils;
import com.libra.expr.compiler.lex.SymbolToken;
import com.libra.expr.compiler.syntax.Expr;
import com.libra.expr.compiler.syntax.FloatExpr;
import com.libra.expr.compiler.syntax.IntegerExpr;
import com.libra.expr.compiler.syntax.RegisterExpr;
import com.libra.expr.compiler.syntax.StringExpr;
import com.libra.expr.compiler.syntax.VarExpr;
import com.libra.virtualview.common.ExprCommon;

/**
 * Created by gujicheng on 16/9/9.
 */
public class BinOperator extends Operator {
    private static final String TAG = "BinOperator_TMTEST";

    private static final int FUNCODE_LEN = 5;
    private static final byte[] sfunCode = {
            ExprCommon.VAR_VAR, ExprCommon.VAR_INT, ExprCommon.VAR_FLT, ExprCommon.VAR_STR, ExprCommon.VAR_REG,
            ExprCommon.INT_VAR, ExprCommon.NON_NON, ExprCommon.NON_NON, ExprCommon.NON_NON, ExprCommon.INT_REG,
            ExprCommon.FLT_VAR, ExprCommon.NON_NON, ExprCommon.NON_NON, ExprCommon.NON_NON, ExprCommon.FLT_REG,
            ExprCommon.STR_VAR, ExprCommon.NON_NON, ExprCommon.NON_NON, ExprCommon.NON_NON, ExprCommon.STR_REG,
            ExprCommon.REG_VAR, ExprCommon.REG_INT, ExprCommon.REG_FLT, ExprCommon.REG_STR, ExprCommon.REG_REG };

    private boolean isBin(char op) {
        if ((op >= SymbolToken.ADD && op <= SymbolToken.MOD) ||(op >= SymbolToken.EQ && op <= SymbolToken.OR) ) {
            return true;
        }
        return false;
    }

    @Override
    public boolean deal(char op) {
        boolean ret = false;

        if (isBin(op)) {
//            Log.d(TAG, "deal operands size:" + mOperands.size());
            if (mOperands.size() >= 2) {
                Expr exprParam2 = mOperands.pop();
                Expr exprParam1 = mOperands.pop();
//                Log.d(TAG, "param1:" + exprParam1 + "  param2:" + exprParam2);
                Expr expr = binOperate(exprParam1, exprParam2, op);
                if (null != expr) {
                    mOperands.push(expr);
                    ret = true;
                } else {
                    Log.e(TAG, "expr is null");
                }
            } else {
                Log.e(TAG, "mOperands too few:" + mOperands.size());
            }
        } else {
//            Log.e(TAG, "op:" + SymbolToken.show(op) + "  is not operator");
        }

        return ret;
    }

    private static boolean isEq(char op) {
        return (SymbolToken.EQ == op || SymbolToken.ADD_EQ == op || SymbolToken.SUB_EQ == op || SymbolToken.MUL_EQ == op || SymbolToken.DIV_EQ == op || SymbolToken.MOD_EQ == op) ? true : false;
    }

    private Expr binOperate(Expr expr1, Expr expr2, char op) {
        Expr ret = null;

        switch (expr1.mType) {
            case Expr.TYPE_INT: {
                if (isEq(op)) {
                    Log.e(TAG, "left operand is not var:" + SymbolToken.show(op));
                    break;
                }

                IntegerExpr e1 = (IntegerExpr) expr1;
                switch (expr2.mType) {
                    case Expr.TYPE_INT: {
                        IntegerExpr e2 = (IntegerExpr) expr2;
                        ret = new IntegerExpr(intCalc(e1.mValue, e2.mValue, op));
                        break;
                    }

                    case Expr.TYPE_FLOAT: {
                        FloatExpr e2 = (FloatExpr) expr2;
                        ret = new FloatExpr((float) floatCalc(e1.mValue, e2.mValue, op));
                        break;
                    }

                    case Expr.TYPE_STR: {
                        if (SymbolToken.ADD == op) {
//                            StringManager sm = StringManager.getInstance();
                            StringExpr e2 = (StringExpr) expr2;
                            String v = mStringManager.getString(e2.mValue);
                            v = String.format("%d%s", e1.mValue, v);
                            int id = mStringManager.getStringId(v, true);

                            ret = new StringExpr(id);
                        } else {
                            Log.e(TAG, "invalidate string operator:" + SymbolToken.show(op));
                        }
                        break;
                    }

                    case Expr.TYPE_VAR: {
                        writeCode(expr1, expr2, op);
                        int regId = mRegisterManager.malloc();
                        ret = new RegisterExpr(regId);
                        mCodeGenerator.writeByte((byte)regId);
                        break;
                    }

                    case Expr.TYPE_REG: {
                        writeCode(expr1, expr2, op);
                        ret = expr2;
                        break;
                    }
                }
                break;
            }

            case Expr.TYPE_FLOAT: {
                if (isEq(op)) {
                    Log.e(TAG, "left operand is not var:" + SymbolToken.show(op));
                    break;
                }

                FloatExpr e1 = (FloatExpr) expr1;
                switch (expr2.mType) {
                    case Expr.TYPE_INT: {
                        IntegerExpr e2 = (IntegerExpr) expr2;
                        ret = new FloatExpr((float)floatCalc(e1.mValue, e2.mValue, op));
                        break;
                    }

                    case Expr.TYPE_FLOAT: {
                        FloatExpr e2 = (FloatExpr) expr2;
                        ret = new FloatExpr((float) floatCalc(e1.mValue, e2.mValue, op));
                        break;
                    }

                    case Expr.TYPE_STR: {
                        if (SymbolToken.ADD == op) {
//                            StringManager sm = StringManager.getInstance();
                            StringExpr e2 = (StringExpr) expr2;
                            String v = mStringManager.getString(e2.mValue);
                            v = String.format("%f%s", e1.mValue, v);
                            int id = mStringManager.getStringId(v, true);

                            ret = new StringExpr(id);
                        } else {
                            Log.e(TAG, "invalidate string operator:" + SymbolToken.show(op));
                        }
                        break;
                    }

                    case Expr.TYPE_VAR: {
                        writeCode(expr1, expr2, op);
                        int regId = mRegisterManager.malloc();
                        ret = new RegisterExpr(regId);
                        mCodeGenerator.writeByte((byte)regId);
                        break;
                    }

                    case Expr.TYPE_REG:
                        writeCode(expr1, expr2, op);
                        ret = expr2;
                        break;
                }
                break;
            }

            case Expr.TYPE_STR: {
                if (isEq(op)) {
                    Log.e(TAG, "left operand is not var:" + SymbolToken.show(op));
                    break;
                }

                StringExpr e1 = (StringExpr) expr1;
                String v1 = mStringManager.getString(e1.mValue);
                if (SymbolToken.ADD == op) {
                    switch (expr2.mType) {
                        case Expr.TYPE_INT: {
                            IntegerExpr e2 = (IntegerExpr) expr2;
                            v1 = String.format("%s%d", v1, e2.mValue);
                            int id = mStringManager.getStringId(v1, true);
                            ret = new StringExpr(id);
                            break;
                        }

                        case Expr.TYPE_FLOAT: {
                            FloatExpr e2 = (FloatExpr) expr2;
                            v1 = String.format("%s%f", v1, e2.mValue);
                            int id = mStringManager.getStringId(v1, true);
                            ret = new StringExpr(id);
                            break;
                        }

                        case Expr.TYPE_STR: {
                            StringExpr e2 = (StringExpr) expr2;
                            String v2 = mStringManager.getString(e2.mValue);
                            v2 = String.format("%s%s", v1, v2);
                            int id = mStringManager.getStringId(v2, true);

                            ret = new StringExpr(id);
                            break;
                        }

                        case Expr.TYPE_VAR: {
                            writeCode(expr1, expr2, op);
                            int regId = mRegisterManager.malloc();
                            ret = new RegisterExpr(regId);
                            mCodeGenerator.writeByte((byte)regId);
                            break;
                        }

                        case Expr.TYPE_REG:
                            writeCode(expr1, expr2, op);
                            ret = expr2;
                            break;
                    }
                } else if (SymbolToken.EQ_EQ == op) {
                    switch (expr2.mType) {
                        case Expr.TYPE_STR: {
                            StringExpr e2 = (StringExpr) expr2;
                            String v2 = mStringManager.getString(e2.mValue);
                            int v = 0;
                            if (TextUtils.equals(v1, v2)) {
                                v = 1;
                            }
                            ret = new IntegerExpr(v);
                            break;
                        }

                        case Expr.TYPE_VAR: {
                            writeCode(expr1, expr2, op);
                            int regId = mRegisterManager.malloc();
                            ret = new RegisterExpr(regId);
                            mCodeGenerator.writeByte((byte) regId);
                            break;
                        }

                        case Expr.TYPE_REG:
                            writeCode(expr1, expr2, op);
                            ret = expr2;
                            break;
                    }

                } else {
                    Log.e(TAG, "invalidate string operator:" + SymbolToken.show(op));
                }
                break;
            }

            case Expr.TYPE_VAR: {
                switch (expr2.mType) {
                    case Expr.TYPE_STR:
                        if (SymbolToken.ADD != op && SymbolToken.EQ != op && SymbolToken.ADD_EQ != op && SymbolToken.EQ_EQ != op) {
                            Log.e(TAG, "invalidate string operator:" + SymbolToken.show(op));
                            break;
                        }
                    case Expr.TYPE_INT:
                    case Expr.TYPE_FLOAT:
                    case Expr.TYPE_VAR:
                        writeCode(expr1, expr2, op);
                        int regId = mRegisterManager.malloc();
                        ret = new RegisterExpr(regId);
//                        Log.d(TAG, "regId:" + regId);
                        mCodeGenerator.writeByte((byte)regId);
                        break;

                    case Expr.TYPE_REG:
                        writeCode(expr1, expr2, op);
                        ret = expr2;
                        break;
                }
                break;
            }

            case Expr.TYPE_REG: {
                if (SymbolToken.EQ == op) {
                    Log.e(TAG, "left operand is not var:" + SymbolToken.show(op));
                    break;
                }

                switch (expr2.mType) {
                    case Expr.TYPE_STR:
                        if (SymbolToken.ADD != op && SymbolToken.EQ_EQ != op) {
                            Log.e(TAG, "invalidate string operator:" + SymbolToken.show(op));
                            break;
                        }
                    case Expr.TYPE_INT:
                    case Expr.TYPE_FLOAT:
                    case Expr.TYPE_VAR:
                        writeCode(expr1, expr2, op);
                        ret = expr1;
                        break;

                    case Expr.TYPE_REG: {
                        writeCode(expr1, expr2, op);
                        int id1 = ((RegisterExpr)expr1).mRegId;
                        int id2 = ((RegisterExpr)expr2).mRegId;
                        if (id1 < id2) {
                            ret = expr1;
                        } else {
                            ret = expr2;
                        }
                        mRegisterManager.free();
                        break;
                    }
                }
                break;
            }
        }

        return ret;
    }

    private int intCalc(int v1, int v2, char op) {
        int ret = 0;

//        Log.d(TAG, "intCalc op:" + op + " v1:" + v1 + "  v2:" + v2);
        switch (op) {
            case SymbolToken.ADD:
                ret = v1 + v2;
                break;

            case SymbolToken.SUB:
                ret = v1 - v2;
                break;

            case SymbolToken.MUL:
                ret = v1 * v2;
                break;

            case SymbolToken.DIV:
                ret = v1 / v2;
                break;

            case SymbolToken.MOD:
                ret = v1 % v2;
                break;

            case SymbolToken.GT:
                ret = (v1 > v2) ? 1 : 0;
                break;

            case SymbolToken.LT:
                ret = (v1 < v2) ? 1 : 0;
                break;

            case SymbolToken.GE:
                ret = (v1 >= v2) ? 1 : 0;
                break;

            case SymbolToken.LE:
                ret = (v1 <= v2) ? 1 : 0;
                break;

            case SymbolToken.NOT_EQ:
                ret = (v1 != v2) ? 1 : 0;
                break;

            case SymbolToken.EQ_EQ:
                ret = (v1 == v2) ? 1 : 0;
                break;

            default:
                Log.e(TAG, "invalidate op:" + SymbolToken.show(op));
                break;
        }

        return ret;
    }

    private double floatCalc(double v1, double v2, char op) {
        double ret = 0;

        switch (op) {
            case SymbolToken.ADD:
                ret = v1 + v2;
                break;

            case SymbolToken.SUB:
                ret = v1 - v2;
                break;

            case SymbolToken.MUL:
                ret = v1 * v2;
                break;

            case SymbolToken.DIV:
                ret = v1 / v2;
                break;

            case SymbolToken.GT:
                ret = (v1 > v2) ? 1 : 0;
                break;

            case SymbolToken.LT:
                ret = (v1 < v2) ? 1 : 0;
                break;

            case SymbolToken.GE:
                ret = (v1 >= v2) ? 1 : 0;
                break;

            case SymbolToken.LE:
                ret = (v1 <= v2) ? 1 : 0;
                break;

            case SymbolToken.NOT_EQ:
                ret = (v1 != v2) ? 1 : 0;
                break;

            case SymbolToken.EQ_EQ:
                ret = (v1 == v2) ? 1 : 0;
                break;

            default:
                Log.e(TAG, "invalidate op:" + SymbolToken.show(op));
                break;
        }

        return ret;
    }

    private void writeCode(Expr expr1, Expr expr2, char op) {
        byte code = -1;
        switch (op) {
            case SymbolToken.ADD:
                code = ExprCommon.OPCODE_ADD;
                break;
            case SymbolToken.SUB:
                code = ExprCommon.OPCODE_SUB;
                break;
            case SymbolToken.MUL:
                code = ExprCommon.OPCODE_MUL;
                break;
            case SymbolToken.DIV:
                code = ExprCommon.OPCODE_DIV;
                break;
            case SymbolToken.MOD:
                code = ExprCommon.OPCODE_MOD;
                break;
            case SymbolToken.EQ:
                code = ExprCommon.OPCODE_EQUAL;
                break;
            case SymbolToken.GT:
                code = ExprCommon.OPCODE_GT;
                break;
            case SymbolToken.LT:
                code = ExprCommon.OPCODE_LT;
                break;
            case SymbolToken.ADD_EQ:
                code = ExprCommon.OPCODE_ADD_EQ;
                break;
            case SymbolToken.SUB_EQ:
                code = ExprCommon.OPCODE_SUB_EQ;
                break;
            case SymbolToken.MUL_EQ:
                code = ExprCommon.OPCODE_MUL_EQ;
                break;
            case SymbolToken.DIV_EQ:
                code = ExprCommon.OPCODE_DIV_EQ;
                break;
            case SymbolToken.MOD_EQ:
                code = ExprCommon.OPCODE_MOD_EQ;
                break;
            case SymbolToken.NOT_EQ:
                code = ExprCommon.OPCODE_NOT_EQ;
                break;
            case SymbolToken.EQ_EQ:
                code = ExprCommon.OPCODE_EQ_EQ;
                break;
            case SymbolToken.GE:
                code = ExprCommon.OPCODE_GE;
                break;
            case SymbolToken.LE:
                code = ExprCommon.OPCODE_LE;
                break;
            case SymbolToken.AND:
                code = ExprCommon.OPCODE_AND;
                break;
            case SymbolToken.OR:
                code = ExprCommon.OPCODE_OR;
                break;
            default:
                Log.e(TAG, "wirteBinCode op is invalidate:" + SymbolToken.show(op));
                break;
        }
//        Log.d(TAG, "write opCode:" + code);
        mCodeGenerator.writeByte(code);

        int type1 = expr1.mType;
        int type2 = expr2.mType;
        if (type1 < FUNCODE_LEN && type2 < FUNCODE_LEN) {
            byte funCode = sfunCode[type1 * FUNCODE_LEN + type2];
            if (-1 == funCode) {
                Log.e(TAG, "fun code error type1:" + type1 + "  type2:"
                        + type2);
            } else {
                mCodeGenerator.writeByte(funCode);
                switch (funCode) {
                    case ExprCommon.VAR_VAR:
                        writeVar((VarExpr)expr1);
                        writeVar((VarExpr)expr2);
                        break;
                    case ExprCommon.VAR_INT:
                        writeVar((VarExpr)expr1);
                        writeInt((IntegerExpr)expr2);
                        break;
                    case ExprCommon.VAR_FLT:
                        writeVar((VarExpr)expr1);
                        writeFloat((FloatExpr)expr2);
                        break;
                    case ExprCommon.VAR_STR:
                        writeVar((VarExpr)expr1);
                        writeString((StringExpr)expr2);
                        break;
                    case ExprCommon.VAR_REG:
                        writeVar((VarExpr)expr1);
                        writeRegister((RegisterExpr)expr2);
                        break;

                    case ExprCommon.INT_VAR:
                        writeInt((IntegerExpr)expr1);
                        writeVar((VarExpr)expr2);
                        break;
                    case ExprCommon.INT_REG:
                        writeInt((IntegerExpr)expr1);
                        writeRegister((RegisterExpr)expr2);
                        break;

                    case ExprCommon.FLT_VAR:
                        writeFloat((FloatExpr)expr1);
                        writeVar((VarExpr)expr2);
                        break;
                    case ExprCommon.FLT_REG:
                        writeFloat((FloatExpr)expr1);
                        writeRegister((RegisterExpr)expr2);
                        break;

                    case ExprCommon.STR_VAR:
                        writeString((StringExpr)expr1);
                        writeVar((VarExpr)expr2);
                        break;
                    case ExprCommon.STR_REG:
                        writeString((StringExpr)expr1);
                        writeRegister((RegisterExpr)expr2);
                        break;

                    case ExprCommon.REG_VAR:
                        writeRegister((RegisterExpr)expr1);
                        writeVar((VarExpr)expr2);
                        break;
                    case ExprCommon.REG_INT:
                        writeRegister((RegisterExpr)expr1);
                        writeInt((IntegerExpr)expr2);
                        break;
                    case ExprCommon.REG_FLT:
                        writeRegister((RegisterExpr)expr1);
                        writeFloat((FloatExpr)expr2);
                        break;
                    case ExprCommon.REG_STR:
                        writeRegister((RegisterExpr)expr1);
                        writeString((StringExpr)expr2);
                        break;
                    case ExprCommon.REG_REG:
                        writeRegister((RegisterExpr)expr1);
                        writeRegister((RegisterExpr)expr2);
                        break;
                }
            }
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy