summaryrefslogtreecommitdiff
path: root/evaluate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'evaluate.cpp')
-rw-r--r--evaluate.cpp45
1 files changed, 27 insertions, 18 deletions
diff --git a/evaluate.cpp b/evaluate.cpp
index c73d59a..ebfb773 100644
--- a/evaluate.cpp
+++ b/evaluate.cpp
@@ -1,4 +1,4 @@
-#include <map>
+#include <stdexcept>
#include <cassert>
#include "evaluate.h"
@@ -9,37 +9,46 @@ Value::Value(double numval)
:type(Type::number),numval(numval){}
Value::Value(const string &strval)
:type(Type::string),strval(strval){}
-Value::Value(const Scope &scope)
+Value::Value(ScopeVal *scope)
:type(Type::scope),scope(scope){}
namespace A {
- map<Value*,int> collection;
-
- template <typename ...Args>
- Value* ref_create(Args... args){
- Value *value=new Value(args...);
- return ref(value);
+ struct CollItem{
+ int count;
+ void (*deleter)(void*);
+ };
+
+ template <typename T>
+ static void generic_deleter(void *p){
+ delete (T*)p;
}
- Value* ref(Value *value){
- auto it=collection.find(value);
+ unordered_map<void*,CollItem> collection;
+
+ template <typename T>
+ T* ref(T *p){
+ auto it=collection.find((void*)p);
if(it==collection.end()){
- collection.emplace(value,1);
+ collection.emplace((void*)p,(CollItem){1,generic_deleter<T>});
} else {
- it->second++;
+ it->second.count++;
}
- return value;
+ return p;
}
- void unref(Value *value){
- auto it=collection.find(value);
+ template <typename T>
+ void unref(T *p){
+ auto it=collection.find(p);
assert(it!=collection.end());
- if(it->second==1){
- delete value;
+ if(it->second.count==1){
+ if(it->second.deleter!=generic_deleter<T>){
+ throw runtime_error("Unref'd pointer type not the same as the ref'd version!");
+ }
+ it->second.deleter(p);
collection.erase(it);
} else {
- it->second--;
+ it->second.count--;
}
}
}