Change the value_t::POINTER type to value_t::SCOPE

scope_t pointers are the only kind that are ever stored in value
objects, so there was no need to make it generic and use boost::any.
This commit is contained in:
John Wiegley 2009-10-30 17:56:44 -04:00
parent 5f2c766e0d
commit 7ca80112fc
6 changed files with 37 additions and 68 deletions

View file

@ -118,9 +118,9 @@ void interactive_t::verify_arguments() const
label = _("any value"); label = _("any value");
wrong_arg = false; wrong_arg = false;
break; break;
case 'P': case '^':
label = _("a pointer"); label = _("a scope");
wrong_arg = ! next_arg->is_pointer(); wrong_arg = ! next_arg->is_scope();
break; break;
case 'S': case 'S':
label = _("a sequence"); label = _("a sequence");

View file

@ -172,12 +172,12 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
left()->left() && left()->left()->is_function()) { left()->left() && left()->left()->is_function()) {
call_scope_t call_args(scope); call_scope_t call_args(scope);
if (value_t obj = left()->left()->as_function()(call_args)) { if (value_t obj = left()->left()->as_function()(call_args)) {
if (obj.is_pointer()) { if (obj.is_scope()) {
if (obj.as_pointer_lval<scope_t>() == NULL) { if (obj.as_scope() == NULL) {
throw_(calc_error, throw_(calc_error,
_("Left operand of . operator is NULL")); _("Left operand of . operator is NULL"));
} else { } else {
scope_t& objscope(obj.as_ref_lval<scope_t>()); scope_t& objscope(*obj.as_scope());
if (ptr_op_t member = objscope.lookup(right()->as_ident())) { if (ptr_op_t member = objscope.lookup(right()->as_ident())) {
result = member->calc(objscope, NULL, depth + 1); result = member->calc(objscope, NULL, depth + 1);
break; break;

View file

@ -45,8 +45,8 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(value_overloads, value, 0, 2)
namespace { namespace {
expr_t py_value_getattr(const value_t& value, const string& name) expr_t py_value_getattr(const value_t& value, const string& name)
{ {
if (value.is_pointer()) { if (value.is_scope()) {
if (scope_t * scope = value.as_pointer<scope_t>()) if (scope_t * scope = value.as_scope())
return expr_t(scope->lookup(name), scope); return expr_t(scope->lookup(name), scope);
} }
throw_(value_error, _("Cannot lookup attributes in %1") << value.label()); throw_(value_error, _("Cannot lookup attributes in %1") << value.label());
@ -283,7 +283,7 @@ void export_value()
.value("BALANCE", value_t::BALANCE) .value("BALANCE", value_t::BALANCE)
.value("STRING", value_t::STRING) .value("STRING", value_t::STRING)
.value("SEQUENCE", value_t::SEQUENCE) .value("SEQUENCE", value_t::SEQUENCE)
.value("POINTER", value_t::POINTER) .value("SCOPE", value_t::SCOPE)
; ;
scope().attr("NULL_VALUE") = NULL_VALUE; scope().attr("NULL_VALUE") = NULL_VALUE;

View file

@ -138,7 +138,6 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/any.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/cast.hpp> #include <boost/cast.hpp>
#include <boost/current_function.hpp> #include <boost/current_function.hpp>

View file

@ -113,8 +113,8 @@ value_t::operator bool() const
} }
} }
return false; return false;
case POINTER: case SCOPE:
return ! as_any_pointer().empty(); return as_scope() != NULL;
default: default:
break; break;
} }
@ -1206,8 +1206,8 @@ bool value_t::is_realzero() const
case SEQUENCE: case SEQUENCE:
return as_sequence().empty(); return as_sequence().empty();
case POINTER: case SCOPE:
return as_any_pointer().empty(); return as_scope() == NULL;
default: default:
throw_(value_error, _("Cannot determine if %1 is really zero") << label()); throw_(value_error, _("Cannot determine if %1 is really zero") << label());
@ -1235,8 +1235,8 @@ bool value_t::is_zero() const
case SEQUENCE: case SEQUENCE:
return as_sequence().empty(); return as_sequence().empty();
case POINTER: case SCOPE:
return as_any_pointer().empty(); return as_scope() == NULL;
default: default:
throw_(value_error, _("Cannot determine if %1 is zero") << label()); throw_(value_error, _("Cannot determine if %1 is zero") << label());
@ -1474,7 +1474,7 @@ value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const
case DATE: case DATE:
case STRING: case STRING:
case MASK: case MASK:
case POINTER: case SCOPE:
return *this; return *this;
case SEQUENCE: { case SEQUENCE: {
@ -1579,8 +1579,8 @@ void value_t::print(std::ostream& out,
break; break;
} }
case POINTER: case SCOPE:
out << "<POINTER>"; out << "<SCOPE>";
break; break;
default: default:
@ -1647,8 +1647,8 @@ void value_t::dump(std::ostream& out, const bool relaxed) const
out << '/' << as_mask() << '/'; out << '/' << as_mask() << '/';
break; break;
case POINTER: case SCOPE:
out << boost::unsafe_any_cast<const void *>(&as_any_pointer()); out << as_scope();
break; break;
case SEQUENCE: { case SEQUENCE: {

View file

@ -56,6 +56,8 @@ namespace ledger {
DECLARE_EXCEPTION(value_error, std::runtime_error); DECLARE_EXCEPTION(value_error, std::runtime_error);
class scope_t;
/** /**
* @class value_t * @class value_t
* *
@ -107,7 +109,7 @@ public:
STRING, // a string object STRING, // a string object
MASK, // a regular expression mask MASK, // a regular expression mask
SEQUENCE, // a vector of value_t objects SEQUENCE, // a vector of value_t objects
POINTER // an opaque pointer of any type SCOPE // a pointer to a scope
}; };
private: private:
@ -134,7 +136,7 @@ private:
string, // STRING string, // STRING
mask_t, // MASK mask_t, // MASK
sequence_t *, // SEQUENCE sequence_t *, // SEQUENCE
boost::any // POINTER scope_t * // SCOPE
> data; > data;
type_t type; type_t type;
@ -332,10 +334,9 @@ public:
set_sequence(val); set_sequence(val);
} }
template <typename T> explicit value_t(scope_t * item) {
explicit value_t(T * item) { TRACE_CTOR(value_t, "scope_t *");
TRACE_CTOR(value_t, "T *"); set_scope(item);
set_pointer(item);
} }
/** /**
@ -687,50 +688,19 @@ public:
} }
/** /**
* Dealing with pointers is bit involved because we actually deal * Dealing with scope pointers.
* with typed pointers. For example, if you call as_pointer it
* returns a boost::any object, but if you use as_pointer<void>,
* then it returns a void *. The latter form only succeeds if the
* stored pointers was assigned to the value as a void*, otherwise
* it throws an exception.
*/ */
bool is_pointer() const { bool is_scope() const {
return is_type(POINTER); return is_type(SCOPE);
} }
boost::any& as_any_pointer_lval() { scope_t * as_scope() const {
VERIFY(is_pointer()); VERIFY(is_scope());
_dup(); return boost::get<scope_t *>(storage->data);
return boost::get<boost::any>(storage->data);
} }
template <typename T> void set_scope(scope_t * val) {
T * as_pointer_lval() { set_type(SCOPE);
return any_cast<T *>(as_any_pointer_lval());
}
template <typename T>
T& as_ref_lval() {
return *as_pointer_lval<T>();
}
const boost::any& as_any_pointer() const {
VERIFY(is_pointer());
return boost::get<boost::any>(storage->data);
}
template <typename T>
T * as_pointer() const {
return any_cast<T *>(as_any_pointer());
}
template <typename T>
T& as_ref() const {
return *as_pointer<T>();
}
void set_any_pointer(const boost::any& val) {
set_type(POINTER);
storage->data = val; storage->data = val;
} }
template <typename T>
void set_pointer(T * val) {
set_type(POINTER);
storage->data = boost::any(val);
}
/** /**
* Data conversion methods. These methods convert a value object to * Data conversion methods. These methods convert a value object to
@ -902,8 +872,8 @@ public:
return _("a regexp"); return _("a regexp");
case SEQUENCE: case SEQUENCE:
return _("a sequence"); return _("a sequence");
case POINTER: case SCOPE:
return _("a pointer"); return _("a scope");
default: default:
assert(false); assert(false);
break; break;