Beispiel #1
0
void FunctionScope::outputCPPArguments(ExpressionListPtr params,
                                       CodeGenerator &cg,
                                       AnalysisResultPtr ar, int extraArg,
                                       bool variableArgument,
                                       int extraArgArrayId /* = -1 */,
                                       int extraArgArrayHash /* = -1 */,
                                       int extraArgArrayIndex /* = -1 */) {

  int paramCount = params ? params->getOutputCount() : 0;
  ASSERT(extraArg <= paramCount);
  int iMax = paramCount - extraArg;
  bool extra = false;

  if (variableArgument) {
    if (paramCount == 0) {
      cg_printf("0");
    } else {
      cg_printf("%d, ", paramCount);
    }
  }
  int firstExtra = 0;
  for (int i = 0; i < paramCount; i++) {
    ExpressionPtr param = (*params)[i];
    cg.setItemIndex(i);
    if (i > 0) cg_printf(extra ? "." : ", ");
    if (!extra && (i == iMax || extraArg < 0)) {
      if (extraArgArrayId != -1) {
        assert(extraArgArrayHash != -1 && extraArgArrayIndex != -1);
        ar->outputCPPScalarArrayId(cg, extraArgArrayId, extraArgArrayHash,
                                   extraArgArrayIndex);
        break;
      }
      extra = true;
      // Parameter arrays are always vectors.
      if (Option::GenArrayCreate &&
          cg.getOutput() != CodeGenerator::SystemCPP) {
        if (!params->hasNonArrayCreateValue(false, i)) {
          ar->m_arrayIntegerKeySizes.insert(paramCount - i);
          cg_printf("Array(");
          params->outputCPPUniqLitKeyArrayInit(cg, ar, paramCount - i,
                                               false, i);
          cg_printf(")");
          return;
        }
      }
      firstExtra = i;
      cg_printf("Array(ArrayInit(%d, true).", paramCount - i);
    }
    if (extra) {
      bool needRef = param->hasContext(Expression::RefValue) &&
                     !param->hasContext(Expression::NoRefWrapper) &&
                     param->isRefable();
      cg_printf("set%s(", needRef ? "Ref" : "");
      if (needRef) {
        // The parameter itself shouldn't be wrapped with ref() any more.
        param->setContext(Expression::NoRefWrapper);
      }
      param->outputCPP(cg, ar);
      cg_printf(")");
    } else {
      param->outputCPP(cg, ar);
    }
  }
  if (extra) {
    cg_printf(".create())");
  }
}
void UnaryOpExpression::outputCPPImpl(CodeGenerator &cg,
                                      AnalysisResultPtr ar) {
  if ((m_op == T_INC || m_op == T_DEC) && outputCPPImplOpEqual(cg, ar)) {
    return;
  }
  if (m_op == T_ARRAY &&
      (getContext() & (RefValue|LValue)) == 0 &&
      !ar->getInsideScalarArray()) {
    int id = -1;
    int hash = -1;
    int index = -1;
    string text;
    if (m_exp) {
      ExpressionListPtr pairs = dynamic_pointer_cast<ExpressionList>(m_exp);
      Variant v;
      if (pairs && pairs->isScalarArrayPairs() && pairs->getScalarValue(v)) {
        id = ar->registerScalarArray(getFileScope(), m_exp, hash, index, text);
      }
    } else {
      id = ar->registerScalarArray(getFileScope(), m_exp,
                                   hash, index, text); // empty array
    }
    if (id != -1) {
      if (Option::UseNamedScalarArray &&
          cg.getContext() == CodeGenerator::CppParameterDefaultValueDecl) {
        getFileScope()->addUsedDefaultValueScalarArray(text);
      }
      ar->outputCPPScalarArrayId(cg, id, hash, index);
      return;
    }
  }

  if ((m_op == T_ISSET || m_op == T_EMPTY || m_op == T_UNSET) && m_exp) {
    if (m_exp->is(Expression::KindOfExpressionList)) {
      ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp);
      if (exps->getListKind() == ExpressionList::ListKindParam) {
        int count = exps->getCount();
        if (count > 1) {
          cg_printf("(");
        }
        for (int i = 0; i < count; i++) {
          if (m_op == T_UNSET) {
            if (i > 0) cg_printf(", ");
            (*exps)[i]->outputCPPUnset(cg, ar);
          } else {
            if (i > 0) cg_printf(" && ");
            (*exps)[i]->outputCPPExistTest(cg, ar, m_op);
          }
        }
        if (exps->getCount() > 1) {
          cg_printf(")");
        }
        return;
      }
    }
    if (m_op == T_UNSET) {
      m_exp->outputCPPUnset(cg, ar);
    } else {
      m_exp->outputCPPExistTest(cg, ar, m_op);
    }
    return;
  }

  if (m_front) {
    switch (m_op) {
    case T_CLONE:         cg_printf("f_clone(");   break;
    case T_INC:           cg_printf("++");         break;
    case T_DEC:           cg_printf("--");         break;
    case '+':             cg_printf("+");          break;
    case '-':             cg_printf("negate(");    break;
    case '!':             cg_printf("!(");         break;
    case '~':             cg_printf("~");          break;
    case '(':             cg_printf("(");          break;
    case T_INT_CAST:      cg_printf("(");          break;
    case T_DOUBLE_CAST:   cg_printf("(");          break;
    case T_STRING_CAST:   cg_printf("(");          break;
    case T_ARRAY_CAST:    cg_printf("(");          break;
    case T_OBJECT_CAST:   cg_printf("(");          break;
    case T_BOOL_CAST:     cg_printf("(");          break;
    case T_UNSET_CAST:
      if (m_exp->hasCPPTemp()) {
        cg_printf("(id(");
      } else {
        cg_printf("(");
      }
      break;
    case T_EXIT:          cg_printf("f_exit(");    break;
    case T_ARRAY:
      cg_printf("Array(");
      break;
    case T_PRINT:         cg_printf("print(");     break;
    case T_EVAL:
      if (Option::EnableEval > Option::NoEval) {
        bool instance;
        if (getClassScope()) {
          FunctionScopePtr fs = getFunctionScope();
          instance = fs && !fs->isStatic();
        } else {
          instance = false;
        }
        cg_printf("eval(%s, Object(%s), ",
                  getScope()->inPseudoMain() ?
                  "get_variable_table()" : "variables",
                  instance ? "this" : "");
      } else {
        cg_printf("f_eval(");
      }
      break;
    case '@':
      if (m_silencer >= 0) {
        cg_printf("(%s%d.enable(),%s%d.disable(",
                  Option::SilencerPrefix, m_silencer,
                  Option::SilencerPrefix, m_silencer);
      }
      break;
    case T_FILE:
      cg_printf("get_source_filename(\"%s\")", getLocation()->file);
      break;
      break;
    default:
      ASSERT(false);
    }
  }


  if (m_exp) {
    switch (m_op) {
    case '+':
    case '-':
      if (m_exp->getActualType() &&
          (m_exp->getActualType()->is(Type::KindOfString) ||
           m_exp->getActualType()->is(Type::KindOfArray))) {
        cg_printf("(Variant)(");
        m_exp->outputCPP(cg, ar);
        cg_printf(")");
      } else {
        m_exp->outputCPP(cg, ar);
      }
      break;
    case '@':
      if (m_silencer < 0 && isUnused()) {
        m_exp->outputCPPUnneeded(cg, ar);
      } else if (!m_exp->hasCPPTemp() && !m_exp->getActualType()) {
        // Void needs to return something to silenceDec
        cg_printf("(");
        m_exp->outputCPP(cg, ar);
        cg_printf(",null)");
      } else {
        m_exp->outputCPP(cg, ar);
      }
      break;
    default:
      m_exp->outputCPP(cg, ar);
      break;
    }
  }

  if (m_front) {
    switch (m_op) {
    case T_ARRAY:
      {
        ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp);
        if (!exps) {
          cg_printf("ArrayData::Create()");
        }
        cg_printf(")");
      }
      break;
    case T_UNSET_CAST:
      if (m_exp->hasCPPTemp()) {
        cg_printf("),null");
      } else {
        cg_printf(",null");
      }
    case T_CLONE:
    case '!':
    case '(':
    case '-':
    case T_INT_CAST:
    case T_DOUBLE_CAST:
    case T_STRING_CAST:
    case T_ARRAY_CAST:
    case T_OBJECT_CAST:
    case T_BOOL_CAST:
    case T_EXIT:
    case T_PRINT:
    case T_EVAL:
    case T_INCLUDE:
    case T_INCLUDE_ONCE:
    case T_REQUIRE:
    case T_REQUIRE_ONCE:
      cg_printf(")");
      break;
    case '@':
      if (m_silencer >= 0) {
        cg_printf("))");
      }
      break;
    default:
      break;
    }
  } else {
    switch (m_op) {
    case T_INC:           cg_printf("++"); break;
    case T_DEC:           cg_printf("--"); break;
    default:
      ASSERT(false);
    }
  }
}
void UnaryOpExpression::outputCPPImpl(CodeGenerator &cg,
                                      AnalysisResultPtr ar) {
  if ((m_op == T_INC || m_op == T_DEC) && outputCPPImplOpEqual(cg, ar)) {
    return;
  }
  if (m_op == T_ARRAY &&
      (getContext() & (RefValue|LValue)) == 0 &&
      !cg.getInsideScalarArray()) {
    int id = -1;
    int hash = -1;
    int index = -1;
    string text;
    if (m_exp) {
      ExpressionListPtr pairs = dynamic_pointer_cast<ExpressionList>(m_exp);
      Variant v;
      if (pairs && pairs->isScalarArrayPairs() && pairs->getScalarValue(v)) {
        id = ar->registerScalarArray(cg.getInsideScalarArray(), getFileScope(),
                                     m_exp, hash, index, text);
      }
    } else {
      id = ar->registerScalarArray(cg.getInsideScalarArray(), getFileScope(),
                                   m_exp, hash, index, text); // empty array
    }
    if (id != -1) {
      bool scalarVariant =
        Option::UseScalarVariant && cg.hasScalarVariant();
      if (scalarVariant) {
        ar->addNamedScalarVarArray(text);
        getFileScope()->addUsedScalarVarArray(text);
      }
      if (Option::UseNamedScalarArray && cg.isFileOrClassHeader()) {
        if (getClassScope()) {
          getClassScope()->addUsedDefaultValueScalarArray(text);
          if (scalarVariant) {
            getClassScope()->addUsedDefaultValueScalarVarArray(text);
          }
        } else {
          getFileScope()->addUsedDefaultValueScalarArray(text);
          if (scalarVariant) {
            getFileScope()->addUsedDefaultValueScalarVarArray(text);
          }
        }
      }
      ar->outputCPPScalarArrayId(cg, id, hash, index, scalarVariant);
      return;
    }
  }

  if ((m_op == T_ISSET || m_op == T_EMPTY || m_op == T_UNSET) && m_exp) {
    if (m_exp->is(Expression::KindOfExpressionList)) {
      ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp);
      if (exps->getListKind() == ExpressionList::ListKindParam) {
        int count = exps->getCount();
        if (count > 1) {
          cg_printf("(");
        }
        for (int i = 0; i < count; i++) {
          if (m_op == T_UNSET) {
            if (i > 0) cg_printf(", ");
            (*exps)[i]->outputCPPUnset(cg, ar);
          } else {
            if (i > 0) cg_printf(" && ");
            (*exps)[i]->outputCPPExistTest(cg, ar, m_op);
          }
        }
        if (exps->getCount() > 1) {
          cg_printf(")");
        }
        return;
      }
    }
    if (m_op == T_UNSET) {
      m_exp->outputCPPUnset(cg, ar);
    } else {
      m_exp->outputCPPExistTest(cg, ar, m_op);
    }
    return;
  }

  ASSERT(m_op != T_CLASS && m_op != T_FUNCTION);

  const char *cstr = 0;
  if (m_front) {
    switch (m_op) {
      case T_CLONE:         cg_printf("f_clone(");   break;
      case T_INC:           cg_printf("++");         break;
      case T_DEC:           cg_printf("--");         break;
      case '+':             cg_printf("+");          break;
      case '-':             cg_printf("negate(");    break;
      case '!':             cg_printf("!(");         break;
      case '~':             cg_printf("~");          break;
      case T_INT_CAST:      cg_printf("(");          break;
      case T_DOUBLE_CAST:   cg_printf("(");          break;
      case T_STRING_CAST:   cstr = "String"; goto null_cast;
      case T_ARRAY_CAST:    cstr = "Array"; goto null_cast;
      case T_OBJECT_CAST:   cstr = "Object"; goto null_cast;
      null_cast: {
        TypePtr at = m_exp->getActualType();
        TypePtr et = m_exp->getType();
        TypePtr it = m_exp->getCPPType();
        if (at && Type::SameType(at, et) && Type::SameType(it, at)) {
          cg_printf("to%s(", cstr);
        } else {
          cg_printf("(");
        }
        break;
      }
      case T_BOOL_CAST:     cg_printf("(");          break;
      case T_UNSET_CAST:
        if (m_exp->isScalar()) {
          cg_printf("(null)");
          return;
        }
        if (m_exp->hasCPPTemp()) {
          cg_printf("(id(");
        } else {
          cg_printf("(");
        }
        break;
      case T_EXIT:          cg_printf("f_exit(");    break;
      case T_ARRAY:
        cg_printf("Array(");
        break;
      case T_PRINT:         cg_printf("print(");     break;
      case T_EVAL:
        if (Option::EnableEval > Option::NoEval) {
          bool instance;
          if (getClassScope()) {
            FunctionScopePtr fs = getFunctionScope();
            instance = fs && !fs->isStatic();
          } else {
            instance = false;
          }
          cg_printf("eval(%s, Object(%s), ",
                    getScope()->inPseudoMain() ?
                    "get_variable_table()" : "variables",
                    instance ? "this" : "");
        } else {
          cg_printf("f_eval(");
        }
        break;
      case '@':
        break;
      case T_FILE:
        cg_printf("get_source_filename(\"%s\")", getLocation()->file);
        break;
      case T_DIR:
        cg_printf("get_source_filename(\"%s\", true)", getLocation()->file);
        break;
      default:
        ASSERT(false);
    }
  }

  if (m_exp) {
    switch (m_op) {
      case '+':
      case '-':
        if (!m_exp->outputCPPArithArg(cg, ar, false)) {
          m_exp->outputCPP(cg, ar);
        }
        break;
      case '@':
        if (isUnused()) {
          m_exp->outputCPPUnneeded(cg, ar);
        } else {
          m_exp->outputCPP(cg, ar);
        }
        break;
      default:
        m_exp->outputCPP(cg, ar);
        break;
    }
  }

  if (m_front) {
    switch (m_op) {
    case T_ARRAY:
      {
        ExpressionListPtr exps = dynamic_pointer_cast<ExpressionList>(m_exp);
        if (!exps) {
          cg_printf("ArrayData::Create()");
        }
        cg_printf(")");
      }
      break;
    case T_UNSET_CAST:
      if (m_exp->hasCPPTemp()) {
        cg_printf("),null");
      } else {
        cg_printf(",null");
      }
    case T_CLONE:
    case '!':
    case '-':
    case T_INT_CAST:
    case T_DOUBLE_CAST:
    case T_STRING_CAST:
    case T_ARRAY_CAST:
    case T_OBJECT_CAST:
    case T_BOOL_CAST:
    case T_EXIT:
    case T_PRINT:
    case T_EVAL:
    case T_INCLUDE:
    case T_INCLUDE_ONCE:
    case T_REQUIRE:
    case T_REQUIRE_ONCE:
      cg_printf(")");
      break;
    case '@':
      break;
    default:
      break;
    }
  } else {
    switch (m_op) {
    case T_INC:           cg_printf("++"); break;
    case T_DEC:           cg_printf("--"); break;
    default:
      ASSERT(false);
    }
  }
}