%{
  from gyb_syntax_support import *
  # -*- mode: C++ -*-
  # Ignore the following admonition; it applies to the resulting .cpp file only
}%
//// Automatically Generated From ParsedSyntaxRecorder.cpp.gyb.
//// Do Not Edit Directly!
//===--- ParsedSyntaxRecorder.cpp - Parsed Syntax Recorder ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/Parse/ParsedSyntaxRecorder.h"
#include "swift/Parse/ParsedRawSyntaxRecorder.h"
#include "swift/Parse/SyntaxParsingContext.h"
#include "swift/Syntax/SyntaxFactory.h"

using namespace swift;
using namespace swift::syntax;

bool ParsedSyntaxRecorder::formExactLayoutFor(syntax::SyntaxKind Kind,
        ArrayRef<ParsedRawSyntaxNode> Elements,
        function_ref<void(syntax::SyntaxKind, ArrayRef<ParsedRawSyntaxNode>)> receiver) {
  switch (Kind) {
% for node in SYNTAX_NODES:
  case SyntaxKind::${node.syntax_kind}: {
% if node.children:
%   child_count = len(node.children)
    ParsedRawSyntaxNode Layout[${child_count}];
    unsigned I = 0;
%   for (child_idx, child) in enumerate(node.children):
    // child[${child_idx}] ${child.name}
    if (I == Elements.size() ||
        !${check_parsed_child_condition_raw(child)}(Elements[I])) {
%     if child.is_optional:
      Layout[${child_idx}] = ParsedRawSyntaxNode::null();
%     else:
      return false;
%     end
    } else {
      Layout[${child_idx}] = Elements[I];
      ++I;
    }
%   end
    if (I != Elements.size())
      return false;
    receiver(Kind, Layout);
    return true;
% elif node.is_syntax_collection():
    for (auto &E : Elements) {
      if (!SyntaxFactory::canServeAsCollectionMemberRaw(SyntaxKind::${node.syntax_kind}, E.getKind()))
        return false;
    }
    receiver(Kind, Elements);
    return true;
% else:
    return false;
% end
  }
% end
  default:
    return false;
  }
}

% for node in SYNTAX_NODES:
%   if node.children:
%     child_params = []
%     child_move_args = []
%     for child in node.children:
%         param_type = "Parsed%s" % child.type_name
%         if child.is_optional:
%            param_type = "Optional<%s>" % param_type
%         child_params.append("%s %s" % (param_type, child.name))
%         child_move_args.append("std::move(%s)" % (child.name))
%     child_params = ', '.join(child_params)
%     child_move_args = ', '.join(child_move_args)
Parsed${node.name}
ParsedSyntaxRecorder::record${node.syntax_kind}(${child_params},
                                       ParsedRawSyntaxRecorder &rec) {
  auto raw = rec.recordRawSyntax(SyntaxKind::${node.syntax_kind}, {
%     for child in node.children:
%       if child.is_optional:
    ${child.name}.hasValue() ? ${child.name}->getRaw() : ParsedRawSyntaxNode::null(),
%       else:
    ${child.name}.getRaw(),
%       end
%     end
  });
  return Parsed${node.name}(std::move(raw));
}

Parsed${node.name}
ParsedSyntaxRecorder::defer${node.syntax_kind}(${child_params}) {
  auto raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind}, {
%     for child in node.children:
%       if child.is_optional:
    ${child.name}.hasValue() ? ${child.name}->getRaw() : ParsedRawSyntaxNode::null(),
%       else:
    ${child.name}.getRaw(),
%       end
%     end
  });
  return Parsed${node.name}(std::move(raw));
}

Parsed${node.name}
ParsedSyntaxRecorder::make${node.syntax_kind}(${child_params},
    SyntaxParsingContext &SPCtx) {
  if (SPCtx.isBacktracking())
    return defer${node.syntax_kind}(${child_move_args});
  return record${node.syntax_kind}(${child_move_args}, SPCtx.getRecorder());
}

%   elif node.is_syntax_collection():
Parsed${node.name}
ParsedSyntaxRecorder::record${node.syntax_kind}(
    ArrayRef<Parsed${node.collection_element_type}> elements,
    ParsedRawSyntaxRecorder &rec) {
  SmallVector<ParsedRawSyntaxNode, 16> layout;
  layout.reserve(elements.size());
  for (auto &element : elements) {
    layout.push_back(element.getRaw());
  }
  auto raw = rec.recordRawSyntax(SyntaxKind::${node.syntax_kind}, layout);
  return Parsed${node.name}(std::move(raw));
}

Parsed${node.name}
ParsedSyntaxRecorder::defer${node.syntax_kind}(
    ArrayRef<Parsed${node.collection_element_type}> elements) {
  SmallVector<ParsedRawSyntaxNode, 16> layout;
  layout.reserve(elements.size());
  for (auto &element : elements) {
    layout.push_back(element.getRaw());
  }
  auto raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind},
                             layout);
  return Parsed${node.name}(std::move(raw));
}

Parsed${node.name}
ParsedSyntaxRecorder::make${node.syntax_kind}(
    ArrayRef<Parsed${node.collection_element_type}> elements,
    SyntaxParsingContext &SPCtx) {
  if (SPCtx.isBacktracking())
    return defer${node.syntax_kind}(elements);
  return record${node.syntax_kind}(elements, SPCtx.getRecorder());
}

Parsed${node.name}
ParsedSyntaxRecorder::makeBlank${node.syntax_kind}(SourceLoc loc,
        SyntaxParsingContext &SPCtx) {
  ParsedRawSyntaxNode raw;
  if (SPCtx.isBacktracking()) {
    // FIXME: 'loc' is not preserved when capturing a deferred layout.
    raw = ParsedRawSyntaxNode::makeDeferred(SyntaxKind::${node.syntax_kind}, {});
  } else {
    raw = SPCtx.getRecorder().recordEmptyRawSyntaxCollection(SyntaxKind::${node.syntax_kind}, loc);
  }
  return Parsed${node.name}(std::move(raw));
}
%   end
% end

ParsedTupleTypeElementSyntax
ParsedSyntaxRecorder::makeTupleTypeElement(ParsedTypeSyntax Type,
                                    llvm::Optional<ParsedTokenSyntax> TrailingComma,
                                    SyntaxParsingContext &SPCtx) {
  return makeTupleTypeElement(None, None, None, None, Type, None, None,
                              TrailingComma, SPCtx);
}
