// _gen/data_lang/pretty.asdl.cc is generated by asdl_main.py

#include "_gen/data_lang/pretty.asdl.h"
#include <assert.h>
#include "prebuilt/asdl/runtime.mycpp.h"  // generated code uses wrappers here

// Generated code uses these types
using hnode_asdl::hnode;
using hnode_asdl::Field;
using hnode_asdl::color_e;


namespace pretty_asdl {


hnode_t* MeasuredDoc::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(StrFromC("MeasuredDoc"));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = this->doc->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("doc"), x0));

  hnode_t* x1 = this->measure->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("measure"), x1));

  return out_node;
}


hnode_t* Measure::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(StrFromC("Measure"));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = Alloc<hnode::Leaf>(str(this->flat), color_e::OtherConst);
  L->append(Alloc<Field>(StrFromC("flat"), x0));

  hnode_t* x1 = Alloc<hnode::Leaf>(str(this->nonflat), color_e::OtherConst);
  L->append(Alloc<Field>(StrFromC("nonflat"), x1));

  return out_node;
}

BigStr* doc_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case doc_e::Break:
    v = "Break"; break;
  case doc_e::Text:
    v = "Text"; break;
  case doc_e::Indent:
    v = "Indent"; break;
  case doc_e::Concat:
    v = "Concat"; break;
  case doc_e::Group:
    v = "Group"; break;
  case doc_e::IfFlat:
    v = "IfFlat"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "doc.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

hnode_t* doc__Break::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(doc_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = runtime::NewLeaf(this->string, color_e::StringConst);
  L->append(Alloc<Field>(StrFromC("string"), x0));

  return out_node;
}


hnode_t* doc__Text::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(doc_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = runtime::NewLeaf(this->string, color_e::StringConst);
  L->append(Alloc<Field>(StrFromC("string"), x0));

  return out_node;
}


hnode_t* doc__Indent::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(doc_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = Alloc<hnode::Leaf>(str(this->indent), color_e::OtherConst);
  L->append(Alloc<Field>(StrFromC("indent"), x0));

  hnode_t* x1 = this->mdoc->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("mdoc"), x1));

  return out_node;
}


hnode_t* doc__Concat::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(doc_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->mdocs != nullptr) {  // List
    hnode::Array* x0 = Alloc<hnode::Array>(Alloc<List<hnode_t*>>());
    for (ListIter<MeasuredDoc*> it(this->mdocs); !it.Done(); it.Next()) {
      MeasuredDoc* i0 = it.Value();
      hnode_t* h = (i0 == nullptr) ? Alloc<hnode::Leaf>(StrFromC("_"),
                    color_e::OtherConst) : i0->PrettyTree(seen);
      x0->children->append(h);
    }
    L->append(Alloc<Field>(StrFromC("mdocs"), x0));
  }

  return out_node;
}


hnode_t* doc__Group::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(doc_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = this->mdoc->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("mdoc"), x0));

  return out_node;
}


hnode_t* doc__IfFlat::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(doc_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = this->flat_mdoc->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("flat_mdoc"), x0));

  hnode_t* x1 = this->nonflat_mdoc->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("nonflat_mdoc"), x1));

  return out_node;
}


hnode_t* doc_t::PrettyTree(Dict<int, bool>* seen) {
  switch (this->tag()) {
  case doc_e::Break: {
    doc__Break* obj = static_cast<doc__Break*>(this);
    return obj->PrettyTree(seen);
  }
  case doc_e::Text: {
    doc__Text* obj = static_cast<doc__Text*>(this);
    return obj->PrettyTree(seen);
  }
  case doc_e::Indent: {
    doc__Indent* obj = static_cast<doc__Indent*>(this);
    return obj->PrettyTree(seen);
  }
  case doc_e::Concat: {
    doc__Concat* obj = static_cast<doc__Concat*>(this);
    return obj->PrettyTree(seen);
  }
  case doc_e::Group: {
    doc__Group* obj = static_cast<doc__Group*>(this);
    return obj->PrettyTree(seen);
  }
  case doc_e::IfFlat: {
    doc__IfFlat* obj = static_cast<doc__IfFlat*>(this);
    return obj->PrettyTree(seen);
  }
  default:
    assert(0);
  }
}

hnode_t* DocFragment::PrettyTree(Dict<int, bool>* seen) {
  seen = seen ? seen : Alloc<Dict<int, bool>>();
  int heap_id = ObjectId(this);
  if (dict_contains(seen, heap_id)) {
    return Alloc<hnode::AlreadySeen>(heap_id);
  }
  seen->set(heap_id, true);
  hnode::Record* out_node = runtime::NewRecord(StrFromC("DocFragment"));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = this->mdoc->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("mdoc"), x0));

  hnode_t* x1 = Alloc<hnode::Leaf>(str(this->indent), color_e::OtherConst);
  L->append(Alloc<Field>(StrFromC("indent"), x1));

  hnode_t* x2 = Alloc<hnode::Leaf>(this->is_flat ? runtime::TRUE_STR :
                                   runtime::FALSE_STR, color_e::OtherConst);
  L->append(Alloc<Field>(StrFromC("is_flat"), x2));

  hnode_t* x3 = this->measure->PrettyTree(seen);
  L->append(Alloc<Field>(StrFromC("measure"), x3));

  return out_node;
}


}  // namespace pretty_asdl
