Skip to content

Commit

Permalink
Improved interface
Browse files Browse the repository at this point in the history
chg: simplified redundant interface
fix: left-hand side of assignment may also be a reference
new: M-ary operations for references; def(reference)
chg: compile-time de-reference where possible
  • Loading branch information
Alexander Dreyer authored and Oleksandr Motsak committed Sep 5, 2012
1 parent 4d55e48 commit 971984c
Showing 1 changed file with 156 additions and 108 deletions.
264 changes: 156 additions & 108 deletions Singular/countedref.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,72 +32,48 @@
#include "attrib.h"


/** @class CountedRefData
* This class stores a reference counter as well as a Singular interpreter object.
*
* It also stores the Singular token number, once per type.
**/
class CountedRefData {
typedef CountedRefData self;
class CountedRef {
typedef CountedRef self;

public:
class access {
typedef access self;

public:
access(CountedRefData* data):
m_data(NULL), m_owns(true) { init(&data->m_data, data->m_ring); }


access(leftv data):
m_data(data), m_owns(is_ref(data)) {
if(m_owns)
init((CountedRefData*)(data->Data()));
}

access(const self& rhs):
m_data(rhs.m_data), m_owns(rhs.m_owns) {

if (m_owns){
m_data = (leftv)omAlloc0(sizeof(sleftv));
if(rhs.m_data != NULL) memcpy(m_data, rhs.m_data, sizeof(sleftv));
}
}

~access() { if (m_owns) omFree(m_data); }

leftv operator->() { return *this; }
operator leftv() { return m_data; }
typedef int id_type;

private:
/// Set Singular type identitfier
CountedRef(blackbox& bbx) {
CountedRefAccess_id() = setBlackboxStuff(&bbx, "reference");
}
CountedRef() { }

void init(CountedRefData* all) { init(&(all->m_data), all->m_ring); }

void init(leftv data, ring ringdata) {
m_data = (leftv)omAlloc0(sizeof(sleftv));
if (RingDependend(data->Typ()) && (ringdata != currRing)) {
Werror("Can only use references from current ring.");
return;
}
memcpy(m_data, data, sizeof(sleftv));
data->next = NULL;
}
leftv m_data;
bool m_owns;
};
/// Get Singular type identitfier
static id_type id() { return CountedRefAccess_id(); }

/// Check for being reference in Singular interpreter object
static BOOLEAN is_ref(leftv arg) { return (arg->Typ() == id()); }
private:
/// Access identifier (one per class)
static id_type& CountedRefAccess_id() {
static id_type g_id = 0;
return g_id;
}

};
/** @class CountedRefData
* This class stores a reference counter as well as a Singular interpreter object.
*
* It also stores the Singular token number, once per type.
**/
class CountedRefData: public CountedRef {
typedef CountedRefData self;

/// Forbit copy construction and normal assignment
CountedRefData(const self&);
self& operator=(const self&);

public:
typedef int id_type;
typedef unsigned long count_type;

/// Construct reference for Singular object
CountedRefData(leftv data): m_data(*data), m_count(1), m_ring(NULL) {
CountedRefData(leftv data): m_data(*data), m_count(0), m_ring(NULL) {

if (RingDependend(data->Typ()) && (currRing != NULL) ) {
m_ring = currRing;
Expand All @@ -112,7 +88,7 @@ class CountedRefData {
/// Destructor
~CountedRefData() {
assume(m_count == 0);
if(m_data.e) omFree(m_data.e);
if (m_data.e) omFree(m_data.e);
if (m_ring) --m_ring->ref;
}

Expand All @@ -129,69 +105,116 @@ class CountedRefData {
}
return (op == NONE? TRUE: FALSE);
}
static BOOLEAN none(leftv result) { return set_to(result, NULL, NONE); }




/// Set Singular type identitfier
static void set_id(id_type new_id) { access_id() = new_id; }
static BOOLEAN construct(leftv result, leftv arg) {
self* pRef(is_ref(arg)? static_cast<self*>(arg->Data()): new self(arg));
pRef->reclaim();

/// Get Singular type identitfier
static id_type id() { return access_id(); }

static void* copy(self* ptr) {
if (ptr) ptr->reclaim();
return ptr;
return set_to(result, pRef, id());
}


static void destroy(self* ptr) {
if(ptr && !ptr->release())
delete ptr;
}

static BOOLEAN assign(leftv result, leftv arg) {
// Case: replace assignment behind reference
if (result->Data() != NULL)
return iiAssign(access(result), arg);

// Case: new reference
if(arg->rtyp == IDHDL)
return set_to(result, (is_ref(arg)? (self*)copy(static_cast<self*>(arg->Data())):
new self(arg)), id());

Werror("Can only take reference from identifier");
return none(result);
}

/// Check for being reference in Singular interpreter object
static BOOLEAN is_ref(leftv arg) { return (arg->Typ() == id()); }
private:
/// @name Reference counter management
//@{
count_type reclaim() { return ++m_count; }
count_type release() { return --m_count; }
count_type count() const { return m_count; }
//@}

private:
leftv get () {
leftv result = (leftv)omAlloc0(sizeof(sleftv));
get(*result);
return result;
}

/// Access identifier (one per class)
static id_type& access_id() {
static id_type g_id = 0;
return g_id;
void get(sleftv& result) {
if (m_ring && (m_ring != currRing)) {
Werror("Can only use references from current ring.");
return;
}
leftv next = result.next;
memcpy(&result, &m_data, sizeof(sleftv));
result.next = next;
}

private:
/// Reference counter
count_type m_count;

/// Singular object
sleftv m_data;

/// Store ring for ring-dependent objects
ring m_ring;
};

class CountedRefAccessBase {
typedef CountedRefAccessBase self;

public:
CountedRefAccessBase(leftv data):
m_data(data) {}

CountedRefAccessBase(const self& rhs):
m_data(rhs.m_data) {}

~CountedRefAccessBase() {}

leftv operator->() { return *this; }
operator leftv() { return m_data; }

protected:
leftv m_data;
};


class CountedRefAccess:
public CountedRefAccessBase {
typedef CountedRefAccess self;
typedef CountedRefAccessBase base;

public:
CountedRefAccess(CountedRefData* data):
m_owns(true), base(data->get()) { }


CountedRefAccess(leftv data):
m_owns(CountedRef::is_ref(data)), base(data) {
if (m_owns) m_data = static_cast<CountedRefData*>(data->Data())->get();
}

CountedRefAccess(const self& rhs):
m_owns(rhs.m_owns), base(rhs) {

if (m_owns){
m_data = (leftv)omAlloc0(sizeof(sleftv));
if(rhs.m_data != NULL) memcpy(m_data, rhs.m_data, sizeof(sleftv));
}
}

~CountedRefAccess() { if (m_owns) omFree(m_data); }

private:
bool m_owns;
};

class CountedRefCast:
public CountedRefAccessBase {
typedef CountedRefCast self;
typedef CountedRefAccessBase base;
public:
CountedRefCast(void* data):
base(static_cast<CountedRefData*>(data)->get()) { }

CountedRefCast(leftv data):
base(static_cast<CountedRefData*>(data->Data())->get()) { }

CountedRefCast(const self& rhs):
base((leftv)omAlloc0(sizeof(sleftv))) {
memcpy(m_data, rhs.m_data, sizeof(sleftv));
}

~CountedRefCast() { omFree(m_data); }
};

/// blackbox support - initialization
void* countedref_Init(blackbox*)
Expand All @@ -202,27 +225,35 @@ void* countedref_Init(blackbox*)
/// blackbox support - convert to string representation
void countedref_Print(blackbox *b, void* ptr)
{
if (ptr != NULL)
CountedRefData::access(static_cast<CountedRefData*>(ptr))->Print();
if (ptr != NULL) CountedRefCast(ptr)->Print();
}

/// blackbox support - convert to string representation
char* countedref_String(blackbox *b, void* ptr)
{
if (ptr != NULL)
return CountedRefData::access(static_cast<CountedRefData*>(ptr))->String();
if (ptr != NULL) return CountedRefCast(ptr)->String();
}

/// blackbox support - copy element
void* countedref_Copy(blackbox*b, void* ptr)
{
return CountedRefData::copy(static_cast<CountedRefData*>(ptr));
if (ptr) static_cast<CountedRefData*>(ptr)->reclaim();
return ptr;
}

/// blackbox support - assign element
BOOLEAN countedref_Assign(leftv l, leftv r)
BOOLEAN countedref_Assign(leftv result, leftv arg)
{
return CountedRefData::assign(l, r);
// Case: replace assignment behind reference
if (result->Data() != NULL)
return iiAssign(CountedRefCast(result), CountedRefAccess(arg));

// Case: new reference
if(arg->rtyp == IDHDL)
return CountedRefData::construct(result, arg);

Werror("Can only take reference from identifier");
return CountedRefData::set_to(result, NULL, NONE);
}


Expand All @@ -232,35 +263,52 @@ BOOLEAN countedref_Op1(int op, leftv res, leftv head)
if(op == TYPEOF_CMD)
return CountedRefData::set_to(res, omStrDup("reference"), STRING_CMD);

typedef CountedRefData::access access;
return iiExprArith1(res, access(head), op);
CountedRefCast value(head);
if (op == DEF_CMD){
res->rtyp = value->Typ();
return iiAssign(res, value);
}
return iiExprArith1(res, value, op);
}

/// blackbox support - binary operations
BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
{
typedef CountedRefData::access access;
return iiExprArith2(res, access(head), op, access(arg));
return iiExprArith2(res, CountedRefCast(head), op, CountedRefAccess(arg));
}

/// blackbox support - ternary operations
BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
{
typedef CountedRefData::access access;
return iiExprArith3(res, op, access(head), access(arg1), access(arg2));
return iiExprArith3(res, op, CountedRefCast(head),
CountedRefAccess(arg1), CountedRefAccess(arg2));
}


/// blackbox support - n-ary operations
BOOLEAN countedref_OpM(int op, leftv res, leftv args)
{
return iiExprArithM(res, CountedRefData::access(args), op);
CountedRefCast value(args);
value->next = args->next;
for(leftv current = args->next; current != NULL; current = current->next) {
if(CountedRef::is_ref(current)) {
CountedRefData* pRef = static_cast<CountedRefData*>(current->Data());
pRef->get(*current);
pRef->release();
assume(pRef->count() > 0);
}
}
args->next = NULL;

return iiExprArithM(res, value, op);
}

/// blackbox support - destruction
void countedref_destroy(blackbox *b, void* ptr)
{
CountedRefData::destroy(static_cast<CountedRefData*>(ptr));
CountedRefData* pRef = static_cast<CountedRefData*>(ptr);
if(ptr && !pRef->release())
delete pRef;
}

void countedref_init()
Expand All @@ -277,7 +325,7 @@ void countedref_init()
bbx->blackbox_Op3 = countedref_Op3;
bbx->blackbox_OpM = countedref_OpM;
bbx->data = omAlloc0(newstruct_desc_size());
CountedRefData::set_id(setBlackboxStuff(bbx,"reference"));
CountedRef init(*bbx);
}

extern "C" { void mod_init() { countedref_init(); } }
Expand Down

0 comments on commit 971984c

Please sign in to comment.