//=== ClangASTPropsEmitter.cpp - Generate Clang AST properties --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend emits code for working with Clang AST properties.
//
//===----------------------------------------------------------------------===//

#include "ASTTableGen.h"
#include "TableGenBackends.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cctype>
#include <map>
#include <set>
#include <string>
using namespace llvm;
using namespace clang;
using namespace clang::tblgen;

static StringRef getReaderResultType(TypeNode _) { return "QualType"; }

namespace {

struct ReaderWriterInfo {
  bool IsReader;

  /// The name of the node hierarchy.  Not actually sensitive to IsReader,
  /// but useful to cache here anyway.
  StringRef HierarchyName;

  /// The suffix on classes: Reader/Writer
  StringRef ClassSuffix;

  /// The base name of methods: read/write
  StringRef MethodPrefix;

  /// The name of the property helper member: R/W
  StringRef HelperVariable;

  /// The result type of methods on the class.
  StringRef ResultType;

  template <class NodeClass>
  static ReaderWriterInfo forReader() {
    return ReaderWriterInfo{
      true,
      NodeClass::getASTHierarchyName(),
      "Reader",
      "read",
      "R",
      getReaderResultType(NodeClass())
    };
  }

  template <class NodeClass>
  static ReaderWriterInfo forWriter() {
    return ReaderWriterInfo{
      false,
      NodeClass::getASTHierarchyName(),
      "Writer",
      "write",
      "W",
      "void"
    };
  }
};

struct NodeInfo {
  std::vector<Property> Properties;
  CreationRule Creator = nullptr;
  OverrideRule Override = nullptr;
  ReadHelperRule ReadHelper = nullptr;
};

struct CasedTypeInfo {
  TypeKindRule KindRule;
  std::vector<TypeCase> Cases;
};

class ASTPropsEmitter {
	raw_ostream &Out;
	RecordKeeper &Records;
	std::map<HasProperties, NodeInfo> NodeInfos;
  std::vector<PropertyType> AllPropertyTypes;
  std::map<PropertyType, CasedTypeInfo> CasedTypeInfos;

public:
	ASTPropsEmitter(RecordKeeper &records, raw_ostream &out)
		: Out(out), Records(records) {

		// Find all the properties.
		for (Property property :
           records.getAllDerivedDefinitions(PropertyClassName)) {
			HasProperties node = property.getClass();
			NodeInfos[node].Properties.push_back(property);
		}

    // Find all the creation rules.
    for (CreationRule creationRule :
           records.getAllDerivedDefinitions(CreationRuleClassName)) {
      HasProperties node = creationRule.getClass();

      auto &info = NodeInfos[node];
      if (info.Creator) {
        PrintFatalError(creationRule.getLoc(),
                        "multiple creator rules for \"" + node.getName()
                          + "\"");
      }
      info.Creator = creationRule;
    }

    // Find all the override rules.
    for (OverrideRule overrideRule :
           records.getAllDerivedDefinitions(OverrideRuleClassName)) {
      HasProperties node = overrideRule.getClass();

      auto &info = NodeInfos[node];
      if (info.Override) {
        PrintFatalError(overrideRule.getLoc(),
                        "multiple override rules for \"" + node.getName()
                          + "\"");
      }
      info.Override = overrideRule;
    }

    // Find all the write helper rules.
    for (ReadHelperRule helperRule :
           records.getAllDerivedDefinitions(ReadHelperRuleClassName)) {
      HasProperties node = helperRule.getClass();

      auto &info = NodeInfos[node];
      if (info.ReadHelper) {
        PrintFatalError(helperRule.getLoc(),
                        "multiple write helper rules for \"" + node.getName()
                          + "\"");
      }
      info.ReadHelper = helperRule;
    }

    // Find all the concrete property types.
    for (PropertyType type :
           records.getAllDerivedDefinitions(PropertyTypeClassName)) {
      // Ignore generic specializations; they're generally not useful when
      // emitting basic emitters etc.
      if (type.isGenericSpecialization()) continue;

      AllPropertyTypes.push_back(type);
    }

    // Find all the type kind rules.
    for (TypeKindRule kindRule :
           records.getAllDerivedDefinitions(TypeKindClassName)) {
      PropertyType type = kindRule.getParentType();
      auto &info = CasedTypeInfos[type];
      if (info.KindRule) {
        PrintFatalError(kindRule.getLoc(),
                        "multiple kind rules for \""
                           + type.getCXXTypeName() + "\"");
      }
      info.KindRule = kindRule;
    }

    // Find all the type cases.
    for (TypeCase typeCase :
           records.getAllDerivedDefinitions(TypeCaseClassName)) {
      CasedTypeInfos[typeCase.getParentType()].Cases.push_back(typeCase);
    }

    Validator(*this).validate();
	}

  void visitAllProperties(HasProperties derived, const NodeInfo &derivedInfo,
                          function_ref<void (Property)> visit) {
    std::set<StringRef> ignoredProperties;

    auto overrideRule = derivedInfo.Override;
    if (overrideRule) {
      auto list = overrideRule.getIgnoredProperties();
      ignoredProperties.insert(list.begin(), list.end());
    }

    // TODO: we should sort the properties in various ways
    //   - put arrays at the end to enable abbreviations
    //   - put conditional properties after properties used in the condition

    visitAllNodesWithInfo(derived, derivedInfo,
                          [&](HasProperties node, const NodeInfo &info) {
      for (Property prop : info.Properties) {
        if (ignoredProperties.count(prop.getName()))
          continue;

        visit(prop);
      }
    });
  }

  void visitAllNodesWithInfo(HasProperties derivedNode,
                             const NodeInfo &derivedNodeInfo,
                             llvm::function_ref<void (HasProperties node,
                                                      const NodeInfo &info)>
                               visit) {
    visit(derivedNode, derivedNodeInfo);

    // Also walk the bases if appropriate.
    if (ASTNode base = derivedNode.getAs<ASTNode>()) {
      for (base = base.getBase(); base; base = base.getBase()) {
        auto it = NodeInfos.find(base);

        // Ignore intermediate nodes that don't add interesting properties.
        if (it == NodeInfos.end()) continue;
        auto &baseInfo = it->second;

        visit(base, baseInfo);
      }
    }
  }

  template <class NodeClass>
  void emitNodeReaderClass() {
    auto info = ReaderWriterInfo::forReader<NodeClass>();
    emitNodeReaderWriterClass<NodeClass>(info);
  }

  template <class NodeClass>
  void emitNodeWriterClass() {
    auto info = ReaderWriterInfo::forWriter<NodeClass>();
    emitNodeReaderWriterClass<NodeClass>(info);
  }

  template <class NodeClass>
  void emitNodeReaderWriterClass(const ReaderWriterInfo &info);

  template <class NodeClass>
  void emitNodeReaderWriterMethod(NodeClass node,
                                  const ReaderWriterInfo &info);

  void emitPropertiedReaderWriterBody(HasProperties node,
                                      const ReaderWriterInfo &info);

  void emitReadOfProperty(StringRef readerName, Property property);
  void emitReadOfProperty(StringRef readerName, StringRef name,
                          PropertyType type, StringRef condition = "");

  void emitWriteOfProperty(StringRef writerName, Property property);
  void emitWriteOfProperty(StringRef writerName, StringRef name,
                           PropertyType type, StringRef readCode,
                           StringRef condition = "");

  void emitBasicReaderWriterFile(const ReaderWriterInfo &info);
  void emitDispatcherTemplate(const ReaderWriterInfo &info);
  void emitPackUnpackOptionalTemplate(const ReaderWriterInfo &info);
  void emitBasicReaderWriterTemplate(const ReaderWriterInfo &info);

  void emitCasedReaderWriterMethodBody(PropertyType type,
                                       const CasedTypeInfo &typeCases,
                                       const ReaderWriterInfo &info);

private:
  class Validator {
    ASTPropsEmitter &Emitter;
    std::set<HasProperties> ValidatedNodes;

  public:
    Validator(ASTPropsEmitter &emitter) : Emitter(emitter) {}
    void validate();

  private:
    void validateNode(HasProperties node, const NodeInfo &nodeInfo);
    void validateType(PropertyType type, WrappedRecord context);
  };
};

} // end anonymous namespace

void ASTPropsEmitter::Validator::validate() {
  for (auto &entry : Emitter.NodeInfos) {
    validateNode(entry.first, entry.second);
  }

  if (ErrorsPrinted > 0) {
    PrintFatalError("property validation failed");
  }
}

void ASTPropsEmitter::Validator::validateNode(HasProperties derivedNode,
                                              const NodeInfo &derivedNodeInfo) {
  if (!ValidatedNodes.insert(derivedNode).second) return;

  // A map from property name to property.
  std::map<StringRef, Property> allProperties;

  Emitter.visitAllNodesWithInfo(derivedNode, derivedNodeInfo,
                                [&](HasProperties node,
                                    const NodeInfo &nodeInfo) {
    for (Property property : nodeInfo.Properties) {
      validateType(property.getType(), property);

      auto result = allProperties.insert(
                      std::make_pair(property.getName(), property));

      // Diagnose non-unique properties.
      if (!result.second) {
        // The existing property is more likely to be associated with a
        // derived node, so use it as the error.
        Property existingProperty = result.first->second;
        PrintError(existingProperty.getLoc(),
                   "multiple properties named \"" + property.getName()
                      + "\" in hierarchy of " + derivedNode.getName());
        PrintNote(property.getLoc(), "existing property");
      }
    }
  });
}

void ASTPropsEmitter::Validator::validateType(PropertyType type,
                                              WrappedRecord context) {
  if (!type.isGenericSpecialization()) {
    if (type.getCXXTypeName() == "") {
      PrintError(type.getLoc(),
                 "type is not generic but has no C++ type name");
      if (context) PrintNote(context.getLoc(), "type used here");
    }
  } else if (auto eltType = type.getArrayElementType()) {
    validateType(eltType, context);
  } else if (auto valueType = type.getOptionalElementType()) {
    validateType(valueType, context);

    if (valueType.getPackOptionalCode().empty()) {
      PrintError(valueType.getLoc(),
                 "type doesn't provide optional-packing code");
      if (context) PrintNote(context.getLoc(), "type used here");
    } else if (valueType.getUnpackOptionalCode().empty()) {
      PrintError(valueType.getLoc(),
                 "type doesn't provide optional-unpacking code");
      if (context) PrintNote(context.getLoc(), "type used here");
    }
  } else {
    PrintError(type.getLoc(), "unknown generic property type");
    if (context) PrintNote(context.getLoc(), "type used here");
  }
}

/****************************************************************************/
/**************************** AST READER/WRITERS ****************************/
/****************************************************************************/

template <class NodeClass>
void ASTPropsEmitter::emitNodeReaderWriterClass(const ReaderWriterInfo &info) {
  StringRef suffix = info.ClassSuffix;
  StringRef var = info.HelperVariable;

  // Enter the class declaration.
  Out << "template <class Property" << suffix << ">\n"
         "class Abstract" << info.HierarchyName << suffix << " {\n"
         "public:\n"
         "  Property" << suffix << " &" << var << ";\n\n";

  // Emit the constructor.
  Out << "  Abstract" << info.HierarchyName << suffix
                      << "(Property" << suffix << " &" << var << ") : "
                      << var << "(" << var << ") {}\n\n";

  // Emit a method that dispatches on a kind to the appropriate node-specific
  // method.
  Out << "  " << info.ResultType << " " << info.MethodPrefix << "(";
  if (info.IsReader)
    Out       << NodeClass::getASTIdTypeName() << " kind";
  else
    Out       << "const " << info.HierarchyName << " *node";
  Out         << ") {\n"
         "    switch (";
  if (info.IsReader)
    Out         << "kind";
  else
    Out         << "node->" << NodeClass::getASTIdAccessorName() << "()";
  Out           << ") {\n";
  visitASTNodeHierarchy<NodeClass>(Records, [&](NodeClass node, NodeClass _) {
    if (node.isAbstract()) return;
    Out << "    case " << info.HierarchyName << "::" << node.getId() << ":\n"
           "      return " << info.MethodPrefix << node.getClassName() << "(";
    if (!info.IsReader)
      Out                  << "static_cast<const " << node.getClassName()
                           << " *>(node)";
    Out                    << ");\n";
  });
  Out << "    }\n"
         "    llvm_unreachable(\"bad kind\");\n"
         "  }\n\n";

  // Emit node-specific methods for all the concrete nodes.
  visitASTNodeHierarchy<NodeClass>(Records,
                                   [&](NodeClass node, NodeClass base) {
    if (node.isAbstract()) return;
    emitNodeReaderWriterMethod(node, info);
  });

  // Finish the class.
  Out << "};\n\n";
}

/// Emit a reader method for the given concrete AST node class.
template <class NodeClass>
void ASTPropsEmitter::emitNodeReaderWriterMethod(NodeClass node,
                                           const ReaderWriterInfo &info) {
  // Declare and start the method.
  Out << "  " << info.ResultType << " "
              << info.MethodPrefix << node.getClassName() << "(";
  if (!info.IsReader)
    Out <<       "const " << node.getClassName() << " *node";
  Out <<         ") {\n";
  if (info.IsReader)
    Out << "    auto &ctx = " << info.HelperVariable << ".getASTContext();\n";

  emitPropertiedReaderWriterBody(node, info);

  // Finish the method declaration.
  Out << "  }\n\n";
}

void ASTPropsEmitter::emitPropertiedReaderWriterBody(HasProperties node,
                                               const ReaderWriterInfo &info) {
  // Find the information for this node.
  auto it = NodeInfos.find(node);
  if (it == NodeInfos.end())
    PrintFatalError(node.getLoc(),
                    "no information about how to deserialize \""
                      + node.getName() + "\"");
  auto &nodeInfo = it->second;

  StringRef creationCode;
  if (info.IsReader) {
    // We should have a creation rule.
    if (!nodeInfo.Creator)
      PrintFatalError(node.getLoc(),
                      "no " CreationRuleClassName " for \""
                        + node.getName() + "\"");

    creationCode = nodeInfo.Creator.getCreationCode();
  }

  // Emit the ReadHelper code, if present.
  if (!info.IsReader && nodeInfo.ReadHelper) {
    Out << "    " << nodeInfo.ReadHelper.getHelperCode() << "\n";
  }

  // Emit code to read all the properties.
  visitAllProperties(node, nodeInfo, [&](Property prop) {
    // Verify that the creation code refers to this property.
    if (info.IsReader && creationCode.find(prop.getName()) == StringRef::npos)
      PrintFatalError(nodeInfo.Creator.getLoc(),
                      "creation code for " + node.getName()
                        + " doesn't refer to property \""
                        + prop.getName() + "\"");

    // Emit code to read or write this property.
    if (info.IsReader)
      emitReadOfProperty(info.HelperVariable, prop);
    else
      emitWriteOfProperty(info.HelperVariable, prop);
  });

  // Emit the final creation code.
  if (info.IsReader)
    Out << "    " << creationCode << "\n";
}

static void emitBasicReaderWriterMethodSuffix(raw_ostream &out,
                                              PropertyType type,
                                              bool isForRead) {
  if (!type.isGenericSpecialization()) {
    out << type.getAbstractTypeName();
  } else if (auto eltType = type.getArrayElementType()) {
    out << "Array";
    // We only include an explicit template argument for reads so that
    // we don't cause spurious const mismatches.
    if (isForRead) {
      out << "<";
      eltType.emitCXXValueTypeName(isForRead, out);
      out << ">";
    }
  } else if (auto valueType = type.getOptionalElementType()) {
    out << "Optional";
    // We only include an explicit template argument for reads so that
    // we don't cause spurious const mismatches.
    if (isForRead) {
      out << "<";
      valueType.emitCXXValueTypeName(isForRead, out);
      out << ">";
    }
  } else {
    PrintFatalError(type.getLoc(), "unexpected generic property type");
  }
}

/// Emit code to read the given property in a node-reader method.
void ASTPropsEmitter::emitReadOfProperty(StringRef readerName,
                                         Property property) {
  emitReadOfProperty(readerName, property.getName(), property.getType(),
                     property.getCondition());
}

void ASTPropsEmitter::emitReadOfProperty(StringRef readerName,
                                         StringRef name,
                                         PropertyType type,
                                         StringRef condition) {
  // Declare all the necessary buffers.
  auto bufferTypes = type.getBufferElementTypes();
  for (size_t i = 0, e = bufferTypes.size(); i != e; ++i) {
    Out << "    llvm::SmallVector<";
    PropertyType(bufferTypes[i]).emitCXXValueTypeName(/*for read*/ true, Out);
    Out << ", 8> " << name << "_buffer_" << i << ";\n";
  }

  //   T prop = R.find("prop").read##ValueType(buffers...);
  // We intentionally ignore shouldPassByReference here: we're going to
  // get a pr-value back from read(), and we should be able to forward
  // that in the creation rule.
  Out << "    ";
  if (!condition.empty()) Out << "llvm::Optional<";
  type.emitCXXValueTypeName(true, Out);
  if (!condition.empty()) Out << ">";
  Out << " " << name;

  if (condition.empty()) {
    Out << " = ";
  } else {
    Out << ";\n"
           "    if (" << condition << ") {\n"
           "      " << name << ".emplace(";
  }

  Out << readerName << ".find(\"" << name << "\")."
      << (type.isGenericSpecialization() ? "template " : "") << "read";
  emitBasicReaderWriterMethodSuffix(Out, type, /*for read*/ true);
  Out << "(";
  for (size_t i = 0, e = bufferTypes.size(); i != e; ++i) {
    Out << (i > 0 ? ", " : "") << name << "_buffer_" << i;
  }
  Out << ")";

  if (condition.empty()) {
    Out << ";\n";
  } else {
    Out << ");\n"
           "    }\n";
  }
}

/// Emit code to write the given property in a node-writer method.
void ASTPropsEmitter::emitWriteOfProperty(StringRef writerName,
                                          Property property) {
  emitWriteOfProperty(writerName, property.getName(), property.getType(),
                      property.getReadCode(), property.getCondition());
}

void ASTPropsEmitter::emitWriteOfProperty(StringRef writerName,
                                          StringRef name,
                                          PropertyType type,
                                          StringRef readCode,
                                          StringRef condition) {
  if (!condition.empty()) {
    Out << "    if (" << condition << ") {\n";
  }

  // Focus down to the property:
  //   T prop = <READ>;
  //   W.find("prop").write##ValueType(prop);
  Out << "    ";
  type.emitCXXValueTypeName(false, Out);
  Out << " " << name << " = (" << readCode << ");\n"
         "    " << writerName << ".find(\"" << name << "\").write";
  emitBasicReaderWriterMethodSuffix(Out, type, /*for read*/ false);
  Out << "(" << name << ");\n";

  if (!condition.empty()) {
    Out << "    }\n";
  }
}

/// Emit an .inc file that defines the AbstractFooReader class
/// for the given AST class hierarchy.
template <class NodeClass>
static void emitASTReader(RecordKeeper &records, raw_ostream &out,
                          StringRef description) {
  emitSourceFileHeader(description, out);

  ASTPropsEmitter(records, out).emitNodeReaderClass<NodeClass>();
}

void clang::EmitClangTypeReader(RecordKeeper &records, raw_ostream &out) {
  emitASTReader<TypeNode>(records, out, "A CRTP reader for Clang Type nodes");
}

/// Emit an .inc file that defines the AbstractFooWriter class
/// for the given AST class hierarchy.
template <class NodeClass>
static void emitASTWriter(RecordKeeper &records, raw_ostream &out,
                          StringRef description) {
  emitSourceFileHeader(description, out);

  ASTPropsEmitter(records, out).emitNodeWriterClass<NodeClass>();
}

void clang::EmitClangTypeWriter(RecordKeeper &records, raw_ostream &out) {
  emitASTWriter<TypeNode>(records, out, "A CRTP writer for Clang Type nodes");
}

/****************************************************************************/
/*************************** BASIC READER/WRITERS ***************************/
/****************************************************************************/

void
ASTPropsEmitter::emitDispatcherTemplate(const ReaderWriterInfo &info) {
  // Declare the {Read,Write}Dispatcher template.
  StringRef dispatcherPrefix = (info.IsReader ? "Read" : "Write");
  Out << "template <class ValueType>\n"
         "struct " << dispatcherPrefix << "Dispatcher;\n";

  // Declare a specific specialization of the dispatcher template.
  auto declareSpecialization =
    [&](StringRef specializationParameters,
        const Twine &cxxTypeName,
        StringRef methodSuffix) {
    StringRef var = info.HelperVariable;
    Out << "template " << specializationParameters << "\n"
           "struct " << dispatcherPrefix << "Dispatcher<"
                     << cxxTypeName << "> {\n";
    Out << "  template <class Basic" << info.ClassSuffix << ", class... Args>\n"
           "  static " << (info.IsReader ? cxxTypeName : "void") << " "
                       << info.MethodPrefix
                       << "(Basic" << info.ClassSuffix << " &" << var
                       << ", Args &&... args) {\n"
           "    return " << var << "."
                         << info.MethodPrefix << methodSuffix
                         << "(std::forward<Args>(args)...);\n"
           "  }\n"
           "};\n";
  };

  // Declare explicit specializations for each of the concrete types.
  for (PropertyType type : AllPropertyTypes) {
    declareSpecialization("<>",
                          type.getCXXTypeName(),
                          type.getAbstractTypeName());
    // Also declare a specialization for the const type when appropriate.
    if (!info.IsReader && type.isConstWhenWriting()) {
      declareSpecialization("<>",
                            "const " + type.getCXXTypeName(),
                            type.getAbstractTypeName());
    }
  }
  // Declare partial specializations for ArrayRef and Optional.
  declareSpecialization("<class T>",
                        "llvm::ArrayRef<T>",
                        "Array");
  declareSpecialization("<class T>",
                        "llvm::Optional<T>",
                        "Optional");
  Out << "\n";
}

void
ASTPropsEmitter::emitPackUnpackOptionalTemplate(const ReaderWriterInfo &info) {
  StringRef classPrefix = (info.IsReader ? "Unpack" : "Pack");
  StringRef methodName = (info.IsReader ? "unpack" : "pack");

  // Declare the {Pack,Unpack}OptionalValue template.
  Out << "template <class ValueType>\n"
         "struct " << classPrefix << "OptionalValue;\n";

  auto declareSpecialization = [&](const Twine &typeName,
                                   StringRef code) {
    Out << "template <>\n"
           "struct " << classPrefix << "OptionalValue<" << typeName << "> {\n"
           "  static " << (info.IsReader ? "Optional<" : "") << typeName
                       << (info.IsReader ? "> " : " ") << methodName << "("
                       << (info.IsReader ? "" : "Optional<") << typeName
                       << (info.IsReader ? "" : ">") << " value) {\n"
           "    return " << code << ";\n"
           "  }\n"
           "};\n";
  };

  for (PropertyType type : AllPropertyTypes) {
    StringRef code = (info.IsReader ? type.getUnpackOptionalCode()
                                    : type.getPackOptionalCode());
    if (code.empty()) continue;

    StringRef typeName = type.getCXXTypeName();
    declareSpecialization(typeName, code);
    if (type.isConstWhenWriting() && !info.IsReader)
      declareSpecialization("const " + typeName, code);
  }
  Out << "\n";
}

void
ASTPropsEmitter::emitBasicReaderWriterTemplate(const ReaderWriterInfo &info) {
  // Emit the Basic{Reader,Writer}Base template.
  Out << "template <class Impl>\n"
         "class Basic" << info.ClassSuffix << "Base {\n";
  Out << "  ASTContext &C;\n";
  Out << "protected:\n"
         "  Basic"
      << info.ClassSuffix << "Base" << ("(ASTContext &ctx) : C(ctx)")
      << " {}\n"
         "public:\n";
  Out << "  ASTContext &getASTContext() { return C; }\n";
  Out << "  Impl &asImpl() { return static_cast<Impl&>(*this); }\n";

  auto enterReaderWriterMethod = [&](StringRef cxxTypeName,
                                     StringRef abstractTypeName,
                                     bool shouldPassByReference,
                                     bool constWhenWriting,
                                     StringRef paramName) {
    Out << "  " << (info.IsReader ? cxxTypeName : "void")
                << " " << info.MethodPrefix << abstractTypeName << "(";
    if (!info.IsReader)
      Out       << (shouldPassByReference || constWhenWriting ? "const " : "")
                << cxxTypeName
                << (shouldPassByReference ? " &" : "") << " " << paramName;
    Out         << ") {\n";
  };

  // Emit {read,write}ValueType methods for all the enum and subclass types
  // that default to using the integer/base-class implementations.
  for (PropertyType type : AllPropertyTypes) {
    auto enterMethod = [&](StringRef paramName) {
      enterReaderWriterMethod(type.getCXXTypeName(),
                              type.getAbstractTypeName(),
                              type.shouldPassByReference(),
                              type.isConstWhenWriting(),
                              paramName);
    };
    auto exitMethod = [&] {
      Out << "  }\n";
    };

    // Handled cased types.
    auto casedIter = CasedTypeInfos.find(type);
    if (casedIter != CasedTypeInfos.end()) {
      enterMethod("node");
      emitCasedReaderWriterMethodBody(type, casedIter->second, info);
      exitMethod();

    } else if (type.isEnum()) {
      enterMethod("value");
      if (info.IsReader)
        Out << "    return asImpl().template readEnum<"
            <<         type.getCXXTypeName() << ">();\n";
      else
        Out << "    asImpl().writeEnum(value);\n";
      exitMethod();

    } else if (PropertyType superclass = type.getSuperclassType()) {
      enterMethod("value");
      if (info.IsReader)
        Out << "    return cast_or_null<" << type.getSubclassClassName()
                                          << ">(asImpl().read"
                                          << superclass.getAbstractTypeName()
                                          << "());\n";
      else
        Out << "    asImpl().write" << superclass.getAbstractTypeName()
                                    << "(value);\n";
      exitMethod();

    } else {
      // The other types can't be handled as trivially.
    }
  }
  Out << "};\n\n";
}

void ASTPropsEmitter::emitCasedReaderWriterMethodBody(PropertyType type,
                                             const CasedTypeInfo &typeCases,
                                             const ReaderWriterInfo &info) {
  if (typeCases.Cases.empty()) {
    assert(typeCases.KindRule);
    PrintFatalError(typeCases.KindRule.getLoc(),
                    "no cases found for \"" + type.getCXXTypeName() + "\"");
  }
  if (!typeCases.KindRule) {
    assert(!typeCases.Cases.empty());
    PrintFatalError(typeCases.Cases.front().getLoc(),
                    "no kind rule for \"" + type.getCXXTypeName() + "\"");
  }

  auto var = info.HelperVariable;
  std::string subvar = ("sub" + var).str();

  // Bind `ctx` for readers.
  if (info.IsReader)
    Out << "    auto &ctx = asImpl().getASTContext();\n";

  // Start an object.
  Out << "    auto &&" << subvar << " = asImpl()."
                       << info.MethodPrefix << "Object();\n";

  // Read/write the kind property;
  TypeKindRule kindRule = typeCases.KindRule;
  StringRef kindProperty = kindRule.getKindPropertyName();
  PropertyType kindType = kindRule.getKindType();
  if (info.IsReader) {
    emitReadOfProperty(subvar, kindProperty, kindType);
  } else {
    // Write the property.  Note that this will implicitly read the
    // kind into a local variable with the right name.
    emitWriteOfProperty(subvar, kindProperty, kindType,
                        kindRule.getReadCode());
  }

  // Prepare a ReaderWriterInfo with a helper variable that will use
  // the sub-reader/writer.
  ReaderWriterInfo subInfo = info;
  subInfo.HelperVariable = subvar;

  // Switch on the kind.
  Out << "    switch (" << kindProperty << ") {\n";
  for (TypeCase typeCase : typeCases.Cases) {
    Out << "    case " << type.getCXXTypeName() << "::"
                       << typeCase.getCaseName() << ": {\n";
    emitPropertiedReaderWriterBody(typeCase, subInfo);
    if (!info.IsReader)
      Out << "    return;\n";
    Out << "    }\n\n";
  }
  Out << "    }\n"
         "    llvm_unreachable(\"bad " << kindType.getCXXTypeName()
                                       << "\");\n";
}

void ASTPropsEmitter::emitBasicReaderWriterFile(const ReaderWriterInfo &info) {
  emitDispatcherTemplate(info);
  emitPackUnpackOptionalTemplate(info);
  emitBasicReaderWriterTemplate(info);
}

/// Emit an .inc file that defines some helper classes for reading
/// basic values.
void clang::EmitClangBasicReader(RecordKeeper &records, raw_ostream &out) {
  emitSourceFileHeader("Helper classes for BasicReaders", out);

  // Use any property, we won't be using those properties.
  auto info = ReaderWriterInfo::forReader<TypeNode>();
  ASTPropsEmitter(records, out).emitBasicReaderWriterFile(info);
}

/// Emit an .inc file that defines some helper classes for writing
/// basic values.
void clang::EmitClangBasicWriter(RecordKeeper &records, raw_ostream &out) {
  emitSourceFileHeader("Helper classes for BasicWriters", out);

  // Use any property, we won't be using those properties.
  auto info = ReaderWriterInfo::forWriter<TypeNode>();
  ASTPropsEmitter(records, out).emitBasicReaderWriterFile(info);
}
