Exemplo n.º 1
0
void BreakStatement::outputCPPImpl(CodeGenerator &cg, AnalysisResultPtr ar) {
  const std::vector<int> &labelIds = cg.getBreakScopes();
  if (labelIds.empty()) {
    cg_printf("throw_fatal(\"bad %s\");\n", m_name);
    return;
  }

  int64 depth = getDepth();

  if (!depth) {
    unsigned size = labelIds.size();
    int labelId = 0;

    int varId = cg.createNewLocalId(shared_from_this());
    cg_printf("int64 %s%d;\n", Option::TempPrefix, varId);

    m_exp->outputCPPBegin(cg, ar);
    cg_printf("%s%d = (", Option::TempPrefix, varId);
    m_exp->outputCPP(cg, ar);
    cg_printf(");\n");
    m_exp->outputCPPEnd(cg, ar);

    if (size > 1) {
      cg_printf("switch (");
      cg_printf("%s%d", Option::TempPrefix, varId);
      cg_printf(") {\n");
      for (unsigned int i = 0; i < size; i++) {
        labelId = labelIds[i];
        labelId &= ~CodeGenerator::BreakScopeBitMask;
        cg_printf("case %d: goto %s%d;\n",
                  int(labelIds.size() - i), m_name, labelId);
        cg.addLabelId(m_name, labelId);
      }
      cg_printf("default:\n");
    } else {
      labelId = labelIds.back();
      labelId &= ~CodeGenerator::BreakScopeBitMask;
      cg.addLabelId(m_name, labelId);
    }
    cg_printf("if (");
    cg_printf("%s%d", Option::TempPrefix, varId);
    cg_printf("<2) {\n");
    cg_printf("goto %s%d;\n", m_name, labelId);
    cg_printf("} else {\n");
    cg_printf("throw_fatal(\"bad %s\");\n", m_name);
    cg_printf("}\n");
    if (size > 1) {
      cg_printf("}\n");
    }
    return;
  }

  assert(depth >= 1);

  if (depth > (int64)labelIds.size()) {
    cg_printf("throw_fatal(\"bad %s\");\n", m_name);
    return;
  }

  int labelId = labelIds[labelIds.size() - depth];
  if (depth > 1 || labelId & CodeGenerator::InsideSwitch) {
    if (depth == 1 && labelId & CodeGenerator::StaticCases) {
      cg_printf("break;\n"); // continue will turn into break as well
    } else {
      labelId &= ~CodeGenerator::BreakScopeBitMask;
      cg_printf("goto %s%d;\n", m_name, labelId);
      cg.addLabelId(m_name, labelId);
    }
  } else {
    cg_printf("%s;\n", m_name);
  }
}