summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/item.h
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/item.h')
-rw-r--r--Build/source/utils/asymptote/item.h315
1 files changed, 315 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/item.h b/Build/source/utils/asymptote/item.h
new file mode 100644
index 00000000000..70d4923445e
--- /dev/null
+++ b/Build/source/utils/asymptote/item.h
@@ -0,0 +1,315 @@
+/*****
+ * item.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 <cfloat>
+#include <cmath>
+
+#if COMPACT
+#include <cassert>
+#else
+#include <typeinfo>
+#endif
+
+namespace vm {
+
+class item;
+class bad_item_value {};
+
+template<typename T>
+T get(const item&);
+
+#if COMPACT
+// Identify a default argument.
+extern const Int DefaultValue;
+
+// Identify an undefined item.
+extern const Int Undefined;
+
+// Values for true and false unlikely to match other values.
+extern const Int BoolTruthValue;
+extern const Int BoolFalseValue;
+
+inline Int valueFromBool(bool b) {
+ return b ? BoolTruthValue : BoolFalseValue;
+}
+#endif
+
+extern const item Default;
+
+class item : public gc {
+private:
+
+#if !COMPACT
+ const std::type_info *kind;
+#endif
+
+ union {
+ Int i;
+ double x;
+#if !COMPACT
+ bool b;
+#endif
+ void *p;
+ };
+
+public:
+#if COMPACT
+ bool empty() const
+ {return i >= Undefined;}
+
+ item() : i(Undefined) {}
+
+ item(Int i)
+ : i(i) {}
+ item(int i)
+ : i(i) {}
+ item(double x)
+ : x(x) {}
+ item(bool b)
+ : i(valueFromBool(b)) {}
+
+ item& operator= (int a)
+ { i=a; return *this; }
+ item& operator= (unsigned int a)
+ { i=a; return *this; }
+ item& operator= (Int a)
+ { i=a; return *this; }
+ item& operator= (double a)
+ { x=a; return *this; }
+ item& operator= (bool b)
+ { i=valueFromBool(b); return *this; }
+
+ template<class T>
+ item(T *p)
+ : p((void *) p) {
+ assert(!empty());
+ }
+
+ template<class T>
+ item(const T &p)
+ : p(new(UseGC) T(p)) {
+ assert(!empty());
+ }
+
+ template<class T>
+ item& operator= (T *a)
+ { p=(void *) a; return *this; }
+
+ template<class T>
+ item& operator= (const T &it)
+ { p=new(UseGC) T(it); return *this; }
+#else
+ bool empty() const
+ {return *kind == typeid(void);}
+
+ item()
+ : kind(&typeid(void)) {}
+
+ item(Int i)
+ : kind(&typeid(Int)), i(i) {}
+ item(int i)
+ : kind(&typeid(Int)), i(i) {}
+ item(double x)
+ : kind(&typeid(double)), x(x) {}
+ item(bool b)
+ : kind(&typeid(bool)), b(b) {}
+
+ item& operator= (int a)
+ { kind=&typeid(Int); i=a; return *this; }
+ item& operator= (unsigned int a)
+ { kind=&typeid(Int); i=a; return *this; }
+ 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<class T>
+ item(T *p)
+ : kind(&typeid(T)), p((void *) p) {}
+
+ template<class T>
+ item(const T &p)
+ : kind(&typeid(T)), p(new(UseGC) T(p)) {}
+
+ template<class T>
+ item& operator= (T *a)
+ { kind=&typeid(T); p=(void *) a; return *this; }
+
+ template<class T>
+ item& operator= (const T &it)
+ { kind=&typeid(T); p=new(UseGC) T(it); return *this; }
+
+ const std::type_info &type() const
+ { return *kind; }
+#endif
+
+ template<typename T>
+ friend inline T get(const item&);
+
+ friend inline bool isdefault(const item&);
+
+ friend ostream& operator<< (ostream& out, const item& i);
+
+private:
+ template <typename T>
+ struct help;
+
+ template <typename T>
+ struct help<T*> {
+ static T* unwrap(const item& it)
+ {
+#if COMPACT
+ if(!it.empty())
+ return (T*) it.p;
+#else
+ if(*it.kind == typeid(T))
+ return (T*) it.p;
+#endif
+ throw vm::bad_item_value();
+ }
+ };
+
+ template <typename T>
+ struct help {
+ static T& unwrap(const item& it)
+ {
+#if COMPACT
+ if(!it.empty())
+ return *(T*) it.p;
+#else
+ if(*it.kind == typeid(T))
+ return *(T*) it.p;
+#endif
+ throw vm::bad_item_value();
+ }
+ };
+};
+
+#ifdef SIMPLE_FRAME
+// In the simple implementation, a frame is just an array of items.
+typedef item frame;
+#else
+class frame : public gc {
+#ifdef DEBUG_FRAME
+ string name;
+ Int parentIndex;
+#endif
+ typedef mem::vector<item> internal_vars_t;
+ internal_vars_t vars;
+
+ // Allow the stack direct access to vars.
+ friend class stack;
+public:
+#ifdef DEBUG_FRAME
+ frame(string name, Int parentIndex, size_t size)
+ : name(name), parentIndex(parentIndex), vars(size)
+ {}
+
+ string getName() { return name; }
+
+ Int getParentIndex() { return parentIndex; }
+#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);
+ }
+};
+#endif
+
+
+template<typename T>
+inline T get(const item& it)
+{
+ return item::help<T>::unwrap(it);
+}
+
+template <>
+inline int get<int>(const item&)
+{
+ throw vm::bad_item_value();
+}
+
+template <>
+inline Int get<Int>(const item& it)
+{
+#if COMPACT
+ if(!it.empty())
+ return it.i;
+#else
+ if(*it.kind == typeid(Int))
+ return it.i;
+#endif
+ throw vm::bad_item_value();
+}
+
+template <>
+inline double get<double>(const item& it)
+{
+#if COMPACT
+ if(!it.empty())
+ return it.x;
+#else
+ if(*it.kind == typeid(double))
+ return it.x;
+#endif
+ throw vm::bad_item_value();
+}
+
+template <>
+inline bool get<bool>(const item& it)
+{
+#if COMPACT
+ if(it.i == BoolTruthValue)
+ return true;
+ if(it.i == BoolFalseValue)
+ return false;
+#else
+ if(*it.kind == typeid(bool))
+ return it.b;
+#endif
+ throw vm::bad_item_value();
+}
+
+#if !COMPACT
+// This serves as the object for representing a default argument.
+struct default_t : public gc {};
+#endif
+
+inline bool isdefault(const item& it)
+{
+#if COMPACT
+ return it.i == DefaultValue;
+#else
+ return *it.kind == typeid(default_t);
+#endif
+}
+
+ostream& operator<< (ostream& out, const item& i);
+
+} // namespace vm
+
+#endif // ITEM_H