summaryrefslogtreecommitdiff
path: root/scope.h
diff options
context:
space:
mode:
Diffstat (limited to 'scope.h')
-rw-r--r--scope.h72
1 files changed, 64 insertions, 8 deletions
diff --git a/scope.h b/scope.h
index 1bf50a3e..f0badb54 100644
--- a/scope.h
+++ b/scope.h
@@ -56,8 +56,28 @@ public:
else
return NULL_VALUE;
}
+
+ virtual optional<scope_t&> find_scope(const std::type_info&, bool = true) {
+ return none;
+ }
};
+template <typename T>
+inline T& find_scope(scope_t& scope, bool skip_this = true) {
+ optional<scope_t&> found = scope.find_scope(typeid(T), skip_this);
+ assert(found);
+ return downcast<T>(*found);
+}
+
+template <typename T>
+inline optional<T&> maybe_find_scope(scope_t& scope, bool skip_this = true) {
+ optional<scope_t&> found = scope.find_scope(typeid(T), skip_this);
+ if (found)
+ return optional<T&>(downcast<T>(*found));
+ else
+ return none;
+}
+
class child_scope_t : public noncopyable, public scope_t
{
public:
@@ -79,6 +99,17 @@ public:
return parent->lookup(name);
return expr_t::ptr_op_t();
}
+
+ virtual optional<scope_t&> find_scope(const std::type_info& type,
+ bool skip_this = true) {
+ for (scope_t * ptr = (skip_this ? parent : this);
+ ptr;
+ ptr = polymorphic_downcast<child_scope_t *>(ptr)->parent)
+ if (typeid(ptr) == type)
+ return *ptr;
+
+ return none;
+ }
};
class symbol_scope_t : public child_scope_t
@@ -152,30 +183,55 @@ public:
};
template <typename T>
-class var_t : public noncopyable
+class ptr_t : public noncopyable
{
T * value;
- var_t();
+ ptr_t();
public:
- // jww (2008-07-21): Give a good exception here if we can't find "name"
- var_t(scope_t& scope, const string& name)
+ ptr_t(scope_t& scope, const string& name)
: value(scope.resolve(name).template as_pointer<T>()) {
- TRACE_CTOR(var_t, "scope_t&, const string&");
+ TRACE_CTOR(ptr_t, "scope_t&, const string&");
}
- var_t(call_scope_t& scope, const unsigned int idx)
+ ptr_t(call_scope_t& scope, const unsigned int idx)
: value(scope[idx].template as_pointer<T>()) {
+ TRACE_CTOR(ptr_t, "call_scope_t&, const unsigned int");
+ }
+ ~ptr_t() throw() {
+ TRACE_DTOR(ptr_t);
+ }
+
+ T& operator *() { return *value; }
+ T * operator->() { return value; }
+};
+
+template <typename T>
+class var_t : public noncopyable
+{
+ value_t value;
+
+ var_t();
+
+public:
+ var_t(scope_t& scope, const string& name) : value(scope.resolve(name)) {
+ TRACE_CTOR(var_t, "scope_t&, const string&");
+ }
+ var_t(call_scope_t& scope, const unsigned int idx) : value(scope[idx]) {
TRACE_CTOR(var_t, "call_scope_t&, const unsigned int");
}
~var_t() throw() {
TRACE_DTOR(var_t);
}
- T& operator *() { return *value; }
- T * operator->() { return value; }
+ operator T() { assert(false); }
};
+template <>
+inline var_t<long>::operator long() {
+ return value.to_long();
+}
+
} // namespace ledger
#endif // _SCOPE_H