構造体の実装

メモを取ることは大切。公開することも大切。
という訳で、こまめに実装メモを取っていくことにしました。


構造体を実装するにあたって、さて、どうするか。


構造体をスタック上でどのように表現するかは、
単純に、全体サイズ分アロケートして、メンバを並べる形にします。
そうなると、アクセスする際スタック上でのメンバのオフセット情報が必要になってくるので、
その情報を持ったものを要素とした、構造体の定義のテーブルを
コンパイラ本体に持たせることにしました。
構造体、およびそのメンバにアクセスするときはこのテーブルからオフセットを取ることにします。


ここら辺は、関数テーブルでのやり方を参考にしました。

class CTypeTagMember {
public:
  CTypeTagMember(int type, int offset)
    : isUserDefinedType_(false)
    , type_(type)
    , typeName_()
    , offset_(offset)
  {
  }

  CTypeTagMember(const std::string& typeName, int offset)
    : isUserDefinedType_(false)
    , type_(0)
    , typeName_(typeName)
    , offset_(offset)
  {
  }

public:
  bool isUserDefinedType() { return isUserDefinedType_; }
  int type() { return type_; }
  const std::string& typeName() const { return typeName_; }
  int offset() { return offset_; }

private:
  bool isUserDefinedType_;
  int type_;
  std::string typeName_;
  int offset_;
};

class CTypeTag {
  typedef std::map<std::string, CTypeTagMember>::iterator itr;
  typedef std::map<std::string, CTypeTagMember>::const_iterator const_itr;
public:
  CTypeTag()
    : size_()
    , addrList_()
  {
  }

  int size() const { return size_; }

  // 追加に失敗したときはfalseが返る
  void setMembers(Compiler& c, const CTypeMemberList* typeMembers);

private:
  int size_;// すべてのメンバの総量
  std::map<std::string, CTypeTagMember> addrList_;
};

//-----------------------------------------------------------------
// TypeTagTable
//-----------------------------------------------------------------
class CTypeTable {
private:
  typedef std::map<std::string, CTypeTag>::iterator itr;
  typedef std::map<std::string, CTypeTag>::const_iterator const_itr;
public:
  CTypeTable()
    : typeList_()
  {
  }

  // 追加
  const CTypeTag* add(const std::string& name, const CTypeTag& typeTag)
  {
    std::pair<itr, bool> result = typeList_.insert(make_pair(name, typeTag));
    if (result.second) {
      return &result.first->second;
    }
    return NULL;
  }

  // 型の検索
  const CTypeTag* find(const std::string& name) const
  {
    const_itr it = typeList_.find(name);
    if (it != typeList_.end()) {
      return &it->second;
    }
    // 見つからなかったらNULL
    return NULL;
  }

  CTypeTag* find(const std::string& name)
  {
    itr it = typeList_.find(name);
    if (it != typeList_.end()) {
      return &it->second;
    }
    return NULL;
  }

private:
  std::map<std::string, CTypeTag> typeList_;
};

定義情報はとりあえず。こんな感じで。
parserに通してみたけど、現状では問題なさそう。