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

#include "_gen/core/runtime.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/value.asdl.h"  // "use" in ASDL 

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

using id_kind_asdl::Id_str;

namespace runtime_asdl {


hnode_t* AssignArg::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("AssignArg"));
  List<Field*>* L = out_node->fields;

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

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

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

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

  return out_node;
}


hnode_t* ProcArgs::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("ProcArgs"));
  List<Field*>* L = out_node->fields;

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

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

  if (this->named_args != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, value_asdl::value_t*> it(this->named_args);
         !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_args"), hdict));
  }

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

  return out_node;
}

BigStr* cmd_value_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case cmd_value_e::Argv:
    v = "Argv"; break;
  case cmd_value_e::Assign:
    v = "Assign"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "cmd_value.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

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

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

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

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

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

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

  return out_node;
}


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

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

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

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

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

  return out_node;
}


hnode_t* cmd_value_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case cmd_value_e::Argv: {
    cmd_value__Argv* obj = static_cast<cmd_value__Argv*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case cmd_value_e::Assign: {
    cmd_value__Assign* obj = static_cast<cmd_value__Assign*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}

hnode_t* Piece::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("Piece"));
  List<Field*>* L = out_node->fields;

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

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

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

  return out_node;
}

BigStr* part_value_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case part_value_e::String:
    v = "String"; break;
  case part_value_e::Array:
    v = "Array"; break;
  case part_value_e::ExtGlob:
    v = "ExtGlob"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "part_value.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

hnode_t* part_value__Array::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(part_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));
  }

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

  return out_node;
}


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

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

  return out_node;
}


hnode_t* part_value_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case part_value_e::String: {
    Piece* obj = static_cast<Piece*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case part_value_e::Array: {
    part_value__Array* obj = static_cast<part_value__Array*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case part_value_e::ExtGlob: {
    part_value__ExtGlob* obj = static_cast<part_value__ExtGlob*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}
BigStr* coerced_str(coerced_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case coerced_e::Int:
    v = "Int"; break;
  case coerced_e::Float:
    v = "Float"; break;
  case coerced_e::Neither:
    v = "Neither"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "coerced.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

hnode_t* VarSubState::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("VarSubState"));
  List<Field*>* L = out_node->fields;

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

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

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

  return out_node;
}


hnode_t* Cell::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("Cell"));
  List<Field*>* L = out_node->fields;

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

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

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

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

  return out_node;
}

BigStr* scope_str(scope_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case scope_e::Shopt:
    v = "Shopt"; break;
  case scope_e::Dynamic:
    v = "Dynamic"; break;
  case scope_e::LocalOrGlobal:
    v = "LocalOrGlobal"; break;
  case scope_e::LocalOnly:
    v = "LocalOnly"; break;
  case scope_e::GlobalOnly:
    v = "GlobalOnly"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "scope.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* a_index_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case a_index_e::Str:
    v = "Str"; break;
  case a_index_e::Int:
    v = "Int"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "a_index.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

hnode_t* a_index__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(a_index_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* a_index__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(a_index_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* a_index_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case a_index_e::Str: {
    a_index__Str* obj = static_cast<a_index__Str*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case a_index_e::Int: {
    a_index__Int* obj = static_cast<a_index__Int*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}

hnode_t* VTestPlace::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("VTestPlace"));
  List<Field*>* L = out_node->fields;

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

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

  return out_node;
}

BigStr* redirect_arg_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case redirect_arg_e::Path:
    v = "Path"; break;
  case redirect_arg_e::CopyFd:
    v = "CopyFd"; break;
  case redirect_arg_e::MoveFd:
    v = "MoveFd"; break;
  case redirect_arg_e::CloseFd:
    v = "CloseFd"; break;
  case redirect_arg_e::HereDoc:
    v = "HereDoc"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "redirect_arg.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

redirect_arg__CloseFd* redirect_arg::CloseFd = &gredirect_arg__CloseFd.obj;

GcGlobal<redirect_arg__CloseFd> gredirect_arg__CloseFd = 
  { ObjHeader::Global(redirect_arg_e::CloseFd) };

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

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

  return out_node;
}


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

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

  return out_node;
}


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

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

  return out_node;
}


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


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

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

  return out_node;
}


hnode_t* redirect_arg_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case redirect_arg_e::Path: {
    redirect_arg__Path* obj = static_cast<redirect_arg__Path*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case redirect_arg_e::CopyFd: {
    redirect_arg__CopyFd* obj = static_cast<redirect_arg__CopyFd*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case redirect_arg_e::MoveFd: {
    redirect_arg__MoveFd* obj = static_cast<redirect_arg__MoveFd*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case redirect_arg_e::CloseFd: {
    redirect_arg__CloseFd* obj = static_cast<redirect_arg__CloseFd*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case redirect_arg_e::HereDoc: {
    redirect_arg__HereDoc* obj = static_cast<redirect_arg__HereDoc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}

hnode_t* RedirValue::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("RedirValue"));
  List<Field*>* L = out_node->fields;

  hnode_t* x0 = Alloc<hnode::Leaf>(Id_str(this->op_id, false),
                                   color_e::UserType);
  L->append(Alloc<Field>(StrFromC("op_id"), x0));

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

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

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

  return out_node;
}


hnode_t* StatusArray::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("StatusArray"));
  List<Field*>* L = out_node->fields;

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

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

  return out_node;
}


hnode_t* CommandStatus::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("CommandStatus"));
  List<Field*>* L = out_node->fields;

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

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

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

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

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

  return out_node;
}

BigStr* job_state_str(job_state_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case job_state_e::Running:
    v = "Running"; break;
  case job_state_e::Exited:
    v = "Exited"; break;
  case job_state_e::Stopped:
    v = "Stopped"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "job_state.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* wait_status_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case wait_status_e::Proc:
    v = "Proc"; break;
  case wait_status_e::Pipeline:
    v = "Pipeline"; break;
  case wait_status_e::Cancelled:
    v = "Cancelled"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "wait_status.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

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

  hnode_t* x0 = Alloc<hnode::Leaf>(job_state_str(this->state),
                                   color_e::TypeName);
  L->append(Alloc<Field>(StrFromC("state"), x0));

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

  return out_node;
}


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

  hnode_t* x0 = Alloc<hnode::Leaf>(job_state_str(this->state),
                                   color_e::TypeName);
  L->append(Alloc<Field>(StrFromC("state"), x0));

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

  return out_node;
}


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

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

  return out_node;
}


hnode_t* wait_status_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case wait_status_e::Proc: {
    wait_status__Proc* obj = static_cast<wait_status__Proc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case wait_status_e::Pipeline: {
    wait_status__Pipeline* obj = static_cast<wait_status__Pipeline*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case wait_status_e::Cancelled: {
    wait_status__Cancelled* obj = static_cast<wait_status__Cancelled*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}
BigStr* flow_str(flow_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case flow_e::Nothing:
    v = "Nothing"; break;
  case flow_e::Break:
    v = "Break"; break;
  case flow_e::Raise:
    v = "Raise"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "flow.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* span_str(span_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case span_e::Black:
    v = "Black"; break;
  case span_e::Delim:
    v = "Delim"; break;
  case span_e::Backslash:
    v = "Backslash"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "span.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* emit_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case emit_i::Part:
    v = "Part"; break;
  case emit_i::Delim:
    v = "Delim"; break;
  case emit_i::Empty:
    v = "Empty"; break;
  case emit_i::Escape:
    v = "Escape"; break;
  case emit_i::Nothing:
    v = "Nothing"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "emit.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* state_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case state_i::Invalid:
    v = "Invalid"; break;
  case state_i::Start:
    v = "Start"; break;
  case state_i::DE_White1:
    v = "DE_White1"; break;
  case state_i::DE_Gray:
    v = "DE_Gray"; break;
  case state_i::DE_White2:
    v = "DE_White2"; break;
  case state_i::Black:
    v = "Black"; break;
  case state_i::Backslash:
    v = "Backslash"; break;
  case state_i::Done:
    v = "Done"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "state.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* char_kind_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case char_kind_i::DE_White:
    v = "DE_White"; break;
  case char_kind_i::DE_Gray:
    v = "DE_Gray"; break;
  case char_kind_i::Black:
    v = "Black"; break;
  case char_kind_i::Backslash:
    v = "Backslash"; break;
  case char_kind_i::Sentinel:
    v = "Sentinel"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "char_kind.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* error_code_str(error_code_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case error_code_e::OK:
    v = "OK"; break;
  case error_code_e::IndexOutOfRange:
    v = "IndexOutOfRange"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "error_code.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* flag_type_str(flag_type_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case flag_type_e::Bool:
    v = "Bool"; break;
  case flag_type_e::Int:
    v = "Int"; break;
  case flag_type_e::Float:
    v = "Float"; break;
  case flag_type_e::Str:
    v = "Str"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "flag_type.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* trace_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case trace_e::External:
    v = "External"; break;
  case trace_e::CommandSub:
    v = "CommandSub"; break;
  case trace_e::ForkWait:
    v = "ForkWait"; break;
  case trace_e::Fork:
    v = "Fork"; break;
  case trace_e::PipelinePart:
    v = "PipelinePart"; break;
  case trace_e::ProcessSub:
    v = "ProcessSub"; break;
  case trace_e::HereDoc:
    v = "HereDoc"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "trace.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

trace__CommandSub* trace::CommandSub = &gtrace__CommandSub.obj;

GcGlobal<trace__CommandSub> gtrace__CommandSub = 
  { ObjHeader::Global(trace_e::CommandSub) };

trace__ForkWait* trace::ForkWait = &gtrace__ForkWait.obj;

GcGlobal<trace__ForkWait> gtrace__ForkWait = 
  { ObjHeader::Global(trace_e::ForkWait) };

trace__Fork* trace::Fork = &gtrace__Fork.obj;

GcGlobal<trace__Fork> gtrace__Fork = 
  { ObjHeader::Global(trace_e::Fork) };

trace__PipelinePart* trace::PipelinePart = &gtrace__PipelinePart.obj;

GcGlobal<trace__PipelinePart> gtrace__PipelinePart = 
  { ObjHeader::Global(trace_e::PipelinePart) };

trace__ProcessSub* trace::ProcessSub = &gtrace__ProcessSub.obj;

GcGlobal<trace__ProcessSub> gtrace__ProcessSub = 
  { ObjHeader::Global(trace_e::ProcessSub) };

trace__HereDoc* trace::HereDoc = &gtrace__HereDoc.obj;

GcGlobal<trace__HereDoc> gtrace__HereDoc = 
  { ObjHeader::Global(trace_e::HereDoc) };

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

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

  return out_node;
}


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


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


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


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


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


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


hnode_t* trace_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case trace_e::External: {
    trace__External* obj = static_cast<trace__External*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case trace_e::CommandSub: {
    trace__CommandSub* obj = static_cast<trace__CommandSub*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case trace_e::ForkWait: {
    trace__ForkWait* obj = static_cast<trace__ForkWait*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case trace_e::Fork: {
    trace__Fork* obj = static_cast<trace__Fork*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case trace_e::PipelinePart: {
    trace__PipelinePart* obj = static_cast<trace__PipelinePart*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case trace_e::ProcessSub: {
    trace__ProcessSub* obj = static_cast<trace__ProcessSub*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case trace_e::HereDoc: {
    trace__HereDoc* obj = static_cast<trace__HereDoc*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}
BigStr* word_style_str(word_style_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case word_style_e::Expr:
    v = "Expr"; break;
  case word_style_e::Unquoted:
    v = "Unquoted"; break;
  case word_style_e::DQ:
    v = "DQ"; break;
  case word_style_e::SQ:
    v = "SQ"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "word_style.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

hnode_t* HayNode::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("HayNode"));
  List<Field*>* L = out_node->fields;

  if (this->children != nullptr) {  // Dict
    auto* unnamed = NewList<hnode_t*>();
    auto* hdict = Alloc<hnode::Record>(kEmptyString, StrFromC("{"),
                                                                 StrFromC("}"),
                                                                 NewList<Field*>(), unnamed);
    for (DictIter<BigStr*, HayNode*> it(this->children); !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("children"), hdict));
  }

  return out_node;
}

BigStr* comp_action_str(comp_action_e tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case comp_action_e::Other:
    v = "Other"; break;
  case comp_action_e::FileSystem:
    v = "FileSystem"; break;
  case comp_action_e::BashFunc:
    v = "BashFunc"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "comp_action.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}
BigStr* trap_action_str(int tag, bool dot) {
  char buf[32];
  const char* v = nullptr;
  switch (tag) {
  case trap_action_e::Ignored:
    v = "Ignored"; break;
  case trap_action_e::Command:
    v = "Command"; break;
  default:
    assert(0);
  }
  if (dot) {
    snprintf(buf, 32, "trap_action.%s", v);
    return StrFromC(buf);
  } else {
    return StrFromC(v);
  }
}

trap_action__Ignored* trap_action::Ignored = &gtrap_action__Ignored.obj;

GcGlobal<trap_action__Ignored> gtrap_action__Ignored = 
  { ObjHeader::Global(trap_action_e::Ignored) };

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


hnode_t* trap_action__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(trap_action_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* trap_action_t::PrettyTree(bool do_abbrev, Dict<int, bool>* seen) {
  switch (this->tag()) {
  case trap_action_e::Ignored: {
    trap_action__Ignored* obj = static_cast<trap_action__Ignored*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  case trap_action_e::Command: {
    trap_action__Command* obj = static_cast<trap_action__Command*>(this);
    return obj->PrettyTree(do_abbrev, seen);
  }
  default:
    assert(0);
  }
}

}  // namespace runtime_asdl
