Example #1
0
  @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;
  }