frame.hh

00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #ifndef FRAME_HH
00019 # define FRAME_HH
00020 
00021 # include "../memory/pool_allocator.hh"
00022 
00023 namespace aurelia {
00024   namespace llstack {
00025 
00026 struct real_frame {
00027   virtual real_frame* clone() const = 0;
00028   virtual unsigned hash() const = 0;
00029   virtual bool operator==(const real_frame& other) const = 0;
00030   virtual ~real_frame() {
00031   }
00032   virtual std::string toString() const = 0;
00033 };
00034 
00035 template <typename T>
00036 struct real_frame_helper: public real_frame {
00037   void* operator new
00038 #ifdef NDEBUG
00039   (size_t) {
00040 #else
00041   (size_t t) {
00042 #endif
00043     assert(t == sizeof(T));
00044     return chunk_alloc<T>::alloc();
00045   }
00046 
00047   void operator delete(void *p) {
00048     chunk_alloc<T>::del((T*) p);
00049   }
00050 
00051   virtual real_frame* clone() const {
00052     return new T(*static_cast<const T*>(this));
00053   }
00054 
00055   virtual bool operator==(const real_frame& other) const {
00056     const T* rother = dynamic_cast<const T*>(&other);
00057     if (rother == NULL)
00058       return false;
00059     return static_cast<const T*>(this)->opeq_impl(*rother);
00060   }
00061 };
00062 
00063 struct empty_frame: real_frame_helper<empty_frame> {
00064   virtual unsigned hash() const {
00065     return 4182910;
00066   }
00067   bool opeq_impl(const empty_frame&) const {
00068     return true;
00069   }
00070   virtual std::string toString() const {
00071     return "empty_frame";
00072   }
00073 };
00074 
00075 struct frame {
00076 private:
00077   std::shared_ptr<real_frame> rf;
00078   unsigned _hash;
00079 
00080 public:
00081   std::string toString() const {
00082     return rf->toString();
00083   }
00084 
00085   frame(const real_frame& rf): rf(rf.clone()), _hash(rf.hash()) {}
00086   frame(const frame& other): rf(other.rf), _hash(other._hash) {}
00087   frame(frame&& other): rf(std::move(other.rf)), _hash(std::move(other._hash)) {
00088   }
00089 
00090   frame(): rf(), _hash(0) {
00091   }
00092 
00093   frame& operator=(const frame& other) {
00094     return *this = frame(other);
00095   }
00096 
00097   frame& operator=(frame&& other) {
00098     std::swap(rf, other.rf);
00099     std::swap(_hash, other._hash);
00100     return *this;
00101   }
00102 
00103   struct hash_op {
00104     unsigned operator()(const frame& a) const {
00105       return a._hash;
00106     }
00107   };
00108 
00109   struct eq {
00110     unsigned operator()(const frame& a, const frame& b) const {
00111       return *(a.rf) == *(b.rf);
00112     }
00113   };
00114 
00115   unsigned hash() const {
00116     return _hash;
00117   }
00118 
00119   bool operator==(const frame& other) const {
00120     if (&*rf == &*other.rf)
00121       return true;
00122     return *rf == *(other.rf);
00123   }
00124 
00125   template <typename T>
00126   const T& as() const {
00127 #if NDEBUG
00128     return *static_cast<const T*>(&*rf);
00129 #else
00130     const T* ret = dynamic_cast<const T*>(&*rf);
00131     assert(ret != NULL);
00132     return *ret;
00133 #endif
00134   }
00135 };
00136 
00137 template <typename T>
00138 struct ret_frame: real_frame_helper<ret_frame<T> > {
00139   frame parent;
00140   T t;
00141   ret_frame(const frame& f, const T& t): parent(f), t(t) {}
00142   ret_frame(const ret_frame& other): parent(other.parent), t(other.t) {}
00143   bool opeq_impl(const ret_frame& other) const {
00144     return (parent == other.parent) && (other.t == t);
00145   }
00146   virtual unsigned hash() const {
00147     unsigned h = parent.hash();
00148     h = (h << 1) | (h >> 31);
00149     h ^= t.hash();
00150     return h;
00151   }
00152   virtual std::string toString() const {
00153     std::stringstream ss;
00154     ss << t;
00155     return "ret_frame(" + parent.toString() + "," + ss.str() + ")";
00156   }
00157 };
00158 
00159 struct void_return {
00160   unsigned hash() const {
00161     return 201293;
00162   }
00163   bool operator==(const void_return&) const {
00164     return true;
00165   }
00166 };
00167 
00168 template <typename Stream>
00169 Stream& operator<<(Stream& s, const void_return&) {
00170   s << "Void";
00171   return s;
00172 }
00173 
00174   }
00175 }
00176 
00177 #endif