// _gen/core/value.asdl.cc is generated by asdl_main.py

#include "_gen/core/value.asdl.h"
#include <assert.h>
#include "prebuilt/asdl/runtime.mycpp.h"  // generated code uses wrappers here
#include "_gen/frontend/syntax.asdl.h"  // "use" in ASDL 
#include "_gen/core/runtime.asdl.h"  // "use" in ASDL 

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


namespace value_asdl {


hnode_t* IntBox::PrettyTree(bool do_abbrev, 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("IntBox"));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->i);
  L->append(Alloc<Field>(StrFromC("i"), x0));

  return out_node;
}


hnode_t* InitializerValue::PrettyTree(bool do_abbrev, 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("InitializerValue"));
  List<Field*>* L = out_node->fields;

  if (this->key) {  // Optional
    hnode_t* x0 = ToPretty(this->key);
    L->append(Alloc<Field>(StrFromC("key"), x0));
  }

  hnode_t* x1 = ToPretty(this->rval);
  L->append(Alloc<Field>(StrFromC("rval"), x1));

  hnode_t* x2 = ToPretty(this->plus_eq);
  L->append(Alloc<Field>(StrFromC("plus_eq"), x2));

  return out_node;
}


hnode_t* ProcDefaults::PrettyTree(bool do_abbrev, 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("ProcDefaults"));
  List<Field*>* L = out_node->fields;

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

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

  if (this->for_named != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, value_t*> it(this->for_named); !it.Done();
         it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("for_named"), hdict));
  }

  if (this->for_block) {  // Optional
    hnode_t* x3 = this->for_block->PrettyTree(do_abbrev, seen);
    L->append(Alloc<Field>(StrFromC("for_block"), x3));
  }

  return out_node;
}


hnode_t* LeftName::PrettyTree(bool do_abbrev, 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("LeftName"));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->name);
  L->append(Alloc<Field>(StrFromC("name"), x0));

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

  return out_node;
}

BigStr* y_lvalue_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case y_lvalue_e::Local:
    v = "Local"; break;
  case y_lvalue_e::Container:
    v = "Container"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "y_lvalue.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

hnode_t* y_lvalue__Container::PrettyTree(bool do_abbrev, 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(y_lvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

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

  return out_node;
}


hnode_t* y_lvalue_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case y_lvalue_e::Local: {
    LeftName* obj = static_cast<LeftName*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case y_lvalue_e::Container: {
    y_lvalue__Container* obj = static_cast<y_lvalue__Container*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}
BigStr* sh_lvalue_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case sh_lvalue_e::Var:
    v = "Var"; break;
  case sh_lvalue_e::Indexed:
    v = "Indexed"; break;
  case sh_lvalue_e::Keyed:
    v = "Keyed"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "sh_lvalue.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

hnode_t* sh_lvalue__Indexed::PrettyTree(bool do_abbrev, 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(sh_lvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->name);
  L->append(Alloc<Field>(StrFromC("name"), x0));

  hnode_t* x1 = ToPretty(this->index);
  L->append(Alloc<Field>(StrFromC("index"), x1));

  hnode_t* x2 = this->blame_loc->PrettyTree(do_abbrev, seen);
  L->append(Alloc<Field>(StrFromC("blame_loc"), x2));

  return out_node;
}


hnode_t* sh_lvalue__Keyed::PrettyTree(bool do_abbrev, 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(sh_lvalue_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->name);
  L->append(Alloc<Field>(StrFromC("name"), x0));

  hnode_t* x1 = ToPretty(this->key);
  L->append(Alloc<Field>(StrFromC("key"), x1));

  hnode_t* x2 = this->blame_loc->PrettyTree(do_abbrev, seen);
  L->append(Alloc<Field>(StrFromC("blame_loc"), x2));

  return out_node;
}


hnode_t* sh_lvalue_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case sh_lvalue_e::Var: {
    LeftName* obj = static_cast<LeftName*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case sh_lvalue_e::Indexed: {
    sh_lvalue__Indexed* obj = static_cast<sh_lvalue__Indexed*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case sh_lvalue_e::Keyed: {
    sh_lvalue__Keyed* obj = static_cast<sh_lvalue__Keyed*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}
BigStr* eggex_ops_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case eggex_ops_e::No:
    v = "No"; break;
  case eggex_ops_e::Yes:
    v = "Yes"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "eggex_ops.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

eggex_ops__No* eggex_ops::No = &geggex_ops__No.obj;

GcGlobal<eggex_ops__No> geggex_ops__No = 
  { ObjHeader::Global(eggex_ops_e::No) };

hnode_t* eggex_ops__No::PrettyTree(bool do_abbrev, 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(eggex_ops_str(this->tag()));
  return out_node;
}


hnode_t* eggex_ops__Yes::PrettyTree(bool do_abbrev, 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(eggex_ops_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

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

  if (this->capture_names != nullptr) {  // List
    hnode::Array* x2 = Alloc<hnode::Array>(Alloc<List<hnode_t*>>());
    for (ListIter<BigStr*> it(this->capture_names); !it.Done(); it.Next()) {
      BigStr* v_ = it.Value();
      hnode_t* h = ToPretty(v_);
      x2->children->append(h);
    }
    L->append(Alloc<Field>(StrFromC("capture_names"), x2));
  }

  return out_node;
}


hnode_t* eggex_ops_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case eggex_ops_e::No: {
    eggex_ops__No* obj = static_cast<eggex_ops__No*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case eggex_ops_e::Yes: {
    eggex_ops__Yes* obj = static_cast<eggex_ops__Yes*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}

hnode_t* RegexMatch::PrettyTree(bool do_abbrev, 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("RegexMatch"));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->s);
  L->append(Alloc<Field>(StrFromC("s"), x0));

  if (this->indices != nullptr) {  // List
    hnode::Array* x1 = Alloc<hnode::Array>(Alloc<List<hnode_t*>>());
    for (ListIter<int> it(this->indices); !it.Done(); it.Next()) {
      int v_ = it.Value();
      hnode_t* h = ToPretty(v_);
      x1->children->append(h);
    }
    L->append(Alloc<Field>(StrFromC("indices"), x1));
  }

  hnode_t* x2 = this->ops->PrettyTree(do_abbrev, seen);
  L->append(Alloc<Field>(StrFromC("ops"), x2));

  return out_node;
}

BigStr* regex_match_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case regex_match_e::No:
    v = "No"; break;
  case regex_match_e::Yes:
    v = "Yes"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "regex_match.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

regex_match__No* regex_match::No = &gregex_match__No.obj;

GcGlobal<regex_match__No> gregex_match__No = 
  { ObjHeader::Global(regex_match_e::No) };

hnode_t* regex_match__No::PrettyTree(bool do_abbrev, 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(regex_match_str(this->tag()));
  return out_node;
}


hnode_t* regex_match_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case regex_match_e::No: {
    regex_match__No* obj = static_cast<regex_match__No*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case regex_match_e::Yes: {
    RegexMatch* obj = static_cast<RegexMatch*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}

hnode_t* Obj::PrettyTree(bool do_abbrev, 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("Obj"));
  List<Field*>* L = out_node->fields;

  if (this->prototype) {  // Optional
    hnode_t* x0 = this->prototype->PrettyTree(do_abbrev, seen);
    L->append(Alloc<Field>(StrFromC("prototype"), x0));
  }

  if (this->d != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, value_t*> it(this->d); !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("d"), hdict));
  }

  return out_node;
}

BigStr* value_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case value_e::Interrupted:
    v = "Interrupted"; break;
  case value_e::Stdin:
    v = "Stdin"; break;
  case value_e::Slice:
    v = "Slice"; break;
  case value_e::Undef:
    v = "Undef"; break;
  case value_e::Str:
    v = "Str"; break;
  case value_e::InitializerList:
    v = "InitializerList"; break;
  case value_e::InternalStringArray:
    v = "InternalStringArray"; break;
  case value_e::BashArray:
    v = "BashArray"; break;
  case value_e::BashAssoc:
    v = "BashAssoc"; break;
  case value_e::Null:
    v = "Null"; break;
  case value_e::Bool:
    v = "Bool"; break;
  case value_e::Int:
    v = "Int"; break;
  case value_e::Float:
    v = "Float"; break;
  case value_e::List:
    v = "List"; break;
  case value_e::Dict:
    v = "Dict"; break;
  case value_e::Obj:
    v = "Obj"; break;
  case value_e::Range:
    v = "Range"; break;
  case value_e::Eggex:
    v = "Eggex"; break;
  case value_e::Match:
    v = "Match"; break;
  case value_e::Place:
    v = "Place"; break;
  case value_e::Frame:
    v = "Frame"; break;
  case value_e::DebugFrame:
    v = "DebugFrame"; break;
  case value_e::BoundFunc:
    v = "BoundFunc"; break;
  case value_e::BuiltinFunc:
    v = "BuiltinFunc"; break;
  case value_e::Func:
    v = "Func"; break;
  case value_e::BuiltinProc:
    v = "BuiltinProc"; break;
  case value_e::Proc:
    v = "Proc"; break;
  case value_e::Expr:
    v = "Expr"; break;
  case value_e::CommandFrag:
    v = "CommandFrag"; break;
  case value_e::Command:
    v = "Command"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "value.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

value__Interrupted* value::Interrupted = &gvalue__Interrupted.obj;

GcGlobal<value__Interrupted> gvalue__Interrupted = 
  { ObjHeader::Global(value_e::Interrupted) };

value__Stdin* value::Stdin = &gvalue__Stdin.obj;

GcGlobal<value__Stdin> gvalue__Stdin = 
  { ObjHeader::Global(value_e::Stdin) };

value__Undef* value::Undef = &gvalue__Undef.obj;

GcGlobal<value__Undef> gvalue__Undef = 
  { ObjHeader::Global(value_e::Undef) };

value__Null* value::Null = &gvalue__Null.obj;

GcGlobal<value__Null> gvalue__Null = 
  { ObjHeader::Global(value_e::Null) };

hnode_t* value__Interrupted::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  return out_node;
}


hnode_t* value__Stdin::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  return out_node;
}


hnode_t* value__Slice::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->lower) {  // Optional
    hnode_t* x0 = this->lower->PrettyTree(do_abbrev, seen);
    L->append(Alloc<Field>(StrFromC("lower"), x0));
  }

  if (this->upper) {  // Optional
    hnode_t* x1 = this->upper->PrettyTree(do_abbrev, seen);
    L->append(Alloc<Field>(StrFromC("upper"), x1));
  }

  return out_node;
}


hnode_t* value__Undef::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  return out_node;
}


hnode_t* value__Str::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->s);
  L->append(Alloc<Field>(StrFromC("s"), x0));

  return out_node;
}


hnode_t* value__InitializerList::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* value__InternalStringArray::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->strs != nullptr) {  // List
    hnode::Array* x0 = Alloc<hnode::Array>(Alloc<List<hnode_t*>>());
    for (ListIter<BigStr*> it(this->strs); !it.Done(); it.Next()) {
      BigStr* v_ = it.Value();
      hnode_t* h = ToPretty(v_);
      x0->children->append(h);
    }
    L->append(Alloc<Field>(StrFromC("strs"), x0));
  }

  return out_node;
}


hnode_t* value__BashArray::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->d != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<mops::BigInt, BigStr*> it(this->d); !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(ToPretty(v));
    }
    L->append(Alloc<Field>(StrFromC("d"), hdict));
  }

  hnode_t* x1 = ToPretty(this->max_index);
  L->append(Alloc<Field>(StrFromC("max_index"), x1));

  return out_node;
}


hnode_t* value__BashAssoc::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->d != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, BigStr*> it(this->d); !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(ToPretty(v));
    }
    L->append(Alloc<Field>(StrFromC("d"), hdict));
  }

  return out_node;
}


hnode_t* value__Null::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  return out_node;
}


hnode_t* value__Bool::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->b);
  L->append(Alloc<Field>(StrFromC("b"), x0));

  return out_node;
}


hnode_t* value__Int::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->i);
  L->append(Alloc<Field>(StrFromC("i"), x0));

  return out_node;
}


hnode_t* value__Float::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->f);
  L->append(Alloc<Field>(StrFromC("f"), x0));

  return out_node;
}


hnode_t* value__List::PrettyTree(bool do_abbrev, 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(value_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<value_t*> it(this->items); !it.Done(); it.Next()) {
      value_t* v_ = it.Value();
      hnode_t* h = (v_ == nullptr) ? Alloc<hnode::Leaf>(StrFromC("_"),
                    color_e::OtherConst) : v_->PrettyTree(do_abbrev, seen);
      x0->children->append(h);
    }
    L->append(Alloc<Field>(StrFromC("items"), x0));
  }

  return out_node;
}


hnode_t* value__Dict::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->d != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, value_t*> it(this->d); !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("d"), hdict));
  }

  return out_node;
}


hnode_t* value__Range::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->lower);
  L->append(Alloc<Field>(StrFromC("lower"), x0));

  hnode_t* x1 = ToPretty(this->upper);
  L->append(Alloc<Field>(StrFromC("upper"), x1));

  return out_node;
}


hnode_t* value__Eggex::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  hnode_t* x1 = ToPretty(this->canonical_flags);
  L->append(Alloc<Field>(StrFromC("canonical_flags"), x1));

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

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

  if (this->as_ere) {  // Optional
    hnode_t* x4 = ToPretty(this->as_ere);
    L->append(Alloc<Field>(StrFromC("as_ere"), x4));
  }

  if (this->capture_names != nullptr) {  // List
    hnode::Array* x5 = Alloc<hnode::Array>(Alloc<List<hnode_t*>>());
    for (ListIter<BigStr*> it(this->capture_names); !it.Done(); it.Next()) {
      BigStr* v_ = it.Value();
      hnode_t* h = ToPretty(v_);
      x5->children->append(h);
    }
    L->append(Alloc<Field>(StrFromC("capture_names"), x5));
  }

  return out_node;
}


hnode_t* value__Place::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  if (this->frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->frame); !it.Done();
         it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("frame"), hdict));
  }

  return out_node;
}


hnode_t* value__Frame::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  if (this->frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->frame); !it.Done();
         it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("frame"), hdict));
  }

  return out_node;
}


hnode_t* value__DebugFrame::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* value__BoundFunc::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

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

  return out_node;
}


hnode_t* value__BuiltinFunc::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = Alloc<hnode::Leaf>(StrFromC("<extern>"), color_e::External);
  L->append(Alloc<Field>(StrFromC("callable"), x0));

  return out_node;
}


hnode_t* value__Func::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->name);
  L->append(Alloc<Field>(StrFromC("name"), x0));

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

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

  if (this->named_defaults != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, value_t*> it(this->named_defaults); !it.Done();
         it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("named_defaults"), hdict));
  }

  if (this->captured_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->captured_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("captured_frame"), hdict));
  }

  if (this->module_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->module_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("module_frame"), hdict));
  }

  return out_node;
}


hnode_t* value__BuiltinProc::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = Alloc<hnode::Leaf>(StrFromC("<extern>"), color_e::External);
  L->append(Alloc<Field>(StrFromC("builtin"), x0));

  return out_node;
}


hnode_t* value__Proc::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = ToPretty(this->name);
  L->append(Alloc<Field>(StrFromC("name"), x0));

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

  hnode_t* x2 = this->sig->PrettyTree(do_abbrev, seen);
  L->append(Alloc<Field>(StrFromC("sig"), x2));

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

  if (this->defaults) {  // Optional
    hnode_t* x4 = this->defaults->PrettyTree(do_abbrev, seen);
    L->append(Alloc<Field>(StrFromC("defaults"), x4));
  }

  hnode_t* x5 = ToPretty(this->sh_compat);
  L->append(Alloc<Field>(StrFromC("sh_compat"), x5));

  if (this->captured_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->captured_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("captured_frame"), hdict));
  }

  if (this->module_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->module_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("module_frame"), hdict));
  }

  if (this->code_str) {  // Optional
    hnode_t* x8 = ToPretty(this->code_str);
    L->append(Alloc<Field>(StrFromC("code_str"), x8));
  }

  return out_node;
}


hnode_t* value__Expr::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  if (this->captured_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->captured_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("captured_frame"), hdict));
  }

  if (this->module_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->module_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("module_frame"), hdict));
  }

  return out_node;
}


hnode_t* value__CommandFrag::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  return out_node;
}


hnode_t* value__Command::PrettyTree(bool do_abbrev, 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(value_str(this->tag()));
  List<Field*>* L = out_node->fields;

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

  if (this->captured_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->captured_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("captured_frame"), hdict));
  }

  if (this->module_frame != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, runtime_asdl::Cell*> it(this->module_frame);
         !it.Done(); it.Next()) {
      auto k = it.Key();
      auto v = it.Value();
      unnamed->append(ToPretty(k));
      unnamed->append(v->PrettyTree(do_abbrev, seen));
    }
    L->append(Alloc<Field>(StrFromC("module_frame"), hdict));
  }

  return out_node;
}


hnode_t* value_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case value_e::Interrupted: {
    value__Interrupted* obj = static_cast<value__Interrupted*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Stdin: {
    value__Stdin* obj = static_cast<value__Stdin*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Slice: {
    value__Slice* obj = static_cast<value__Slice*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Undef: {
    value__Undef* obj = static_cast<value__Undef*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Str: {
    value__Str* obj = static_cast<value__Str*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::InitializerList: {
    value__InitializerList* obj = static_cast<value__InitializerList*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::InternalStringArray: {
    value__InternalStringArray* obj =
static_cast<value__InternalStringArray*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::BashArray: {
    value__BashArray* obj = static_cast<value__BashArray*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::BashAssoc: {
    value__BashAssoc* obj = static_cast<value__BashAssoc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Null: {
    value__Null* obj = static_cast<value__Null*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Bool: {
    value__Bool* obj = static_cast<value__Bool*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Int: {
    value__Int* obj = static_cast<value__Int*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Float: {
    value__Float* obj = static_cast<value__Float*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::List: {
    value__List* obj = static_cast<value__List*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Dict: {
    value__Dict* obj = static_cast<value__Dict*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Obj: {
    Obj* obj = static_cast<Obj*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Range: {
    value__Range* obj = static_cast<value__Range*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Eggex: {
    value__Eggex* obj = static_cast<value__Eggex*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Match: {
    RegexMatch* obj = static_cast<RegexMatch*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Place: {
    value__Place* obj = static_cast<value__Place*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Frame: {
    value__Frame* obj = static_cast<value__Frame*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::DebugFrame: {
    value__DebugFrame* obj = static_cast<value__DebugFrame*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::BoundFunc: {
    value__BoundFunc* obj = static_cast<value__BoundFunc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::BuiltinFunc: {
    value__BuiltinFunc* obj = static_cast<value__BuiltinFunc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Func: {
    value__Func* obj = static_cast<value__Func*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::BuiltinProc: {
    value__BuiltinProc* obj = static_cast<value__BuiltinProc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Proc: {
    value__Proc* obj = static_cast<value__Proc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Expr: {
    value__Expr* obj = static_cast<value__Expr*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::CommandFrag: {
    value__CommandFrag* obj = static_cast<value__CommandFrag*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case value_e::Command: {
    value__Command* obj = static_cast<value__Command*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}

}  // namespace value_asdl
