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");
wrong_arg = false;
break;
case 'P':
label = _("a pointer");
wrong_arg = ! next_arg->is_pointer();
case '^':
label = _("a scope");
wrong_arg = ! next_arg->is_scope();
break;
case 'S':
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()) {
call_scope_t call_args(scope);
if (value_t obj = left()->left()->as_function()(call_args)) {
if (obj.is_pointer()) {
if (obj.as_pointer_lval<scope_t>() == NULL) {
if (obj.is_scope()) {
if (obj.as_scope() == NULL) {
throw_(calc_error,
_("Left operand of . operator is NULL"));
} 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())) {
result = member->calc(objscope, NULL, depth + 1);
break;

View file

@ -45,8 +45,8 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(value_overloads, value, 0, 2)
namespace {
expr_t py_value_getattr(const value_t& value, const string& name)
{
if (value.is_pointer()) {
if (scope_t * scope = value.as_pointer<scope_t>())
if (value.is_scope()) {
if (scope_t * scope = value.as_scope())
return expr_t(scope->lookup(name), scope);
}
throw_(value_error, _("Cannot lookup attributes in %1") << value.label());
@ -283,7 +283,7 @@ void export_value()
.value("BALANCE", value_t::BALANCE)
.value("STRING", value_t::STRING)
.value("SEQUENCE", value_t::SEQUENCE)
.value("POINTER", value_t::POINTER)
.value("SCOPE", value_t::SCOPE)
;
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/predicate.hpp>
#include <boost/any.hpp>
#include <boost/bind.hpp>
#include <boost/cast.hpp>
#include <boost/current_function.hpp>

View file

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

View file

@ -56,6 +56,8 @@ namespace ledger {
DECLARE_EXCEPTION(value_error, std::runtime_error);
class scope_t;
/**
* @class value_t
*
@ -107,7 +109,7 @@ public:
STRING, // a string object
MASK, // a regular expression mask
SEQUENCE, // a vector of value_t objects
POINTER // an opaque pointer of any type
SCOPE // a pointer to a scope
};
private:
@ -134,7 +136,7 @@ private:
string, // STRING
mask_t, // MASK
sequence_t *, // SEQUENCE
boost::any // POINTER
scope_t * // SCOPE
> data;
type_t type;
@ -332,10 +334,9 @@ public:
set_sequence(val);
}
template <typename T>
explicit value_t(T * item) {
TRACE_CTOR(value_t, "T *");
set_pointer(item);
explicit value_t(scope_t * item) {
TRACE_CTOR(value_t, "scope_t *");
set_scope(item);
}
/**
@ -687,50 +688,19 @@ public:
}
/**
* Dealing with pointers is bit involved because we actually deal
* 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.
* Dealing with scope pointers.
*/
bool is_pointer() const {
return is_type(POINTER);
bool is_scope() const {
return is_type(SCOPE);
}
boost::any& as_any_pointer_lval() {
VERIFY(is_pointer());
_dup();
return boost::get<boost::any>(storage->data);
scope_t * as_scope() const {
VERIFY(is_scope());
return boost::get<scope_t *>(storage->data);
}
template <typename T>
T * as_pointer_lval() {
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);
void set_scope(scope_t * val) {
set_type(SCOPE);
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
@ -902,8 +872,8 @@ public:
return _("a regexp");
case SEQUENCE:
return _("a sequence");
case POINTER:
return _("a pointer");
case SCOPE:
return _("a scope");
default:
assert(false);
break;