#pragma once

#include <ostream>

#include "ast/visitors.h"

namespace bpftrace {
namespace ast {

class Printer : public Visitor {
public:
  explicit Printer(std::ostream &out) : out_(out)
  {
  }

  void print(Node *root);

  void visit(Integer &integer) override;
  void visit(PositionalParameter &param) override;
  void visit(String &string) override;
  void visit(StackMode &mode) override;
  void visit(Identifier &identifier) override;
  void visit(Builtin &builtin) override;
  void visit(Call &call) override;
  void visit(Sizeof &szof) override;
  void visit(Offsetof &ofof) override;
  void visit(Map &map) override;
  void visit(Variable &var) override;
  void visit(Binop &binop) override;
  void visit(Unop &unop) override;
  void visit(Ternary &ternary) override;
  void visit(FieldAccess &acc) override;
  void visit(ArrayAccess &arr) override;
  void visit(Cast &cast) override;
  void visit(Tuple &tuple) override;
  void visit(ExprStatement &expr) override;
  void visit(AssignMapStatement &assignment) override;
  void visit(AssignVarStatement &assignment) override;
  void visit(AssignConfigVarStatement &assignment) override;
  void visit(VarDeclStatement &decl) override;
  void visit(If &if_node) override;
  void visit(Unroll &unroll) override;
  void visit(While &while_block) override;
  void visit(For &for_loop) override;
  void visit(Config &config) override;
  void visit(Block &block) override;
  void visit(Jump &jump) override;
  void visit(Predicate &pred) override;
  void visit(AttachPoint &ap) override;
  void visit(Probe &probe) override;
  void visit(Subprog &subprog) override;
  void visit(Program &program) override;

  int depth_ = -1;

private:
  std::ostream &out_;

  std::string type(const SizedType &ty);
};

} // namespace ast
} // namespace bpftrace
