// yaks_main.cc: translated from Python by mycpp

// #include "_gen/yaks/yaks_main.mycpp.h"

#include "yaks/preamble.h"
// BEGIN mycpp output

#include "mycpp/runtime.h"

namespace runtime {  // forward declare
  class TraversalState;
}

namespace format {  // forward declare
}

namespace bash_impl {  // forward declare
}

namespace error {  // forward declare
  class _ErrorWithLocation;
  class Usage;
  class Parse;
  class WordFailure;
  class FailGlob;
  class VarSubFailure;
  class RedirectEval;
  class FatalRuntime;
  class Strict;
  class ErrExit;
  class Expr;
  class Structured;
  class AssertionErr;
  class TypeErrVerbose;
  class TypeErr;
  class Runtime;
  class Decode;
  class Encode;
}

namespace num {  // forward declare
}

namespace j8 {  // forward declare
  class InstancePrinter;
  class LexerDecoder;
  class _Parser;
  class Parser;
  class Nil8Parser;
  class J8LinesParser;
}

namespace j8_lite {  // forward declare
}

namespace ansi {  // forward declare
}

namespace pp_hnode {  // forward declare
  class BaseEncoder;
  class HNodeEncoder;
}

namespace pretty {  // forward declare
  class PrettyPrinter;
}

namespace syntax_abbrev {  // forward declare
}

namespace gen_cpp {  // forward declare
}

namespace transform {  // forward declare
}

namespace yaks_main {  // forward declare
}

GLOBAL_STR(S_Aoo, "");
GLOBAL_STR(S_nfs, "\n");
GLOBAL_STR(S_yfk, "\u001b[0;0m");
GLOBAL_STR(S_aaF, "\u001b[1m");
GLOBAL_STR(S_sqm, "\u001b[31m");
GLOBAL_STR(S_eda, "\u001b[32m");
GLOBAL_STR(S_ysf, "\u001b[33m");
GLOBAL_STR(S_osl, "\u001b[34m");
GLOBAL_STR(S_vie, "\u001b[35m");
GLOBAL_STR(S_mmi, "\u001b[36m");
GLOBAL_STR(S_rpo, "\u001b[37m");
GLOBAL_STR(S_sCc, "\u001b[4m");
GLOBAL_STR(S_woy, "\u001b[7m");
GLOBAL_STR(S_yfw, " ");
GLOBAL_STR(S_kps, "  return ");
GLOBAL_STR(S_dtA, " --> ");
GLOBAL_STR(S_xbi, "\"BashArray\",");
GLOBAL_STR(S_ojw, "\"BashAssoc\",");
GLOBAL_STR(S_vBu, "\"SparseArray\",");
GLOBAL_STR(S_eqo, "\"data\":");
GLOBAL_STR(S_EDa, "\"type\":");
GLOBAL_STR(S_FxD, "#include \"mycpp/runtime.h\"\n");
GLOBAL_STR(S_Czx, "$");
GLOBAL_STR(S_hqF, "${");
GLOBAL_STR(S_ijB, "(");
GLOBAL_STR(S_zxb, "()");
GLOBAL_STR(S_Ehr, "(...)");
GLOBAL_STR(S_hxb, ")");
GLOBAL_STR(S_hag, ") {\n");
GLOBAL_STR(S_Cce, ",");
GLOBAL_STR(S_tgp, ", ");
GLOBAL_STR(S_Bjq, "-");
GLOBAL_STR(S_fyj, ":");
GLOBAL_STR(S_nbf, ";");
GLOBAL_STR(S_tAA, ";\n");
GLOBAL_STR(S_eox, "<");
GLOBAL_STR(S_nsk, "=>");
GLOBAL_STR(S_jye, ">");
GLOBAL_STR(S_ydF, ">*");
GLOBAL_STR(S_fnE, "Action required");
GLOBAL_STR(S_vBF, "BigStr*");
GLOBAL_STR(S_AED, "Bool");
GLOBAL_STR(S_sjc, "C");
GLOBAL_STR(S_kdC, "Can't encode value of type Obj");
GLOBAL_STR(S_egA, "Code point can't be greater than U+10ffff");
GLOBAL_STR(S_wac, "Comments aren't part of JSON; you may want 'json8 read'");
GLOBAL_STR(S_wcu, "Const");
GLOBAL_STR(S_lAz, "DQ");
GLOBAL_STR(S_vbu, "Dict");
GLOBAL_STR(S_gFh, "F");
GLOBAL_STR(S_BvB, "INFINITY");
GLOBAL_STR(S_Ckc, "Int");
GLOBAL_STR(S_zDl, "Integer is too big");
GLOBAL_STR(S_Czs, "J8");
GLOBAL_STR(S_ApC, "J8 Lines can't have unescaped ASCII control chars");
GLOBAL_STR(S_dqg, "JSON");
GLOBAL_STR(S_bDF, "List");
GLOBAL_STR(S_lkg, "List<");
GLOBAL_STR(S_tax, "Module shouldn't be empty");
GLOBAL_STR(S_ywk, "NAN");
GLOBAL_STR(S_Ahj, "Pure JSON does not accept j\"\" prefix");
GLOBAL_STR(S_mip, "SQ");
GLOBAL_STR(S_trv, "Signature should have 3 items: =>  params  return");
GLOBAL_STR(S_sir, "Signature should start with =>");
GLOBAL_STR(S_hBp, "Single quotes aren't part of JSON; you may want 'json8 read'");
GLOBAL_STR(S_sEv, "Statement shouldn't be empty");
GLOBAL_STR(S_DsF, "Str");
GLOBAL_STR(S_cor, "T");
GLOBAL_STR(S_oDA, "Unexpected trailing input");
GLOBAL_STR(S_mfF, "Unexpected trailing input in J8 Lines");
GLOBAL_STR(S_CsA, "Var");
GLOBAL_STR(S_Eax, "[");
GLOBAL_STR(S_Aek, "[...]");
GLOBAL_STR(S_xmu, "[]");
GLOBAL_STR(S_pcD, "]");
GLOBAL_STR(S_nuz, "]=");
GLOBAL_STR(S_tci, "_");
GLOBAL_STR(S_gfw, "___ GC: after printing");
GLOBAL_STR(S_pch, "break");
GLOBAL_STR(S_Cnd, "call");
GLOBAL_STR(S_voB, "check");
GLOBAL_STR(S_yBr, "chunk");
GLOBAL_STR(S_nuD, "class");
GLOBAL_STR(S_gFE, "code");
GLOBAL_STR(S_ohy, "continue");
GLOBAL_STR(S_npw, "cpp");
GLOBAL_STR(S_xho, "failglob: ");
GLOBAL_STR(S_Ctn, "false");
GLOBAL_STR(S_lqB, "foo");
GLOBAL_STR(S_zmF, "func");
GLOBAL_STR(S_qCj, "global");
GLOBAL_STR(S_cEk, "hi");
GLOBAL_STR(S_gcE, "int");
GLOBAL_STR(S_pBg, "message");
GLOBAL_STR(S_lbA, "null");
GLOBAL_STR(S_rbu, "path");
GLOBAL_STR(S_ddf, "return");
GLOBAL_STR(S_lyA, "setvar");
GLOBAL_STR(S_omF, "t");
GLOBAL_STR(S_FsF, "true");
GLOBAL_STR(S_fhn, "var");
GLOBAL_STR(S_pfC, "w");
GLOBAL_STR(S_ato, "{");
GLOBAL_STR(S_qnA, "{...}");
GLOBAL_STR(S_Fni, "{}");
GLOBAL_STR(S_cEn, "}");
GLOBAL_STR(S_tve, "}\n");

namespace runtime {  // declare

extern int NO_SPID;
hnode::Record* NewRecord(BigStr* node_type);
hnode::Leaf* NewLeaf(BigStr* s, hnode_asdl::color_t e_color);
class TraversalState {
 public:
  TraversalState();
  Dict<int, bool>* seen{};
  Dict<int, int>* ref_count{};

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassScanned(2, sizeof(TraversalState));
  }

  DISALLOW_COPY_AND_ASSIGN(TraversalState)
};

extern BigStr* TRUE_STR;
extern BigStr* FALSE_STR;

}  // declare namespace runtime

namespace format {  // declare

int _HNodeCount(hnode_asdl::hnode_t* h);
int _DocCount(pretty_asdl::doc_t* d);
void _HNodePrettyPrint(bool perf_stats, bool doc_debug, hnode_asdl::hnode_t* node, mylib::Writer* f, int max_width = 80);
void HNodePrettyPrint(hnode_asdl::hnode_t* node, mylib::Writer* f, int max_width = 80);

}  // declare namespace format

namespace bash_impl {  // declare

bool BigInt_Greater(mops::BigInt a, mops::BigInt b);
bool BigInt_Less(mops::BigInt a, mops::BigInt b);
bool BigInt_GreaterEq(mops::BigInt a, mops::BigInt b);
bool BigInt_LessEq(mops::BigInt a, mops::BigInt b);
bool BashArray_IsEmpty(value::BashArray* array_val);
int BashArray_Count(value::BashArray* array_val);
int BashArray_Length(value::BashArray* array_val);
List<int>* BashArray_GetKeys(value::BashArray* array_val);
List<BigStr*>* BashArray_GetValues(value::BashArray* array_val);
void BashArray_AppendValues(value::BashArray* array_val, List<BigStr*>* strs);
Tuple3<int, int, runtime_asdl::error_code_t> _BashArray_CanonicalizeIndex(value::BashArray* array_val, int index);
Tuple2<bool, runtime_asdl::error_code_t> BashArray_HasElement(value::BashArray* array_val, int index);
Tuple2<BigStr*, runtime_asdl::error_code_t> BashArray_GetElement(value::BashArray* array_val, int index);
runtime_asdl::error_code_t BashArray_SetElement(value::BashArray* array_val, int index, BigStr* s);
runtime_asdl::error_code_t BashArray_UnsetElement(value::BashArray* array_val, int index);
bool BashArray_Equals(value::BashArray* lhs, value::BashArray* rhs);
bool _BashArray_HasHoles(value::BashArray* array_val);
BigStr* BashArray_ToStrForShellPrint(value::BashArray* array_val, BigStr* name);
bool BashAssoc_IsEmpty(value::BashAssoc* assoc_val);
int BashAssoc_Count(value::BashAssoc* assoc_val);
Dict<BigStr*, BigStr*>* BashAssoc_GetDict(value::BashAssoc* assoc_val);
void BashAssoc_AppendDict(value::BashAssoc* assoc_val, Dict<BigStr*, BigStr*>* d);
List<BigStr*>* BashAssoc_GetKeys(value::BashAssoc* assoc_val);
List<BigStr*>* BashAssoc_GetValues(value::BashAssoc* assoc_val);
bool BashAssoc_HasElement(value::BashAssoc* assoc_val, BigStr* s);
BigStr* BashAssoc_GetElement(value::BashAssoc* assoc_val, BigStr* s);
void BashAssoc_SetElement(value::BashAssoc* assoc_val, BigStr* key, BigStr* s);
void BashAssoc_UnsetElement(value::BashAssoc* assoc_val, BigStr* key);
bool BashAssoc_Equals(value::BashAssoc* lhs, value::BashAssoc* rhs);
BigStr* BashAssoc_ToStrForShellPrint(value::BashAssoc* assoc_val);
bool SparseArray_IsEmpty(value::SparseArray* sparse_val);
int SparseArray_Count(value::SparseArray* sparse_val);
mops::BigInt SparseArray_Length(value::SparseArray* sparse_val);
List<mops::BigInt>* SparseArray_GetKeys(value::SparseArray* sparse_val);
List<BigStr*>* SparseArray_GetValues(value::SparseArray* sparse_val);
void SparseArray_AppendValues(value::SparseArray* sparse_val, List<BigStr*>* strs);
Tuple2<mops::BigInt, runtime_asdl::error_code_t> _SparseArray_CanonicalizeIndex(value::SparseArray* sparse_val, mops::BigInt index);
Tuple2<bool, runtime_asdl::error_code_t> SparseArray_HasElement(value::SparseArray* sparse_val, mops::BigInt index);
Tuple2<BigStr*, runtime_asdl::error_code_t> SparseArray_GetElement(value::SparseArray* sparse_val, mops::BigInt index);
runtime_asdl::error_code_t SparseArray_SetElement(value::SparseArray* sparse_val, mops::BigInt index, BigStr* s);
runtime_asdl::error_code_t SparseArray_UnsetElement(value::SparseArray* sparse_val, mops::BigInt index);
bool SparseArray_Equals(value::SparseArray* lhs, value::SparseArray* rhs);
BigStr* SparseArray_ToStrForShellPrint(value::SparseArray* sparse_val);

}  // declare namespace bash_impl

namespace error {  // declare

BigStr* _ValType(value_asdl::value_t* val);
class _ErrorWithLocation {
 public:
  _ErrorWithLocation(BigStr* msg, syntax_asdl::loc_t* location);
  bool HasLocation();
  BigStr* UserErrorString();
  syntax_asdl::loc_t* location{};
  BigStr* msg{};
  
  static constexpr uint32_t field_mask() {
    return maskbit(offsetof(_ErrorWithLocation, location))
         | maskbit(offsetof(_ErrorWithLocation, msg));
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(_ErrorWithLocation));
  }

  DISALLOW_COPY_AND_ASSIGN(_ErrorWithLocation)
};

class Usage : public ::error::_ErrorWithLocation {
 public:
  Usage(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::_ErrorWithLocation::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(Usage));
  }

  DISALLOW_COPY_AND_ASSIGN(Usage)
};

class Parse : public ::error::_ErrorWithLocation {
 public:
  Parse(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::_ErrorWithLocation::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(Parse));
  }

  DISALLOW_COPY_AND_ASSIGN(Parse)
};

class WordFailure : public ::error::_ErrorWithLocation {
 public:
  WordFailure(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::_ErrorWithLocation::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(WordFailure));
  }

  DISALLOW_COPY_AND_ASSIGN(WordFailure)
};

class FailGlob : public ::error::WordFailure {
 public:
  FailGlob(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::WordFailure::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(FailGlob));
  }

  DISALLOW_COPY_AND_ASSIGN(FailGlob)
};

class VarSubFailure : public ::error::WordFailure {
 public:
  VarSubFailure(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::WordFailure::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(VarSubFailure));
  }

  DISALLOW_COPY_AND_ASSIGN(VarSubFailure)
};

class RedirectEval : public ::error::_ErrorWithLocation {
 public:
  RedirectEval(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::_ErrorWithLocation::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(RedirectEval));
  }

  DISALLOW_COPY_AND_ASSIGN(RedirectEval)
};

class FatalRuntime : public ::error::_ErrorWithLocation {
 public:
  FatalRuntime(int exit_status, BigStr* msg, syntax_asdl::loc_t* location);
  int ExitStatus();

  int exit_status{};
  
  static constexpr uint32_t field_mask() {
    return ::error::_ErrorWithLocation::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(FatalRuntime));
  }

  DISALLOW_COPY_AND_ASSIGN(FatalRuntime)
};

class Strict : public ::error::FatalRuntime {
 public:
  Strict(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::FatalRuntime::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(Strict));
  }

  DISALLOW_COPY_AND_ASSIGN(Strict)
};

class ErrExit : public ::error::FatalRuntime {
 public:
  ErrExit(int exit_status, BigStr* msg, syntax_asdl::loc_t* location, bool show_code = false);

  bool show_code{};
  
  static constexpr uint32_t field_mask() {
    return ::error::FatalRuntime::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(ErrExit));
  }

  DISALLOW_COPY_AND_ASSIGN(ErrExit)
};

class Expr : public ::error::FatalRuntime {
 public:
  Expr(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::FatalRuntime::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(Expr));
  }

  DISALLOW_COPY_AND_ASSIGN(Expr)
};

class Structured : public ::error::FatalRuntime {
 public:
  Structured(int status, BigStr* msg, syntax_asdl::loc_t* location, Dict<BigStr*, value_asdl::value_t*>* properties = nullptr);
  value::Dict* ToDict();

  Dict<BigStr*, value_asdl::value_t*>* properties{};
  
  static constexpr uint32_t field_mask() {
    return ::error::FatalRuntime::field_mask()
         | maskbit(offsetof(Structured, properties));
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(Structured));
  }

  DISALLOW_COPY_AND_ASSIGN(Structured)
};

class AssertionErr : public ::error::Expr {
 public:
  AssertionErr(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::Expr::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(AssertionErr));
  }

  DISALLOW_COPY_AND_ASSIGN(AssertionErr)
};

class TypeErrVerbose : public ::error::Expr {
 public:
  TypeErrVerbose(BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::Expr::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(TypeErrVerbose));
  }

  DISALLOW_COPY_AND_ASSIGN(TypeErrVerbose)
};

class TypeErr : public ::error::TypeErrVerbose {
 public:
  TypeErr(value_asdl::value_t* actual_val, BigStr* msg, syntax_asdl::loc_t* location);
  
  static constexpr uint32_t field_mask() {
    return ::error::TypeErrVerbose::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(TypeErr));
  }

  DISALLOW_COPY_AND_ASSIGN(TypeErr)
};

class Runtime {
 public:
  Runtime(BigStr* msg);
  BigStr* UserErrorString();
  BigStr* msg{};

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassScanned(1, sizeof(Runtime));
  }

  DISALLOW_COPY_AND_ASSIGN(Runtime)
};

class Decode {
 public:
  Decode(BigStr* msg, BigStr* s, int start_pos, int end_pos, int line_num);
  BigStr* Message();
  BigStr* __str__();
  BigStr* msg{};
  BigStr* s{};
  int start_pos{};
  int end_pos{};
  int line_num{};

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassScanned(2, sizeof(Decode));
  }

  DISALLOW_COPY_AND_ASSIGN(Decode)
};

class Encode {
 public:
  Encode(BigStr* msg);
  BigStr* Message();
  BigStr* msg{};

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassScanned(1, sizeof(Encode));
  }

  DISALLOW_COPY_AND_ASSIGN(Encode)
};

[[noreturn]] void e_usage(BigStr* msg, syntax_asdl::loc_t* location);
[[noreturn]] void e_strict(BigStr* msg, syntax_asdl::loc_t* location);
[[noreturn]] void p_die(BigStr* msg, syntax_asdl::loc_t* location);
[[noreturn]] void e_die(BigStr* msg, syntax_asdl::loc_t* location = nullptr);
[[noreturn]] void e_die_status(int status, BigStr* msg, syntax_asdl::loc_t* location = nullptr);

}  // declare namespace error

namespace num {  // declare

value::Int* ToBig(int i);
mops::BigInt Exponent(mops::BigInt x, mops::BigInt y);

}  // declare namespace num

namespace j8 {  // declare

BigStr* ValType(value_asdl::value_t* val);
int ValueId(value_asdl::value_t* val);
BigStr* ValueIdString(value_asdl::value_t* val);
BigStr* Utf8Encode(int code);
extern int SHOW_CYCLES;
extern int SHOW_NON_DATA;
extern int LOSSY_JSON;
extern int INF_NAN_ARE_NULL;
void _Print(value_asdl::value_t* val, mylib::BufWriter* buf, int indent, int options = 0);
void PrintMessage(value_asdl::value_t* val, mylib::BufWriter* buf, int indent);
void PrintJsonMessage(value_asdl::value_t* val, mylib::BufWriter* buf, int indent);
void PrintLine(value_asdl::value_t* val, mylib::Writer* f);
void EncodeString(BigStr* s, mylib::BufWriter* buf, bool unquoted_ok = false);
BigStr* MaybeEncodeString(BigStr* s);
BigStr* MaybeEncodeJsonString(BigStr* s);
class InstancePrinter {
 public:
  InstancePrinter(mylib::BufWriter* buf, int indent, int options);
  void _ItemIndent(int level);
  void _BracketIndent(int level);
  void _MaybeNewline();
  void _MaybeSpace();
  void _PrintList(value::List* val, int level);
  void _PrintMapping(Dict<BigStr*, value_asdl::value_t*>* d, BigStr* left, BigStr* right, int level);
  void _PrintDict(value::Dict* val, int level);
  void _PrintObj(value_asdl::Obj* val, int level);
  void _PrintBashPrefix(BigStr* type_str, int level);
  void _PrintBashSuffix(int level);
  void _PrintSparseArray(value::SparseArray* val, int level);
  void _PrintBashArray(value::BashArray* val, int level);
  void _PrintBashAssoc(value::BashAssoc* val, int level);
  void Print(value_asdl::value_t* val, int level = 0);
  mylib::BufWriter* buf{};
  Dict<int, bool>* visiting{};
  int indent{};
  int options{};

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassScanned(2, sizeof(InstancePrinter));
  }

  DISALLOW_COPY_AND_ASSIGN(InstancePrinter)
};

class LexerDecoder {
 public:
  LexerDecoder(BigStr* s, bool is_j8, BigStr* lang_str);
  error::Decode* _Error(BigStr* msg, int end_pos);
  Tuple3<int, int, BigStr*> Next();
  Tuple3<int, int, BigStr*> NextForLines();
  Tuple3<int, int, BigStr*> _DecodeString(int left_id, int str_pos);
  BigStr* s{};
  BigStr* lang_str{};
  mylib::BufWriter* decoded{};
  bool is_j8{};
  int pos{};
  int cur_line_num{};

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassScanned(3, sizeof(LexerDecoder));
  }

  DISALLOW_COPY_AND_ASSIGN(LexerDecoder)
};

class _Parser {
 public:
  _Parser(BigStr* s, bool is_j8);
  void _Next();
  void _Eat(int tok_id);
  void _NextForLines();
  error::Decode* _ParseError(BigStr* msg);
  BigStr* decoded{};
  int end_pos{};
  bool is_j8{};
  BigStr* lang_str{};
  j8::LexerDecoder* lexer{};
  BigStr* s{};
  int start_pos{};
  int tok_id{};
  
  static constexpr uint32_t field_mask() {
    return maskbit(offsetof(_Parser, decoded))
         | maskbit(offsetof(_Parser, lang_str))
         | maskbit(offsetof(_Parser, lexer))
         | maskbit(offsetof(_Parser, s));
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(_Parser));
  }

  DISALLOW_COPY_AND_ASSIGN(_Parser)
};

class Parser : public ::j8::_Parser {
 public:
  Parser(BigStr* s, bool is_j8);
  Tuple2<BigStr*, value_asdl::value_t*> _ParsePair();
  value_asdl::value_t* _ParseDict();
  value_asdl::value_t* _ParseList();
  value_asdl::value_t* _ParseValue();
  value_asdl::value_t* ParseValue();
  
  static constexpr uint32_t field_mask() {
    return ::j8::_Parser::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(Parser));
  }

  DISALLOW_COPY_AND_ASSIGN(Parser)
};

class Nil8Parser : public ::j8::_Parser {
 public:
  Nil8Parser(BigStr* s, bool is_j8);
  nil8_asdl::nvalue_t* _ParseRecord();
  nil8_asdl::nvalue_t* _ParseList8();
  nil8_asdl::nvalue_t* _ParseNil8();
  nil8_asdl::nvalue_t* ParseNil8();
  
  static constexpr uint32_t field_mask() {
    return ::j8::_Parser::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(Nil8Parser));
  }

  DISALLOW_COPY_AND_ASSIGN(Nil8Parser)
};

class J8LinesParser : public ::j8::_Parser {
 public:
  J8LinesParser(BigStr* s);
  void _Show(BigStr* s);
  void _ParseLine(List<BigStr*>* out);
  List<BigStr*>* Parse();
  
  static constexpr uint32_t field_mask() {
    return ::j8::_Parser::field_mask();
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(J8LinesParser));
  }

  DISALLOW_COPY_AND_ASSIGN(J8LinesParser)
};

List<BigStr*>* SplitJ8Lines(BigStr* s);

}  // declare namespace j8

namespace j8_lite {  // declare

BigStr* EncodeString(BigStr* s, bool unquoted_ok = false);
BigStr* YshEncodeString(BigStr* s);
BigStr* MaybeShellEncode(BigStr* s);
BigStr* ShellEncode(BigStr* s);
BigStr* YshEncode(BigStr* s, bool unquoted_ok = false);

}  // declare namespace j8_lite

namespace ansi {  // declare

extern BigStr* RESET;
extern BigStr* BOLD;
extern BigStr* UNDERLINE;
extern BigStr* REVERSE;
extern BigStr* RED;
extern BigStr* GREEN;
extern BigStr* YELLOW;
extern BigStr* BLUE;
extern BigStr* MAGENTA;
extern BigStr* CYAN;
extern BigStr* WHITE;

}  // declare namespace ansi

namespace pp_hnode {  // declare

class BaseEncoder {
 public:
  BaseEncoder();
  void SetIndent(int indent);
  void SetUseStyles(bool use_styles);
  void SetMaxTabularWidth(int max_tabular_width);
  pretty_asdl::MeasuredDoc* _Styled(BigStr* style, pretty_asdl::MeasuredDoc* mdoc);
  pretty_asdl::MeasuredDoc* _StyledAscii(BigStr* style, BigStr* s);
  pretty_asdl::MeasuredDoc* _Surrounded(BigStr* left, pretty_asdl::MeasuredDoc* mdoc, BigStr* right);
  pretty_asdl::MeasuredDoc* _SurroundedAndPrefixed(BigStr* left, pretty_asdl::MeasuredDoc* prefix, BigStr* sep, pretty_asdl::MeasuredDoc* mdoc, BigStr* right);
  pretty_asdl::MeasuredDoc* _Join(List<pretty_asdl::MeasuredDoc*>* items, BigStr* sep, BigStr* space);
  pretty_asdl::MeasuredDoc* _Tabular(List<pretty_asdl::MeasuredDoc*>* items, BigStr* sep);
  int indent{};
  int max_tabular_width{};
  bool use_styles{};
  Dict<int, bool>* visiting{};
  
  static constexpr uint32_t field_mask() {
    return maskbit(offsetof(BaseEncoder, visiting));
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(BaseEncoder));
  }

  DISALLOW_COPY_AND_ASSIGN(BaseEncoder)
};

class HNodeEncoder : public ::pp_hnode::BaseEncoder {
 public:
  HNodeEncoder();
  pretty_asdl::MeasuredDoc* HNode(hnode_asdl::hnode_t* h);
  pretty_asdl::MeasuredDoc* _Field(hnode_asdl::Field* field);
  pretty_asdl::MeasuredDoc* _HNode(hnode_asdl::hnode_t* h);

  BigStr* field_color{};
  BigStr* type_color{};
  
  static constexpr uint32_t field_mask() {
    return ::pp_hnode::BaseEncoder::field_mask()
         | maskbit(offsetof(HNodeEncoder, field_color))
         | maskbit(offsetof(HNodeEncoder, type_color));
  }

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassFixed(field_mask(), sizeof(HNodeEncoder));
  }

  DISALLOW_COPY_AND_ASSIGN(HNodeEncoder)
};


}  // declare namespace pp_hnode

namespace pretty {  // declare

pretty_asdl::Measure* _EmptyMeasure();
pretty_asdl::Measure* _FlattenMeasure(pretty_asdl::Measure* measure);
pretty_asdl::Measure* _ConcatMeasure(pretty_asdl::Measure* m1, pretty_asdl::Measure* m2);
int _SuffixLen(pretty_asdl::Measure* measure);
pretty_asdl::MeasuredDoc* AsciiText(BigStr* string);
pretty_asdl::MeasuredDoc* _Break(BigStr* string);
pretty_asdl::MeasuredDoc* _Indent(int indent, pretty_asdl::MeasuredDoc* mdoc);
pretty_asdl::Measure* _Splice(List<pretty_asdl::MeasuredDoc*>* out, List<pretty_asdl::MeasuredDoc*>* mdocs);
pretty_asdl::MeasuredDoc* _Concat(List<pretty_asdl::MeasuredDoc*>* mdocs);
pretty_asdl::MeasuredDoc* _Group(pretty_asdl::MeasuredDoc* mdoc);
pretty_asdl::MeasuredDoc* _IfFlat(pretty_asdl::MeasuredDoc* flat_mdoc, pretty_asdl::MeasuredDoc* nonflat_mdoc);
pretty_asdl::MeasuredDoc* _Flat(pretty_asdl::MeasuredDoc* mdoc);
class PrettyPrinter {
 public:
  PrettyPrinter(int max_width);
  bool _Fits(int prefix_len, pretty_asdl::MeasuredDoc* group, pretty_asdl::Measure* suffix_measure);
  void PrintDoc(pretty_asdl::MeasuredDoc* document, mylib::BufWriter* buf);
  int max_width{};

  static constexpr ObjHeader obj_header() {
    return ObjHeader::ClassScanned(0, sizeof(PrettyPrinter));
  }

  DISALLOW_COPY_AND_ASSIGN(PrettyPrinter)
};


}  // declare namespace pretty

namespace syntax_abbrev {  // declare

void _AbbreviateToken(syntax_asdl::Token* tok, List<hnode_asdl::hnode_t*>* out);
hnode_asdl::hnode_t* _Token(syntax_asdl::Token* obj);
hnode_asdl::hnode_t* _CompoundWord(syntax_asdl::CompoundWord* obj);
hnode_asdl::hnode_t* _DoubleQuoted(syntax_asdl::DoubleQuoted* obj);
hnode_asdl::hnode_t* _SingleQuoted(syntax_asdl::SingleQuoted* obj);
hnode_asdl::hnode_t* _SimpleVarSub(syntax_asdl::SimpleVarSub* obj);
hnode_asdl::hnode_t* _BracedVarSub(syntax_asdl::BracedVarSub* obj);
hnode_asdl::hnode_t* _command__Simple(command::Simple* obj);
hnode_asdl::hnode_t* _expr__Var(expr::Var* obj);
hnode_asdl::hnode_t* _expr__Const(expr::Const* obj);

}  // declare namespace syntax_abbrev

namespace gen_cpp {  // declare

void GenType(yaks_asdl::ktype_t* typ, mylib::Writer* f);
void GenParam(yaks_asdl::NameType* p, mylib::Writer* f);
void GenExpr(yaks_asdl::kexpr_t* expr, mylib::Writer* f);
void GenStatement(yaks_asdl::stmt_t* st, mylib::Writer* f);
void GenFunction(mod_def::Func* func, mylib::Writer* f);
void GenCpp(yaks_asdl::Program* prog, mylib::Writer* f);

}  // declare namespace gen_cpp

namespace transform {  // declare

BigStr* MustBeSymbol(nil8_asdl::nvalue_t* nval);
List<nil8_asdl::nvalue_t*>* MustBeList(nil8_asdl::nvalue_t* nval);
yaks_asdl::kexpr_t* TransformExpr(nil8_asdl::nvalue_t* nval);
yaks_asdl::ktype_t* TransformType(nil8_asdl::nvalue_t* nval);
yaks_asdl::NameType* TransformParam(List<nil8_asdl::nvalue_t*>* param_n);
List<yaks_asdl::NameType*>* TransformParams(List<nil8_asdl::nvalue_t*>* params_n);
yaks_asdl::Signature* TransformSignature(nil8_asdl::nvalue_t* nval);
mod_def::Func* TransformFunc(List<nil8_asdl::nvalue_t*>* func_n);
yaks_asdl::Module* TransformModule(List<nil8_asdl::nvalue_t*>* mod_n);
yaks_asdl::Program* Transform(nil8_asdl::nvalue_t* nval);

}  // declare namespace transform

namespace yaks_main {  // declare

int main(List<BigStr*>* argv);

}  // declare namespace yaks_main

namespace runtime {  // define

using hnode_asdl::hnode;
using hnode_asdl::color_t;
using hnode_asdl::color_e;
int NO_SPID = -1;

hnode::Record* NewRecord(BigStr* node_type) {
  StackRoot _root0(&node_type);

  return Alloc<hnode::Record>(node_type, S_ijB, S_hxb, Alloc<List<hnode_asdl::Field*>>(), nullptr);
}

hnode::Leaf* NewLeaf(BigStr* s, hnode_asdl::color_t e_color) {
  StackRoot _root0(&s);

  if (s == nullptr) {
    return Alloc<hnode::Leaf>(S_tci, color_e::OtherConst);
  }
  else {
    return Alloc<hnode::Leaf>(s, e_color);
  }
}

TraversalState::TraversalState() {
  this->seen = Alloc<Dict<int, bool>>();
  this->ref_count = Alloc<Dict<int, int>>();
}
BigStr* TRUE_STR = S_cor;
BigStr* FALSE_STR = S_gFh;

}  // define namespace runtime

namespace format {  // define

using hnode_asdl::hnode;
using hnode_asdl::hnode_e;
using hnode_asdl::hnode_t;
using pretty_asdl::doc;
using pretty_asdl::doc_e;
using pretty_asdl::doc_t;
using pretty_asdl::MeasuredDoc;
using pretty_asdl::List_Measured;

int _HNodeCount(hnode_asdl::hnode_t* h) {
  hnode_asdl::hnode_t* UP_h = nullptr;
  int n;
  StackRoot _root0(&h);
  StackRoot _root1(&UP_h);

  UP_h = h;
  switch (h->tag()) {
    case hnode_e::AlreadySeen: {
      return 1;
    }
      break;
    case hnode_e::Leaf: {
      return 1;
    }
      break;
    case hnode_e::Array: {
      hnode::Array* h = static_cast<hnode::Array*>(UP_h);
      n = 1;
      for (ListIter<hnode_asdl::hnode_t*> it(h->children); !it.Done(); it.Next()) {
        hnode_asdl::hnode_t* child = it.Value();
        StackRoot _for(&child      );
        n += _HNodeCount(child);
      }
      return n;
    }
      break;
    case hnode_e::Record: {
      hnode::Record* h = static_cast<hnode::Record*>(UP_h);
      n = 1;
      for (ListIter<hnode_asdl::Field*> it(h->fields); !it.Done(); it.Next()) {
        hnode_asdl::Field* field = it.Value();
        StackRoot _for(&field      );
        n += _HNodeCount(field->val);
      }
      if (h->unnamed_fields != nullptr) {
        for (ListIter<hnode_asdl::hnode_t*> it(h->unnamed_fields); !it.Done(); it.Next()) {
          hnode_asdl::hnode_t* child = it.Value();
          StackRoot _for(&child        );
          n += _HNodeCount(child);
        }
      }
      return n;
    }
      break;
    default: {
      assert(0);  // AssertionError
    }
  }
}

int _DocCount(pretty_asdl::doc_t* d) {
  pretty_asdl::doc_t* UP_d = nullptr;
  int n;
  StackRoot _root0(&d);
  StackRoot _root1(&UP_d);

  UP_d = d;
  switch (d->tag()) {
    case doc_e::Break: {
      return 1;
    }
      break;
    case doc_e::Text: {
      return 1;
    }
      break;
    case doc_e::Indent: {
      doc::Indent* d = static_cast<doc::Indent*>(UP_d);
      return (1 + _DocCount(d->mdoc->doc));
    }
      break;
    case doc_e::Group: {
      MeasuredDoc* d = static_cast<MeasuredDoc*>(UP_d);
      return (1 + _DocCount(d->doc));
    }
      break;
    case doc_e::Flat: {
      doc::Flat* d = static_cast<doc::Flat*>(UP_d);
      return (1 + _DocCount(d->mdoc->doc));
    }
      break;
    case doc_e::IfFlat: {
      doc::IfFlat* d = static_cast<doc::IfFlat*>(UP_d);
      return ((1 + _DocCount(d->flat_mdoc->doc)) + _DocCount(d->nonflat_mdoc->doc));
    }
      break;
    case doc_e::Concat: {
      List_Measured* d = static_cast<List_Measured*>(UP_d);
      n = 1;
      for (ListIter<pretty_asdl::MeasuredDoc*> it(d); !it.Done(); it.Next()) {
        pretty_asdl::MeasuredDoc* mdoc = it.Value();
        StackRoot _for(&mdoc      );
        n += _DocCount(mdoc->doc);
      }
      return n;
    }
      break;
    default: {
      assert(0);  // AssertionError
    }
  }
}

void _HNodePrettyPrint(bool perf_stats, bool doc_debug, hnode_asdl::hnode_t* node, mylib::Writer* f, int max_width) {
  pp_hnode::HNodeEncoder* enc = nullptr;
  pretty_asdl::MeasuredDoc* d = nullptr;
  hnode_asdl::hnode_t* p = nullptr;
  pretty::PrettyPrinter* printer = nullptr;
  mylib::BufWriter* buf = nullptr;
  StackRoot _root0(&node);
  StackRoot _root1(&f);
  StackRoot _root2(&enc);
  StackRoot _root3(&d);
  StackRoot _root4(&p);
  StackRoot _root5(&printer);
  StackRoot _root6(&buf);

  mylib::MaybeCollect();
  if (perf_stats) {
    mylib::print_stderr(StrFormat("___ HNODE COUNT %d", _HNodeCount(node)));
    mylib::print_stderr(S_Aoo);
  }
  enc = Alloc<pp_hnode::HNodeEncoder>();
  enc->SetUseStyles(f->isatty());
  enc->SetIndent(2);
  d = enc->HNode(node);
  mylib::MaybeCollect();
  if (perf_stats) {
    if (doc_debug) {
      p = d->PrettyTree(false);
      _HNodePrettyPrint(perf_stats, false, p, f);
    }
    mylib::print_stderr(StrFormat("___ DOC COUNT %d", _DocCount(d)));
    mylib::print_stderr(S_Aoo);
  }
  printer = Alloc<pretty::PrettyPrinter>(max_width);
  buf = Alloc<mylib::BufWriter>();
  printer->PrintDoc(d, buf);
  f->write(buf->getvalue());
  f->write(S_nfs);
  mylib::MaybeCollect();
  if (perf_stats) {
    mylib::print_stderr(S_gfw);
    mylib::PrintGcStats();
    mylib::print_stderr(S_Aoo);
  }
}

void HNodePrettyPrint(hnode_asdl::hnode_t* node, mylib::Writer* f, int max_width) {
  StackRoot _root0(&node);
  StackRoot _root1(&f);

  _HNodePrettyPrint(false, true, node, f, max_width);
}

}  // define namespace format

namespace bash_impl {  // define

using runtime_asdl::error_code_e;
using runtime_asdl::error_code_t;
using value_asdl::value;

bool BigInt_Greater(mops::BigInt a, mops::BigInt b) {
  return mops::Greater(a, b);
}

bool BigInt_Less(mops::BigInt a, mops::BigInt b) {
  return mops::Greater(b, a);
}

bool BigInt_GreaterEq(mops::BigInt a, mops::BigInt b) {
  return !mops::Greater(b, a);
}

bool BigInt_LessEq(mops::BigInt a, mops::BigInt b) {
  return !mops::Greater(a, b);
}

bool BashArray_IsEmpty(value::BashArray* array_val) {
  StackRoot _root0(&array_val);

  return len(array_val->strs) == 0;
}

int BashArray_Count(value::BashArray* array_val) {
  int length;
  StackRoot _root0(&array_val);

  length = 0;
  for (ListIter<BigStr*> it(array_val->strs); !it.Done(); it.Next()) {
    BigStr* s = it.Value();
    StackRoot _for(&s  );
    if (s != nullptr) {
      length += 1;
    }
  }
  return length;
}

int BashArray_Length(value::BashArray* array_val) {
  StackRoot _root0(&array_val);

  return len(array_val->strs);
}

List<int>* BashArray_GetKeys(value::BashArray* array_val) {
  List<int>* indices = nullptr;
  int i;
  StackRoot _root0(&array_val);
  StackRoot _root1(&indices);

  indices = Alloc<List<int>>();
  i = 0;
  for (ListIter<BigStr*> it(array_val->strs); !it.Done(); it.Next(), ++i) {
    BigStr* s = it.Value();
    StackRoot _for(&s  );
    if (s != nullptr) {
      indices->append(i);
    }
  }
  return indices;
}

List<BigStr*>* BashArray_GetValues(value::BashArray* array_val) {
  StackRoot _root0(&array_val);

  return array_val->strs;
}

void BashArray_AppendValues(value::BashArray* array_val, List<BigStr*>* strs) {
  StackRoot _root0(&array_val);
  StackRoot _root1(&strs);

  array_val->strs->extend(strs);
}

Tuple3<int, int, runtime_asdl::error_code_t> _BashArray_CanonicalizeIndex(value::BashArray* array_val, int index) {
  int n;
  StackRoot _root0(&array_val);

  n = len(array_val->strs);
  if (index < 0) {
    index += n;
    if (index < 0) {
      return Tuple3<int, int, runtime_asdl::error_code_t>(-1, n, error_code_e::IndexOutOfRange);
    }
  }
  return Tuple3<int, int, runtime_asdl::error_code_t>(index, n, error_code_e::OK);
}

Tuple2<bool, runtime_asdl::error_code_t> BashArray_HasElement(value::BashArray* array_val, int index) {
  int n;
  runtime_asdl::error_code_t error_code;
  StackRoot _root0(&array_val);

  Tuple3<int, int, runtime_asdl::error_code_t> tup0 = _BashArray_CanonicalizeIndex(array_val, index);
  index = tup0.at0();
  n = tup0.at1();
  error_code = tup0.at2();
  if (error_code != error_code_e::OK) {
    return Tuple2<bool, runtime_asdl::error_code_t>(false, error_code);
  }
  if (index < n) {
    return Tuple2<bool, runtime_asdl::error_code_t>(array_val->strs->at(index) != nullptr, error_code_e::OK);
  }
  return Tuple2<bool, runtime_asdl::error_code_t>(false, error_code_e::OK);
}

Tuple2<BigStr*, runtime_asdl::error_code_t> BashArray_GetElement(value::BashArray* array_val, int index) {
  int n;
  runtime_asdl::error_code_t error_code;
  BigStr* s = nullptr;
  StackRoot _root0(&array_val);
  StackRoot _root1(&s);

  Tuple3<int, int, runtime_asdl::error_code_t> tup1 = _BashArray_CanonicalizeIndex(array_val, index);
  index = tup1.at0();
  n = tup1.at1();
  error_code = tup1.at2();
  if (error_code != error_code_e::OK) {
    return Tuple2<BigStr*, runtime_asdl::error_code_t>(nullptr, error_code);
  }
  if (index < n) {
    s = array_val->strs->at(index);
  }
  else {
    s = nullptr;
  }
  return Tuple2<BigStr*, runtime_asdl::error_code_t>(s, error_code_e::OK);
}

runtime_asdl::error_code_t BashArray_SetElement(value::BashArray* array_val, int index, BigStr* s) {
  List<BigStr*>* strs = nullptr;
  int n;
  runtime_asdl::error_code_t error_code;
  StackRoot _root0(&array_val);
  StackRoot _root1(&s);
  StackRoot _root2(&strs);

  strs = array_val->strs;
  Tuple3<int, int, runtime_asdl::error_code_t> tup2 = _BashArray_CanonicalizeIndex(array_val, index);
  index = tup2.at0();
  n = tup2.at1();
  error_code = tup2.at2();
  if (error_code != error_code_e::OK) {
    return error_code;
  }
  if (index < n) {
    array_val->strs->set(index, s);
  }
  else {
    for (int i = 0; i < ((index - n) + 1); ++i) {
      array_val->strs->append(nullptr);
    }
    array_val->strs->set(index, s);
  }
  return error_code_e::OK;
}

runtime_asdl::error_code_t BashArray_UnsetElement(value::BashArray* array_val, int index) {
  List<BigStr*>* strs = nullptr;
  int n;
  int last_index;
  StackRoot _root0(&array_val);
  StackRoot _root1(&strs);

  strs = array_val->strs;
  n = len(strs);
  last_index = (n - 1);
  if (index < 0) {
    index += n;
    if (index < 0) {
      return error_code_e::IndexOutOfRange;
    }
  }
  if (index == last_index) {
    strs->pop();
    while ((len(strs) > 0 and strs->at(-1) == nullptr)) {
      strs->pop();
    }
  }
  else {
    if (index < last_index) {
      strs->set(index, nullptr);
    }
    else {
      ;  // pass
    }
  }
  return error_code_e::OK;
}

bool BashArray_Equals(value::BashArray* lhs, value::BashArray* rhs) {
  int len_lhs;
  int len_rhs;
  StackRoot _root0(&lhs);
  StackRoot _root1(&rhs);

  len_lhs = len(lhs->strs);
  len_rhs = len(rhs->strs);
  if (len_lhs != len_rhs) {
    return false;
  }
  for (int i = 0; i < len_lhs; ++i) {
    if (!(str_equals(lhs->strs->at(i), rhs->strs->at(i)))) {
      return false;
    }
  }
  return true;
}

bool _BashArray_HasHoles(value::BashArray* array_val) {
  StackRoot _root0(&array_val);

  for (ListIter<BigStr*> it(array_val->strs); !it.Done(); it.Next()) {
    BigStr* s = it.Value();
    StackRoot _for(&s  );
    if (s == nullptr) {
      return true;
    }
  }
  return false;
}

BigStr* BashArray_ToStrForShellPrint(value::BashArray* array_val, BigStr* name) {
  List<BigStr*>* buff = nullptr;
  bool first;
  int i;
  StackRoot _root0(&array_val);
  StackRoot _root1(&name);
  StackRoot _root2(&buff);

  buff = Alloc<List<BigStr*>>();
  first = true;
  if (_BashArray_HasHoles(array_val)) {
    if (name != nullptr) {
      buff->append(S_zxb);
      i = 0;
      for (ListIter<BigStr*> it(array_val->strs); !it.Done(); it.Next(), ++i) {
        BigStr* element = it.Value();
        StackRoot _for(&element      );
        if (element != nullptr) {
          if (first) {
            buff->append(S_nbf);
            first = false;
          }
          buff->extend(NewList<BigStr*>(std::initializer_list<BigStr*>{S_yfw, name, S_Eax, str(i), S_nuz, j8_lite::MaybeShellEncode(element)}));
        }
      }
    }
    else {
      buff->append(S_ijB);
      i = 0;
      for (ListIter<BigStr*> it(array_val->strs); !it.Done(); it.Next(), ++i) {
        BigStr* element = it.Value();
        StackRoot _for(&element      );
        if (element != nullptr) {
          if (!first) {
            buff->append(S_yfw);
          }
          else {
            first = false;
            buff->extend(NewList<BigStr*>(std::initializer_list<BigStr*>{S_Eax, str(i), S_nuz, j8_lite::MaybeShellEncode(element)}));
          }
        }
      }
      buff->append(S_hxb);
    }
  }
  else {
    buff->append(S_ijB);
    for (ListIter<BigStr*> it(array_val->strs); !it.Done(); it.Next()) {
      BigStr* element = it.Value();
      StackRoot _for(&element    );
      if (!first) {
        buff->append(S_yfw);
      }
      else {
        first = false;
      }
      buff->append(j8_lite::MaybeShellEncode(element));
    }
    buff->append(S_hxb);
  }
  return S_Aoo->join(buff);
}

bool BashAssoc_IsEmpty(value::BashAssoc* assoc_val) {
  StackRoot _root0(&assoc_val);

  return len(assoc_val->d) == 0;
}

int BashAssoc_Count(value::BashAssoc* assoc_val) {
  StackRoot _root0(&assoc_val);

  return len(assoc_val->d);
}

Dict<BigStr*, BigStr*>* BashAssoc_GetDict(value::BashAssoc* assoc_val) {
  StackRoot _root0(&assoc_val);

  return assoc_val->d;
}

void BashAssoc_AppendDict(value::BashAssoc* assoc_val, Dict<BigStr*, BigStr*>* d) {
  StackRoot _root0(&assoc_val);
  StackRoot _root1(&d);

  for (DictIter<BigStr*, BigStr*> it(d); !it.Done(); it.Next()) {
    BigStr* key = it.Key();
    StackRoot _for(&key  );
    assoc_val->d->set(key, d->at(key));
  }
}

List<BigStr*>* BashAssoc_GetKeys(value::BashAssoc* assoc_val) {
  StackRoot _root0(&assoc_val);

  return assoc_val->d->keys();
}

List<BigStr*>* BashAssoc_GetValues(value::BashAssoc* assoc_val) {
  StackRoot _root0(&assoc_val);

  return assoc_val->d->values();
}

bool BashAssoc_HasElement(value::BashAssoc* assoc_val, BigStr* s) {
  StackRoot _root0(&assoc_val);
  StackRoot _root1(&s);

  return dict_contains(assoc_val->d, s);
}

BigStr* BashAssoc_GetElement(value::BashAssoc* assoc_val, BigStr* s) {
  StackRoot _root0(&assoc_val);
  StackRoot _root1(&s);

  return assoc_val->d->get(s);
}

void BashAssoc_SetElement(value::BashAssoc* assoc_val, BigStr* key, BigStr* s) {
  StackRoot _root0(&assoc_val);
  StackRoot _root1(&key);
  StackRoot _root2(&s);

  assoc_val->d->set(key, s);
}

void BashAssoc_UnsetElement(value::BashAssoc* assoc_val, BigStr* key) {
  StackRoot _root0(&assoc_val);
  StackRoot _root1(&key);

  mylib::dict_erase(assoc_val->d, key);
}

bool BashAssoc_Equals(value::BashAssoc* lhs, value::BashAssoc* rhs) {
  StackRoot _root0(&lhs);
  StackRoot _root1(&rhs);

  if (len(lhs->d) != len(rhs->d)) {
    return false;
  }
  for (DictIter<BigStr*, BigStr*> it(lhs->d); !it.Done(); it.Next()) {
    BigStr* k = it.Key();
    StackRoot _for(&k  );
    if ((!dict_contains(rhs->d, k) or !(str_equals(rhs->d->at(k), lhs->d->at(k))))) {
      return false;
    }
  }
  return true;
}

BigStr* BashAssoc_ToStrForShellPrint(value::BashAssoc* assoc_val) {
  List<BigStr*>* buff = nullptr;
  bool first;
  BigStr* key_quoted = nullptr;
  BigStr* value_quoted = nullptr;
  StackRoot _root0(&assoc_val);
  StackRoot _root1(&buff);
  StackRoot _root2(&key_quoted);
  StackRoot _root3(&value_quoted);

  buff = NewList<BigStr*>(std::initializer_list<BigStr*>{S_ijB});
  first = true;
  for (ListIter<BigStr*> it(sorted(assoc_val->d)); !it.Done(); it.Next()) {
    BigStr* key = it.Value();
    StackRoot _for(&key  );
    if (!first) {
      buff->append(S_yfw);
    }
    else {
      first = false;
    }
    key_quoted = j8_lite::ShellEncode(key);
    value_quoted = j8_lite::MaybeShellEncode(assoc_val->d->at(key));
    buff->extend(NewList<BigStr*>(std::initializer_list<BigStr*>{S_Eax, key_quoted, S_nuz, value_quoted}));
  }
  buff->append(S_hxb);
  return S_Aoo->join(buff);
}

bool SparseArray_IsEmpty(value::SparseArray* sparse_val) {
  StackRoot _root0(&sparse_val);

  return len(sparse_val->d) == 0;
}

int SparseArray_Count(value::SparseArray* sparse_val) {
  StackRoot _root0(&sparse_val);

  return len(sparse_val->d);
}

mops::BigInt SparseArray_Length(value::SparseArray* sparse_val) {
  StackRoot _root0(&sparse_val);

  return mops::Add(sparse_val->max_index, mops::ONE);
}

List<mops::BigInt>* SparseArray_GetKeys(value::SparseArray* sparse_val) {
  List<mops::BigInt>* keys = nullptr;
  StackRoot _root0(&sparse_val);
  StackRoot _root1(&keys);

  keys = sparse_val->d->keys();
  mylib::BigIntSort(keys);
  return keys;
}

List<BigStr*>* SparseArray_GetValues(value::SparseArray* sparse_val) {
  List<BigStr*>* values = nullptr;
  StackRoot _root0(&sparse_val);
  StackRoot _root1(&values);

  values = Alloc<List<BigStr*>>();
  for (ListIter<mops::BigInt> it(SparseArray_GetKeys(sparse_val)); !it.Done(); it.Next()) {
    mops::BigInt index = it.Value();
    values->append(sparse_val->d->at(index));
  }
  return values;
}

void SparseArray_AppendValues(value::SparseArray* sparse_val, List<BigStr*>* strs) {
  StackRoot _root0(&sparse_val);
  StackRoot _root1(&strs);

  for (ListIter<BigStr*> it(strs); !it.Done(); it.Next()) {
    BigStr* s = it.Value();
    StackRoot _for(&s  );
    sparse_val->max_index = mops::Add(sparse_val->max_index, mops::ONE);
    sparse_val->d->set(sparse_val->max_index, s);
  }
}

Tuple2<mops::BigInt, runtime_asdl::error_code_t> _SparseArray_CanonicalizeIndex(value::SparseArray* sparse_val, mops::BigInt index) {
  StackRoot _root0(&sparse_val);

  if (BigInt_Less(index, mops::ZERO)) {
    index = mops::Add(index, mops::Add(sparse_val->max_index, mops::ONE));
    if (BigInt_Less(index, mops::ZERO)) {
      return Tuple2<mops::BigInt, runtime_asdl::error_code_t>(mops::MINUS_ONE, error_code_e::IndexOutOfRange);
    }
  }
  return Tuple2<mops::BigInt, runtime_asdl::error_code_t>(index, error_code_e::OK);
}

Tuple2<bool, runtime_asdl::error_code_t> SparseArray_HasElement(value::SparseArray* sparse_val, mops::BigInt index) {
  runtime_asdl::error_code_t error_code;
  StackRoot _root0(&sparse_val);

  Tuple2<mops::BigInt, runtime_asdl::error_code_t> tup3 = _SparseArray_CanonicalizeIndex(sparse_val, index);
  index = tup3.at0();
  error_code = tup3.at1();
  if (error_code != error_code_e::OK) {
    return Tuple2<bool, runtime_asdl::error_code_t>(false, error_code);
  }
  return Tuple2<bool, runtime_asdl::error_code_t>(dict_contains(sparse_val->d, index), error_code_e::OK);
}

Tuple2<BigStr*, runtime_asdl::error_code_t> SparseArray_GetElement(value::SparseArray* sparse_val, mops::BigInt index) {
  runtime_asdl::error_code_t error_code;
  StackRoot _root0(&sparse_val);

  Tuple2<mops::BigInt, runtime_asdl::error_code_t> tup4 = _SparseArray_CanonicalizeIndex(sparse_val, index);
  index = tup4.at0();
  error_code = tup4.at1();
  if (error_code != error_code_e::OK) {
    return Tuple2<BigStr*, runtime_asdl::error_code_t>(nullptr, error_code);
  }
  return Tuple2<BigStr*, runtime_asdl::error_code_t>(sparse_val->d->get(index), error_code_e::OK);
}

runtime_asdl::error_code_t SparseArray_SetElement(value::SparseArray* sparse_val, mops::BigInt index, BigStr* s) {
  runtime_asdl::error_code_t error_code;
  StackRoot _root0(&sparse_val);
  StackRoot _root1(&s);

  Tuple2<mops::BigInt, runtime_asdl::error_code_t> tup5 = _SparseArray_CanonicalizeIndex(sparse_val, index);
  index = tup5.at0();
  error_code = tup5.at1();
  if (error_code != error_code_e::OK) {
    return error_code;
  }
  if (BigInt_Greater(index, sparse_val->max_index)) {
    sparse_val->max_index = index;
  }
  sparse_val->d->set(index, s);
  return error_code_e::OK;
}

runtime_asdl::error_code_t SparseArray_UnsetElement(value::SparseArray* sparse_val, mops::BigInt index) {
  runtime_asdl::error_code_t error_code;
  StackRoot _root0(&sparse_val);

  Tuple2<mops::BigInt, runtime_asdl::error_code_t> tup6 = _SparseArray_CanonicalizeIndex(sparse_val, index);
  index = tup6.at0();
  error_code = tup6.at1();
  if (error_code != error_code_e::OK) {
    return error_code;
  }
  mylib::dict_erase(sparse_val->d, index);
  if (mops::Equal(index, sparse_val->max_index)) {
    sparse_val->max_index = mops::MINUS_ONE;
    for (DictIter<mops::BigInt, BigStr*> it(sparse_val->d); !it.Done(); it.Next()) {
      mops::BigInt index = it.Key();
      if (mops::Greater(index, sparse_val->max_index)) {
        sparse_val->max_index = index;
      }
    }
  }
  return error_code_e::OK;
}

bool SparseArray_Equals(value::SparseArray* lhs, value::SparseArray* rhs) {
  int len_lhs;
  int len_rhs;
  StackRoot _root0(&lhs);
  StackRoot _root1(&rhs);

  len_lhs = len(lhs->d);
  len_rhs = len(rhs->d);
  if (len_lhs != len_rhs) {
    return false;
  }
  for (DictIter<mops::BigInt, BigStr*> it(lhs->d); !it.Done(); it.Next()) {
    mops::BigInt index = it.Key();
    if ((!dict_contains(rhs->d, index) or !(str_equals(rhs->d->at(index), lhs->d->at(index))))) {
      return false;
    }
  }
  return true;
}

BigStr* SparseArray_ToStrForShellPrint(value::SparseArray* sparse_val) {
  List<BigStr*>* body = nullptr;
  StackRoot _root0(&sparse_val);
  StackRoot _root1(&body);

  body = Alloc<List<BigStr*>>();
  for (ListIter<mops::BigInt> it(SparseArray_GetKeys(sparse_val)); !it.Done(); it.Next()) {
    mops::BigInt index = it.Value();
    if (len(body) > 0) {
      body->append(S_yfw);
    }
    body->extend(NewList<BigStr*>(std::initializer_list<BigStr*>{S_Eax, mops::ToStr(index), S_nuz, j8_lite::MaybeShellEncode(sparse_val->d->at(index))}));
  }
  return StrFormat("(%s)", S_Aoo->join(body));
}

}  // define namespace bash_impl

namespace error {  // define

using syntax_asdl::loc_e;
using syntax_asdl::loc_t;
using syntax_asdl::loc;
using value_asdl::value;
using value_asdl::value_t;
using value_asdl::value_str;

BigStr* _ValType(value_asdl::value_t* val) {
  StackRoot _root0(&val);

  return value_str(val->tag(), false);
}

_ErrorWithLocation::_ErrorWithLocation(BigStr* msg, syntax_asdl::loc_t* location) {
  this->msg = msg;
  if (location == nullptr) {
    this->location = loc::Missing;
  }
  else {
    this->location = location;
  }
}

bool _ErrorWithLocation::HasLocation() {
  return this->location->tag() != loc_e::Missing;
}

BigStr* _ErrorWithLocation::UserErrorString() {
  return this->msg;
}

Usage::Usage(BigStr* msg, syntax_asdl::loc_t* location) : ::error::_ErrorWithLocation(msg, location) {
}

Parse::Parse(BigStr* msg, syntax_asdl::loc_t* location) : ::error::_ErrorWithLocation(msg, location) {
}

WordFailure::WordFailure(BigStr* msg, syntax_asdl::loc_t* location) : ::error::_ErrorWithLocation(msg, location) {
}

FailGlob::FailGlob(BigStr* msg, syntax_asdl::loc_t* location) : ::error::WordFailure(str_concat(S_xho, msg), location) {
}

VarSubFailure::VarSubFailure(BigStr* msg, syntax_asdl::loc_t* location) : ::error::WordFailure(msg, location) {
}

RedirectEval::RedirectEval(BigStr* msg, syntax_asdl::loc_t* location) : ::error::_ErrorWithLocation(msg, location) {
}

FatalRuntime::FatalRuntime(int exit_status, BigStr* msg, syntax_asdl::loc_t* location) : ::error::_ErrorWithLocation(msg, location) {
  this->exit_status = exit_status;
}

int FatalRuntime::ExitStatus() {
  return this->exit_status;
}

Strict::Strict(BigStr* msg, syntax_asdl::loc_t* location) : ::error::FatalRuntime(1, msg, location) {
}

ErrExit::ErrExit(int exit_status, BigStr* msg, syntax_asdl::loc_t* location, bool show_code) : ::error::FatalRuntime(exit_status, msg, location) {
  this->show_code = show_code;
}

Expr::Expr(BigStr* msg, syntax_asdl::loc_t* location) : ::error::FatalRuntime(3, msg, location) {
}

Structured::Structured(int status, BigStr* msg, syntax_asdl::loc_t* location, Dict<BigStr*, value_asdl::value_t*>* properties) : ::error::FatalRuntime(status, msg, location) {
  this->properties = properties;
}

value::Dict* Structured::ToDict() {
  Dict<BigStr*, value_asdl::value_t*>* d = nullptr;
  StackRoot _root0(&d);

  d = Alloc<Dict<BigStr*, value_asdl::value_t*>>();
  if (this->properties != nullptr) {
    d->update(this->properties);
  }
  d->set(S_gFE, num::ToBig(this->ExitStatus()));
  d->set(S_pBg, Alloc<value::Str>(this->msg));
  return Alloc<value::Dict>(d);
}

AssertionErr::AssertionErr(BigStr* msg, syntax_asdl::loc_t* location) : ::error::Expr(msg, location) {
}

TypeErrVerbose::TypeErrVerbose(BigStr* msg, syntax_asdl::loc_t* location) : ::error::Expr(msg, location) {
}

TypeErr::TypeErr(value_asdl::value_t* actual_val, BigStr* msg, syntax_asdl::loc_t* location) : ::error::TypeErrVerbose(StrFormat("%s, got %s", msg, _ValType(actual_val)), location) {
}

Runtime::Runtime(BigStr* msg) {
  this->msg = msg;
}

BigStr* Runtime::UserErrorString() {
  return this->msg;
}

Decode::Decode(BigStr* msg, BigStr* s, int start_pos, int end_pos, int line_num) {
  this->msg = msg;
  this->s = s;
  this->start_pos = start_pos;
  this->end_pos = end_pos;
  this->line_num = line_num;
}

BigStr* Decode::Message() {
  int start;
  int end;
  BigStr* part = nullptr;
  StackRoot _root0(&part);

  start = max(0, (this->start_pos - 4));
  end = min(len(this->s), (this->end_pos + 4));
  part = this->s->slice(start, end);
  return str_concat(this->msg, StrFormat(" (line %d, offset %d-%d: %r)", this->line_num, this->start_pos, this->end_pos, part));
}

BigStr* Decode::__str__() {
  return this->Message();
}

Encode::Encode(BigStr* msg) {
  this->msg = msg;
}

BigStr* Encode::Message() {
  return this->msg;
}

[[noreturn]] void e_usage(BigStr* msg, syntax_asdl::loc_t* location) {
  StackRoot _root0(&msg);
  StackRoot _root1(&location);

  throw Alloc<Usage>(msg, location);
}

[[noreturn]] void e_strict(BigStr* msg, syntax_asdl::loc_t* location) {
  StackRoot _root0(&msg);
  StackRoot _root1(&location);

  throw Alloc<Strict>(msg, location);
}

[[noreturn]] void p_die(BigStr* msg, syntax_asdl::loc_t* location) {
  StackRoot _root0(&msg);
  StackRoot _root1(&location);

  throw Alloc<Parse>(msg, location);
}

[[noreturn]] void e_die(BigStr* msg, syntax_asdl::loc_t* location) {
  StackRoot _root0(&msg);
  StackRoot _root1(&location);

  throw Alloc<FatalRuntime>(1, msg, location);
}

[[noreturn]] void e_die_status(int status, BigStr* msg, syntax_asdl::loc_t* location) {
  StackRoot _root0(&msg);
  StackRoot _root1(&location);

  throw Alloc<FatalRuntime>(status, msg, location);
}

}  // define namespace error

namespace num {  // define

using value_asdl::value;

value::Int* ToBig(int i) {
  return Alloc<value::Int>(mops::IntWiden(i));
}

mops::BigInt Exponent(mops::BigInt x, mops::BigInt y) {
  int y_int;
  mops::BigInt result;
  y_int = mops::BigTruncate(y);
  result = mops::BigInt(1);
  for (int i = 0; i < y_int; ++i) {
    result = mops::Mul(result, x);
  }
  return result;
}

}  // define namespace num

namespace j8 {  // define

using id_kind_asdl::Id;
using id_kind_asdl::Id_t;
using id_kind_asdl::Id_str;
using nil8_asdl::nvalue;
using nil8_asdl::nvalue_t;
using runtime_asdl::error_code_e;
using value_asdl::value;
using value_asdl::value_e;
using value_asdl::value_t;
using value_asdl::value_str;
using value_asdl::Obj;

BigStr* ValType(value_asdl::value_t* val) {
  StackRoot _root0(&val);

  return value_str(val->tag(), false);
}

int ValueId(value_asdl::value_t* val) {
  StackRoot _root0(&val);

  switch (val->tag()) {
    case value_e::Null: 
    case value_e::Bool: 
    case value_e::Int: 
    case value_e::Float: 
    case value_e::Str: {
      return -1;
    }
      break;
    default: {
      return HeapValueId(val);
    }
  }
}

BigStr* ValueIdString(value_asdl::value_t* val) {
  int heap_id;
  StackRoot _root0(&val);

  heap_id = ValueId(val);
  if (heap_id == -1) {
    return S_Aoo;
  }
  else {
    return StrFormat(" 0x%s", mylib::hex_lower(heap_id));
  }
}

BigStr* Utf8Encode(int code) {
  int num_cont_bytes;
  List<int>* bytes_ = nullptr;
  int b;
  List<BigStr*>* tmp = nullptr;
  StackRoot _root0(&bytes_);
  StackRoot _root1(&tmp);

  num_cont_bytes = 0;
  if (code <= 127) {
    return chr((code & 127));
  }
  else {
    if (code <= 2047) {
      num_cont_bytes = 1;
    }
    else {
      if (code <= 65535) {
        num_cont_bytes = 2;
      }
      else {
        num_cont_bytes = 3;
      }
    }
  }
  bytes_ = Alloc<List<int>>();
  for (int _ = 0; _ < num_cont_bytes; ++_) {
    bytes_->append((128 | (code & 63)));
    code >>= 6;
  }
  b = ((30 << (6 - num_cont_bytes)) | (code & (63 >> num_cont_bytes)));
  bytes_->append(b);
  bytes_->reverse();
  tmp = Alloc<List<BigStr*>>();
  for (ListIter<int> it(bytes_); !it.Done(); it.Next()) {
    int b = it.Value();
    tmp->append(chr((b & 255)));
  }
  return S_Aoo->join(tmp);
}
int SHOW_CYCLES = (1 << 1);
int SHOW_NON_DATA = (1 << 2);
int LOSSY_JSON = (1 << 3);
int INF_NAN_ARE_NULL = (1 << 4);

void _Print(value_asdl::value_t* val, mylib::BufWriter* buf, int indent, int options) {
  j8::InstancePrinter* p = nullptr;
  StackRoot _root0(&val);
  StackRoot _root1(&buf);
  StackRoot _root2(&p);

  p = Alloc<InstancePrinter>(buf, indent, options);
  p->Print(val);
}

void PrintMessage(value_asdl::value_t* val, mylib::BufWriter* buf, int indent) {
  StackRoot _root0(&val);
  StackRoot _root1(&buf);

  _Print(val, buf, indent);
}

void PrintJsonMessage(value_asdl::value_t* val, mylib::BufWriter* buf, int indent) {
  StackRoot _root0(&val);
  StackRoot _root1(&buf);

  _Print(val, buf, indent, (LOSSY_JSON | INF_NAN_ARE_NULL));
}

void PrintLine(value_asdl::value_t* val, mylib::Writer* f) {
  mylib::BufWriter* buf = nullptr;
  StackRoot _root0(&val);
  StackRoot _root1(&f);
  StackRoot _root2(&buf);

  buf = Alloc<mylib::BufWriter>();
  _Print(val, buf, -1, (SHOW_CYCLES | SHOW_NON_DATA));
  f->write(buf->getvalue());
  f->write(S_nfs);
}

void EncodeString(BigStr* s, mylib::BufWriter* buf, bool unquoted_ok) {
  StackRoot _root0(&s);
  StackRoot _root1(&buf);

  if ((unquoted_ok and fastfunc::CanOmitQuotes(s))) {
    buf->write(s);
    return ;
  }
  _Print(Alloc<value::Str>(s), buf, -1);
}

BigStr* MaybeEncodeString(BigStr* s) {
  mylib::BufWriter* buf = nullptr;
  StackRoot _root0(&s);
  StackRoot _root1(&buf);

  buf = Alloc<mylib::BufWriter>();
  _Print(Alloc<value::Str>(s), buf, -1);
  return buf->getvalue();
}

BigStr* MaybeEncodeJsonString(BigStr* s) {
  mylib::BufWriter* buf = nullptr;
  StackRoot _root0(&s);
  StackRoot _root1(&buf);

  buf = Alloc<mylib::BufWriter>();
  _Print(Alloc<value::Str>(s), buf, -1, LOSSY_JSON);
  return buf->getvalue();
}

InstancePrinter::InstancePrinter(mylib::BufWriter* buf, int indent, int options) {
  this->buf = buf;
  this->indent = indent;
  this->options = options;
  this->visiting = Alloc<Dict<int, bool>>();
}

void InstancePrinter::_ItemIndent(int level) {
  if (this->indent == -1) {
    return ;
  }
  this->buf->write_spaces(((level + 1) * this->indent));
}

void InstancePrinter::_BracketIndent(int level) {
  if (this->indent == -1) {
    return ;
  }
  this->buf->write_spaces((level * this->indent));
}

void InstancePrinter::_MaybeNewline() {
  if (this->indent == -1) {
    return ;
  }
  this->buf->write(S_nfs);
}

void InstancePrinter::_MaybeSpace() {
  if (this->indent == -1) {
    return ;
  }
  this->buf->write(S_yfw);
}

void InstancePrinter::_PrintList(value::List* val, int level) {
  int i;
  StackRoot _root0(&val);

  if (len(val->items) == 0) {
    this->buf->write(S_xmu);
  }
  else {
    this->buf->write(S_Eax);
    this->_MaybeNewline();
    i = 0;
    for (ListIter<value_asdl::value_t*> it(val->items); !it.Done(); it.Next(), ++i) {
      value_asdl::value_t* item = it.Value();
      StackRoot _for(&item    );
      if (i != 0) {
        this->buf->write(S_Cce);
        this->_MaybeNewline();
      }
      this->_ItemIndent(level);
      this->Print(item, (level + 1));
    }
    this->_MaybeNewline();
    this->_BracketIndent(level);
    this->buf->write(S_pcD);
  }
}

void InstancePrinter::_PrintMapping(Dict<BigStr*, value_asdl::value_t*>* d, BigStr* left, BigStr* right, int level) {
  int i;
  StackRoot _root0(&d);
  StackRoot _root1(&left);
  StackRoot _root2(&right);

  if (len(d) == 0) {
    this->buf->write(left);
    this->buf->write(right);
  }
  else {
    this->buf->write(left);
    this->_MaybeNewline();
    i = 0;
    for (DictIter<BigStr*, value_asdl::value_t*> it(d); !it.Done(); it.Next()) {
      BigStr* k = it.Key();
      value_asdl::value_t* v = it.Value();
      if (i != 0) {
        this->buf->write(S_Cce);
        this->_MaybeNewline();
      }
      this->_ItemIndent(level);
      pyj8::WriteString(k, this->options, this->buf);
      this->buf->write(S_fyj);
      this->_MaybeSpace();
      this->Print(v, (level + 1));
      i += 1;
    }
    this->_MaybeNewline();
    this->_BracketIndent(level);
    this->buf->write(right);
  }
}

void InstancePrinter::_PrintDict(value::Dict* val, int level) {
  StackRoot _root0(&val);

  this->_PrintMapping(val->d, S_ato, S_cEn, level);
}

void InstancePrinter::_PrintObj(value_asdl::Obj* val, int level) {
  StackRoot _root0(&val);

  this->_PrintMapping(val->d, S_ijB, S_hxb, level);
  if (val->prototype) {
    this->buf->write(S_dtA);
    this->_PrintObj(val->prototype, level);
  }
}

void InstancePrinter::_PrintBashPrefix(BigStr* type_str, int level) {
  StackRoot _root0(&type_str);

  this->buf->write(S_ato);
  this->_MaybeNewline();
  this->_ItemIndent(level);
  this->buf->write(S_EDa);
  this->_MaybeSpace();
  this->buf->write(type_str);
  this->_MaybeNewline();
  this->_ItemIndent(level);
  this->buf->write(S_eqo);
  this->_MaybeSpace();
}

void InstancePrinter::_PrintBashSuffix(int level) {
  this->_MaybeNewline();
  this->_BracketIndent(level);
  this->buf->write(S_cEn);
}

void InstancePrinter::_PrintSparseArray(value::SparseArray* val, int level) {
  int i;
  BigStr* v = nullptr;
  runtime_asdl::error_code_t error_code;
  StackRoot _root0(&val);
  StackRoot _root1(&v);

  this->_PrintBashPrefix(S_vBu, level);
  if (bash_impl::SparseArray_Count(val) == 0) {
    this->buf->write(S_Fni);
  }
  else {
    this->buf->write(S_ato);
    this->_MaybeNewline();
    i = 0;
    for (ListIter<mops::BigInt> it(bash_impl::SparseArray_GetKeys(val)); !it.Done(); it.Next()) {
      mops::BigInt k = it.Value();
      if (i != 0) {
        this->buf->write(S_Cce);
        this->_MaybeNewline();
      }
      this->_ItemIndent((level + 1));
      pyj8::WriteString(mops::ToStr(k), this->options, this->buf);
      this->buf->write(S_fyj);
      this->_MaybeSpace();
      Tuple2<BigStr*, runtime_asdl::error_code_t> tup0 = bash_impl::SparseArray_GetElement(val, k);
      v = tup0.at0();
      error_code = tup0.at1();
      pyj8::WriteString(v, this->options, this->buf);
      i += 1;
    }
    this->_MaybeNewline();
    this->_BracketIndent((level + 1));
    this->buf->write(S_cEn);
  }
  this->_PrintBashSuffix(level);
}

void InstancePrinter::_PrintBashArray(value::BashArray* val, int level) {
  bool first;
  int i;
  StackRoot _root0(&val);

  this->_PrintBashPrefix(S_xbi, level);
  if (bash_impl::BashArray_Count(val) == 0) {
    this->buf->write(S_Fni);
  }
  else {
    this->buf->write(S_ato);
    this->_MaybeNewline();
    first = true;
    i = 0;
    for (ListIter<BigStr*> it(bash_impl::BashArray_GetValues(val)); !it.Done(); it.Next(), ++i) {
      BigStr* s = it.Value();
      StackRoot _for(&s    );
      if (s == nullptr) {
        continue;
      }
      if (!first) {
        this->buf->write(S_Cce);
        this->_MaybeNewline();
      }
      this->_ItemIndent((level + 1));
      pyj8::WriteString(str(i), this->options, this->buf);
      this->buf->write(S_fyj);
      this->_MaybeSpace();
      pyj8::WriteString(s, this->options, this->buf);
      first = false;
    }
    this->_MaybeNewline();
    this->_BracketIndent((level + 1));
    this->buf->write(S_cEn);
  }
  this->_PrintBashSuffix(level);
}

void InstancePrinter::_PrintBashAssoc(value::BashAssoc* val, int level) {
  int i;
  StackRoot _root0(&val);

  this->_PrintBashPrefix(S_ojw, level);
  if (bash_impl::BashAssoc_Count(val) == 0) {
    this->buf->write(S_Fni);
  }
  else {
    this->buf->write(S_ato);
    this->_MaybeNewline();
    i = 0;
    for (DictIter<BigStr*, BigStr*> it(bash_impl::BashAssoc_GetDict(val)); !it.Done(); it.Next()) {
      BigStr* k2 = it.Key();
      BigStr* v2 = it.Value();
      if (i != 0) {
        this->buf->write(S_Cce);
        this->_MaybeNewline();
      }
      this->_ItemIndent((level + 1));
      pyj8::WriteString(k2, this->options, this->buf);
      this->buf->write(S_fyj);
      this->_MaybeSpace();
      pyj8::WriteString(v2, this->options, this->buf);
      i += 1;
    }
    this->_MaybeNewline();
    this->_BracketIndent((level + 1));
    this->buf->write(S_cEn);
  }
  this->_PrintBashSuffix(level);
}

void InstancePrinter::Print(value_asdl::value_t* val, int level) {
  value_asdl::value_t* UP_val = nullptr;
  double fl;
  BigStr* s = nullptr;
  int heap_id;
  BigStr* ysh_type = nullptr;
  StackRoot _root0(&val);
  StackRoot _root1(&UP_val);
  StackRoot _root2(&s);
  StackRoot _root3(&ysh_type);

  UP_val = val;
  switch (val->tag()) {
    case value_e::Null: {
      this->buf->write(S_lbA);
    }
      break;
    case value_e::Bool: {
      value::Bool* val = static_cast<value::Bool*>(UP_val);
      this->buf->write(val->b ? S_FsF : S_Ctn);
    }
      break;
    case value_e::Int: {
      value::Int* val = static_cast<value::Int*>(UP_val);
      this->buf->write(mops::ToStr(val->i));
    }
      break;
    case value_e::Float: {
      value::Float* val = static_cast<value::Float*>(UP_val);
      fl = val->f;
      if (math::isinf(fl)) {
        if ((this->options & INF_NAN_ARE_NULL)) {
          s = S_lbA;
        }
        else {
          s = S_BvB;
          if (fl < 0) {
            s = str_concat(S_Bjq, s);
          }
        }
      }
      else {
        if (math::isnan(fl)) {
          if ((this->options & INF_NAN_ARE_NULL)) {
            s = S_lbA;
          }
          else {
            s = S_ywk;
          }
        }
        else {
          s = str(fl);
        }
      }
      this->buf->write(s);
    }
      break;
    case value_e::Str: {
      value::Str* val = static_cast<value::Str*>(UP_val);
      pyj8::WriteString(val->s, this->options, this->buf);
    }
      break;
    case value_e::List: {
      value::List* val = static_cast<value::List*>(UP_val);
      heap_id = HeapValueId(val);
      if (this->visiting->get(heap_id, false)) {
        if ((this->options & SHOW_CYCLES)) {
          this->buf->write(S_Aek);
          return ;
        }
        else {
          throw Alloc<error::Encode>(StrFormat("Can't encode List%s in object cycle", ValueIdString(val)));
        }
      }
      else {
        this->visiting->set(heap_id, true);
        this->_PrintList(val, level);
        this->visiting->set(heap_id, false);
      }
    }
      break;
    case value_e::Dict: {
      value::Dict* val = static_cast<value::Dict*>(UP_val);
      heap_id = HeapValueId(val);
      if (this->visiting->get(heap_id, false)) {
        if ((this->options & SHOW_CYCLES)) {
          this->buf->write(S_qnA);
          return ;
        }
        else {
          throw Alloc<error::Encode>(StrFormat("Can't encode Dict%s in object cycle", ValueIdString(val)));
        }
      }
      else {
        this->visiting->set(heap_id, true);
        this->_PrintDict(val, level);
        this->visiting->set(heap_id, false);
      }
    }
      break;
    case value_e::Obj: {
      Obj* val = static_cast<Obj*>(UP_val);
      if (!(this->options & SHOW_NON_DATA)) {
        throw Alloc<error::Encode>(S_kdC);
      }
      heap_id = HeapValueId(val);
      if (this->visiting->get(heap_id, false)) {
        if ((this->options & SHOW_CYCLES)) {
          this->buf->write(S_Ehr);
          return ;
        }
        else {
          throw Alloc<error::Encode>(StrFormat("Can't encode Obj%s in object cycle", ValueIdString(val)));
        }
      }
      else {
        this->visiting->set(heap_id, true);
        this->_PrintObj(val, level);
        this->visiting->set(heap_id, false);
      }
    }
      break;
    case value_e::SparseArray: {
      value::SparseArray* val = static_cast<value::SparseArray*>(UP_val);
      this->_PrintSparseArray(val, level);
    }
      break;
    case value_e::BashArray: {
      value::BashArray* val = static_cast<value::BashArray*>(UP_val);
      this->_PrintBashArray(val, level);
    }
      break;
    case value_e::BashAssoc: {
      value::BashAssoc* val = static_cast<value::BashAssoc*>(UP_val);
      this->_PrintBashAssoc(val, level);
    }
      break;
    default: {
      ;  // pass
      if ((this->options & SHOW_NON_DATA)) {
        ysh_type = ValType(val);
        this->buf->write(StrFormat("<%s>", ysh_type));
      }
      else {
        throw Alloc<error::Encode>(StrFormat("Can't serialize object of type %s", ValType(val)));
      }
    }
  }
}

LexerDecoder::LexerDecoder(BigStr* s, bool is_j8, BigStr* lang_str) {
  this->s = s;
  this->is_j8 = is_j8;
  this->lang_str = lang_str;
  this->pos = 0;
  this->cur_line_num = 1;
  this->decoded = Alloc<mylib::BufWriter>();
}

error::Decode* LexerDecoder::_Error(BigStr* msg, int end_pos) {
  StackRoot _root0(&msg);

  return Alloc<error::Decode>(msg, this->s, this->pos, end_pos, this->cur_line_num);
}

Tuple3<int, int, BigStr*> LexerDecoder::Next() {
  int tok_id;
  int end_pos;
  Tuple2<int, int> tup1 = match::MatchJ8Token(this->s, this->pos);
  tok_id = tup1.at0();
  end_pos = tup1.at1();
  if (!this->is_j8) {
    if ((tok_id == Id::Left_BSingleQuote || tok_id == Id::Left_USingleQuote)) {
      throw this->_Error(S_hBp, end_pos);
    }
    if (tok_id == Id::Ignored_Comment) {
      throw this->_Error(S_wac, end_pos);
    }
  }
  if ((tok_id == Id::Left_DoubleQuote || tok_id == Id::Left_BSingleQuote || tok_id == Id::Left_USingleQuote)) {
    return this->_DecodeString(tok_id, end_pos);
  }
  if (tok_id == Id::Left_JDoubleQuote) {
    if (this->is_j8) {
      return this->_DecodeString(tok_id, end_pos);
    }
    else {
      throw this->_Error(S_Ahj, end_pos);
    }
  }
  if (tok_id == Id::Ignored_Newline) {
    this->cur_line_num += 1;
  }
  this->pos = end_pos;
  return Tuple3<int, int, BigStr*>(tok_id, end_pos, nullptr);
}

Tuple3<int, int, BigStr*> LexerDecoder::NextForLines() {
  int tok_id;
  int end_pos;
  Tuple2<int, int> tup2 = match::MatchJ8LinesToken(this->s, this->pos);
  tok_id = tup2.at0();
  end_pos = tup2.at1();
  if ((tok_id == Id::Left_DoubleQuote || tok_id == Id::Left_JDoubleQuote || tok_id == Id::Left_BSingleQuote || tok_id == Id::Left_USingleQuote)) {
    return this->_DecodeString(tok_id, end_pos);
  }
  if ((tok_id == Id::Lit_Chars and !pyj8::PartIsUtf8(this->s, this->pos, end_pos))) {
    throw this->_Error(StrFormat("Invalid UTF-8 in %s string literal", this->lang_str), end_pos);
  }
  if (tok_id == Id::Char_AsciiControl) {
    throw this->_Error(S_ApC, end_pos);
  }
  if (tok_id == Id::J8_Newline) {
    this->cur_line_num += 1;
  }
  this->pos = end_pos;
  return Tuple3<int, int, BigStr*>(tok_id, end_pos, nullptr);
}

Tuple3<int, int, BigStr*> LexerDecoder::_DecodeString(int left_id, int str_pos) {
  int tok_id;
  int str_end;
  BigStr* s = nullptr;
  BigStr* part = nullptr;
  BigStr* ch = nullptr;
  BigStr* h = nullptr;
  int i;
  BigStr* h1 = nullptr;
  BigStr* h2 = nullptr;
  int i1;
  int i2;
  int code_point;
  StackRoot _root0(&s);
  StackRoot _root1(&part);
  StackRoot _root2(&ch);
  StackRoot _root3(&h);
  StackRoot _root4(&h1);
  StackRoot _root5(&h2);

  while (true) {
    if ((left_id == Id::Left_DoubleQuote || left_id == Id::Left_JDoubleQuote)) {
      Tuple2<int, int> tup3 = match::MatchJsonStrToken(this->s, str_pos);
      tok_id = tup3.at0();
      str_end = tup3.at1();
    }
    else {
      Tuple2<int, int> tup4 = match::MatchJ8StrToken(this->s, str_pos);
      tok_id = tup4.at0();
      str_end = tup4.at1();
    }
    if (tok_id == Id::Eol_Tok) {
      throw this->_Error(StrFormat("Unexpected EOF while lexing %s string", this->lang_str), str_end);
    }
    if (tok_id == Id::Unknown_Backslash) {
      throw this->_Error(StrFormat("Bad backslash escape in %s string", this->lang_str), str_end);
    }
    if (tok_id == Id::Char_AsciiControl) {
      throw this->_Error(StrFormat("%s strings can't have unescaped ASCII control chars", this->lang_str), str_end);
    }
    if ((tok_id == Id::Right_SingleQuote || tok_id == Id::Right_DoubleQuote)) {
      this->pos = str_end;
      s = this->decoded->getvalue();
      this->decoded->clear();
      return Tuple3<int, int, BigStr*>(Id::J8_String, str_end, s);
    }
    if (tok_id == Id::Lit_Chars) {
      part = this->s->slice(str_pos, str_end);
      if (!pyj8::PartIsUtf8(this->s, str_pos, str_end)) {
        throw this->_Error(StrFormat("Invalid UTF-8 in %s string literal", this->lang_str), str_end);
      }
    }
    else {
      if (tok_id == Id::Char_OneChar) {
        ch = this->s->at((str_pos + 1));
        part = consts::LookupCharC(ch);
      }
      else {
        if (tok_id == Id::Char_UBraced) {
          h = this->s->slice((str_pos + 3), (str_end - 1));
          i = to_int(h, 16);
          if (i > 1114111) {
            throw this->_Error(S_egA, str_end);
          }
          if ((55296 <= i and i < 57344)) {
            throw this->_Error(StrFormat("\\u{%s} escape is illegal because it's in the surrogate range", h), str_end);
          }
          part = Utf8Encode(i);
        }
        else {
          if (tok_id == Id::Char_YHex) {
            h = this->s->slice((str_pos + 2), str_end);
            if (left_id != Id::Left_BSingleQuote) {
              throw this->_Error(StrFormat("\\y%s escapes not allowed in u'' strings", h), str_end);
            }
            i = to_int(h, 16);
            part = chr(i);
          }
          else {
            if (tok_id == Id::Char_SurrogatePair) {
              h1 = this->s->slice((str_pos + 2), (str_pos + 6));
              h2 = this->s->slice((str_pos + 8), (str_pos + 12));
              i1 = (to_int(h1, 16) - 55296);
              i2 = (to_int(h2, 16) - 56320);
              code_point = ((65536 + (i1 << 10)) + i2);
              part = Utf8Encode(code_point);
            }
            else {
              if (tok_id == Id::Char_Unicode4) {
                h = this->s->slice((str_pos + 2), str_end);
                i = to_int(h, 16);
                part = Utf8Encode(i);
              }
              else {
                assert(0);  // AssertionError
              }
            }
          }
        }
      }
    }
    this->decoded->write(part);
    str_pos = str_end;
  }
}

_Parser::_Parser(BigStr* s, bool is_j8) {
  this->s = s;
  this->is_j8 = is_j8;
  this->lang_str = is_j8 ? S_Czs : S_dqg;
  this->lexer = Alloc<LexerDecoder>(s, is_j8, this->lang_str);
  this->tok_id = Id::Undefined_Tok;
  this->start_pos = 0;
  this->end_pos = 0;
  this->decoded = S_Aoo;
}

void _Parser::_Next() {
  while (true) {
    this->start_pos = this->end_pos;
    Tuple3<int, int, BigStr*> tup5 = this->lexer->Next();
    this->tok_id = tup5.at0();
    this->end_pos = tup5.at1();
    this->decoded = tup5.at2();
    if ((this->tok_id != Id::Ignored_Space && this->tok_id != Id::Ignored_Newline && this->tok_id != Id::Ignored_Comment)) {
      break;
    }
  }
}

void _Parser::_Eat(int tok_id) {
  if (this->tok_id != tok_id) {
    throw this->_ParseError(StrFormat("Expected %s, got %s", Id_str(tok_id), Id_str(this->tok_id)));
  }
  this->_Next();
}

void _Parser::_NextForLines() {
  this->start_pos = this->end_pos;
  Tuple3<int, int, BigStr*> tup6 = this->lexer->NextForLines();
  this->tok_id = tup6.at0();
  this->end_pos = tup6.at1();
  this->decoded = tup6.at2();
}

error::Decode* _Parser::_ParseError(BigStr* msg) {
  StackRoot _root0(&msg);

  return Alloc<error::Decode>(msg, this->s, this->start_pos, this->end_pos, this->lexer->cur_line_num);
}

Parser::Parser(BigStr* s, bool is_j8) : ::j8::_Parser(s, is_j8) {
}

Tuple2<BigStr*, value_asdl::value_t*> Parser::_ParsePair() {
  BigStr* k = nullptr;
  value_asdl::value_t* v = nullptr;
  StackRoot _root0(&k);
  StackRoot _root1(&v);

  k = this->decoded;
  this->_Eat(Id::J8_String);
  this->_Eat(Id::J8_Colon);
  v = this->_ParseValue();
  return Tuple2<BigStr*, value_asdl::value_t*>(k, v);
}

value_asdl::value_t* Parser::_ParseDict() {
  Dict<BigStr*, value_asdl::value_t*>* d = nullptr;
  BigStr* k = nullptr;
  value_asdl::value_t* v = nullptr;
  StackRoot _root0(&d);
  StackRoot _root1(&k);
  StackRoot _root2(&v);

  d = Alloc<Dict<BigStr*, value_asdl::value_t*>>();
  this->_Next();
  if (this->tok_id == Id::J8_RBrace) {
    this->_Next();
    return Alloc<value::Dict>(d);
  }
  Tuple2<BigStr*, value_asdl::value_t*> tup7 = this->_ParsePair();
  k = tup7.at0();
  v = tup7.at1();
  d->set(k, v);
  while (this->tok_id == Id::J8_Comma) {
    this->_Next();
    Tuple2<BigStr*, value_asdl::value_t*> tup8 = this->_ParsePair();
    k = tup8.at0();
    v = tup8.at1();
    d->set(k, v);
  }
  this->_Eat(Id::J8_RBrace);
  return Alloc<value::Dict>(d);
}

value_asdl::value_t* Parser::_ParseList() {
  List<value_asdl::value_t*>* items = nullptr;
  StackRoot _root0(&items);

  items = Alloc<List<value_asdl::value_t*>>();
  this->_Next();
  if (this->tok_id == Id::J8_RBracket) {
    this->_Next();
    return Alloc<value::List>(items);
  }
  items->append(this->_ParseValue());
  while (this->tok_id == Id::J8_Comma) {
    this->_Next();
    items->append(this->_ParseValue());
  }
  this->_Eat(Id::J8_RBracket);
  return Alloc<value::List>(items);
}

value_asdl::value_t* Parser::_ParseValue() {
  value::Bool* b = nullptr;
  BigStr* part = nullptr;
  bool ok;
  mops::BigInt big;
  value::Str* str_val = nullptr;
  StackRoot _root0(&b);
  StackRoot _root1(&part);
  StackRoot _root2(&str_val);

  if (this->tok_id == Id::J8_LBrace) {
    return this->_ParseDict();
  }
  else {
    if (this->tok_id == Id::J8_LBracket) {
      return this->_ParseList();
    }
    else {
      if (this->tok_id == Id::J8_Null) {
        this->_Next();
        return value::Null;
      }
      else {
        if (this->tok_id == Id::J8_Bool) {
          b = Alloc<value::Bool>(str_equals(this->s->at(this->start_pos), S_omF));
          this->_Next();
          return b;
        }
        else {
          if (this->tok_id == Id::J8_Int) {
            part = this->s->slice(this->start_pos, this->end_pos);
            this->_Next();
            Tuple2<bool, mops::BigInt> tup9 = mops::FromStr2(part);
            ok = tup9.at0();
            big = tup9.at1();
            if (!ok) {
              throw this->_ParseError(S_zDl);
            }
            return Alloc<value::Int>(big);
          }
          else {
            if (this->tok_id == Id::J8_Float) {
              part = this->s->slice(this->start_pos, this->end_pos);
              this->_Next();
              return Alloc<value::Float>(to_float(part));
            }
            else {
              if (this->tok_id == Id::J8_String) {
                str_val = Alloc<value::Str>(this->decoded);
                this->_Next();
                return str_val;
              }
              else {
                if (this->tok_id == Id::Eol_Tok) {
                  throw this->_ParseError(StrFormat("Unexpected EOF while parsing %s", this->lang_str));
                }
                else {
                  throw this->_ParseError(StrFormat("Invalid token while parsing %s: %s", this->lang_str, Id_str(this->tok_id)));
                }
              }
            }
          }
        }
      }
    }
  }
}

value_asdl::value_t* Parser::ParseValue() {
  value_asdl::value_t* obj = nullptr;
  int n;
  int extra;
  StackRoot _root0(&obj);

  this->_Next();
  obj = this->_ParseValue();
  n = len(this->s);
  if (this->start_pos != n) {
    extra = (n - this->start_pos);
    throw this->_ParseError(StrFormat("Got %d bytes of unexpected trailing input", extra));
  }
  return obj;
}

Nil8Parser::Nil8Parser(BigStr* s, bool is_j8) : ::j8::_Parser(s, is_j8) {
}

nil8_asdl::nvalue_t* Nil8Parser::_ParseRecord() {
  List<nil8_asdl::nvalue_t*>* items = nullptr;
  StackRoot _root0(&items);

  items = Alloc<List<nil8_asdl::nvalue_t*>>();
  this->_Next();
  if (this->tok_id == Id::J8_RParen) {
    this->_Next();
    return Alloc<nvalue::List>(items);
  }
  while (this->tok_id != Id::J8_RParen) {
    items->append(this->_ParseNil8());
  }
  this->_Eat(Id::J8_RParen);
  return Alloc<nvalue::List>(items);
}

nil8_asdl::nvalue_t* Nil8Parser::_ParseList8() {
  List<nil8_asdl::nvalue_t*>* items = nullptr;
  StackRoot _root0(&items);

  items = Alloc<List<nil8_asdl::nvalue_t*>>();
  this->_Next();
  if (this->tok_id == Id::J8_RBracket) {
    this->_Next();
    return Alloc<nvalue::List>(items);
  }
  while (this->tok_id != Id::J8_RBracket) {
    items->append(this->_ParseNil8());
  }
  this->_Eat(Id::J8_RBracket);
  return Alloc<nvalue::List>(items);
}

nil8_asdl::nvalue_t* Nil8Parser::_ParseNil8() {
  nil8_asdl::nvalue_t* obj = nullptr;
  nvalue::Bool* b = nullptr;
  BigStr* part = nullptr;
  nvalue::Str* str_val = nullptr;
  nvalue::Symbol* op = nullptr;
  nil8_asdl::nvalue_t* operand2 = nullptr;
  nil8_asdl::nvalue_t* infix = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&b);
  StackRoot _root2(&part);
  StackRoot _root3(&str_val);
  StackRoot _root4(&op);
  StackRoot _root5(&operand2);
  StackRoot _root6(&infix);

  if (this->tok_id == Id::J8_LParen) {
    obj = this->_ParseRecord();
  }
  else {
    if (this->tok_id == Id::J8_LBracket) {
      obj = this->_ParseList8();
    }
    else {
      if (this->tok_id == Id::J8_Null) {
        this->_Next();
        obj = nvalue::Null;
      }
      else {
        if (this->tok_id == Id::J8_Bool) {
          b = Alloc<nvalue::Bool>(str_equals(this->s->at(this->start_pos), S_omF));
          this->_Next();
          obj = b;
        }
        else {
          if (this->tok_id == Id::J8_Int) {
            part = this->s->slice(this->start_pos, this->end_pos);
            this->_Next();
            obj = Alloc<nvalue::Int>(to_int(part));
          }
          else {
            if (this->tok_id == Id::J8_Float) {
              part = this->s->slice(this->start_pos, this->end_pos);
              this->_Next();
              obj = Alloc<nvalue::Float>(to_float(part));
            }
            else {
              if (this->tok_id == Id::J8_String) {
                str_val = Alloc<nvalue::Str>(this->decoded);
                this->_Next();
                obj = str_val;
              }
              else {
                if ((this->tok_id == Id::J8_Identifier || this->tok_id == Id::J8_Operator || this->tok_id == Id::J8_Colon || this->tok_id == Id::J8_Comma)) {
                  part = this->s->slice(this->start_pos, this->end_pos);
                  this->_Next();
                  obj = Alloc<nvalue::Symbol>(part);
                }
                else {
                  if (this->tok_id == Id::Eol_Tok) {
                    throw this->_ParseError(StrFormat("Unexpected EOF while parsing %s", this->lang_str));
                  }
                  else {
                    throw this->_ParseError(StrFormat("Invalid token while parsing %s: %s", this->lang_str, Id_str(this->tok_id)));
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  if ((this->tok_id == Id::J8_Operator || this->tok_id == Id::J8_Colon || this->tok_id == Id::J8_Comma)) {
    part = this->s->slice(this->start_pos, this->end_pos);
    op = Alloc<nvalue::Symbol>(part);
    this->_Next();
    operand2 = this->_ParseNil8();
    infix = Alloc<nvalue::List>(NewList<nil8_asdl::nvalue_t*>(std::initializer_list<nil8_asdl::nvalue_t*>{op, obj, operand2}));
    return infix;
  }
  return obj;
}

nil8_asdl::nvalue_t* Nil8Parser::ParseNil8() {
  nil8_asdl::nvalue_t* obj = nullptr;
  StackRoot _root0(&obj);

  this->_Next();
  obj = this->_ParseNil8();
  if (this->tok_id != Id::Eol_Tok) {
    throw this->_ParseError(S_oDA);
  }
  return obj;
}

J8LinesParser::J8LinesParser(BigStr* s) : ::j8::_Parser(s, true) {
}

void J8LinesParser::_Show(BigStr* s) {
  StackRoot _root0(&s);

  mylib::print_stderr(StrFormat("%s tok_id %s %d-%d", s, Id_str(this->tok_id), this->start_pos, this->end_pos));
}

void J8LinesParser::_ParseLine(List<BigStr*>* out) {
  int string_start;
  int prev_id;
  int prev_start;
  int string_end;
  StackRoot _root0(&out);

  if (this->tok_id == Id::WS_Space) {
    this->_NextForLines();
  }
  if ((this->tok_id == Id::J8_Newline || this->tok_id == Id::Eol_Tok)) {
    this->_NextForLines();
    return ;
  }
  if (this->tok_id == Id::J8_String) {
    out->append(this->decoded);
    this->_NextForLines();
    if (this->tok_id == Id::WS_Space) {
      this->_NextForLines();
    }
    if ((this->tok_id != Id::J8_Newline && this->tok_id != Id::Eol_Tok)) {
      throw this->_ParseError(StrFormat("Unexpected text after J8 Line (%s)", Id_str(this->tok_id)));
    }
    this->_NextForLines();
    return ;
  }
  if (this->tok_id == Id::Lit_Chars) {
    string_start = this->start_pos;
    while (true) {
      prev_id = this->tok_id;
      prev_start = this->start_pos;
      this->_NextForLines();
      if ((this->tok_id == Id::J8_Newline || this->tok_id == Id::Eol_Tok)) {
        break;
      }
    }
    if (prev_id == Id::WS_Space) {
      string_end = prev_start;
    }
    else {
      string_end = this->start_pos;
    }
    out->append(this->s->slice(string_start, string_end));
    this->_NextForLines();
    return ;
  }
  assert(0);  // AssertionError
}

List<BigStr*>* J8LinesParser::Parse() {
  List<BigStr*>* lines = nullptr;
  StackRoot _root0(&lines);

  this->_NextForLines();
  lines = Alloc<List<BigStr*>>();
  while (this->tok_id != Id::Eol_Tok) {
    this->_ParseLine(lines);
  }
  if (this->tok_id != Id::Eol_Tok) {
    throw this->_ParseError(S_mfF);
  }
  return lines;
}

List<BigStr*>* SplitJ8Lines(BigStr* s) {
  j8::J8LinesParser* p = nullptr;
  StackRoot _root0(&s);
  StackRoot _root1(&p);

  p = Alloc<J8LinesParser>(s);
  return p->Parse();
}

}  // define namespace j8

namespace j8_lite {  // define


BigStr* EncodeString(BigStr* s, bool unquoted_ok) {
  StackRoot _root0(&s);

  if ((unquoted_ok and fastfunc::CanOmitQuotes(s))) {
    return s;
  }
  return fastfunc::J8EncodeString(s, 1);
}

BigStr* YshEncodeString(BigStr* s) {
  StackRoot _root0(&s);

  return fastfunc::ShellEncodeString(s, 1);
}

BigStr* MaybeShellEncode(BigStr* s) {
  StackRoot _root0(&s);

  if (fastfunc::CanOmitQuotes(s)) {
    return s;
  }
  return fastfunc::ShellEncodeString(s, 0);
}

BigStr* ShellEncode(BigStr* s) {
  StackRoot _root0(&s);

  return fastfunc::ShellEncodeString(s, 0);
}

BigStr* YshEncode(BigStr* s, bool unquoted_ok) {
  StackRoot _root0(&s);

  if ((unquoted_ok and fastfunc::CanOmitQuotes(s))) {
    return s;
  }
  return fastfunc::ShellEncodeString(s, 1);
}

}  // define namespace j8_lite

namespace ansi {  // define

BigStr* RESET = S_yfk;
BigStr* BOLD = S_aaF;
BigStr* UNDERLINE = S_sCc;
BigStr* REVERSE = S_woy;
BigStr* RED = S_sqm;
BigStr* GREEN = S_eda;
BigStr* YELLOW = S_ysf;
BigStr* BLUE = S_osl;
BigStr* MAGENTA = S_vie;
BigStr* CYAN = S_mmi;
BigStr* WHITE = S_rpo;

}  // define namespace ansi

namespace pp_hnode {  // define

using hnode_asdl::hnode;
using hnode_asdl::hnode_e;
using hnode_asdl::hnode_t;
using hnode_asdl::Field;
using hnode_asdl::color_e;
using pretty_asdl::doc;
using pretty_asdl::MeasuredDoc;
using pretty_asdl::Measure;
using pretty::_Break;
using pretty::_Concat;
using pretty::_Flat;
using pretty::_Group;
using pretty::_IfFlat;
using pretty::_Indent;
using pretty::_EmptyMeasure;
using pretty::AsciiText;

BaseEncoder::BaseEncoder() {
  this->indent = 4;
  this->use_styles = true;
  this->max_tabular_width = 22;
  this->visiting = Alloc<Dict<int, bool>>();
}

void BaseEncoder::SetIndent(int indent) {
  this->indent = indent;
}

void BaseEncoder::SetUseStyles(bool use_styles) {
  this->use_styles = use_styles;
}

void BaseEncoder::SetMaxTabularWidth(int max_tabular_width) {
  this->max_tabular_width = max_tabular_width;
}

pretty_asdl::MeasuredDoc* BaseEncoder::_Styled(BigStr* style, pretty_asdl::MeasuredDoc* mdoc) {
  StackRoot _root0(&style);
  StackRoot _root1(&mdoc);

  if (this->use_styles) {
    return _Concat(NewList<pretty_asdl::MeasuredDoc*>(std::initializer_list<pretty_asdl::MeasuredDoc*>{Alloc<MeasuredDoc>(Alloc<doc::Text>(style), _EmptyMeasure()), mdoc, Alloc<MeasuredDoc>(Alloc<doc::Text>(ansi::RESET), _EmptyMeasure())}));
  }
  else {
    return mdoc;
  }
}

pretty_asdl::MeasuredDoc* BaseEncoder::_StyledAscii(BigStr* style, BigStr* s) {
  pretty_asdl::Measure* measure = nullptr;
  StackRoot _root0(&style);
  StackRoot _root1(&s);
  StackRoot _root2(&measure);

  measure = Alloc<Measure>(len(s), -1);
  if (this->use_styles) {
    s = StrFormat("%s%s%s", style, s, ansi::RESET);
  }
  return Alloc<MeasuredDoc>(Alloc<doc::Text>(s), measure);
}

pretty_asdl::MeasuredDoc* BaseEncoder::_Surrounded(BigStr* left, pretty_asdl::MeasuredDoc* mdoc, BigStr* right) {
  StackRoot _root0(&left);
  StackRoot _root1(&mdoc);
  StackRoot _root2(&right);

  return _Group(_Concat(NewList<pretty_asdl::MeasuredDoc*>(std::initializer_list<pretty_asdl::MeasuredDoc*>{AsciiText(left), _Indent(this->indent, _Concat(NewList<pretty_asdl::MeasuredDoc*>(std::initializer_list<pretty_asdl::MeasuredDoc*>{_Break(S_Aoo), mdoc}))), _Break(S_Aoo), AsciiText(right)})));
}

pretty_asdl::MeasuredDoc* BaseEncoder::_SurroundedAndPrefixed(BigStr* left, pretty_asdl::MeasuredDoc* prefix, BigStr* sep, pretty_asdl::MeasuredDoc* mdoc, BigStr* right) {
  StackRoot _root0(&left);
  StackRoot _root1(&prefix);
  StackRoot _root2(&sep);
  StackRoot _root3(&mdoc);
  StackRoot _root4(&right);

  return _Group(_Concat(NewList<pretty_asdl::MeasuredDoc*>(std::initializer_list<pretty_asdl::MeasuredDoc*>{AsciiText(left), prefix, _Indent(this->indent, _Concat(NewList<pretty_asdl::MeasuredDoc*>(std::initializer_list<pretty_asdl::MeasuredDoc*>{_Break(sep), mdoc}))), _Break(S_Aoo), AsciiText(right)})));
}

pretty_asdl::MeasuredDoc* BaseEncoder::_Join(List<pretty_asdl::MeasuredDoc*>* items, BigStr* sep, BigStr* space) {
  List<pretty_asdl::MeasuredDoc*>* seq = nullptr;
  int i;
  StackRoot _root0(&items);
  StackRoot _root1(&sep);
  StackRoot _root2(&space);
  StackRoot _root3(&seq);

  seq = Alloc<List<pretty_asdl::MeasuredDoc*>>();
  i = 0;
  for (ListIter<pretty_asdl::MeasuredDoc*> it(items); !it.Done(); it.Next(), ++i) {
    pretty_asdl::MeasuredDoc* item = it.Value();
    StackRoot _for(&item  );
    if (i != 0) {
      seq->append(AsciiText(sep));
      seq->append(_Break(space));
    }
    seq->append(item);
  }
  return _Concat(seq);
}

pretty_asdl::MeasuredDoc* BaseEncoder::_Tabular(List<pretty_asdl::MeasuredDoc*>* items, BigStr* sep) {
  int max_flat_len;
  List<pretty_asdl::MeasuredDoc*>* seq = nullptr;
  int i;
  pretty_asdl::MeasuredDoc* non_tabular = nullptr;
  int sep_width;
  List<pretty_asdl::MeasuredDoc*>* tabular_seq = nullptr;
  int padding;
  pretty_asdl::MeasuredDoc* tabular = nullptr;
  StackRoot _root0(&items);
  StackRoot _root1(&sep);
  StackRoot _root2(&seq);
  StackRoot _root3(&non_tabular);
  StackRoot _root4(&tabular_seq);
  StackRoot _root5(&tabular);

  if (len(items) == 0) {
    return AsciiText(S_Aoo);
  }
  max_flat_len = 0;
  seq = Alloc<List<pretty_asdl::MeasuredDoc*>>();
  i = 0;
  for (ListIter<pretty_asdl::MeasuredDoc*> it(items); !it.Done(); it.Next(), ++i) {
    pretty_asdl::MeasuredDoc* item = it.Value();
    StackRoot _for(&item  );
    if (i != 0) {
      seq->append(AsciiText(sep));
      seq->append(_Break(S_yfw));
    }
    seq->append(item);
    max_flat_len = max(max_flat_len, item->measure->flat);
  }
  non_tabular = _Concat(seq);
  sep_width = len(sep);
  if (((max_flat_len + sep_width) + 1) <= this->max_tabular_width) {
    tabular_seq = Alloc<List<pretty_asdl::MeasuredDoc*>>();
    i = 0;
    for (ListIter<pretty_asdl::MeasuredDoc*> it(items); !it.Done(); it.Next(), ++i) {
      pretty_asdl::MeasuredDoc* item = it.Value();
      StackRoot _for(&item    );
      tabular_seq->append(_Flat(item));
      if (i != (len(items) - 1)) {
        padding = ((max_flat_len - item->measure->flat) + 1);
        tabular_seq->append(AsciiText(sep));
        tabular_seq->append(_Group(_Break(str_repeat(S_yfw, padding))));
      }
    }
    tabular = _Concat(tabular_seq);
    return _Group(_IfFlat(non_tabular, tabular));
  }
  else {
    return non_tabular;
  }
}

HNodeEncoder::HNodeEncoder() : ::pp_hnode::BaseEncoder() {
  this->type_color = ansi::YELLOW;
  this->field_color = ansi::MAGENTA;
}

pretty_asdl::MeasuredDoc* HNodeEncoder::HNode(hnode_asdl::hnode_t* h) {
  StackRoot _root0(&h);

  this->visiting->clear();
  return this->_HNode(h);
}

pretty_asdl::MeasuredDoc* HNodeEncoder::_Field(hnode_asdl::Field* field) {
  pretty_asdl::MeasuredDoc* name = nullptr;
  StackRoot _root0(&field);
  StackRoot _root1(&name);

  name = AsciiText(str_concat(field->name, S_fyj));
  return _Concat(NewList<pretty_asdl::MeasuredDoc*>(std::initializer_list<pretty_asdl::MeasuredDoc*>{name, this->_HNode(field->val)}));
}

pretty_asdl::MeasuredDoc* HNodeEncoder::_HNode(hnode_asdl::hnode_t* h) {
  hnode_asdl::hnode_t* UP_h = nullptr;
  BigStr* color = nullptr;
  BigStr* s = nullptr;
  List<pretty_asdl::MeasuredDoc*>* children = nullptr;
  pretty_asdl::MeasuredDoc* type_name = nullptr;
  List<pretty_asdl::MeasuredDoc*>* mdocs = nullptr;
  List<pretty_asdl::MeasuredDoc*>* m = nullptr;
  pretty_asdl::MeasuredDoc* child = nullptr;
  StackRoot _root0(&h);
  StackRoot _root1(&UP_h);
  StackRoot _root2(&color);
  StackRoot _root3(&s);
  StackRoot _root4(&children);
  StackRoot _root5(&type_name);
  StackRoot _root6(&mdocs);
  StackRoot _root7(&m);
  StackRoot _root8(&child);

  UP_h = h;
  switch (h->tag()) {
    case hnode_e::AlreadySeen: {
      hnode::AlreadySeen* h = static_cast<hnode::AlreadySeen*>(UP_h);
      return pretty::AsciiText(StrFormat("...0x%s", mylib::hex_lower(h->heap_id)));
    }
      break;
    case hnode_e::Leaf: {
      hnode::Leaf* h = static_cast<hnode::Leaf*>(UP_h);
      switch (h->color) {
        case color_e::TypeName: {
          color = ansi::YELLOW;
        }
          break;
        case color_e::StringConst: {
          color = ansi::BOLD;
        }
          break;
        case color_e::OtherConst: {
          color = ansi::GREEN;
        }
          break;
        case color_e::External: {
          color = str_concat(ansi::BOLD, ansi::BLUE);
        }
          break;
        case color_e::UserType: {
          color = ansi::GREEN;
        }
          break;
        default: {
          assert(0);  // AssertionError
        }
      }
      s = j8_lite::EncodeString(h->s, true);
      return this->_StyledAscii(color, s);
    }
      break;
    case hnode_e::Array: {
      hnode::Array* h = static_cast<hnode::Array*>(UP_h);
      mylib::MaybeCollect();
      if (len(h->children) == 0) {
        return AsciiText(S_xmu);
      }
      children = Alloc<List<pretty_asdl::MeasuredDoc*>>();
      for (ListIter<hnode_asdl::hnode_t*> it(h->children); !it.Done(); it.Next()) {
        hnode_asdl::hnode_t* item = it.Value();
        children->append(this->_HNode(item));
      }
      return this->_Surrounded(S_Eax, this->_Tabular(children, S_Aoo), S_pcD);
    }
      break;
    case hnode_e::Record: {
      hnode::Record* h = static_cast<hnode::Record*>(UP_h);
      type_name = nullptr;
      if (len(h->node_type)) {
        type_name = this->_StyledAscii(this->type_color, h->node_type);
      }
      mdocs = nullptr;
      if ((h->unnamed_fields != nullptr and len(h->unnamed_fields))) {
        mdocs = Alloc<List<pretty_asdl::MeasuredDoc*>>();
        for (ListIter<hnode_asdl::hnode_t*> it(h->unnamed_fields); !it.Done(); it.Next()) {
          hnode_asdl::hnode_t* item = it.Value();
          mdocs->append(this->_HNode(item));
        }
      }
      else {
        if (len(h->fields) != 0) {
          mdocs = Alloc<List<pretty_asdl::MeasuredDoc*>>();
          for (ListIter<hnode_asdl::Field*> it(h->fields); !it.Done(); it.Next()) {
            hnode_asdl::Field* field = it.Value();
            mdocs->append(this->_Field(field));
          }
        }
      }
      if (mdocs == nullptr) {
        m = NewList<pretty_asdl::MeasuredDoc*>(std::initializer_list<pretty_asdl::MeasuredDoc*>{AsciiText(h->left)});
        if (type_name != nullptr) {
          m->append(type_name);
        }
        m->append(AsciiText(h->right));
        return _Concat(m);
      }
      child = this->_Join(mdocs, S_Aoo, S_yfw);
      if (type_name != nullptr) {
        return this->_SurroundedAndPrefixed(h->left, type_name, S_yfw, child, h->right);
      }
      else {
        return this->_Surrounded(h->left, child, h->right);
      }
    }
      break;
    default: {
      assert(0);  // AssertionError
    }
  }
}

}  // define namespace pp_hnode

namespace pretty {  // define

using pretty_asdl::doc;
using pretty_asdl::doc_e;
using pretty_asdl::DocFragment;
using pretty_asdl::Measure;
using pretty_asdl::MeasuredDoc;
using pretty_asdl::List_Measured;
using mylib::BufWriter;

pretty_asdl::Measure* _EmptyMeasure() {
  return Alloc<Measure>(0, -1);
}

pretty_asdl::Measure* _FlattenMeasure(pretty_asdl::Measure* measure) {
  StackRoot _root0(&measure);

  return Alloc<Measure>(measure->flat, -1);
}

pretty_asdl::Measure* _ConcatMeasure(pretty_asdl::Measure* m1, pretty_asdl::Measure* m2) {
  StackRoot _root0(&m1);
  StackRoot _root1(&m2);

  if (m1->nonflat != -1) {
    return Alloc<Measure>((m1->flat + m2->flat), m1->nonflat);
  }
  else {
    if (m2->nonflat != -1) {
      return Alloc<Measure>((m1->flat + m2->flat), (m1->flat + m2->nonflat));
    }
    else {
      return Alloc<Measure>((m1->flat + m2->flat), -1);
    }
  }
}

int _SuffixLen(pretty_asdl::Measure* measure) {
  StackRoot _root0(&measure);

  if (measure->nonflat != -1) {
    return measure->nonflat;
  }
  else {
    return measure->flat;
  }
}

pretty_asdl::MeasuredDoc* AsciiText(BigStr* string) {
  StackRoot _root0(&string);

  return Alloc<MeasuredDoc>(Alloc<doc::Text>(string), Alloc<Measure>(len(string), -1));
}

pretty_asdl::MeasuredDoc* _Break(BigStr* string) {
  StackRoot _root0(&string);

  return Alloc<MeasuredDoc>(Alloc<doc::Break>(string), Alloc<Measure>(len(string), 0));
}

pretty_asdl::MeasuredDoc* _Indent(int indent, pretty_asdl::MeasuredDoc* mdoc) {
  StackRoot _root0(&mdoc);

  return Alloc<MeasuredDoc>(Alloc<doc::Indent>(indent, mdoc), mdoc->measure);
}

pretty_asdl::Measure* _Splice(List<pretty_asdl::MeasuredDoc*>* out, List<pretty_asdl::MeasuredDoc*>* mdocs) {
  pretty_asdl::Measure* measure = nullptr;
  pretty_asdl::List_Measured* child = nullptr;
  StackRoot _root0(&out);
  StackRoot _root1(&mdocs);
  StackRoot _root2(&measure);
  StackRoot _root3(&child);

  measure = _EmptyMeasure();
  for (ListIter<pretty_asdl::MeasuredDoc*> it(mdocs); !it.Done(); it.Next()) {
    pretty_asdl::MeasuredDoc* mdoc = it.Value();
    StackRoot _for(&mdoc  );
    switch (mdoc->doc->tag()) {
      case doc_e::Concat: {
        child = static_cast<List_Measured*>(mdoc->doc);
        _Splice(out, child);
      }
        break;
      default: {
        out->append(mdoc);
      }
    }
    measure = _ConcatMeasure(measure, mdoc->measure);
  }
  return measure;
}

pretty_asdl::MeasuredDoc* _Concat(List<pretty_asdl::MeasuredDoc*>* mdocs) {
  pretty_asdl::List_Measured* flattened = nullptr;
  pretty_asdl::Measure* measure = nullptr;
  StackRoot _root0(&mdocs);
  StackRoot _root1(&flattened);
  StackRoot _root2(&measure);

  flattened = List_Measured::New();
  measure = _Splice(flattened, mdocs);
  return Alloc<MeasuredDoc>(flattened, measure);
}

pretty_asdl::MeasuredDoc* _Group(pretty_asdl::MeasuredDoc* mdoc) {
  StackRoot _root0(&mdoc);

  return Alloc<MeasuredDoc>(mdoc, mdoc->measure);
}

pretty_asdl::MeasuredDoc* _IfFlat(pretty_asdl::MeasuredDoc* flat_mdoc, pretty_asdl::MeasuredDoc* nonflat_mdoc) {
  StackRoot _root0(&flat_mdoc);
  StackRoot _root1(&nonflat_mdoc);

  return Alloc<MeasuredDoc>(Alloc<doc::IfFlat>(flat_mdoc, nonflat_mdoc), Alloc<Measure>(flat_mdoc->measure->flat, nonflat_mdoc->measure->nonflat));
}

pretty_asdl::MeasuredDoc* _Flat(pretty_asdl::MeasuredDoc* mdoc) {
  StackRoot _root0(&mdoc);

  return Alloc<MeasuredDoc>(Alloc<doc::Flat>(mdoc), _FlattenMeasure(mdoc->measure));
}

PrettyPrinter::PrettyPrinter(int max_width) {
  this->max_width = max_width;
}

bool PrettyPrinter::_Fits(int prefix_len, pretty_asdl::MeasuredDoc* group, pretty_asdl::Measure* suffix_measure) {
  pretty_asdl::Measure* measure = nullptr;
  StackRoot _root0(&group);
  StackRoot _root1(&suffix_measure);
  StackRoot _root2(&measure);

  measure = _ConcatMeasure(_FlattenMeasure(group->measure), suffix_measure);
  return (prefix_len + _SuffixLen(measure)) <= this->max_width;
}

void PrettyPrinter::PrintDoc(pretty_asdl::MeasuredDoc* document, mylib::BufWriter* buf) {
  int prefix_len;
  List<pretty_asdl::DocFragment*>* fragments = nullptr;
  int max_stack;
  pretty_asdl::DocFragment* frag = nullptr;
  pretty_asdl::doc_t* UP_doc = nullptr;
  pretty_asdl::Measure* measure = nullptr;
  bool is_flat;
  pretty_asdl::MeasuredDoc* subdoc = nullptr;
  StackRoot _root0(&document);
  StackRoot _root1(&buf);
  StackRoot _root2(&fragments);
  StackRoot _root3(&frag);
  StackRoot _root4(&UP_doc);
  StackRoot _root5(&measure);
  StackRoot _root6(&subdoc);

  prefix_len = 0;
  fragments = NewList<pretty_asdl::DocFragment*>(std::initializer_list<pretty_asdl::DocFragment*>{Alloc<DocFragment>(_Group(document), 0, false, _EmptyMeasure())});
  max_stack = len(fragments);
  while (len(fragments) > 0) {
    max_stack = max(max_stack, len(fragments));
    frag = fragments->pop();
    UP_doc = frag->mdoc->doc;
    switch (UP_doc->tag()) {
      case doc_e::Text: {
        doc::Text* text = static_cast<doc::Text*>(UP_doc);
        buf->write(text->string);
        prefix_len += frag->mdoc->measure->flat;
      }
        break;
      case doc_e::Break: {
        doc::Break* break_ = static_cast<doc::Break*>(UP_doc);
        if (frag->is_flat) {
          buf->write(break_->string);
          prefix_len += frag->mdoc->measure->flat;
        }
        else {
          buf->write(S_nfs);
          buf->write_spaces(frag->indent);
          prefix_len = frag->indent;
        }
      }
        break;
      case doc_e::Indent: {
        doc::Indent* indented = static_cast<doc::Indent*>(UP_doc);
        fragments->append(Alloc<DocFragment>(indented->mdoc, (frag->indent + indented->indent), frag->is_flat, frag->measure));
      }
        break;
      case doc_e::Concat: {
        List_Measured* concat = static_cast<List_Measured*>(UP_doc);
        measure = frag->measure;
        for (ReverseListIter<pretty_asdl::MeasuredDoc*> it(concat); !it.Done(); it.Next()) {
          pretty_asdl::MeasuredDoc* mdoc = it.Value();
          StackRoot _for(&mdoc        );
          fragments->append(Alloc<DocFragment>(mdoc, frag->indent, frag->is_flat, measure));
          measure = _ConcatMeasure(mdoc->measure, measure);
        }
      }
        break;
      case doc_e::Group: {
        MeasuredDoc* group = static_cast<MeasuredDoc*>(UP_doc);
        is_flat = this->_Fits(prefix_len, group, frag->measure);
        fragments->append(Alloc<DocFragment>(group, frag->indent, is_flat, frag->measure));
      }
        break;
      case doc_e::IfFlat: {
        doc::IfFlat* if_flat = static_cast<doc::IfFlat*>(UP_doc);
        if (frag->is_flat) {
          subdoc = if_flat->flat_mdoc;
        }
        else {
          subdoc = if_flat->nonflat_mdoc;
        }
        fragments->append(Alloc<DocFragment>(subdoc, frag->indent, frag->is_flat, frag->measure));
      }
        break;
      case doc_e::Flat: {
        doc::Flat* flat_doc = static_cast<doc::Flat*>(UP_doc);
        fragments->append(Alloc<DocFragment>(flat_doc->mdoc, frag->indent, true, frag->measure));
      }
        break;
    }
  }
}

}  // define namespace pretty

namespace syntax_abbrev {  // define

using id_kind_asdl::Id;
using id_kind_asdl::Id_str;
using hnode_asdl::hnode;
using hnode_asdl::hnode_t;
using hnode_asdl::color_e;

void _AbbreviateToken(syntax_asdl::Token* tok, List<hnode_asdl::hnode_t*>* out) {
  BigStr* tok_str = nullptr;
  hnode::Leaf* n1 = nullptr;
  hnode::Leaf* n2 = nullptr;
  StackRoot _root0(&tok);
  StackRoot _root1(&out);
  StackRoot _root2(&tok_str);
  StackRoot _root3(&n1);
  StackRoot _root4(&n2);

  tok_str = tok->line->content->slice(tok->col, (tok->col + tok->length));
  n1 = runtime::NewLeaf(Id_str(tok->id, false), color_e::OtherConst);
  out->append(n1);
  n2 = runtime::NewLeaf(tok_str, color_e::StringConst);
  out->append(n2);
}

hnode_asdl::hnode_t* _Token(syntax_asdl::Token* obj) {
  hnode::Record* p_node = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);

  p_node = runtime::NewRecord(S_Aoo);
  p_node->left = S_eox;
  p_node->right = S_jye;
  p_node->unnamed_fields = Alloc<List<hnode_asdl::hnode_t*>>();
  _AbbreviateToken(obj, p_node->unnamed_fields);
  return p_node;
}

hnode_asdl::hnode_t* _CompoundWord(syntax_asdl::CompoundWord* obj) {
  hnode::Record* p_node = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);

  p_node = runtime::NewRecord(S_pfC);
  p_node->left = S_ijB;
  p_node->right = S_hxb;
  p_node->unnamed_fields = Alloc<List<hnode_asdl::hnode_t*>>();
  for (ListIter<syntax_asdl::word_part_t*> it(obj->parts); !it.Done(); it.Next()) {
    syntax_asdl::word_part_t* part = it.Value();
    StackRoot _for(&part  );
    p_node->unnamed_fields->append(part->PrettyTree(true));
  }
  return p_node;
}

hnode_asdl::hnode_t* _DoubleQuoted(syntax_asdl::DoubleQuoted* obj) {
  hnode::Record* p_node = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);

  if (obj->left->id != Id::Left_DoubleQuote) {
    return nullptr;
  }
  p_node = runtime::NewRecord(S_lAz);
  p_node->unnamed_fields = Alloc<List<hnode_asdl::hnode_t*>>();
  for (ListIter<syntax_asdl::word_part_t*> it(obj->parts); !it.Done(); it.Next()) {
    syntax_asdl::word_part_t* part = it.Value();
    StackRoot _for(&part  );
    p_node->unnamed_fields->append(part->PrettyTree(true));
  }
  return p_node;
}

hnode_asdl::hnode_t* _SingleQuoted(syntax_asdl::SingleQuoted* obj) {
  hnode::Record* p_node = nullptr;
  hnode::Leaf* n2 = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);
  StackRoot _root2(&n2);

  if (obj->left->id != Id::Left_SingleQuote) {
    return nullptr;
  }
  p_node = runtime::NewRecord(S_mip);
  p_node->unnamed_fields = Alloc<List<hnode_asdl::hnode_t*>>();
  n2 = runtime::NewLeaf(obj->sval, color_e::StringConst);
  p_node->unnamed_fields->append(n2);
  return p_node;
}

hnode_asdl::hnode_t* _SimpleVarSub(syntax_asdl::SimpleVarSub* obj) {
  hnode::Record* p_node = nullptr;
  syntax_asdl::Token* tok = nullptr;
  BigStr* var_name = nullptr;
  hnode::Leaf* n1 = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);
  StackRoot _root2(&tok);
  StackRoot _root3(&var_name);
  StackRoot _root4(&n1);

  p_node = runtime::NewRecord(S_Czx);
  p_node->unnamed_fields = Alloc<List<hnode_asdl::hnode_t*>>();
  if ((obj->tok->id == Id::VSub_DollarName || obj->tok->id == Id::VSub_Number)) {
    tok = obj->tok;
    var_name = tok->line->content->slice((tok->col + 1), (tok->col + tok->length));
    n1 = runtime::NewLeaf(var_name, color_e::StringConst);
    p_node->unnamed_fields->append(n1);
  }
  else {
    n1 = runtime::NewLeaf(Id_str(obj->tok->id, false), color_e::OtherConst);
    p_node->unnamed_fields->append(n1);
  }
  return p_node;
}

hnode_asdl::hnode_t* _BracedVarSub(syntax_asdl::BracedVarSub* obj) {
  hnode::Record* p_node = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);

  p_node = runtime::NewRecord(S_hqF);
  if ((obj->prefix_op != nullptr or (obj->bracket_op != nullptr or obj->suffix_op != nullptr))) {
    return nullptr;
  }
  p_node->unnamed_fields = Alloc<List<hnode_asdl::hnode_t*>>();
  _AbbreviateToken(obj->name_tok, p_node->unnamed_fields);
  return p_node;
}

hnode_asdl::hnode_t* _command__Simple(command::Simple* obj) {
  hnode::Record* p_node = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);

  p_node = runtime::NewRecord(S_sjc);
  if ((len(obj->more_env) or (obj->typed_args != nullptr or (obj->block != nullptr or obj->is_last_cmd == true)))) {
    return nullptr;
  }
  p_node->unnamed_fields = Alloc<List<hnode_asdl::hnode_t*>>();
  for (ListIter<syntax_asdl::word_t*> it(obj->words); !it.Done(); it.Next()) {
    syntax_asdl::word_t* w = it.Value();
    StackRoot _for(&w  );
    p_node->unnamed_fields->append(w->PrettyTree(true));
  }
  return p_node;
}

hnode_asdl::hnode_t* _expr__Var(expr::Var* obj) {
  hnode::Record* p_node = nullptr;
  hnode::Leaf* n1 = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);
  StackRoot _root2(&n1);

  p_node = runtime::NewRecord(S_CsA);
  n1 = runtime::NewLeaf(obj->name, color_e::StringConst);
  p_node->unnamed_fields = NewList<hnode_asdl::hnode_t*>(std::initializer_list<hnode_asdl::hnode_t*>{n1});
  return p_node;
}

hnode_asdl::hnode_t* _expr__Const(expr::Const* obj) {
  hnode::Record* p_node = nullptr;
  syntax_asdl::Token* tok = nullptr;
  hnode::Leaf* n1 = nullptr;
  hnode::Leaf* n2 = nullptr;
  StackRoot _root0(&obj);
  StackRoot _root1(&p_node);
  StackRoot _root2(&tok);
  StackRoot _root3(&n1);
  StackRoot _root4(&n2);

  p_node = runtime::NewRecord(S_wcu);
  tok = obj->c;
  n1 = runtime::NewLeaf(Id_str(tok->id, false), color_e::OtherConst);
  n2 = runtime::NewLeaf(tok->tval, color_e::StringConst);
  p_node->unnamed_fields = NewList<hnode_asdl::hnode_t*>(std::initializer_list<hnode_asdl::hnode_t*>{n1, n2});
  return p_node;
}

}  // define namespace syntax_abbrev

namespace gen_cpp {  // define

using yaks_asdl::Program;
using yaks_asdl::mod_def;
using yaks_asdl::mod_def_e;
using yaks_asdl::ktype;
using yaks_asdl::ktype_e;
using yaks_asdl::ktype_t;
using yaks_asdl::NameType;
using yaks_asdl::stmt;
using yaks_asdl::stmt_e;
using yaks_asdl::stmt_t;
using yaks_asdl::Int;
using yaks_asdl::kexpr_e;
using yaks_asdl::kexpr_t;

void GenType(yaks_asdl::ktype_t* typ, mylib::Writer* f) {
  yaks_asdl::ktype_t* UP_typ = nullptr;
  StackRoot _root0(&typ);
  StackRoot _root1(&f);
  StackRoot _root2(&UP_typ);

  UP_typ = typ;
  switch (typ->tag()) {
    case ktype_e::Int: {
      f->write(S_gcE);
    }
      break;
    case ktype_e::Str: {
      f->write(S_vBF);
    }
      break;
    case ktype_e::List: {
      ktype::List* typ = static_cast<ktype::List*>(UP_typ);
      f->write(S_lkg);
      GenType(typ->T, f);
      f->write(S_ydF);
    }
      break;
    default: {
      assert(0);  // AssertionError
    }
  }
}

void GenParam(yaks_asdl::NameType* p, mylib::Writer* f) {
  StackRoot _root0(&p);
  StackRoot _root1(&f);

  GenType(p->typ, f);
  f->write(StrFormat(" %s", p->name));
}

void GenExpr(yaks_asdl::kexpr_t* expr, mylib::Writer* f) {
  yaks_asdl::kexpr_t* UP_expr = nullptr;
  StackRoot _root0(&expr);
  StackRoot _root1(&f);
  StackRoot _root2(&UP_expr);

  UP_expr = expr;
  switch (expr->tag()) {
    case kexpr_e::Int: {
      Int* expr = static_cast<Int*>(UP_expr);
      f->write(StrFormat("%d", expr->i));
    }
      break;
    default: {
      assert(0);  // AssertionError
    }
  }
}

void GenStatement(yaks_asdl::stmt_t* st, mylib::Writer* f) {
  yaks_asdl::stmt_t* UP_st = nullptr;
  StackRoot _root0(&st);
  StackRoot _root1(&f);
  StackRoot _root2(&UP_st);

  UP_st = st;
  switch (st->tag()) {
    case stmt_e::Return: {
      stmt::Return* st = static_cast<stmt::Return*>(UP_st);
      f->write(S_kps);
      GenExpr(st->e, f);
      f->write(S_tAA);
    }
      break;
  }
}

void GenFunction(mod_def::Func* func, mylib::Writer* f) {
  int i;
  StackRoot _root0(&func);
  StackRoot _root1(&f);

  GenType(func->sig->return_type, f);
  f->write(StrFormat(" %s(", func->name));
  i = 0;
  for (ListIter<yaks_asdl::NameType*> it(func->sig->params); !it.Done(); it.Next(), ++i) {
    yaks_asdl::NameType* p = it.Value();
    StackRoot _for(&p  );
    if (i != 0) {
      f->write(S_tgp);
    }
    GenParam(p, f);
  }
  f->write(S_hag);
  for (ListIter<yaks_asdl::stmt_t*> it(func->statements); !it.Done(); it.Next()) {
    yaks_asdl::stmt_t* st = it.Value();
    StackRoot _for(&st  );
    GenStatement(st, f);
  }
  f->write(S_tve);
}

void GenCpp(yaks_asdl::Program* prog, mylib::Writer* f) {
  yaks_asdl::mod_def_t* UP_d = nullptr;
  StackRoot _root0(&prog);
  StackRoot _root1(&f);
  StackRoot _root2(&UP_d);

  f->write(S_FxD);
  for (ListIter<yaks_asdl::Module*> it(prog->modules); !it.Done(); it.Next()) {
    yaks_asdl::Module* module = it.Value();
    StackRoot _for(&module  );
    f->write(StrFormat("namespace %s {\n", module->name));
    for (ListIter<yaks_asdl::mod_def_t*> it(module->defs); !it.Done(); it.Next()) {
      yaks_asdl::mod_def_t* d = it.Value();
      StackRoot _for(&d    );
      UP_d = d;
      switch (d->tag()) {
        case mod_def_e::Func: {
          mod_def::Func* d = static_cast<mod_def::Func*>(UP_d);
          GenFunction(d, f);
        }
          break;
      }
    }
    f->write(StrFormat("}  // namespace %s\n", module->name));
  }
}

}  // define namespace gen_cpp

namespace transform {  // define

using nil8_asdl::nvalue;
using nil8_asdl::nvalue_e;
using nil8_asdl::nvalue_t;
using yaks_asdl::Module;
using yaks_asdl::Program;
using yaks_asdl::mod_def;
using yaks_asdl::mod_def_t;
using yaks_asdl::ktype;
using yaks_asdl::ktype_t;
using yaks_asdl::stmt;
using yaks_asdl::stmt_t;
using yaks_asdl::kexpr_t;
using yaks_asdl::Int;
using yaks_asdl::Token;
using yaks_asdl::Signature;
using yaks_asdl::NameType;

BigStr* MustBeSymbol(nil8_asdl::nvalue_t* nval) {
  StackRoot _root0(&nval);

  if (nval->tag() != nvalue_e::Symbol) {
    assert(0);  // AssertionError
  }
  return static_cast<nvalue::Symbol*>(nval)->s;
}

List<nil8_asdl::nvalue_t*>* MustBeList(nil8_asdl::nvalue_t* nval) {
  StackRoot _root0(&nval);

  if (nval->tag() != nvalue_e::List) {
    assert(0);  // AssertionError
  }
  return static_cast<nvalue::List*>(nval)->items;
}

yaks_asdl::kexpr_t* TransformExpr(nil8_asdl::nvalue_t* nval) {
  nil8_asdl::nvalue_t* UP_nval = nullptr;
  yaks_asdl::Token* loc = nullptr;
  StackRoot _root0(&nval);
  StackRoot _root1(&UP_nval);
  StackRoot _root2(&loc);

  UP_nval = nval;
  switch (nval->tag()) {
    case nvalue_e::Int: {
      nvalue::Int* nval = static_cast<nvalue::Int*>(UP_nval);
      loc = Alloc<Token>(S_rbu, S_yBr, 0, 3);
      return Alloc<Int>(nval->i, loc);
    }
      break;
    default: {
      assert(0);  // AssertionError
    }
  }
}

yaks_asdl::ktype_t* TransformType(nil8_asdl::nvalue_t* nval) {
  nil8_asdl::nvalue_t* UP_nval = nullptr;
  BigStr* first = nullptr;
  StackRoot _root0(&nval);
  StackRoot _root1(&UP_nval);
  StackRoot _root2(&first);

  UP_nval = nval;
  switch (nval->tag()) {
    case nvalue_e::Symbol: {
      nvalue::Symbol* nval = static_cast<nvalue::Symbol*>(UP_nval);
      if (str_equals(nval->s, S_AED)) {
        return ktype::Bool;
      }
      else {
        if (str_equals(nval->s, S_Ckc)) {
          return ktype::Int;
        }
        else {
          if (str_equals(nval->s, S_DsF)) {
            return ktype::Str;
          }
          else {
            assert(0);  // AssertionError
          }
        }
      }
    }
      break;
    case nvalue_e::List: {
      nvalue::List* nval = static_cast<nvalue::List*>(UP_nval);
      first = MustBeSymbol(nval->items->at(0));
      if (str_equals(first, S_bDF)) {
        return Alloc<ktype::List>(TransformType(nval->items->at(1)));
      }
      else {
        if (str_equals(first, S_vbu)) {
          return Alloc<ktype::Dict>(TransformType(nval->items->at(1)), TransformType(nval->items->at(2)));
        }
        else {
          assert(0);  // AssertionError
        }
      }
    }
      break;
    default: {
      assert(0);  // AssertionError
    }
  }
}

yaks_asdl::NameType* TransformParam(List<nil8_asdl::nvalue_t*>* param_n) {
  BigStr* name = nullptr;
  yaks_asdl::ktype_t* typ = nullptr;
  StackRoot _root0(&param_n);
  StackRoot _root1(&name);
  StackRoot _root2(&typ);

  if (len(param_n) != 2) {
    assert(0);  // AssertionError
  }
  name = MustBeSymbol(param_n->at(0));
  typ = TransformType(param_n->at(1));
  return Alloc<NameType>(name, typ);
}

List<yaks_asdl::NameType*>* TransformParams(List<nil8_asdl::nvalue_t*>* params_n) {
  List<yaks_asdl::NameType*>* result = nullptr;
  List<nil8_asdl::nvalue_t*>* param_n = nullptr;
  StackRoot _root0(&params_n);
  StackRoot _root1(&result);
  StackRoot _root2(&param_n);

  result = Alloc<List<yaks_asdl::NameType*>>();
  for (ListIter<nil8_asdl::nvalue_t*> it(params_n); !it.Done(); it.Next()) {
    nil8_asdl::nvalue_t* p = it.Value();
    StackRoot _for(&p  );
    param_n = MustBeList(p);
    result->append(TransformParam(param_n));
  }
  return result;
}

yaks_asdl::Signature* TransformSignature(nil8_asdl::nvalue_t* nval) {
  List<nil8_asdl::nvalue_t*>* sig_n = nullptr;
  BigStr* first = nullptr;
  List<nil8_asdl::nvalue_t*>* params_n = nullptr;
  StackRoot _root0(&nval);
  StackRoot _root1(&sig_n);
  StackRoot _root2(&first);
  StackRoot _root3(&params_n);

  sig_n = MustBeList(nval);
  if (len(sig_n) != 3) {
    assert(0);  // AssertionError
  }
  first = MustBeSymbol(sig_n->at(0));
  if (!(str_equals(first, S_nsk))) {
    assert(0);  // AssertionError
  }
  params_n = MustBeList(sig_n->at(1));
  return Alloc<Signature>(TransformParams(params_n), TransformType(sig_n->at(2)));
}

mod_def::Func* TransformFunc(List<nil8_asdl::nvalue_t*>* func_n) {
  BigStr* func_name = nullptr;
  List<yaks_asdl::stmt_t*>* out_stmts = nullptr;
  yaks_asdl::Signature* sig = nullptr;
  mod_def::Func* func = nullptr;
  List<nil8_asdl::nvalue_t*>* stmts = nullptr;
  List<nil8_asdl::nvalue_t*>* stmt_n = nullptr;
  BigStr* first = nullptr;
  yaks_asdl::kexpr_t* expr = nullptr;
  StackRoot _root0(&func_n);
  StackRoot _root1(&func_name);
  StackRoot _root2(&out_stmts);
  StackRoot _root3(&sig);
  StackRoot _root4(&func);
  StackRoot _root5(&stmts);
  StackRoot _root6(&stmt_n);
  StackRoot _root7(&first);
  StackRoot _root8(&expr);

  func_name = MustBeSymbol(func_n->at(1));
  out_stmts = Alloc<List<yaks_asdl::stmt_t*>>();
  sig = TransformSignature(func_n->at(2));
  func = Alloc<mod_def::Func>(func_name, sig, out_stmts);
  stmts = func_n->slice(3);
  for (ListIter<nil8_asdl::nvalue_t*> it(stmts); !it.Done(); it.Next()) {
    nil8_asdl::nvalue_t* st = it.Value();
    StackRoot _for(&st  );
    stmt_n = MustBeList(st);
    if (len(stmt_n) == 0) {
      assert(0);  // AssertionError
    }
    first = MustBeSymbol(stmt_n->at(0));
    if (str_equals(first, S_fhn)) {
      ;  // pass
    }
    else {
      if (str_equals(first, S_lyA)) {
        ;  // pass
      }
      else {
        if (str_equals(first, S_Cnd)) {
          ;  // pass
        }
        else {
          if (str_equals(first, S_ddf)) {
            expr = TransformExpr(stmt_n->at(1));
            out_stmts->append(Alloc<stmt::Return>(expr));
          }
          else {
            if (str_equals(first, S_pch)) {
              ;  // pass
            }
            else {
              if (str_equals(first, S_ohy)) {
                ;  // pass
              }
              else {
                assert(0);  // AssertionError
              }
            }
          }
        }
      }
    }
  }
  return func;
}

yaks_asdl::Module* TransformModule(List<nil8_asdl::nvalue_t*>* mod_n) {
  BigStr* mod_name = nullptr;
  List<yaks_asdl::mod_def_t*>* out_defs = nullptr;
  yaks_asdl::Module* module = nullptr;
  List<nil8_asdl::nvalue_t*>* defs = nullptr;
  List<nil8_asdl::nvalue_t*>* def_n = nullptr;
  BigStr* first = nullptr;
  StackRoot _root0(&mod_n);
  StackRoot _root1(&mod_name);
  StackRoot _root2(&out_defs);
  StackRoot _root3(&module);
  StackRoot _root4(&defs);
  StackRoot _root5(&def_n);
  StackRoot _root6(&first);

  if (len(mod_n) < 2) {
    assert(0);  // AssertionError
  }
  mod_name = MustBeSymbol(mod_n->at(1));
  out_defs = Alloc<List<yaks_asdl::mod_def_t*>>();
  module = Alloc<Module>(mod_name, out_defs);
  defs = mod_n->slice(2);
  for (ListIter<nil8_asdl::nvalue_t*> it(defs); !it.Done(); it.Next()) {
    nil8_asdl::nvalue_t* d = it.Value();
    StackRoot _for(&d  );
    def_n = MustBeList(d);
    if (len(def_n) == 0) {
      assert(0);  // AssertionError
    }
    first = MustBeSymbol(def_n->at(0));
    if (str_equals(first, S_qCj)) {
      ;  // pass
    }
    else {
      if (str_equals(first, S_zmF)) {
        out_defs->append(TransformFunc(def_n));
      }
      else {
        if (str_equals(first, S_nuD)) {
          ;  // pass
        }
        else {
          assert(0);  // AssertionError
        }
      }
    }
  }
  return module;
}

yaks_asdl::Program* Transform(nil8_asdl::nvalue_t* nval) {
  List<nil8_asdl::nvalue_t*>* mod_n = nullptr;
  yaks_asdl::Module* module = nullptr;
  yaks_asdl::Program* prog = nullptr;
  StackRoot _root0(&nval);
  StackRoot _root1(&mod_n);
  StackRoot _root2(&module);
  StackRoot _root3(&prog);

  mod_n = MustBeList(nval);
  module = TransformModule(mod_n);
  prog = Alloc<Program>(S_lqB, NewList<yaks_asdl::Module*>(std::initializer_list<yaks_asdl::Module*>{module}));
  return prog;
}

}  // define namespace transform

namespace yaks_main {  // define

namespace fmt = format;

int main(List<BigStr*>* argv) {
  mylib::Writer* stderr_ = nullptr;
  BigStr* action = nullptr;
  BigStr* path = nullptr;
  List<BigStr*>* lines = nullptr;
  mylib::LineReader* f = nullptr;
  BigStr* line = nullptr;
  BigStr* contents = nullptr;
  j8::Nil8Parser* p = nullptr;
  nil8_asdl::nvalue_t* nval = nullptr;
  yaks_asdl::Program* prog = nullptr;
  yaks_asdl::Module* m = nullptr;
  StackRoot _root0(&argv);
  StackRoot _root1(&stderr_);
  StackRoot _root2(&action);
  StackRoot _root3(&path);
  StackRoot _root4(&lines);
  StackRoot _root5(&f);
  StackRoot _root6(&line);
  StackRoot _root7(&contents);
  StackRoot _root8(&p);
  StackRoot _root9(&nval);
  StackRoot _root10(&prog);
  StackRoot _root11(&m);

  stderr_ = mylib::Stderr();
  try {
    action = argv->at(1);
  }
  catch (IndexError*) {
    throw Alloc<RuntimeError>(S_fnE);
  }
  if (str_equals(action, S_npw)) {
    path = argv->at(2);
    lines = Alloc<List<BigStr*>>();
    f = mylib::open(path);
    while (true) {
      line = f->readline();
      if (len(line) == 0) {
        break;
      }
      lines->append(line);
    }
    contents = S_Aoo->join(lines);
    p = Alloc<j8::Nil8Parser>(contents, true);
    try {
      nval = p->ParseNil8();
    }
    catch (error::Decode* e) {
      return 1;
    }
    fmt::HNodePrettyPrint(nval->PrettyTree(false), stderr_);
    prog = transform::Transform(nval);
    fmt::HNodePrettyPrint(prog->PrettyTree(false), stderr_);
    gen_cpp::GenCpp(prog, mylib::Stdout());
  }
  else {
    if (str_equals(action, S_voB)) {
      path = argv->at(2);
      m = Alloc<yaks_asdl::Module>(S_cEk, Alloc<List<yaks_asdl::mod_def_t*>>());
      fmt::HNodePrettyPrint(m->PrettyTree(false), stderr_);
    }
    else {
      throw Alloc<RuntimeError>(StrFormat("Invalid action %r", action));
    }
  }
  return 0;
}

}  // define namespace yaks_main

int main(int argc, char **argv) {
  mylib::InitCppOnly();  // Initializes gHeap

  auto* args = Alloc<List<BigStr*>>();
  for (int i = 0; i < argc; ++i) {
    args->append(StrFromC(argv[i]));
  }

  int status = yaks_main::main(args);

  gHeap.ProcessExit();

  return status;
}