Search in sources :

Example 1 with MethodNodeImpl

use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.

the class ClassStmtCompiler method writeCopiedMethod.

protected void writeCopiedMethod(ClassStmtToken.Alias alias, String methodName, ClassEntity trait) {
    final MethodEntity methodEntity = fetchClassAndCheck(alias.getTrait()).findMethod(methodName.toLowerCase());
    String name = alias.getName();
    if (name == null)
        name = methodName;
    MethodEntity origin = entity.findMethod(name.toLowerCase());
    if (origin != null) {
        if (origin.getClazz() == entity) {
            if (origin.getTrait() != null) {
                compiler.getEnvironment().error(entity.getTrace(), Messages.ERR_TRAIT_METHOD_COLLISION.fetch(methodName, trait.getName(), origin.getTrait().getName(), entity.getName()));
            }
            return;
        }
    }
    if (methodEntity == null) {
        compiler.getEnvironment().error(entity.getTrace(), Messages.ERR_METHOD_NOT_FOUND.fetch(alias.getTrait(), methodName));
        return;
    }
    MethodEntity dup = methodEntity.duplicateForInject();
    dup.setClazz(entity);
    dup.setTrait(trait);
    if (alias.getName() != null)
        dup.setName(alias.getName());
    if (alias.getModifier() != null)
        dup.setModifier(alias.getModifier());
    MethodNodeImpl methodNode = MethodNodeImpl.duplicate(methodEntity.getAdditionalData("methodNode", MethodNode.class, new Function<MethodNode>() {

        @Override
        public MethodNode call() {
            ClassNode classNode = methodEntity.getClazz().getAdditionalData("classNode", ClassNode.class, new Function<ClassNode>() {

                @Override
                public ClassNode call() {
                    ClassReader classReader;
                    if (methodEntity.getClazz().getData() != null)
                        classReader = new ClassReader(methodEntity.getClazz().getData());
                    else {
                        try {
                            classReader = new ClassReader(methodEntity.getClazz().getName());
                        } catch (IOException e) {
                            throw new CriticalException(e);
                        }
                    }
                    ClassNode classNode = new ClassNode();
                    classReader.accept(classNode, 0);
                    return classNode;
                }
            });
            for (Object m : classNode.methods) {
                MethodNode method = (MethodNode) m;
                if (method.name.equals(methodEntity.getInternalName())) {
                    return method;
                }
            }
            throw new CriticalException("Cannot find MethodNode for method - " + methodEntity.getName() + "(" + methodEntity.getSignatureString(true) + ")");
        }
    }));
    if (origin != null) {
        dup.setPrototype(origin);
    }
    dup.setInternalName(dup.getName() + "$" + entity.nextMethodIndex());
    methodNode.name = dup.getInternalName();
    ClassEntity.SignatureResult result = entity.addMethod(dup, null);
    result.check(compiler.getEnvironment());
    node.methods.add(methodNode);
}
Also used : MethodNodeImpl(org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl) IOException(java.io.IOException) CriticalException(php.runtime.exceptions.CriticalException) Function(php.runtime.common.Function) ClassReader(org.objectweb.asm.ClassReader) BaseObject(php.runtime.lang.BaseObject)

Example 2 with MethodNodeImpl

use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.

the class ClassStmtCompiler method writeDefaultConstructors.

protected void writeDefaultConstructors() {
    if (!isSystem && !isClosure() && entity.getParent() != null && entity.getParent().getNativeClass() != null && !BaseObject.class.isAssignableFrom(entity.getParent().getNativeClass())) {
        for (Constructor el : entity.getParent().getNativeClass().getConstructors()) {
            Class<?>[] parameterTypes = el.getParameterTypes();
            if (parameterTypes.length == 2 && parameterTypes[0] == Environment.class && parameterTypes[1] == ClassEntity.class) {
                continue;
            }
            MethodNode constructor = new MethodNodeImpl();
            constructor.name = Constants.INIT_METHOD;
            constructor.access = el.getModifiers();
            constructor.exceptions = new ArrayList();
            MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, constructor);
            ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
            LabelNode l0 = writeLabel(constructor, statement.getMeta().getStartLine());
            methodCompiler.addLocalVariable("~this", l0);
            Type[] argumentTypes = new Type[parameterTypes.length];
            int i = 0;
            for (Class type : parameterTypes) {
                argumentTypes[i++] = Type.getType(type);
                methodCompiler.addLocalVariable("arg" + i, l0, type);
            }
            constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), argumentTypes);
            methodCompiler.writeHeader();
            expressionCompiler.writeVarLoad("~this");
            for (i = 0; i < argumentTypes.length; i++) {
                expressionCompiler.writeVarLoad("arg" + (i + 1));
            }
            constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, node.superName, Constants.INIT_METHOD, constructor.desc, false));
            methodCompiler.writeFooter();
            constructor.instructions.add(new InsnNode(RETURN));
            node.methods.add(constructor);
        }
    }
}
Also used : Constructor(java.lang.reflect.Constructor) MethodNodeImpl(org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl) ErrorType(php.runtime.exceptions.support.ErrorType) Type(org.objectweb.asm.Type)

Example 3 with MethodNodeImpl

use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.

the class ClassStmtCompiler method writeInitStatic.

@SuppressWarnings("unchecked")
protected void writeInitStatic() {
    MethodNode node = new MethodNodeImpl();
    node.access = ACC_STATIC;
    node.name = Constants.STATIC_INIT_METHOD;
    node.desc = Type.getMethodDescriptor(Type.getType(void.class));
    MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, node);
    ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
    methodCompiler.writeHeader();
    // trace list
    expressionCompiler.writePushSmallInt(traceList.size());
    node.instructions.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(TraceInfo.class)));
    expressionCompiler.stackPush(Memory.Type.REFERENCE);
    int i = 0;
    for (TraceInfo traceInfo : traceList) {
        expressionCompiler.writePushDup();
        expressionCompiler.writePushSmallInt(i);
        expressionCompiler.writePushCreateTraceInfo(traceInfo.getStartLine(), traceInfo.getStartPosition());
        node.instructions.add(new InsnNode(AASTORE));
        expressionCompiler.stackPop();
        expressionCompiler.stackPop();
        i++;
    }
    expressionCompiler.writePutStatic("$TRC", TraceInfo[].class);
    // memory constants
    expressionCompiler.writePushSmallInt(memoryConstants.size());
    node.instructions.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Memory.class)));
    expressionCompiler.stackPush(Memory.Type.REFERENCE);
    i = 0;
    for (Memory memory : memoryConstants) {
        expressionCompiler.writePushDup();
        expressionCompiler.writePushSmallInt(i);
        expressionCompiler.writePushMemory(memory);
        expressionCompiler.writePopBoxing(true, false);
        node.instructions.add(new InsnNode(AASTORE));
        expressionCompiler.stackPop();
        expressionCompiler.stackPop();
        i++;
    }
    expressionCompiler.writePutStatic("$MEM", Memory[].class);
    // memory array constants
    expressionCompiler.writePushSmallInt(memoryArrayConstants.size());
    node.instructions.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Memory[].class)));
    expressionCompiler.stackPush(Memory.Type.REFERENCE);
    i = 0;
    for (Collection<Memory> memories : memoryArrayConstants) {
        expressionCompiler.writePushDup();
        expressionCompiler.writePushSmallInt(i);
        expressionCompiler.writePushParameters(memories);
        node.instructions.add(new InsnNode(AASTORE));
        expressionCompiler.stackPop();
        expressionCompiler.stackPop();
        i++;
    }
    expressionCompiler.writePutStatic("$AMEM", Memory[][].class);
    // cached calls
    expressionCompiler.writePushNewObject(FunctionCallCache.class);
    expressionCompiler.writePutStatic("$CALL_FUNC_CACHE", FunctionCallCache.class);
    expressionCompiler.writePushNewObject(MethodCallCache.class);
    expressionCompiler.writePutStatic("$CALL_METH_CACHE", MethodCallCache.class);
    expressionCompiler.writePushNewObject(ConstantCallCache.class);
    expressionCompiler.writePutStatic("$CALL_CONST_CACHE", ConstantCallCache.class);
    expressionCompiler.writePushNewObject(PropertyCallCache.class);
    expressionCompiler.writePutStatic("$CALL_PROP_CACHE", PropertyCallCache.class);
    node.instructions.add(new InsnNode(RETURN));
    methodCompiler.writeFooter();
    this.node.methods.add(node);
}
Also used : Memory(php.runtime.Memory) MethodNodeImpl(org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl) TraceInfo(php.runtime.env.TraceInfo)

Example 4 with MethodNodeImpl

use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.

the class ClassStmtCompiler method writeInitEnvironment.

@SuppressWarnings("unchecked")
protected void writeInitEnvironment() {
    if (!dynamicConstants.isEmpty() || !dynamicProperties.isEmpty()) {
        initDynamicExists = true;
        MethodNode node = new MethodNodeImpl();
        node.access = ACC_STATIC + ACC_PUBLIC;
        node.name = "__$initEnvironment";
        node.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class));
        if (entity.isTrait()) {
            node.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(String.class));
        }
        MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, node);
        ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
        methodCompiler.writeHeader();
        LabelNode l0 = expressionCompiler.makeLabel();
        methodCompiler.addLocalVariable("~env", l0, Environment.class);
        if (entity.isTrait())
            methodCompiler.addLocalVariable("~class_name", l0, String.class);
        LocalVariable l_class = methodCompiler.addLocalVariable("~class", l0, ClassEntity.class);
        expressionCompiler.writePushEnv();
        if (entity.isTrait()) {
            expressionCompiler.writeVarLoad("~class_name");
            expressionCompiler.writePushDupLowerCase();
        } else {
            expressionCompiler.writePushConstString(entity.getName());
            expressionCompiler.writePushConstString(entity.getLowerName());
        }
        expressionCompiler.writePushConstBoolean(true);
        expressionCompiler.writeSysDynamicCall(Environment.class, "fetchClass", ClassEntity.class, String.class, String.class, Boolean.TYPE);
        expressionCompiler.writeVarStore(l_class, false, false);
        // corrects defination of constants
        final List<ConstStmtToken.Item> first = new ArrayList<ConstStmtToken.Item>();
        final Set<String> usedNames = new HashSet<String>();
        final List<ConstStmtToken.Item> other = new ArrayList<ConstStmtToken.Item>();
        for (ConstStmtToken.Item el : dynamicConstants) {
            Token tk = el.value.getSingle();
            if (tk instanceof StaticAccessExprToken) {
                StaticAccessExprToken access = (StaticAccessExprToken) tk;
                boolean self = false;
                if (access.getClazz() instanceof SelfExprToken)
                    self = true;
                else if (access.getClazz() instanceof FulledNameToken && ((FulledNameToken) access.getClazz()).getName().equalsIgnoreCase(entity.getName())) {
                    self = true;
                }
                if (self) {
                    String name = ((NameToken) access.getField()).getName();
                    if (usedNames.contains(el.getFulledName()))
                        first.add(0, el);
                    else
                        first.add(el);
                    usedNames.add(name);
                    continue;
                }
            }
            if (usedNames.contains(el.getFulledName()))
                first.add(0, el);
            else
                other.add(el);
        }
        other.addAll(0, first);
        for (ConstStmtToken.Item el : other) {
            expressionCompiler.writeVarLoad(l_class);
            expressionCompiler.writePushEnv();
            expressionCompiler.writePushConstString(el.getFulledName());
            expressionCompiler.writeExpression(el.value, true, false, true);
            expressionCompiler.writePopBoxing(true);
            expressionCompiler.writeSysDynamicCall(ClassEntity.class, "addDynamicConstant", void.class, Environment.class, String.class, Memory.class);
        }
        for (ClassVarStmtToken el : dynamicProperties) {
            expressionCompiler.writeVarLoad(l_class);
            expressionCompiler.writePushEnv();
            expressionCompiler.writePushConstString(el.getVariable().getName());
            expressionCompiler.writeExpression(el.getValue(), true, false, true);
            expressionCompiler.writePopBoxing(true);
            expressionCompiler.writeSysDynamicCall(ClassEntity.class, el.isStatic() ? "addDynamicStaticProperty" : "addDynamicProperty", void.class, Environment.class, String.class, Memory.class);
        }
        node.instructions.add(new InsnNode(RETURN));
        methodCompiler.writeFooter();
        this.node.methods.add(node);
    }
}
Also used : StaticAccessExprToken(org.develnext.jphp.core.tokenizer.token.expr.value.StaticAccessExprToken) LocalVariable(org.develnext.jphp.core.compiler.jvm.misc.LocalVariable) ValueExprToken(org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken) StaticAccessExprToken(org.develnext.jphp.core.tokenizer.token.expr.value.StaticAccessExprToken) ClassStmtToken(org.develnext.jphp.core.tokenizer.token.stmt.ClassStmtToken) ClassVarStmtToken(org.develnext.jphp.core.tokenizer.token.stmt.ClassVarStmtToken) MethodStmtToken(org.develnext.jphp.core.tokenizer.token.stmt.MethodStmtToken) Token(org.develnext.jphp.core.tokenizer.token.Token) SelfExprToken(org.develnext.jphp.core.tokenizer.token.expr.value.SelfExprToken) ConstStmtToken(org.develnext.jphp.core.tokenizer.token.stmt.ConstStmtToken) NameToken(org.develnext.jphp.core.tokenizer.token.expr.value.NameToken) FulledNameToken(org.develnext.jphp.core.tokenizer.token.expr.value.FulledNameToken) MethodNodeImpl(org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl) ClassVarStmtToken(org.develnext.jphp.core.tokenizer.token.stmt.ClassVarStmtToken) NameToken(org.develnext.jphp.core.tokenizer.token.expr.value.NameToken) FulledNameToken(org.develnext.jphp.core.tokenizer.token.expr.value.FulledNameToken) ConstStmtToken(org.develnext.jphp.core.tokenizer.token.stmt.ConstStmtToken) SelfExprToken(org.develnext.jphp.core.tokenizer.token.expr.value.SelfExprToken) FulledNameToken(org.develnext.jphp.core.tokenizer.token.expr.value.FulledNameToken)

Example 5 with MethodNodeImpl

use of org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl in project jphp by jphp-compiler.

the class ClassStmtCompiler method writeConstructor.

@SuppressWarnings("unchecked")
protected void writeConstructor() {
    MethodNode constructor = new MethodNodeImpl();
    constructor.name = Constants.INIT_METHOD;
    constructor.access = ACC_PUBLIC;
    constructor.exceptions = new ArrayList();
    MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, constructor);
    ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
    methodCompiler.writeHeader();
    LabelNode l0 = writeLabel(constructor, statement.getMeta().getStartLine());
    methodCompiler.addLocalVariable("~this", l0);
    if (isClosure() || generatorEntity != null) {
        constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(ClassEntity.class), Type.getType(Memory.class), Type.getType(Memory[].class));
        if (isClosure()) {
            constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(ClassEntity.class), Type.getType(Memory.class), Type.getType(String.class), Type.getType(Memory[].class));
        }
        methodCompiler.addLocalVariable("~env", l0, Environment.class);
        methodCompiler.addLocalVariable("~class", l0, ClassEntity.class);
        methodCompiler.addLocalVariable("~self", l0, Memory.class);
        if (isClosure()) {
            methodCompiler.addLocalVariable("~context", l0, String.class);
        }
        methodCompiler.addLocalVariable("~uses", l0, Memory[].class);
        methodCompiler.writeHeader();
        expressionCompiler.writeVarLoad("~this");
        expressionCompiler.writeVarLoad("~env");
        expressionCompiler.writeVarLoad("~class");
        expressionCompiler.writeVarLoad("~self");
        if (isClosure()) {
            expressionCompiler.writeVarLoad("~context");
        }
        expressionCompiler.writeVarLoad("~uses");
        constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, node.superName, Constants.INIT_METHOD, constructor.desc, false));
    } else {
        constructor.desc = Type.getMethodDescriptor(Type.getType(void.class), Type.getType(Environment.class), Type.getType(ClassEntity.class));
        methodCompiler.addLocalVariable("~env", l0, Environment.class);
        methodCompiler.addLocalVariable("~class", l0, String.class);
        expressionCompiler.writeVarLoad("~this");
        expressionCompiler.writeVarLoad("~env");
        expressionCompiler.writeVarLoad("~class");
        constructor.instructions.add(new MethodInsnNode(INVOKESPECIAL, node.superName, Constants.INIT_METHOD, constructor.desc, false));
        // PROPERTIES
        for (ClassVarStmtToken property : statement.getProperties()) {
            ExpressionStmtCompiler expressionStmtCompiler = new ExpressionStmtCompiler(methodCompiler, null);
            Memory value = Memory.NULL;
            if (property.getValue() != null)
                value = expressionStmtCompiler.writeExpression(property.getValue(), true, true, false);
            PropertyEntity prop = new PropertyEntity(compiler.getContext());
            prop.setName(property.getVariable().getName());
            prop.setModifier(property.getModifier());
            prop.setStatic(property.isStatic());
            prop.setDefaultValue(value);
            prop.setDefault(property.getValue() != null);
            prop.setTrace(property.toTraceInfo(compiler.getContext()));
            if (property.getDocComment() != null) {
                prop.setDocComment(new DocumentComment(property.getDocComment().getComment()));
            }
            ClassEntity.PropertyResult result = entity.addProperty(prop);
            result.check(compiler.getEnvironment());
            if (value == null && property.getValue() != null) {
                if (property.getValue().isSingle() && ValueExprToken.isConstable(property.getValue().getSingle(), true))
                    dynamicProperties.add(property);
                else
                    compiler.getEnvironment().error(property.getVariable().toTraceInfo(compiler.getContext()), ErrorType.E_COMPILE_ERROR, Messages.ERR_EXPECTED_CONST_VALUE.fetch(entity.getName() + "::$" + property.getVariable().getName()));
            }
        }
    }
    methodCompiler.writeFooter();
    constructor.instructions.add(new InsnNode(RETURN));
    node.methods.add(constructor);
}
Also used : Memory(php.runtime.Memory) MethodNodeImpl(org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl) ClassVarStmtToken(org.develnext.jphp.core.tokenizer.token.stmt.ClassVarStmtToken)

Aggregations

MethodNodeImpl (org.develnext.jphp.core.compiler.jvm.node.MethodNodeImpl)5 ClassVarStmtToken (org.develnext.jphp.core.tokenizer.token.stmt.ClassVarStmtToken)2 Memory (php.runtime.Memory)2 IOException (java.io.IOException)1 Constructor (java.lang.reflect.Constructor)1 LocalVariable (org.develnext.jphp.core.compiler.jvm.misc.LocalVariable)1 Token (org.develnext.jphp.core.tokenizer.token.Token)1 ValueExprToken (org.develnext.jphp.core.tokenizer.token.expr.ValueExprToken)1 FulledNameToken (org.develnext.jphp.core.tokenizer.token.expr.value.FulledNameToken)1 NameToken (org.develnext.jphp.core.tokenizer.token.expr.value.NameToken)1 SelfExprToken (org.develnext.jphp.core.tokenizer.token.expr.value.SelfExprToken)1 StaticAccessExprToken (org.develnext.jphp.core.tokenizer.token.expr.value.StaticAccessExprToken)1 ClassStmtToken (org.develnext.jphp.core.tokenizer.token.stmt.ClassStmtToken)1 ConstStmtToken (org.develnext.jphp.core.tokenizer.token.stmt.ConstStmtToken)1 MethodStmtToken (org.develnext.jphp.core.tokenizer.token.stmt.MethodStmtToken)1 ClassReader (org.objectweb.asm.ClassReader)1 Type (org.objectweb.asm.Type)1 Function (php.runtime.common.Function)1 TraceInfo (php.runtime.env.TraceInfo)1 CriticalException (php.runtime.exceptions.CriticalException)1