source: git/Singular/countedref.cc @ b83467

spielwiese
Last change on this file since b83467 was b83467, checked in by Alexander Dreyer <alexander.dreyer@…>, 12 years ago
Nested subexpressions via shared
  • Property mode set to 100644
File size: 23.0 KB
Line 
1/// -*- c++ -*-
2//*****************************************************************************
3/** @file countedref.cc
4 *
5 * @author Alexander Dreyer
6 * @date 2010-12-15
7 *
8 * This file defines the @c blackbox operations for the countedref type.
9 *
10 * @par Copyright:
11 *   (c) 2010 by The Singular Team, see LICENSE file
12**/
13//*****************************************************************************
14
15
16
17
18
19#include <Singular/mod2.h>
20
21#include <Singular/ipid.h>
22#include <Singular/blackbox.h>
23#include <Singular/newstruct.h>
24
25#include <omalloc/omalloc.h>
26#include <kernel/febase.h>
27#include <kernel/longrat.h>
28#include <Singular/subexpr.h>
29#include <Singular/ipshell.h>
30
31#include "lists.h"
32#include "attrib.h"
33
34/** @class CountedRefPtr
35 * This class implements a smart pointer which handles pointer-style access
36 * to a reference-counted structure and destructing the latter after use.
37 *
38 * The template arguments, include the pointer type @c PtrType, and two
39 * integral (bool) properties: use @c isWeak to disallow destruction
40 * and @c NeverNull to assume, that @c PtrType cannot be @c NULL.
41 * Finally, @c CountType allows you to select a typ to represent the internal reference count.
42 *
43 * @note The class of @c PtrType must have an accessible integral attribute @c ref.
44 * For convenience use @c RefCounter as public base.
45 * In addition you must overload @c void CountedRefPtr_kill(PtrType) accordingly.
46 **/
47template <class PtrType, bool isWeak = false, bool NeverNull = false, class CountType = short>
48class CountedRefPtr {
49  typedef CountedRefPtr self;
50
51public:
52  //{ @name Name template arguments
53  typedef PtrType ptr_type;
54  typedef CountType count_type;
55  enum { is_weak = isWeak, never_null = NeverNull };
56  //}
57
58  /// Default constructor @note: exisis only if @c NeverNull is false
59  CountedRefPtr(): m_ptr(NULL) {}
60
61  /// Convert from pointer
62  CountedRefPtr(ptr_type ptr): m_ptr(ptr) { reclaim(); }
63
64  /// Convert from compatible smart pointer
65  template <bool Never>
66  CountedRefPtr(const CountedRefPtr<ptr_type, !is_weak, Never, count_type>& rhs):
67    m_ptr(rhs.m_ptr) { reclaim(); }
68
69  /// Construct refernce copy
70  CountedRefPtr(const self& rhs):
71    m_ptr(rhs.m_ptr) { reclaim(); }
72
73  /// Unlink one reference
74  ~CountedRefPtr() { release(); }
75
76  //{ @name Replace data behind reference
77  self& operator=(const self& rhs) { return operator=(rhs.m_ptr); }
78  self& operator=(ptr_type ptr) {
79    release();
80    m_ptr = ptr;
81    reclaim();
82    return *this;
83  }
84  //}
85
86  /// Checking equality
87  bool operator==(const self& rhs) const { return m_ptr == rhs.m_ptr; }
88
89  //{ @name Pointer-style interface
90  bool operator==(ptr_type ptr) const { return m_ptr == ptr; }
91  operator bool() const { return NeverNull || m_ptr; }
92  operator const ptr_type() const { return m_ptr; }
93  operator ptr_type() { return m_ptr; }
94  const ptr_type operator->() const { return *this; }
95  ptr_type operator->() { return *this; }
96  //}
97
98  //{ @name Reference count interface
99  count_type count() const { return (*this? m_ptr->ref: 0); }
100  void reclaim() { if (*this) ++m_ptr->ref; }
101  void release() { 
102    if (*this && (--m_ptr->ref <= 0) && !is_weak)
103      CountedRefPtr_kill(m_ptr); 
104  }
105  //}
106
107private:
108  /// Store actual pointer
109  ptr_type m_ptr;
110};
111
112/// Default constructor only implemented if @c NeverNull is false
113//template <class PtrType, bool isWeak,bool val,class CountType>
114//inline CountedRefPtr<PtrType, isWeak, val, CountType>::CountedRefPtr():
115//  m_ptr(NULL) { }
116
117/** @class RefCounter
118 * This class implements implements a refernce counter which we can use
119 * as a public base of objects managed by @CountedRefPtr.
120 **/
121class RefCounter {
122
123public:
124  /// Name numerical type for enumbering
125  typedef short count_type;
126
127  /// Allow our smart pointer to access internals
128  template <class, bool, bool, class> friend class CountedRefPtr;
129
130  /// Any Constructor resets the counter
131  RefCounter(...): ref(0) {}
132
133  /// Destructor
134  ~RefCounter() { assume(ref == 0); }
135
136private:
137  /// Number of references
138  count_type ref;  // naming consistent with other classes
139};
140
141class CountedRefEnv {
142  typedef CountedRefEnv self;
143
144public:
145  static idhdl idify(leftv head, idhdl* root) {
146    static unsigned int counter = 0;
147    char* name = (char*) omAlloc0(512);
148    sprintf(name, " :%u:%p:_shared_: ", ++counter, head->data);
149    if ((*root) == NULL )
150      enterid(name, 0, head->rtyp, root, TRUE, FALSE);
151    else
152      *root = (*root)->set(name, 0, head->rtyp, TRUE);
153
154    IDDATA(*root) = (char*) head->data;
155    return *root;
156  }
157
158  static void clearid(idhdl handle, idhdl* root) {
159    IDDATA(handle)=NULL;
160    IDTYP(handle)=NONE;
161    killhdl2(handle, root, NULL);
162  }
163  static int& ref_id() {
164    static int g_ref_id = 0;
165    return g_ref_id;
166  }
167
168  static int& sh_id() {
169    static int g_sh_id = 0;
170    return g_sh_id;
171  }
172};
173
174/// Overloading ring destruction
175inline void CountedRefPtr_kill(ring r) { rKill(r); }
176
177
178class LeftvShallow {
179  typedef LeftvShallow self;
180 
181public:
182  LeftvShallow(): m_data(allocate()) { }
183  LeftvShallow(leftv data): 
184    m_data(allocate()) { init(data); }
185
186  LeftvShallow(const self& rhs):
187    m_data(allocate()) {
188    copy(m_data, rhs.m_data);
189  }
190
191  ~LeftvShallow() { 
192    kill(m_data->e);
193    omFree(m_data);
194  }
195  self& operator=(leftv rhs) {
196    kill(m_data->e);
197    return init(rhs);
198  }
199
200  self& operator=(const self& rhs) { return (*this) = rhs.m_data; }
201
202
203
204
205  /// Access to object
206  const leftv operator->() const { return m_data;  }
207  leftv operator->() { return m_data;  }
208
209protected:
210  static leftv allocate() { return (leftv)omAlloc0(sizeof(sleftv)); }
211
212  self& init(leftv data) {
213    memcpy(m_data, data, sizeof(sleftv));
214    data->e = NULL;
215    m_data->next = NULL;
216    return *this;
217  }
218
219  static void copy(leftv result, leftv data)  {
220    memcpy(result, data, sizeof(sleftv));
221    copy(result->e, data->e);
222  }
223
224 static void copy(Subexpr& current, Subexpr rhs)  {
225    if (rhs == NULL) return;
226    current = (Subexpr)memcpy(omAlloc0Bin(sSubexpr_bin), rhs, sizeof(*rhs));
227    copy(current->next, rhs->next);
228  }
229
230  static void kill(Subexpr current) {
231    if(current == NULL) return;
232    kill(current->next);
233    omFree(current);
234  }
235
236protected:
237  leftv m_data;
238};
239
240
241class LeftvDeep:
242  protected LeftvShallow {
243  typedef LeftvDeep self;
244  typedef LeftvShallow base;
245
246  self& operator=(const self&);
247public:
248  LeftvDeep(): base() {}
249  LeftvDeep(leftv data): base(data) {  if(!isid()) m_data->data=data->CopyD(); }
250
251  LeftvDeep(leftv data,int,int): base() {  m_data->Copy(data);  }
252
253  LeftvDeep(const self& rhs): base(rhs) {
254    if(m_data->rtyp != IDHDL)
255      m_data->Copy(rhs.m_data);
256  }
257
258  ~LeftvDeep() { m_data->CleanUp(); }
259  operator const base&() { return static_cast<const base&>(*this); }
260
261  bool like(const self& rhs) const { return m_data->data == rhs.m_data->data; }
262
263  self& operator=(leftv rhs) {
264    if(isid()) {
265      m_data->e = rhs->e;
266      rhs->e = NULL;
267      IDTYP((idhdl)m_data->data) =  rhs->Typ();
268      IDDATA((idhdl)m_data->data) = (char*) rhs->CopyD();
269    }
270    else {
271      m_data->CleanUp();
272      m_data->Copy(rhs);
273    }
274    return *this;
275  }
276
277  leftv access() { return m_data; }
278
279
280  /// Check a given context for our identifier
281  BOOLEAN brokenid(idhdl context) const {
282    assume(isid());
283    return (context == NULL) || 
284      ((context != (idhdl) m_data->data) && brokenid(IDNEXT(context)));
285  }
286  BOOLEAN get(leftv result) {
287    leftv next = result->next;
288    result->next = NULL;
289    result->CleanUp();
290
291    copy(result, m_data);
292    result->next = next;
293    return FALSE;
294  }
295
296  BOOLEAN isid() const { return m_data->rtyp==IDHDL;}
297  BOOLEAN ringed() { return m_data->RingDependend(); }
298  BOOLEAN unassigned() const { return m_data->Typ()==0; }
299};
300
301/** @class CountedRefData
302 * This class stores a reference counter as well as a Singular interpreter object.
303 *
304 * It also stores the Singular token number, once per type.
305 **/
306class CountedRefData:
307  public RefCounter {
308  typedef CountedRefData self;
309  typedef RefCounter base;
310
311  /// Subscripted object
312  CountedRefData(leftv wrapped, CountedRefPtr<self*> back):
313    base(), m_data(wrapped), m_ring(back->m_ring), m_back(back) {
314
315    assume(wrapped->rtyp == IDHDL);
316    ++((idhdl)m_data.access()->data)->ref;
317  }
318
319  /// Disallow assignment
320  self& operator=(const self&);
321public:
322  /// Construct shared memory empty Singular object
323  explicit CountedRefData():
324    base(), m_data(), m_ring(), m_back() { }
325
326  /// Construct reference for Singular object
327  explicit CountedRefData(leftv data):
328    base(), m_data(data), m_ring(parent(data)), m_back() { }
329
330  CountedRefData(leftv data, BOOLEAN global, int):
331    base(), m_data(data, global,0), m_ring(parent(data)), m_back() { }
332
333  /// Construct deep copy
334  CountedRefData(const self& rhs):
335    base(), m_data(rhs.m_data), m_ring(rhs.m_ring), m_back() { }
336 
337  /// Destruct
338  ~CountedRefData() { 
339    if (m_back && (--((idhdl)m_data.access()->data)->ref <= 0))  // clear only if we own
340      CountedRefEnv::clearid((idhdl)m_data.access()->data, root());     
341  }
342
343  CountedRefPtr<self*> subscripted() {
344    if (m_back)
345      return new self(operator*().operator->(), m_back);
346
347    return new self(init(CountedRefEnv::idify(m_data.access(), root())), this);
348  }
349
350  /// Replace with other Singular data
351  self& operator=(leftv rhs) {
352    m_data = rhs;
353    m_ring = parent(rhs);
354    return *this;
355  }
356
357  /// Write (shallow) copy to given handle
358  BOOLEAN get(leftv res) { return broken() || m_data.get(res);  }
359
360  /// Extract (shallow) copy of stored data
361  LeftvShallow operator*() const { return (broken()? LeftvShallow(): (const LeftvShallow&)m_data); }
362
363
364  BOOLEAN rering() {
365    if (m_ring ^ m_data.ringed()) m_ring = (m_ring? NULL: currRing);
366    return (m_back && m_back->rering());
367  }
368
369  /// Get the current context
370  idhdl* root() { return  (m_ring? &m_ring->idroot: &IDROOT); }
371
372  /// Check whether identifier became invalid
373  BOOLEAN broken() const {
374    if (m_ring) {
375      if (m_ring != currRing) 
376        return complain("Referenced identifier not from current ring");   
377
378      return m_data.isid()  && m_data.brokenid(currRing->idroot) &&
379        complain("Referenced identifier not available in ring anymore"); 
380    }
381   
382    if (!m_data.isid()) return FALSE;
383    return  m_data.brokenid(IDROOT) &&
384     ((currPack == basePack) ||  m_data.brokenid(basePack->idroot)) &&
385     complain("Referenced identifier not available in current context");
386  }
387
388  BOOLEAN assign(leftv result, leftv arg) {
389    if (!m_data.isid()) {
390      (*this) = arg;
391      return FALSE;
392    }
393    return get(result) || iiAssign(result, arg) || rering();
394  }
395
396  BOOLEAN retrieve(leftv res) {
397    if (res->data == m_data.access()->data)  {
398      memcpy(m_data.access(), res, sizeof(sleftv));
399      res->Init();
400      return TRUE;
401    }
402    return FALSE;
403  }
404
405  BOOLEAN unassigned() const { return m_data.unassigned(); }
406private:
407
408  /// Raise error message and return @c TRUE
409  BOOLEAN complain(const char* text) const  {
410    Werror(text);
411    return TRUE;
412  }
413
414
415
416  /// Store ring for ring-dependent objects
417  static ring parent(leftv rhs) { 
418    return (rhs->RingDependend()? currRing: NULL); 
419  }
420
421 static leftv init(idhdl handle) {
422    assume(handle);
423    leftv res = (leftv)omAlloc0(sizeof(*res));
424    res->data =(void*) handle;
425    res->rtyp = IDHDL;
426    return res;
427  }
428
429protected:
430  /// Singular object
431  LeftvDeep m_data;
432
433  /// Store namespace for ring-dependent objects
434  CountedRefPtr<ring, true> m_ring;
435
436  /// Reference to actual object for indexed structures 
437  CountedRefPtr<self*> m_back;
438};
439
440/// Supporting smart pointer @c CountedRefPtr
441inline void CountedRefPtr_kill(CountedRefData* data) { delete data; }
442
443
444/// blackbox support - initialization
445/// @note deals as marker for compatible references, too.
446void* countedref_Init(blackbox*)
447{
448  return NULL;
449}
450
451
452class CountedRef {
453  typedef CountedRef self;
454
455public:
456  /// name type for identifiers
457  typedef int id_type;
458
459  /// Name type for handling reference data
460  typedef CountedRefData data_type;
461
462  /// Check whether argument is already a reference type
463  static BOOLEAN is_ref(leftv arg) {
464    int typ = arg->Typ();
465    return ((typ==CountedRefEnv::ref_id())  ||(typ==CountedRefEnv::sh_id()) );
466    //    return ((typ > MAX_TOK) &&
467    //            (getBlackboxStuff(typ)->blackbox_Init == countedref_Init));
468  }
469
470  /// Construct new reference from Singular data 
471  explicit CountedRef(leftv arg):  m_data(new data_type(arg)) { }
472
473protected:
474  /// Recover previously constructed reference
475  CountedRef(data_type* arg):  m_data(arg) { assume(arg); }
476
477public:
478  /// Construct copy
479  CountedRef(const self& rhs): m_data(rhs.m_data) { }
480
481  /// Replace reference
482  self& operator=(const self& rhs) {
483    m_data = rhs.m_data;
484    return *this;
485  }
486
487  BOOLEAN assign(leftv result, leftv arg) { 
488    return m_data->assign(result,arg);
489  }
490  BOOLEAN rering() { return m_data->rering(); }
491
492  /// Extract (shallow) copy of stored data
493  LeftvShallow operator*() { return m_data->operator*(); }
494
495  /// Construct reference data object marked by given identifier number
496  BOOLEAN outcast(leftv res, int typ) {
497    res->rtyp = typ;
498    return outcast(res);
499  }
500
501  /// Construct reference data object from
502  BOOLEAN outcast(leftv res) {
503    if (res->rtyp == IDHDL)
504      IDDATA((idhdl)res->data) = (char *)outcast();
505    else
506      res->data = (void *)outcast();
507    return FALSE;
508  }
509  data_type* outcast() { 
510    m_data.reclaim();
511    return m_data;
512  }
513
514  /// Kills a link to the referenced object
515  void destruct() { m_data.release(); }
516
517  /// Kills the link to the referenced object
518  ~CountedRef() { }
519
520  /// Replaces argument by a shallow copy of the references data
521  BOOLEAN dereference(leftv arg) {
522    //    assume(is_ref(arg));
523    m_data.reclaim();
524    BOOLEAN b= m_data->get(arg) || ((arg->next != NULL) && resolve(arg->next));
525    m_data.release();
526    return b;
527  }
528
529  BOOLEAN broken() {return m_data->broken(); }
530
531  /// Get number of references pointing here, too
532  BOOLEAN count(leftv res) { return construct(res, m_data.count() - 1); }
533
534  // Get internal indentifier
535  BOOLEAN hash(leftv res) { return construct(res, (long)(data_type*)m_data); }
536
537  /// Check for likewise identifiers
538  BOOLEAN likewise(leftv res, leftv arg) {
539    return resolve(arg) || construct(res, operator*()->data == arg->data); 
540  }
541
542  /// Check for identical reference objects
543  BOOLEAN same(leftv res, leftv arg) { 
544    return construct(res, m_data == arg->Data());
545  }
546
547  /// Get type of references data
548  BOOLEAN type(leftv res) { 
549    return construct(res, Tok2Cmdname(operator*()->Typ()));
550  };
551
552  /// Get (possibly) internal identifier name
553  BOOLEAN name(leftv res) { return construct(res, operator*()->Name()); }
554
555  /// Check whther argument is not defined yet
556  BOOLEAN undefined(leftv res) { return construct(res, operator*()->Typ() == NONE); }
557  BOOLEAN unassigned() const { return  m_data->unassigned(); }
558  /// Recover the actual object from raw Singular data
559  static self cast(void* data) {
560    assume(data != NULL);
561    return self(static_cast<data_type*>(data));
562  }
563
564  /// Recover the actual object from Singular interpreter object
565  static self cast(leftv arg) {
566    assume((arg != NULL) && is_ref(arg));
567    return self::cast(arg->Data());
568  }
569
570  /// If necessary dereference.
571  static BOOLEAN resolve(leftv arg) {
572    assume(arg != NULL);
573    while (is_ref(arg)) { if(CountedRef::cast(arg).dereference(arg)) return TRUE; };
574    return (arg->next != NULL) && resolve(arg->next);
575  }
576  //  int Typ() const {return m_data->Typ(); }
577protected:
578  /// Construct integer value
579  static BOOLEAN construct(leftv res, long data) {
580    res->data = (void*) data;
581    res->rtyp = INT_CMD;
582    return FALSE;
583  }
584
585  /// Construct string
586  static BOOLEAN construct(leftv res, const char* data) {
587    res->data = (void*)omStrDup(data);
588    res->rtyp = STRING_CMD;
589    return FALSE;
590  }
591
592  /// Store pointer to actual data
593  CountedRefPtr<data_type*> m_data;
594};
595
596/// blackbox support - convert to string representation
597void countedref_Print(blackbox *b, void* ptr)
598{
599  if (ptr) (*CountedRef::cast(ptr))->Print();
600  else PrintS("<unassigned reference or shared memory>");
601}
602
603/// blackbox support - convert to string representation
604char* countedref_String(blackbox *b, void* ptr)
605{
606  if (ptr == NULL) return omStrDup(sNoName);
607  return (*CountedRef::cast(ptr))->String();
608}
609
610/// blackbox support - copy element
611void* countedref_Copy(blackbox*b, void* ptr)
612{ 
613  if (ptr) return CountedRef::cast(ptr).outcast();
614  return NULL;
615}
616
617/// blackbox support - assign element
618BOOLEAN countedref_Assign(leftv result, leftv arg)
619{
620  // Case: replace assignment behind reference
621  if (result->Data() != NULL) {
622    return CountedRef::resolve(arg) || 
623      CountedRef::cast(result).assign(result, arg);     
624  }
625 
626  // Case: copy reference
627  if (result->Typ() == arg->Typ())
628    return CountedRef::cast(arg).outcast(result);
629
630  // Case: new reference
631  if ((arg->rtyp == IDHDL) || CountedRef::is_ref(arg))
632    return CountedRef(arg).outcast(result);
633
634  Werror("Can only take reference from identifier");
635  return TRUE;
636}
637
638BOOLEAN countedref_CheckInit(leftv res, leftv arg)
639{
640  if (arg->Data() != NULL) return FALSE;
641  res->rtyp = NONE;
642  Werror("Noninitialized access");
643  return TRUE;
644}
645                                                                 
646/// blackbox support - unary operations
647BOOLEAN countedref_Op1(int op, leftv res, leftv head)
648{
649  if(op == TYPEOF_CMD)
650    return blackboxDefaultOp1(op, res, head);
651
652
653  if (countedref_CheckInit(res, head)) return TRUE;
654 
655  if ((op == DEF_CMD) || (op == head->Typ())) {
656    res->rtyp = head->Typ();
657    return iiAssign(res, head);
658  }
659
660  if(op == LINK_CMD) {
661    res->rtyp =  DEF_CMD;
662    return CountedRef::cast(head).dereference(head) || iiAssign(res, head);
663  }
664
665  return CountedRef::cast(head).dereference(head) || iiExprArith1(res, head, op);
666}
667
668/// blackbox support - binary operations
669BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg)
670{
671   return countedref_CheckInit(res, head) ||
672    CountedRef::cast(head).dereference(head) ||
673    CountedRef::resolve(arg) ||
674    iiExprArith2(res, head, op, arg);
675}
676
677
678/// blackbox support - ternary operations
679BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2)
680{
681  return countedref_CheckInit(res, head) ||
682    CountedRef::cast(head).dereference(head) || 
683    CountedRef::resolve(arg1) || CountedRef::resolve(arg2) ||
684    iiExprArith3(res, op, head, arg1, arg2);
685}
686
687
688/// blackbox support - destruction
689void countedref_destroy(blackbox *b, void* ptr)
690{
691  if (ptr) CountedRef::cast(ptr).destruct();
692}
693
694
695class CountedRefShared:
696  public CountedRef {
697  typedef CountedRefShared self;
698  typedef CountedRef base;
699
700  CountedRefShared(const base& rhs):  base(rhs) { }
701  CountedRefShared(data_type* rhs):  base(rhs) { }
702
703public:
704  CountedRefShared():  base(new data_type) { }
705  explicit CountedRefShared(leftv arg):  base(new data_type(arg, FALSE,0)) { }
706
707  /// Construct copy
708  CountedRefShared(const self& rhs): base(rhs) { }
709
710  ~CountedRefShared() { }
711
712  self& operator=(const self& rhs) {
713    return static_cast<self&>(base::operator=(rhs));
714  }
715
716  static self cast(leftv arg) { return base::cast(arg); }
717  static self cast(void* arg) { return base::cast(arg); }
718
719  /// Temporarily wrap with identifier for '[' and '.' operation
720  self subscripted() { return self(m_data->subscripted()); }
721
722  BOOLEAN retrieve(leftv res, int typ) { 
723    return (m_data->retrieve(res) && outcast(res, typ));
724  }
725};
726
727void* countedref_InitShared(blackbox*)
728{
729  return CountedRefShared().outcast();
730}
731
732/// blackbox support - binary operations
733BOOLEAN countedref_Op2Shared(int op, leftv res, leftv head, leftv arg)
734{
735  if  ((op == '[') || (op == '.')) {
736    if (countedref_CheckInit(res, head))  return TRUE;
737    CountedRefShared indexed = CountedRefShared::cast(head).subscripted();
738
739    int typ = head->Typ();
740    return indexed.dereference(head) || CountedRefShared::resolve(arg) || 
741      iiExprArith2(res, head, op, arg) || indexed.retrieve(res, typ);
742  }
743
744  return countedref_Op2(op, res, head, arg);
745}
746
747/// blackbox support - n-ary operations
748BOOLEAN countedref_OpM(int op, leftv res, leftv args)
749{
750  if (args->Data() == NULL) return FALSE;
751
752  if(op == SYSTEM_CMD) {
753    if (args->next) {
754      leftv next = args->next;
755      args->next = NULL;
756      CountedRef obj = CountedRef::cast(args);
757      char* name = (next->Typ() == STRING_CMD? 
758                    (char*) next->Data(): (char*)next->Name());
759      next = next->next;
760      if (next) {
761        if (strcmp(name, "same") == 0) return obj.same(res, next);
762        if (strncmp(name, "like", 4) == 0) return obj.likewise(res, next);
763      }
764      if (strncmp(name, "count", 5) == 0) return obj.count(res);
765      if (strcmp(name, "hash") == 0) return obj.hash(res);
766      if (strcmp(name, "name") == 0) return obj.name(res);
767      if (strncmp(name, "type", 4) == 0) return obj.type(res);
768      if (strncmp(name, "undef", 5) == 0) return obj.undefined(res);
769    }
770    return TRUE;
771  }
772  if (op == LIST_CMD){
773    res->rtyp = op;
774    return jjLIST_PL(res, args);
775  }
776
777  return CountedRef::cast(args).dereference(args) || iiExprArithM(res, args, op);
778}
779
780/// blackbox support - assign element
781BOOLEAN countedref_AssignShared(leftv result, leftv arg)
782{
783  /// Case: replace assignment behind reference
784  if ((result->Data() != NULL)  && !CountedRefShared::cast(result).unassigned()) {
785    if (CountedRefShared::resolve(arg)) return TRUE;
786    return CountedRefShared::cast(result).assign(result, arg);
787    return FALSE;
788  }
789 
790  /// Case: new reference to already shared data
791  if (result->Typ() == arg->Typ()) {
792    if (result->Data() != NULL) 
793      CountedRefShared::cast(result).destruct();
794    return CountedRefShared::cast(arg).outcast(result);
795  } 
796  if(CountedRefShared::cast(result).unassigned()) {
797   // CountedRefShared::cast(result) = arg;
798   return CountedRefShared::cast(result).assign(result, arg);
799
800    return FALSE;
801  }
802   
803  /// Case: new shared data
804  return CountedRefShared(arg).outcast(result);
805}
806
807/// blackbox support - destruction
808void countedref_destroyShared(blackbox *b, void* ptr)
809{
810  if (ptr) CountedRefShared::cast(ptr).destruct();
811}
812
813void countedref_init() 
814{
815  blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox));
816  bbx->blackbox_destroy = countedref_destroy;
817  bbx->blackbox_String  = countedref_String;
818  bbx->blackbox_Print  = countedref_Print;
819  bbx->blackbox_Init    = countedref_Init;
820  bbx->blackbox_Copy    = countedref_Copy;
821  bbx->blackbox_Assign  = countedref_Assign;
822  bbx->blackbox_Op1     = countedref_Op1;
823  bbx->blackbox_Op2     = countedref_Op2;
824  bbx->blackbox_Op3     = countedref_Op3;
825  bbx->blackbox_OpM     = countedref_OpM;
826  bbx->data             = omAlloc0(newstruct_desc_size());
827  CountedRefEnv::ref_id()=setBlackboxStuff(bbx, "reference");
828
829  /// The @c shared type is "inherited" from @c reference.
830  /// It just uses another constructor (to make its own copy of the).
831  blackbox *bbxshared = 
832    (blackbox*)memcpy(omAlloc(sizeof(blackbox)), bbx, sizeof(blackbox));
833  bbxshared->blackbox_Assign  = countedref_AssignShared;
834  bbxshared->blackbox_destroy = countedref_destroyShared;
835  bbxshared->blackbox_Op2     = countedref_Op2Shared;
836  bbxshared->blackbox_Init    = countedref_InitShared;
837  bbxshared->data             = omAlloc0(newstruct_desc_size());
838  CountedRefEnv::sh_id()=setBlackboxStuff(bbxshared, "shared");
839}
840
841extern "C" { void mod_init() { countedref_init(); } }
842
Note: See TracBrowser for help on using the repository browser.