@Override public void write(ListExprToken list, boolean returnValue) { expr.writeExpression(list.getValue(), true, false); int i, length = list.getVariables().size(); for (i = length - 1; i >= 0; i--) { // desc order as in PHP ListExprToken.Variable v = list.getVariables().get(i); expr.writePushDup(); if (v.indexes != null) { for (int index : v.indexes) { expr.writePushConstLong(index); expr.writeSysDynamicCall( Memory.class, "valueOfIndex", Memory.class, expr.stackPeek().type.toClass()); } } expr.writePushConstLong(v.index); expr.writeSysDynamicCall( Memory.class, "valueOfIndex", Memory.class, expr.stackPeek().type.toClass()); if (v.isVariable()) { LocalVariable variable = method.getLocalVariable(v.getVariableName()); expr.writeVarAssign(variable, (VariableExprToken) v.var.getSingle(), false, true); } else if (v.isArray() || v.isStaticProperty() || v.isArrayPush()) { expr.writeExpression(v.var, true, false); if (expr.stackPeek().immutable || expr.stackPeek().isConstant()) expr.unexpectedToken(v.var.getSingle()); expr.writeSysStaticCall( Memory.class, "assignRight", Memory.class, Memory.class, Memory.class); expr.writePopAll(1); } else if (v.isDynamicProperty()) { DynamicAccessExprToken dynamic = (DynamicAccessExprToken) v.var.getLast(); ExprStmtToken var = new ExprStmtToken(v.var.getTokens()); var.getTokens().remove(var.getTokens().size() - 1); expr.writeDynamicAccessInfo(dynamic, false); expr.writeExpression(var, true, false); expr.writePopBoxing(false); expr.writeSysStaticCall( ObjectInvokeHelper.class, "assignPropertyRight", Memory.class, Memory.class, String.class, Environment.class, TraceInfo.class, Memory.class); expr.writePopAll(1); } } if (!returnValue) expr.writePopAll(1); }
@Override public MethodEntity compile() { if (statement != null) { if (external) statement.setDynamicLocal(true); if (statement.getDocComment() != null) entity.setDocComment(new DocumentComment(statement.getDocComment().getComment())); entity.setAbstract(statement.isAbstract()); entity.setAbstractable(statement.getBody() == null); entity.setFinal(statement.isFinal()); entity.setStatic(statement.isStatic()); entity.setModifier(statement.getModifier()); entity.setReturnReference(statement.isReturnReference()); entity.setTrace(statement.toTraceInfo(compiler.getContext())); entity.setImmutable(statement.getArguments().isEmpty()); entity.setGeneratorEntity(generatorEntity); if (clazz.isSystem()) entity.setInternalName(entity.getName()); else entity.setInternalName(entity.getName() + "$" + clazz.entity.nextMethodIndex()); ParameterEntity[] parameters = new ParameterEntity[statement.getArguments().size()]; int i = 0; for (ArgumentStmtToken argument : statement.getArguments()) { parameters[i] = new ParameterEntity(compiler.getContext()); ParameterEntity parameter = parameters[i]; parameter.setReference(argument.isReference()); parameter.setName(argument.getName().getName()); parameter.setTrace(argument.toTraceInfo(compiler.getContext())); parameter.setMutable( statement.isDynamicLocal() || statement.variable(argument.getName()).isMutable()); parameter.setUsed(!statement.isUnusedVariable(argument.getName())); parameter.setVariadic(argument.isVariadic()); parameter.setType(argument.getHintType()); if (argument.getHintTypeClass() != null) { parameter.setTypeClass(argument.getHintTypeClass().getName()); } ExpressionStmtCompiler expressionStmtCompiler = new ExpressionStmtCompiler(compiler); ExprStmtToken value = argument.getValue(); if (value != null) { Memory defaultValue = expressionStmtCompiler.writeExpression(value, true, true, false); // try detect constant if (value.isSingle()) { if (value.getSingle() instanceof NameToken) { parameter.setDefaultValueConstName(((NameToken) value.getSingle()).getName()); if (defaultValue == null) { defaultValue = (new ConstantMemory(((NameToken) value.getSingle()).getName())); parameter.setMutable(true); } } else if (value.getSingle() instanceof StaticAccessExprToken) { StaticAccessExprToken access = (StaticAccessExprToken) value.getSingle(); if (access.getClazz() instanceof NameToken && access.getField() instanceof NameToken) { if (defaultValue == null) defaultValue = (new ClassConstantMemory( ((NameToken) access.getClazz()).getName(), ((NameToken) access.getField()).getName())); parameter.setDefaultValueConstName( ((NameToken) access.getClazz()).getName() + "::" + ((NameToken) access.getField()).getName()); parameter.setMutable(true); } } } if (defaultValue == null) compiler .getEnvironment() .error( argument.toTraceInfo(compiler.getContext()), ErrorType.E_COMPILE_ERROR, Messages.ERR_EXPECTED_CONST_VALUE, "$" + argument.getName().getName()); parameter.setDefaultValue(defaultValue); } i++; } entity.setParameters(parameters); } if (statement != null && clazz.statement.isInterface()) { if (!statement.isInterfacable()) { compiler .getEnvironment() .error( entity.getTrace(), Messages.ERR_INTERFACE_FUNCTION_CANNOT_CONTAIN_BODY.fetch( entity.getSignatureString(false))); } if (statement.isAbstract() || statement.isFinal()) { compiler .getEnvironment() .error( entity.getTrace(), Messages.ERR_ACCESS_TYPE_FOR_INTERFACE_METHOD.fetch( entity.getSignatureString(false))); } } else { writeHeader(); if (statement.isGenerator()) { entity.setEmpty(false); entity.setImmutable(false); GeneratorStmtCompiler generatorStmtCompiler = new GeneratorStmtCompiler(compiler, statement); entity.setGeneratorEntity(generatorStmtCompiler.compile()); ExpressionStmtCompiler expr = new ExpressionStmtCompiler(this, null); expr.makeUnknown(new TypeInsnNode(NEW, entity.getGeneratorEntity().getInternalName())); expr.stackPush(Memory.Type.REFERENCE); expr.writePushDup(); // env expr.writePushEnv(); // classEntity expr.writePushDup(); expr.writePushConstString(compiler.getModule().getInternalName()); expr.writePushConstInt((int) entity.getGeneratorEntity().getId()); expr.writeSysDynamicCall( Environment.class, "__getGenerator", ClassEntity.class, String.class, Integer.TYPE); // self expr.writePushThis(); // uses expr.writeVarLoad("~args"); expr.writeSysCall( entity.getGeneratorEntity().getInternalName(), INVOKESPECIAL, Constants.INIT_METHOD, void.class, Environment.class, ClassEntity.class, Memory.class, Memory[].class); expr.writeSysStaticCall(ObjectMemory.class, "valueOf", Memory.class, IObject.class); expr.makeUnknown(new InsnNode(Opcodes.ARETURN)); expr.stackPop(); } else { ExpressionStmtCompiler expr = new ExpressionStmtCompiler(this, null); entity.setEmpty(true); if (statement != null && statement.getBody() != null) { expr.writeDefineVariables(statement.getLocal()); expr.write(statement.getBody()); if (!statement.getBody().getInstructions().isEmpty()) { entity.setEmpty(false); } } if (generatorEntity != null) { expr.writeVarLoad("~this"); expr.writePushConstBoolean(false); expr.writeSysDynamicCall(null, "_setValid", void.class, Boolean.TYPE); } ReturnStmtToken token = new ReturnStmtToken(new TokenMeta("", 0, 0, 0, 0)); token.setValue(null); expr.getCompiler(ReturnStmtToken.class).write(token); } writeFooter(); } return entity; }