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

#include "_gen/data_lang/nil8.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 nil8_asdl {

BigStr* nvalue_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case nvalue_e::Null:
    v = "Null"; break;
  case nvalue_e::Bool:
    v = "Bool"; break;
  case nvalue_e::Int:
    v = "Int"; break;
  case nvalue_e::Float:
    v = "Float"; break;
  case nvalue_e::Str:
    v = "Str"; break;
  case nvalue_e::Symbol:
    v = "Symbol"; break;
  case nvalue_e::List:
    v = "List"; break;
  case nvalue_e::Record:
    v = "Record"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "nvalue.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

nvalue__Null* nvalue::Null = &gnvalue__Null.obj;

GcGlobal<nvalue__Null> gnvalue__Null = 
  { ObjHeader::Global(nvalue_e::Null) };

hnode_t* nvalue__Null::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(nvalue_str(this->tag()));
  return out_node;
}


hnode_t* nvalue__Bool::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(nvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* nvalue__Int::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(nvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* nvalue__Float::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(nvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* nvalue__Str::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(nvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* nvalue__Symbol::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(nvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* nvalue__List::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(nvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->items != nullptr) {  // List
    hnode::Array* x0 = Alloc<hnode::Array>(Alloc<List<hnode_t*>>());
    for (ListIter<nvalue_t*> it(this->items); !it.Done(); it.Next()) {
      nvalue_t* 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("items"), x0));
  }

  return out_node;
}


hnode_t* nvalue__Record::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(nvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

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

  if (this->named) {  // Dict
    auto m = Alloc<hnode::Leaf>(StrFromC("Dict"), color_e::OtherConst);
    hnode::Array* x2 = Alloc<hnode::Array>(NewList<hnode_t*>({m}));
    for (DictIter<BigStr*, nvalue_t*> it(this->named); !it.Done(); it.Next()) {
      auto k2 = it.Key();
      auto v2 = it.Value();
      x2->children->append(runtime::NewLeaf(k2, color_e::StringConst));
      x2->children->append(v2->PrettyTree(seen));
    }
    L->append(Alloc<Field>(StrFromC ("named"), x2));
  }

  return out_node;
}


hnode_t* nvalue_t::PrettyTree(Dict<int, bool>* seen) {
  switch (this->tag()) {
  case nvalue_e::Null: {
    nvalue__Null* obj = static_cast<nvalue__Null*>(this);
    return obj->PrettyTree(seen);
  }
  case nvalue_e::Bool: {
    nvalue__Bool* obj = static_cast<nvalue__Bool*>(this);
    return obj->PrettyTree(seen);
  }
  case nvalue_e::Int: {
    nvalue__Int* obj = static_cast<nvalue__Int*>(this);
    return obj->PrettyTree(seen);
  }
  case nvalue_e::Float: {
    nvalue__Float* obj = static_cast<nvalue__Float*>(this);
    return obj->PrettyTree(seen);
  }
  case nvalue_e::Str: {
    nvalue__Str* obj = static_cast<nvalue__Str*>(this);
    return obj->PrettyTree(seen);
  }
  case nvalue_e::Symbol: {
    nvalue__Symbol* obj = static_cast<nvalue__Symbol*>(this);
    return obj->PrettyTree(seen);
  }
  case nvalue_e::List: {
    nvalue__List* obj = static_cast<nvalue__List*>(this);
    return obj->PrettyTree(seen);
  }
  case nvalue_e::Record: {
    nvalue__Record* obj = static_cast<nvalue__Record*>(this);
    return obj->PrettyTree(seen);
  }
  default:
    assert(0);
  }
}

}  // namespace nil8_asdl
