#pragma once

#include <optional>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>

#include "Ast.hh"

// Symbols stored in the table (Variables, Parameters, Functions).
using Symbol = std::variant<VarDeclNode*, ParamDeclNode*, FunDeclNode*>;

class SymbolTableVisitor
{
public:
  SymbolTableVisitor ();

  void
  visit (const AstNodePtr& nodePtr);

private:
  void
  visit (AstNode& node);

  void
  enterScope ();

  void
  exitScope ();

  bool
  insertSymbol (const std::string& name, Symbol sym);

  std::optional<Symbol>
  lookupSymbol (const std::string& name) const;

private:
  std::vector<std::unordered_map<std::string, Symbol>> scopeStack_;

  // Built-in I/O function decls for input() and output().
  FunDeclNode inputDecl_;
  FunDeclNode outputDecl_;
};
