/***** * inst.h * Tom Prince and John Bowman 2005/04/12 * * Descibes the items that are used by the virtual machine. *****/ #ifndef ITEM_H #define ITEM_H #include "common.h" #include namespace vm { class item; class bad_item_value {}; template T get(const item&); class item : public gc { public: bool empty() const { return *kind == typeid(void); } item() : kind(&typeid(void)) {} #ifndef Int item(Int i) : kind(&typeid(Int)), i(i) {} #endif item(int i) : kind(&typeid(Int)), i(i) {} item(double x) : kind(&typeid(double)), x(x) {} item(bool b) : kind(&typeid(bool)), b(b) {} #ifndef Int item& operator= (int a) { kind=&typeid(Int); i=a; return *this; } #endif item& operator= (Int a) { kind=&typeid(Int); i=a; return *this; } item& operator= (double a) { kind=&typeid(double); x=a; return *this; } item& operator= (bool a) { kind=&typeid(bool); b=a; return *this; } template item(T *p) : kind(&typeid(T)), p((void *) p) {} template item(const T &p) : kind(&typeid(T)), p(new(UseGC) T(p)) {} template item& operator= (T *a) { kind=&typeid(T); p=(void *) a; return *this; } template item& operator= (const T &it) { kind=&typeid(T); p=new(UseGC) T(it); return *this; } template friend inline T get(const item&); friend inline bool isdefault(const item&); friend inline bool isarray(const item&); const std::type_info &type() const { return *kind; } friend ostream& operator<< (ostream& out, const item& i); private: const std::type_info *kind; union { Int i; double x; bool b; void *p; }; template struct help; template struct help { static T* unwrap(const item& it) { if (*it.kind == typeid(T)) return (T*) it.p; throw vm::bad_item_value(); } }; template struct help { static T& unwrap(const item& it) { if (*it.kind == typeid(T)) return *(T*) it.p; throw vm::bad_item_value(); } }; }; class frame : public gc { #ifdef DEBUG_FRAME string name; #endif typedef mem::vector vars_t; vars_t vars; public: #ifdef DEBUG_FRAME frame(string name, size_t size) : name(name), vars(size) {} string getName() { return name; } #else frame(size_t size) : vars(size) {} #endif item& operator[] (size_t n) { return vars[n]; } item operator[] (size_t n) const { return vars[n]; } size_t size() { return vars.size(); } // Extends vars to ensure it has a place for any variable indexed up to n. void extend(size_t n) { if (vars.size() < n) vars.resize(n); } }; template inline T get(const item& it) { return item::help::unwrap(it); } #ifndef Int template <> inline int get(const item&) { throw vm::bad_item_value(); } #endif template <> inline Int get(const item& it) { if (*it.kind == typeid(Int)) return it.i; throw vm::bad_item_value(); } template <> inline double get(const item& it) { if (*it.kind == typeid(double)) return it.x; throw vm::bad_item_value(); } template <> inline bool get(const item& it) { if (*it.kind == typeid(bool)) return it.b; throw vm::bad_item_value(); } // This serves as the object for representing a default argument. struct default_t : public gc {}; inline bool isdefault(const item& it) { return *it.kind == typeid(default_t); } ostream& operator<< (ostream& out, const item& i); } // namespace vm GC_DECLARE_PTRFREE(vm::default_t); #endif // ITEM_H