static void genConvert()

in unsupported/tools/rustgen/rustgen.cpp [374:481]


static void genConvert() {
  llvh::outs() << "pub unsafe fn cvt_node_ptr<'parser, 'gc>(\n"
                  "  cvt: &mut Converter<'parser>, \n"
                  "  gc: &'gc ast::GCLock, \n"
                  "  n: NodePtr) -> &'gc ast::Node<'gc> {\n";
  llvh::outs() << "    let nr = n.as_ref();\n"
                  "    let range = ast::SourceRange {\n"
                  "        file: cvt.file_id,\n"
                  "        start: cvt.cvt_smloc(nr.source_range.start),\n"
                  "        end: ast::SourceLoc::invalid(),\n"
                  "    };\n"
                  "\n";

  llvh::outs() << "    let res = match nr.kind {\n";

  auto genStruct = [](const TreeClass &cls) {
    if (cls.sentinel != SentinelType::None)
      return;
    if (strncmp(cls.name.c_str(), "Cover", 5) == 0)
      return;

    llvh::outs() << "        NodeKind::" << cls.name << " => {\n";

    // Declare all the fields as local vars to avoid multiple borrows
    // of the context.
    for (const auto &fld : cls.fields) {
      llvh::outs() << "          let " << fld.rustName() << " = ";
      bool close = true;
      switch (fld.type) {
        case FieldType::NodeString:
          llvh::outs() << "cvt_string" << (fld.optional ? "_opt" : "") << "(";
          break;
        case FieldType::NodeLabel:
          if ((cls.name == "UnaryExpression" && fld.name == "operator") ||
              (cls.name == "BinaryExpression" && fld.name == "operator") ||
              (cls.name == "LogicalExpression" && fld.name == "operator") ||
              (cls.name == "UpdateExpression" && fld.name == "operator") ||
              (cls.name == "VariableDeclaration" && fld.name == "kind") ||
              (cls.name == "Property" && fld.name == "kind") ||
              (cls.name == "MethodDefinition" && fld.name == "kind") ||
              (cls.name == "ImportDeclaration" && fld.name == "importKind") ||
              (cls.name == "ImportSpecifier" && fld.name == "importKind") ||
              (cls.name == "ExportNamedDeclaration" &&
               fld.name == "exportKind") ||
              (cls.name == "ExportAllDeclaration" &&
               fld.name == "exportKind") ||
              (cls.name == "AssignmentExpression" && fld.name == "operator"))
            llvh::outs() << "cvt_enum(";
          else
            llvh::outs() << "cvt.cvt_label" << (fld.optional ? "_opt" : "")
                         << "(gc, ";
          break;
        case FieldType::Boolean:
        case FieldType::Number:
        default:
          close = false;
          break;
        case FieldType::NodePtr:
          llvh::outs() << "cvt_node_ptr" << (fld.optional ? "_opt" : "")
                       << "(cvt, gc, ";
          break;
        case FieldType::NodeList:
          llvh::outs() << "cvt_node_list" << (fld.optional ? "_opt" : "")
                       << "(cvt, gc, ";
          break;
      }
      llvh::outs() << "hermes_get_" << cls.name << "_" << fld.name << "(n)";
      if (close)
        llvh::outs() << ")";
      llvh::outs() << ";\n";
    }

    llvh::outs()
        << "          let mut template = ast::template::" << cls.name << " {\n"
        << "              metadata: ast::TemplateMetadata {range, ..Default::default()},\n";

    for (const auto &fld : cls.fields) {
      // Shorthand initialization of each field.
      llvh::outs() << "                  " << fld.rustName() << ",\n";
    }

    llvh::outs()
        << "          };\n" // kind
           "          template.metadata.range.end = cvt.cvt_smloc(nr.source_range.end.pred());\n"
        << "          ast::builder::" << cls.name
        << "::build_template(gc, template)\n"
        << "        }\n"; // match block
  };

  for (const auto &cls : treeClasses_) {
    if (cls.sentinel != SentinelType::None)
      continue;
    genStruct(cls);
  }

  llvh::outs()
      << "        _ => {\n"
         "          cvt.report_invalid_node(gc, n, range);\n"
         "          let template = ast::template::Empty {\n"
         "            metadata: ast::TemplateMetadata {range, ..Default::default()}\n"
         "          };\n"
         "          ast::builder::Empty::build_template(gc, template)\n"
         "        }\n"

         "    };\n\n";
  llvh::outs() << "    res\n";
  llvh::outs() << "}\n";
}