Program Listing for File symbol_table.h

Return to documentation for file (src/symbol_table.h)

#ifndef PROJECT02_SYMBOL_TABLE_H
#define PROJECT02_SYMBOL_TABLE_H

#include <assert.h>

#include <string>
#include <map>

#include "compiler_utils.h" // Uses hash for map
//#include "quack_class.h"
#include "exceptions.h"

typedef std::pair<std::string, bool> SymbolKey;

// Forward declarations
namespace Quack{ class Class; }
namespace CodeGen { class Gen; }

class Symbol {
  friend class CodeGen::Gen;
  friend class Quack::Class;
  friend class Table;
 public:
  class Table {
   public:
    ~Table() {
      for (const auto &symbol_info : objs_)
        delete symbol_info.second;
    }
//    /**
//     * Adds a new symbol the table.  The symbol is set to the base class of all classes.
//     * @param symbol_name Name of the symbol
//     * @param is_field True if the new symbol is a field
//     */
//    void add_new(const std::string &symbol_name, bool is_field) {
//      add_new(symbol_name, is_field, BASE_CLASS);
//    }
    void add_new(const std::string &symbol_name, bool is_field, Quack::Class *new_class) {
      SymbolKey key(symbol_name, is_field);
      objs_[key] = new Symbol(symbol_name, is_field, new_class);

      is_dirty_ = true;
    }
    void update(const std::string &symbol_name, bool is_field, Quack::Class *new_class) {
      SymbolKey key(symbol_name, is_field);

      assert(exists(key));
      is_dirty_ = is_dirty_ || (objs_[key]->get_type() != new_class);
      objs_[key]->set_type(new_class);
    }
    void update(const Symbol * symbol, Quack::Class *new_class) {
      update(symbol->name_, symbol->is_field_, new_class);
    }
    inline const bool is_dirty() const { return is_dirty_; }
    inline void clear_dirty() { is_dirty_ = false; }
    Symbol* get(const std::string &symbol_name, bool is_field) const {
      SymbolKey key(symbol_name, is_field);
      assert(exists(key));

      auto itr = objs_.find(key);
      if (itr == objs_.end())
        throw UnknownSymbolException(symbol_name);
      return itr->second;
    }
    typename std::map<SymbolKey, Symbol*>::iterator begin() { return objs_.begin(); }
    typename std::map<SymbolKey, Symbol*>::iterator end() { return objs_.end(); }
   private:
    bool exists(const SymbolKey &key) const {
      return objs_.find(key) != objs_.end();
    }

    std::map<SymbolKey,Symbol*> objs_;

    bool is_dirty_ = false;
  };
  Symbol(const std::string &name, bool is_field) : Symbol(name, is_field, nullptr) {}

  Symbol(std::string name, bool is_field, Quack::Class* q_class)
      : name_(std::move(name)), is_field_(is_field), class_(q_class) {}
  Quack::Class* get_type() const { return class_; }

 private:
  void set_type(Quack::Class *q_class) { class_ = q_class; }

  std::string name_;
  bool is_field_;
  Quack::Class * class_;
};

#endif //PROJECT02_SYMBOL_TABLE_H