module Prism::DSL
  sig { params(string: String).returns(Prism::Source) }
  def source(string); end

  sig { params(source: Prism::Source, start_offset: Integer, length: Integer).returns(Prism::Location) }
  def location(source: default_source, start_offset: 0, length: 0); end
  <%- nodes.each do |node| -%>
  <%-
  params = [
    ["source", "default_source", "Prism::Source"],
    ["node_id", "0", "Integer"],
    ["location", "default_location", "Prism::Location"],
    ["flags", "0", "Integer"]
  ].concat(node.fields.map { |field|
    case field
    when Prism::Template::NodeField
      kind = field.specific_kind || field.union_kind&.first
      if kind.nil?
        [field.name, "default_node(source, location)", field.rbi_class]
      else
        [field.name, %Q{#{kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}(source: source)}, field.rbi_class]
      end
    when Prism::Template::OptionalNodeField
      [field.name, "nil", field.rbi_class]
    when Prism::Template::NodeListField
      [field.name, "[]", field.rbi_class]
    when Prism::Template::ConstantField
      [field.name, ":\"\"", field.rbi_class]
    when Prism::Template::OptionalConstantField
      [field.name, "nil", field.rbi_class]
    when Prism::Template::ConstantListField
      [field.name, "[]", field.rbi_class]
    when Prism::Template::StringField
      [field.name, "\"\"", field.rbi_class]
    when Prism::Template::LocationField
      [field.name, "location", field.rbi_class]
    when Prism::Template::OptionalLocationField
      [field.name, "nil", field.rbi_class]
    when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField
      [field.name, "0", field.rbi_class]
    when Prism::Template::DoubleField
      [field.name, "0.0", field.rbi_class]
    else
      raise
    end
  })
  -%>

  sig { params(<%= params.map { |(name, _, type)| "#{name}: #{type}" }.join(", ") %>).returns(Prism::<%= node.name %>) }
  def <%= node.human %>(<%= params.map { |(name, default, _)| "#{name}: #{default}" }.join(", ") %>); end
  <%- end -%>
  <%- flags.each do |flag| -%>

  sig { params(name: Symbol).returns(Integer) }
  def <%= flag.human.chomp("s") %>(name); end
  <%- end -%>

  private

  sig { returns(Prism::Source) }
  def default_source; end

  sig { returns(Prism::Location) }
  def default_location; end

  sig { params(source: Prism::Source, location: Prism::Location).returns(Prism::Node) }
  def default_node(source, location); end
end
