// _gen/mycpp/examples/expr.asdl.h is generated by asdl_main.py

#ifndef EXPR_ASDL
#define EXPR_ASDL

#include <cstdint>

#include "mycpp/runtime.h"
#include "_gen/asdl/hnode.asdl.h"
using hnode_asdl::hnode_t;

namespace expr_asdl {

// use struct instead of namespace so 'using' works consistently
#define ASDL_NAMES struct

class expr_t;

enum class tok_e {
  Const = 1,
  Var = 2,
  Op1 = 3,
  Op2 = 4,
  Paren = 5,
  Eof = 6,
  Invalid = 7,
};
typedef tok_e tok_t;

BigStr* tok_str(tok_e tag, bool dot = true);

ASDL_NAMES expr_e {
  enum no_name {
  Const = 1,
  Var = 2,
  Binary = 3,
  };
};

BigStr* expr_str(int tag, bool dot = true);

class expr_t {
 protected:
  expr_t() {
  }
 public:
  int tag() const {
    return ObjHeader::FromObject(this)->type_tag;
  }
  hnode_t* PrettyTree(Dict<int, bool>* seen = nullptr);
  DISALLOW_COPY_AND_ASSIGN(expr_t)
};

class expr__Const : public expr_t {
 public:
  expr__Const(int i)
      : i(i) {
  }

  static expr__Const* CreateNull(bool alloc_lists = false) { 
    return Alloc<expr__Const>(-1);
  }

  hnode_t* PrettyTree(Dict<int, bool>* seen = nullptr);

  static constexpr ObjHeader obj_header() {
    return ObjHeader::AsdlClass(static_cast<uint16_t>(expr_e::Const), 0);
  }

  int i;

  DISALLOW_COPY_AND_ASSIGN(expr__Const)
};

class expr__Var : public expr_t {
 public:
  expr__Var(BigStr* name)
      : name(name) {
  }

  static expr__Var* CreateNull(bool alloc_lists = false) { 
    return Alloc<expr__Var>(kEmptyString);
  }

  hnode_t* PrettyTree(Dict<int, bool>* seen = nullptr);

  static constexpr ObjHeader obj_header() {
    return ObjHeader::AsdlClass(static_cast<uint16_t>(expr_e::Var), 1);
  }

  BigStr* name;

  DISALLOW_COPY_AND_ASSIGN(expr__Var)
};

class expr__Binary : public expr_t {
 public:
  expr__Binary(BigStr* op, expr_t* left, expr_t* right)
      : op(op),
        left(left),
        right(right) {
  }

  static expr__Binary* CreateNull(bool alloc_lists = false) { 
    return Alloc<expr__Binary>(kEmptyString, nullptr, nullptr);
  }

  hnode_t* PrettyTree(Dict<int, bool>* seen = nullptr);

  static constexpr ObjHeader obj_header() {
    return ObjHeader::AsdlClass(static_cast<uint16_t>(expr_e::Binary), 3);
  }

  BigStr* op;
  expr_t* left;
  expr_t* right;

  DISALLOW_COPY_AND_ASSIGN(expr__Binary)
};

ASDL_NAMES expr {
  typedef expr__Const Const;
  typedef expr__Var Var;
  typedef expr__Binary Binary;
};


}  // namespace expr_asdl

#endif  // EXPR_ASDL