Search in sources :

Example 1 with StackItem

use of org.develnext.jphp.core.compiler.common.misc.StackItem in project jphp by jphp-compiler.

the class InstanceOfCompiler method write.

@Override
public void write(InstanceofExprToken instanceOf, boolean returnValue) {
    if (expr.stackEmpty(true))
        expr.unexpectedToken(instanceOf);
    StackItem R = expr.stackPop();
    StackItem L = expr.stackPop();
    boolean isInvert = !R.isKnown();
    if (!R.isKnown() && !L.isKnown() && R.getLevel() > L.getLevel())
        isInvert = false;
    if (isInvert) {
        pushName(R);
        expr.writePopString();
        expr.writePushDupLowerCase();
        expr.writePush(L);
        if (expr.stackPeek().isConstant())
            expr.unexpectedToken(instanceOf);
        expr.writePopBoxing();
        expr.writeSysStaticCall(OperatorUtils.class, "instanceOfRight", Boolean.TYPE, String.class, String.class, Memory.class);
        expr.writePopAll(1);
    } else {
        expr.writePush(L);
        if (expr.stackPeek().isConstant())
            expr.unexpectedToken(instanceOf);
        expr.writePopBoxing();
        pushName(R);
        expr.writeSysDynamicCall(Memory.class, "instanceOf", Boolean.TYPE, String.class, String.class);
    }
    if (!returnValue)
        expr.writePopAll(1);
}
Also used : StackItem(org.develnext.jphp.core.compiler.common.misc.StackItem)

Example 2 with StackItem

use of org.develnext.jphp.core.compiler.common.misc.StackItem in project jphp by jphp-compiler.

the class ExpressionStmtCompiler method writePopAll.

public void writePopAll(int count) {
    int i = 0;
    while (method.getStackCount() > 0 && i < count) {
        i++;
        StackItem o = stackPop();
        ValueExprToken token = o.getToken();
        StackItem.Type type = o.type;
        if (token == null) {
            switch(type.size()) {
                case 2:
                    code.add(new InsnNode(POP2));
                    break;
                case 1:
                    code.add(new InsnNode(POP));
                    break;
                default:
                    throw new IllegalArgumentException("Invalid of size StackItem: " + type.size());
            }
        } else
            /* if (o.isInvalidForOperations())*/
            unexpectedToken(token);
    }
}
Also used : StackItem(org.develnext.jphp.core.compiler.common.misc.StackItem) ValueExprToken(org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken)

Example 3 with StackItem

use of org.develnext.jphp.core.compiler.common.misc.StackItem in project jphp by jphp-compiler.

the class ExpressionStmtCompiler method writeLogicOperator.

Memory writeLogicOperator(LogicOperatorExprToken operator, boolean returnValue, boolean writeOpcode) {
    if (stackEmpty(true))
        unexpectedToken(operator);
    if (!writeOpcode) {
        StackItem top = stackPeek();
        Memory one = tryWritePush(top, false, false, true);
        if (one == null)
            return null;
        Memory two = writeExpression(operator.getRightValue(), true, true, false);
        if (two == null)
            return null;
        stackPop();
        Memory r = operator.calc(getCompiler().getEnvironment(), operator.toTraceInfo(getCompiler().getContext()), one, two);
        stackPush(r);
        return r;
    }
    writeLineNumber(operator);
    StackItem o = stackPop();
    writePush(o);
    writePopBoolean();
    LabelNode end = new LabelNode();
    LabelNode next = new LabelNode();
    if (operator instanceof BooleanOrExprToken || operator instanceof BooleanOr2ExprToken) {
        code.add(new JumpInsnNode(IFEQ, next));
        stackPop();
        if (returnValue) {
            writePushBooleanAsMemory(true);
            stackPop();
        }
    } else if (operator instanceof BooleanAndExprToken || operator instanceof BooleanAnd2ExprToken) {
        code.add(new JumpInsnNode(IFNE, next));
        stackPop();
        if (returnValue) {
            writePushBooleanAsMemory(false);
            stackPop();
        }
    }
    code.add(new JumpInsnNode(GOTO, end));
    code.add(next);
    writeExpression(operator.getRightValue(), returnValue, false);
    if (returnValue) {
        if (operator.getLast() instanceof ValueIfElseToken)
            writePopBoxing();
        else
            writePopBooleanAsObject();
    }
    code.add(end);
    return null;
}
Also used : StackItem(org.develnext.jphp.core.compiler.common.misc.StackItem) UndefinedMemory(php.runtime.memory.helper.UndefinedMemory) Memory(php.runtime.Memory)

Example 4 with StackItem

use of org.develnext.jphp.core.compiler.common.misc.StackItem in project jphp by jphp-compiler.

the class ExpressionStmtCompiler method writeUnaryOperator.

Memory writeUnaryOperator(OperatorExprToken operator, boolean returnValue, boolean writeOpcode) {
    if (stackEmpty(true))
        unexpectedToken(operator);
    StackItem o = stackPop();
    ValueExprToken L = o.getToken();
    Memory mem = tryWritePush(o, false, false, true);
    StackItem.Type type = tryGetType(o);
    if (mem != null) {
        Memory result = CompilerUtils.calcUnary(getCompiler().getEnvironment(), operator.toTraceInfo(getCompiler().getContext()), mem, operator);
        if (operator instanceof ValueIfElseToken) {
            ValueIfElseToken valueIfElseToken = (ValueIfElseToken) operator;
            ExprStmtToken ret = valueIfElseToken.getValue();
            if (mem.toBoolean()) {
                if (ret == null)
                    result = mem;
                else
                    result = writeExpression(ret, true, true, false);
            } else {
                result = writeExpression(valueIfElseToken.getAlternative(), true, true, false);
            }
        } else if (operator instanceof ArrayGetExprToken && !(operator instanceof ArrayGetRefExprToken)) {
        // TODO: check!!!
        /*Memory array = mem;
                ArrayGetExprToken arrayGet = (ArrayGetExprToken)operator;
                for(ExprStmtToken expr : arrayGet.getParameters()){
                    Memory key = writeExpression(expr, true, true, false);
                    if (key == null)
                        break;
                    result = array = array.valueOfIndex(key).toImmutable();
                }*/
        }
        if (result != null) {
            stackPush(result);
            setStackPeekAsImmutable();
            return result;
        }
    }
    if (!writeOpcode)
        return null;
    writeLineNumber(operator);
    String name = operator.getCode();
    Class operatorResult = operator.getResultClass();
    LocalVariable variable = null;
    if (L instanceof VariableExprToken) {
        variable = method.getLocalVariable(((VariableExprToken) L).getName());
        if (operator instanceof ArrayPushExprToken || operator instanceof ArrayGetRefExprToken)
            variable.setValue(null);
    }
    if (operator instanceof IncExprToken || operator instanceof DecExprToken) {
        if (variable == null || variable.isReference()) {
            if (operator.getAssociation() == Association.LEFT && returnValue) {
                writePush(o);
                if (stackPeek().type.isConstant())
                    unexpectedToken(operator);
                writePushDup();
                writePopImmutable();
                code.add(new InsnNode(SWAP));
                writePushDup();
            } else {
                writePush(o);
                if (stackPeek().type.isConstant())
                    unexpectedToken(operator);
                writePushDup();
            }
            writeSysDynamicCall(Memory.class, name, operatorResult);
            writeSysDynamicCall(Memory.class, "assign", Memory.class, operatorResult);
            if (!returnValue || operator.getAssociation() == Association.LEFT) {
                writePopAll(1);
            }
        } else {
            writePush(o);
            if (stackPeek().type.isConstant())
                unexpectedToken(operator);
            if (operator.getAssociation() == Association.LEFT && returnValue) {
                writeVarLoad(variable);
            }
            writeSysDynamicCall(Memory.class, name, operatorResult);
            // TODO for constant values
            variable.setValue(null);
            if (operator.getAssociation() == Association.RIGHT)
                writeVarStore(variable, returnValue);
            else {
                writeVarStore(variable, false);
            }
        }
    } else if (operator instanceof AmpersandRefToken) {
        writePush(o, false, false);
        setStackPeekAsImmutable();
        Token token = o.getToken();
        if (token instanceof VariableExprToken) {
            LocalVariable local = method.getLocalVariable(((VariableExprToken) token).getName());
            local.setValue(null);
        }
    } else if (operator instanceof SilentToken) {
        writePushEnv();
        writeSysDynamicCall(Environment.class, "__pushSilent", void.class);
        writePush(o);
        writePushEnv();
        writeSysDynamicCall(Environment.class, "__popSilent", void.class);
    } else if (operator instanceof ValueIfElseToken) {
        writePush(o);
        ValueIfElseToken valueIfElseToken = (ValueIfElseToken) operator;
        LabelNode end = new LabelNode();
        LabelNode elseL = new LabelNode();
        if (valueIfElseToken.getValue() == null) {
            StackItem.Type dup = stackPeek().type;
            writePushDup();
            if (operator instanceof ValueNullCoalesceIfElseToken) {
                writePopBoxing();
                writeSysDynamicCall(Memory.class, "isNotNull", Boolean.TYPE);
            } else {
                writePopBoolean();
            }
            code.add(new JumpInsnNode(Opcodes.IFEQ, elseL));
            stackPop();
            writePopBoxing();
            stackPop();
            code.add(new JumpInsnNode(Opcodes.GOTO, end));
            code.add(elseL);
            // remove duplicate of condition value , IMPORTANT!!!
            makePop(dup);
            writeExpression(valueIfElseToken.getAlternative(), true, false);
            writePopBoxing();
            code.add(end);
        } else {
            writePopBoolean();
            code.add(new JumpInsnNode(Opcodes.IFEQ, elseL));
            stackPop();
            writeExpression(valueIfElseToken.getValue(), true, false);
            writePopBoxing();
            stackPop();
            // goto end
            code.add(new JumpInsnNode(Opcodes.GOTO, end));
            // else
            code.add(elseL);
            writeExpression(valueIfElseToken.getAlternative(), true, false);
            writePopBoxing();
            code.add(end);
        }
        setStackPeekAsImmutable(false);
    } else if (operator instanceof ArrayGetExprToken) {
        stackPush(o);
        writeArrayGet((ArrayGetExprToken) operator, returnValue);
    } else if (operator instanceof CallOperatorToken) {
        stackPush(o);
        CallOperatorToken call = (CallOperatorToken) operator;
        writePushParameters(call.getParameters());
        writePushEnv();
        writePushTraceInfo(operator);
        writeSysStaticCall(InvokeHelper.class, "callAny", Memory.class, Memory.class, Memory[].class, Environment.class, TraceInfo.class);
        if (!returnValue)
            writePopAll(1);
    } else {
        writePush(o);
        writePopBoxing();
        if (operator.isEnvironmentNeeded() && operator.isTraceNeeded()) {
            writePushEnv();
            writePushTraceInfo(operator);
            writeSysDynamicCall(Memory.class, name, operatorResult, Environment.class, TraceInfo.class);
        } else if (operator.isEnvironmentNeeded()) {
            writePushEnv();
            writeSysDynamicCall(Memory.class, name, operatorResult, Environment.class);
        } else if (operator.isTraceNeeded()) {
            writePushTraceInfo(operator);
            writeSysDynamicCall(Memory.class, name, operatorResult, TraceInfo.class);
        } else
            writeSysDynamicCall(Memory.class, name, operatorResult);
        if (!returnValue) {
            writePopAll(1);
        }
    }
    return null;
}
Also used : UndefinedMemory(php.runtime.memory.helper.UndefinedMemory) Memory(php.runtime.Memory) LocalVariable(org.develnext.jphp.core.compiler.jvm.misc.LocalVariable) ValueExprToken(org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken) OperatorExprToken(org.develnext.jphp.core.tokenizer.token.expr.OperatorExprToken) Token(org.develnext.jphp.core.tokenizer.token.Token) ClassExprToken(org.develnext.jphp.core.tokenizer.token.expr.ClassExprToken) OpenEchoTagToken(org.develnext.jphp.core.tokenizer.token.OpenEchoTagToken) ValueExprToken(org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken) ObjectInvokeHelper(php.runtime.invoke.ObjectInvokeHelper) InvokeHelper(php.runtime.invoke.InvokeHelper) TraceInfo(php.runtime.env.TraceInfo) StackItem(org.develnext.jphp.core.compiler.common.misc.StackItem) Type(org.objectweb.asm.Type) Environment(php.runtime.env.Environment) CompileClass(php.runtime.ext.support.compile.CompileClass)

Example 5 with StackItem

use of org.develnext.jphp.core.compiler.common.misc.StackItem in project jphp by jphp-compiler.

the class ExpressionStmtCompiler method writeOperator.

Memory writeOperator(OperatorExprToken operator, boolean returnValue, boolean writeOpcode) {
    if (writeOpcode) {
        BaseExprCompiler compiler = (BaseExprCompiler) getCompiler(operator.getClass());
        if (compiler != null) {
            if (writeOpcode) {
                writeLineNumber(operator);
            }
            compiler.write(operator, returnValue);
            return null;
        }
    }
    if (operator instanceof LogicOperatorExprToken) {
        return writeLogicOperator((LogicOperatorExprToken) operator, returnValue, writeOpcode);
    }
    if (!operator.isBinary()) {
        return writeUnaryOperator(operator, returnValue, writeOpcode);
    }
    if (stackEmpty(true))
        unexpectedToken(operator);
    StackItem o1 = stackPop();
    if (o1.isInvalidForOperations())
        unexpectedToken(operator);
    if (stackEmpty(true))
        unexpectedToken(operator);
    StackItem o2 = stackPeek();
    ValueExprToken L = stackPopToken();
    if (o2.isInvalidForOperations())
        unexpectedToken(operator);
    if (!(operator instanceof AssignExprToken || operator instanceof AssignOperatorExprToken))
        if (o1.getMemory() != null && o2.getMemory() != null) {
            Memory result;
            stackPush(result = CompilerUtils.calcBinary(getCompiler().getEnvironment(), operator.toTraceInfo(getCompiler().getContext()), o2.getMemory(), o1.getMemory(), operator, false));
            return result;
        }
    LocalVariable variable = null;
    if (L instanceof VariableExprToken) {
        variable = method.getLocalVariable(((VariableExprToken) L).getName());
    }
    if (operator instanceof AssignExprToken) {
        if (L instanceof VariableExprToken) {
            if (!writeOpcode)
                return null;
            writeVariableAssign((VariableExprToken) L, o1, (AssignExprToken) operator, returnValue);
            return null;
        }
    }
    Memory value1 = operator instanceof AssignableOperatorToken ? null : // LEFT
    tryWritePush(o2, false, false, true);
    // RIGHT
    Memory value2 = tryWritePush(o1, false, false, true);
    if (value1 != null && value2 != null) {
        stackPush(value1);
        stackPush(value2);
        return writeOperator(operator, returnValue, writeOpcode);
    }
    if (!returnValue && CompilerUtils.isOperatorAlwaysReturn(operator)) {
        unexpectedToken(operator);
    }
    if (!writeOpcode) {
        stackPush(o2);
        stackPush(o1);
        return null;
    }
    if (writeOpcode) {
        writeLineNumber(operator);
    }
    StackItem.Type Lt = tryGetType(o2);
    StackItem.Type Rt = tryGetType(o1);
    String name = operator.getCode();
    Class operatorResult = operator.getResultClass();
    boolean isInvert = false;
    boolean sideOperator = operator.isSide();
    if (variable != null && !variable.isReference()) {
        if (operator instanceof AssignOperatorExprToken) {
            name = ((AssignOperatorExprToken) operator).getOperatorCode();
            if (operator instanceof AssignConcatExprToken)
                operatorResult = String.class;
            if (operator instanceof AssignPlusExprToken || operator instanceof AssignMulExprToken)
                sideOperator = false;
        }
    }
    if (operator instanceof AssignableOperatorToken && tryIsImmutable(o2))
        unexpectedToken(operator);
    if (Lt.isConstant() && Rt.isConstant()) {
        if (operator instanceof AssignableOperatorToken)
            unexpectedToken(operator);
        writeScalarOperator(o2, Lt, o1, Rt, operator, operatorResult, name);
    } else {
        isInvert = !o1.isKnown();
        if (!o1.isKnown() && !o2.isKnown() && o1.getLevel() > o2.getLevel())
            isInvert = false;
        if (Lt.isConstant() && !isInvert) {
            writePush(o2);
            if (methodExists(OperatorUtils.class, name, Lt.toClass(), Rt.toClass())) {
                writePush(o1);
                writeSysStaticCall(OperatorUtils.class, name, operatorResult, Lt.toClass(), Rt.toClass());
            } else {
                writePopBoxing();
                writePush(o1);
                writeSysDynamicCall(Memory.class, name, operatorResult, Rt.toClass());
            }
        } else {
            if (isInvert) {
                stackPush(o1);
                if (o2.isKnown())
                    writePopBoxing(false);
                writePush(o2);
                if (!o2.isKnown() && !o2.type.isReference()) {
                    writeSysStaticCall(OperatorUtils.class, name, operatorResult, Lt.toClass(), Rt.toClass());
                    name = null;
                } else if (sideOperator) {
                    name += "Right";
                }
            /*if (cloneValue){
                        writeSysDynamicCall(Memory.class, name, operatorResult, isInvert ? Lt.toClass() : Rt.toClass());
                        writePush(o2);
                        name = null;
                    }*/
            } else {
                writePush(o2);
                writePopBoxing(false);
                /*if (cloneValue)
                        writePushDup();*/
                writePush(o1);
                if (Rt.isReference()) {
                    writePopBoxing(false);
                } else if (Rt.isLikeInt()) {
                    // fix bug call int operator.
                    writePopLong();
                    Rt = StackItem.Type.LONG;
                }
                if (!o1.immutable && !operator.isMutableArguments())
                    writePopImmutable();
            }
            if (name != null) {
                writeSysDynamicCall(Memory.class, name, operatorResult, isInvert ? Lt.toClass() : Rt.toClass());
            }
            if (operator.getCheckerCode() != null) {
                writePopBoxing();
                writePushEnv();
                writePushTraceInfo(operator);
                writeSysDynamicCall(Memory.class, operator.getCheckerCode(), Memory.class, Environment.class, TraceInfo.class);
            }
        }
        setStackPeekAsImmutable();
        if (operator instanceof AssignOperatorExprToken) {
            if (variable == null || variable.isReference()) {
                /*if (isInvert)
                        writeSysStaticCall(Memory.class, "assignRight", Memory.class, Rt.toClass(), Memory.class);
                    else
                        writeSysDynamicCall(Memory.class, "assign", Memory.class, stackPeek().type.toClass());
                    */
                if (!returnValue)
                    writePopAll(1);
            } else {
                if (returnValue)
                    writePushDup(StackItem.Type.valueOf(operatorResult));
                writePopBoxing(operatorResult);
                makeVarStore(variable);
                variable.setValue(!stackPeek().isConstant() ? null : stackPeek().getMemory());
                stackPop();
            }
        }
    }
    return null;
}
Also used : UndefinedMemory(php.runtime.memory.helper.UndefinedMemory) Memory(php.runtime.Memory) LocalVariable(org.develnext.jphp.core.compiler.jvm.misc.LocalVariable) StackItem(org.develnext.jphp.core.compiler.common.misc.StackItem) CompileClass(php.runtime.ext.support.compile.CompileClass) ValueExprToken(org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken)

Aggregations

StackItem (org.develnext.jphp.core.compiler.common.misc.StackItem)9 ValueExprToken (org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken)4 Memory (php.runtime.Memory)4 UndefinedMemory (php.runtime.memory.helper.UndefinedMemory)4 LocalVariable (org.develnext.jphp.core.compiler.jvm.misc.LocalVariable)2 TraceInfo (php.runtime.env.TraceInfo)2 CompileClass (php.runtime.ext.support.compile.CompileClass)2 OpenEchoTagToken (org.develnext.jphp.core.tokenizer.token.OpenEchoTagToken)1 Token (org.develnext.jphp.core.tokenizer.token.Token)1 ClassExprToken (org.develnext.jphp.core.tokenizer.token.expr.ClassExprToken)1 OperatorExprToken (org.develnext.jphp.core.tokenizer.token.expr.OperatorExprToken)1 Type (org.objectweb.asm.Type)1 Environment (php.runtime.env.Environment)1 InvokeHelper (php.runtime.invoke.InvokeHelper)1 ObjectInvokeHelper (php.runtime.invoke.ObjectInvokeHelper)1