aboutsummaryrefslogtreecommitdiffstats
path: root/tuplr.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'tuplr.hpp')
-rw-r--r--tuplr.hpp35
1 files changed, 23 insertions, 12 deletions
diff --git a/tuplr.hpp b/tuplr.hpp
index ce0a2f3..48c3fe6 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -142,25 +142,38 @@ struct Object; ///< Object (AST nodes and runtime data)
struct CEnv; ///< Compile-Time Environment
struct GC {
+ enum Tag {
+ TAG_AST = 2, ///< Abstract syntax tree node
+ TAG_TYPE = 4, ///< Type
+ TAG_FRAME = 6 ///< Stack frame
+ };
typedef std::list<const Object*> Roots;
typedef std::list<Object*> Heap;
- void* alloc(size_t size);
- void collect(CEnv& cenv, const Roots& roots);
+ void* alloc(size_t size, Tag tag);
+ void collect(const Roots& roots);
void addRoot(const Object* obj) { if (obj) _roots.push_back(obj); }
void lock() { _roots.insert(_roots.end(), _heap.begin(), _heap.end()); }
const Roots& roots() const { return _roots; }
private:
- Heap _heap;
- Roots _roots;
+ Heap _heap;
+ Roots _roots;
};
+/// Dynamic (garbage-collected) object
struct Object {
- Object() : used(false) {}
- virtual ~Object() {}
+ struct Header {
+ uint8_t mark;
+ uint8_t tag;
+ };
- mutable bool used;
+ /// Always allocated with pool.alloc, so this - sizeof(Header) is a valid Header*.
+ inline Header* header() const { return (Header*)((char*)this - sizeof(Header)); }
- static void* operator new(size_t size) { return pool.alloc(size); }
+ inline bool marked() const { return header()->mark != 0; }
+ inline void mark(bool b) const { header()->mark = 1; }
+ inline GC::Tag tag() const { return (GC::Tag)header()->tag; }
+
+ static void* operator new(size_t size) { return pool.alloc(size, GC::TAG_AST); }
static void operator delete(void* ptr) {}
static GC pool;
};
@@ -181,6 +194,7 @@ extern ostream& operator<<(ostream& out, const AST* ast);
/// Base class for all AST nodes
struct AST : public Object {
AST(Cursor c=Cursor()) : loc(c) {}
+ virtual ~AST() {}
virtual bool operator==(const AST& o) const = 0;
virtual bool contains(const AST* child) const { return false; }
virtual void constrain(TEnv& tenv, Constraints& c) const {}
@@ -233,10 +247,6 @@ struct ATuple : public AST, public vector<AST*> {
push_back(a);
va_end(args);
}
- void free() {
- FOREACH(const_iterator, p, *this)
- delete *p;
- }
bool operator==(const AST& rhs) const {
const ATuple* rt = rhs.to<const ATuple*>();
if (!rt || rt->size() != size()) return false;
@@ -315,6 +325,7 @@ struct AType : public ATuple {
}
return false; // never reached
}
+ static void* operator new(size_t size) { return pool.alloc(size, GC::TAG_TYPE); }
enum { VAR, PRIM, EXPR } kind;
unsigned id;
};