You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

563 lines
19 KiB

25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
25 years ago
Remove exception hooks in favor of real C++ exceptions: * include/cln/exception.h: New file... * include/cln/cln.h: ...included here... * include/cln/rational.h: ...and here. * include/cln/abort.h: Removed. * include/cln/integer.h (ash_exception, exquo_exception): Add exception types. * include/cln/float.h (floating_point_exception, floating_point_nan_exception, floating_point_overflow_exception, floating_point_underflow_exception): Likewise. * include/cln/number_io.h (read_number_exception, read_number_bad_syntax_exception, read_number_junk_exception, read_number_eof_exception): Likewise. * include/cln/object.h (CL_DEFINE_CONVERTER): Replace dynamic assertion with a compile-time assertion. * include/cln/GV.h: Replace nonreturning functions with exceptions. * include/cln/modinteger.h: Likewise. * include/cln/SV.h: Likewise. * include/cln/ring.h: Likewise. * include/cln/string.h: Likewise. * include/cln/univpoly.h: Likewise. * src/base/cl_abort.cc: Removed. * src/base/cl_N_err_d0.cc: Removed. * src/base/cl_d0_exception.cc: New file. * src/base/cl_as_err.cc: Removed. * src/base/cl_as_exception.cc: New file. * src/base/cl_notreached.cc: Removed. * src/base/cl_notreached_exception.cc: New file. * src/base/input/cl_read_err_bad.cc: Removed. * src/base/input/cl_read_bad_syntax_exception.cc: New file. * src/base/input/cl_read_err_junk.cc: Removed. * src/base/input/cl_read_junk_exception.cc: New file. * src/base/input/cl_read_err_eof.cc: Removed. * src/base/input/cl_read_eof_exception.cc: New file. * src/base/cl_N.h (cl_as_error): Removed (see cln/exception.h). * src/base/macros.h (NOTREACHED): Throw. * src/base/cl_malloc.cc (xmalloc): Throw. * src/base/digitseq/cl_2DS_div.cc: Throw. * src/base/digitseq/cl_DS_div.cc: Throw. * src/base/digitseq/cl_DS_mul.cc: Throw. * src/base/digitseq/cl_DS_mul_fftc.h: Throw. * src/base/digitseq/cl_DS_mul_fftcs.h: Throw. * src/base/digitseq/cl_DS_mul_fftm.h: Throw. * src/base/digitseq/cl_DS_mul_fftp.h: Throw. * src/base/digitseq/cl_DS_mul_fftp3.h: Throw. * src/base/digitseq/cl_DS_mul_fftp3m.h: Throw. * src/base/digitseq/cl_DS_mul_fftr.h: Throw. * src/base/digitseq/cl_DS_mul_nuss.h: Throw. * src/base/digitseq/cl_DS_recipsqrt.cc: Throw. * src/base/digitseq/cl_DS_sqrt.cc: Throw. * src/base/hash/cl_hash.h: Throw. * src/base/hash/cl_hash1.h: Throw. * src/base/hash/cl_hash1weak.h: Throw. * src/base/hash/cl_hash2.h: Throw. * src/base/hash/cl_hash2weak.h: Throw. * src/base/hash/cl_hashset.h: Throw. * src/base/hash/cl_hashuniq.h: Throw. * src/base/hash/cl_hashuniqweak.h: Throw. * src/base/proplist/cl_pl_add.cc: Throw. * src/base/ring/cl_no_ring.cc: Throw. * src/base/string/cl_spushstring.h: Throw. * src/base/symbol/cl_symbol.cc: Throw. * src/integer/bitwise/cl_I_ash.h: Removed (see cln/integer.h.) * src/integer/bitwise/cl_I_asherr.cc: Removed. * src/integer/bitwise/cl_I_ash_exception.cc: New file. * src/integer/division/cl_I_exquoerr.cc: Removed. * src/integer/division/cl_I_exquo_exception.cc: New file. * src/integer/cl_I.h: Throw. * src/integer/division/cl_I_exquopos.cc: Throw. * src/integer/bitwise/cl_I_logbitp_I.cc: Throw. * src/integer/bitwise/cl_I_ash.cc: Throw. * src/integer/bitwise/cl_I_ash_I.cc: Throw. * src/integer/division/cl_I_exquo.cc: Throw. * src/integer/gcd/cl_I_gcd_aux2.cc: Throw. * src/integer/conv/cl_I_to_L.cc: Throw. * src/integer/conv/cl_I_to_Q.cc: Throw. * src/integer/conv/cl_I_to_UL.cc: Throw. * src/integer/conv/cl_I_to_UQ.cc: Throw. * src/integer/conv/cl_I_to_digits.cc: Throw. * src/integer/elem/cl_I_div.cc: Throw. * src/integer/algebraic/cl_I_sqrt.cc: Throw. * src/integer/input/cl_I_read.cc: Throw. * src/integer/input/cl_I_read_stream.cc: Throw. * src/integer/misc/cl_I_as.cc: Throw. * src/rational/elem/cl_RA_from_I_I_div.cc: Throw. * src/rational/elem/cl_RA_recip.cc: Throw. * src/rational/input/cl_RA_read.cc: Throw. * src/rational/input/cl_RA_read_stream.cc: Throw. * src/rational/input/cl_RA_readparsed.cc: Throw. * src/rational/misc/cl_RA_as.cc: Throw. * src/float/base/cl_F_err_nan.cc: Removed. * src/float/base/cl_F_nan_exception.cc: New file. * src/float/base/cl_F_err_un.cc: Removed. * src/float/base/cl_F_underflow_exception.cc: New file. * src/float/base/cl_F_err_ov.cc: Removed. * src/float/base/cl_F_overflow_exception.cc: New file. * src/float/cl_F.h (cl_error_floating_point_nan, cl_error_floating_point_overflow, cl_error_floating_point_underflow): Removed (see cln/float.h.) * src/float/sfloat/cl_SF.h: Throw. * src/float/sfloat/elem/cl_SF_div.cc: Throw. * src/float/sfloat/elem/cl_SF_from_RA.cc: Throw. * src/float/sfloat/elem/cl_SF_scale.cc: Throw. * src/float/sfloat/elem/cl_SF_scale_I.cc: Throw. * src/float/sfloat/misc/cl_SF_as.cc: Throw. * src/float/ffloat/cl_FF.h: Throw. * src/float/ffloat/conv/cl_FF_from_float.cc: Throw. * src/float/ffloat/elem/cl_FF_div.cc: Throw. * src/float/ffloat/elem/cl_FF_from_RA.cc: Throw. * src/float/ffloat/elem/cl_FF_scale.cc: Throw. * src/float/ffloat/elem/cl_FF_scale_I.cc: Throw. * src/float/ffloat/misc/cl_FF_as.cc: Throw. * src/float/dfloat/cl_DF.h: Throw. * src/float/dfloat/conv/cl_DF_from_double.cc: Throw. * src/float/dfloat/elem/cl_DF_div.cc: Throw. * src/float/dfloat/elem/cl_DF_from_RA.cc: Throw. * src/float/dfloat/elem/cl_DF_scale.cc: Throw. * src/float/dfloat/elem/cl_DF_scale_I.cc: Throw. * src/float/dfloat/misc/cl_DF_as.cc: Throw. * src/float/lfloat/algebraic/cl_LF_sqrt.cc: Throw. * src/float/lfloat/elem/cl_LF_1plus.cc: Throw. * src/float/lfloat/elem/cl_LF_I_div.cc: Throw. * src/float/lfloat/elem/cl_LF_I_mul.cc: Throw. * src/float/lfloat/elem/cl_LF_div.cc: Throw. * src/float/lfloat/elem/cl_LF_from_I.cc: Throw. * src/float/lfloat/elem/cl_LF_mul.cc: Throw. * src/float/lfloat/elem/cl_LF_scale.cc: Throw. * src/float/lfloat/elem/cl_LF_scale_I.cc: Throw. * src/float/lfloat/elem/cl_LF_square.cc: Throw. * src/float/lfloat/misc/cl_LF_as.cc: Throw. * src/float/lfloat/misc/cl_LF_shorten.cc: Throw. * src/float/lfloat/misc/cl_LF_shortenrel.cc: Throw. * src/float/lfloat/misc/cl_LF_shortenwith.cc: Throw. * src/float/input/cl_F_read.cc: Throw. * src/float/input/cl_F_read_stream.cc: Throw. * src/float/misc/cl_F_as.cc: Throw. * src/float/misc/cl_F_shortenrel.cc: Throw. * src/float/transcendental/cl_LF_coshsinh_aux.cc: Throw. * src/float/transcendental/cl_LF_cossin_aux.cc: Throw. * src/float/transcendental/cl_LF_exp_aux.cc: Throw. * src/float/transcendental/cl_LF_ratseries_a.cc: Throw. * src/float/transcendental/cl_LF_ratseries_ab.cc: Throw. * src/float/transcendental/cl_LF_ratseries_b.cc: Throw. * src/float/transcendental/cl_LF_ratseries_p.cc: Throw. * src/float/transcendental/cl_LF_ratseries_pa.cc: Throw. * src/float/transcendental/cl_LF_ratseries_pab.cc: Throw. * src/float/transcendental/cl_LF_ratseries_pb.cc: Throw. * src/float/transcendental/cl_LF_ratseries_pq.cc: Throw. * src/float/transcendental/cl_LF_ratseries_pqa.cc: Throw. * src/float/transcendental/cl_LF_ratseries_pqab.cc: Throw. * src/float/transcendental/cl_LF_ratseries_pqb.cc: Throw. * src/float/transcendental/cl_LF_ratseries_q.cc: Throw. * src/float/transcendental/cl_LF_ratseries_qa.cc: Throw. * src/float/transcendental/cl_LF_ratseries_qab.cc: Throw. * src/float/transcendental/cl_LF_ratseries_qb.cc: Throw. * src/float/transcendental/cl_LF_ratseries_stream_pq.cc: Throw. * src/float/transcendental/cl_LF_ratseries_stream_pqa.cc: Throw. * src/float/transcendental/cl_LF_ratseries_stream_pqab.cc: Throw. * src/float/transcendental/cl_LF_ratseries_stream_pqb.cc: Throw. * src/float/transcendental/cl_LF_ratsumseries_pqcd_aux.cc: Throw. * src/float/transcendental/cl_LF_ratsumseries_pqd.cc: Throw. * src/float/transcendental/cl_LF_ratsumseries_pqd_aux.cc: Throw. * src/float/transcendental/cl_LF_zeta_int.cc: Throw. * src/real/elem/cl_R_div.cc: Throw. * src/real/format-output/cl_fmt_cardinal.cc: Throw. * src/real/format-output/cl_fmt_newroman.cc: Throw. * src/real/format-output/cl_fmt_oldroman.cc: Throw. * src/real/input/cl_R_read.cc: Throw. * src/real/input/cl_R_read_stream.cc: Throw. * src/real/misc/cl_R_as.cc: Throw. * src/real/random/cl_R_random.cc: Throw. * src/real/transcendental/cl_R_atan2.cc: Throw. * src/real/transcendental/cl_R_log.cc: Throw. * src/complex/input/cl_N_read.cc: Throw. * src/complex/input/cl_N_read_stream.cc: Throw. * src/complex/misc/cl_N_as.cc: Throw. * src/complex/transcendental/cl_C_atanh_aux.cc: Throw. * src/complex/transcendental/cl_C_expt_C.cc: Throw. * src/complex/transcendental/cl_C_log.cc: Throw. * src/complex/transcendental/cl_C_log2.cc: Throw. * src/numtheory/cl_nt_cornacchia1.cc: Throw. * src/numtheory/cl_nt_cornacchia4.cc: Throw. * src/numtheory/cl_nt_isprobprime.cc: Throw. * src/numtheory/cl_nt_jacobi.cc: Throw. * src/numtheory/cl_nt_jacobi_low.cc: Throw. * src/numtheory/cl_nt_sqrtmodp.cc: Throw. * src/modinteger/cl_MI.cc: Throw. * src/modinteger/cl_MI_int.h: Throw. * src/modinteger/cl_MI_montgom.h: Throw. * src/modinteger/cl_MI_pow2.h: Throw. * src/modinteger/cl_MI_rshift.cc: Throw. * src/modinteger/cl_MI_std.h: Throw. * src/polynomial/elem/cl_UP_GF2.h: Throw. * src/polynomial/elem/cl_UP_MI.h: Throw. * src/polynomial/elem/cl_UP_gen.h: Throw. * src/polynomial/elem/cl_UP_named.cc: Throw. * src/polynomial/elem/cl_UP_no_ring.cc (uninitialized_error, uninitialized_ring): Removed (see cln/ring.h.) * src/polynomial/elem/cl_UP_number.h: Throw. * src/polynomial/elem/cl_UP_unnamed.cc: Throw. * src/vector/cl_GV_I.cc: Throw. * src/vector/cl_GV_number.cc: Throw. * tests/timediv2adic-compare.cc: Use default abort(), not cl_abort(). * tests/timeprint-compare.cc: Likewise. * tests/timerecip2adic-compare.cc: Likewise. * doc/cln.tex: Document the exception classes. * examples/contfrac.cc: Use try/catch instead of setjmp/longjmp. * INSTALL: undocument -fno-exceptions. * README: Add exceptions to list of used C++ features.
18 years ago
25 years ago
25 years ago
  1. // General object definitions: pointers, reference counting, garbage collection.
  2. #ifndef _CL_OBJECT_H
  3. #define _CL_OBJECT_H
  4. #include "cln/types.h"
  5. #include "cln/modules.h"
  6. #include <cstdlib>
  7. namespace cln {
  8. // We don't have to deal with circular structures, so normal reference counting
  9. // is sufficient. Is also has the advantage of being mostly non-interrupting.
  10. // An object is either a pointer to heap allocated data
  11. // or immediate data.
  12. // It is possible to distinguish these because pointers are aligned.
  13. // cl_uint_alignment is the guaranteed alignment of a `void*' or `long'
  14. // in memory. Must be > 1.
  15. #if defined(__m68k__)
  16. #define cl_word_alignment 2
  17. #endif
  18. #if defined(__i386__) || defined(__mips__) || defined(__mipsel__) || defined(__sparc__) || defined(__hppa__) || defined(__arm__) || defined(__rs6000__) || defined(__m88k__) || defined(__convex__) || defined(__s390__)
  19. #define cl_word_alignment 4
  20. #endif
  21. #if defined(__alpha__) || defined(__ia64__) || defined(__mips64__) || defined(__powerpc64__) || defined(__sparc64__) || defined(__x86_64__)
  22. #define cl_word_alignment 8
  23. #endif
  24. #if !defined(cl_word_alignment)
  25. #error "Define cl_word_alignment for your CPU!"
  26. #endif
  27. // Four basic classes are introduced:
  28. //
  29. // gcobject rcobject
  30. //
  31. // gcpointer rcpointer
  32. //
  33. // `gcobject' = garbage collectible object (pointer or immediate),
  34. // `gcpointer' = garbage collectible pointer,
  35. // `rcobject' = reference counted object (pointer or immediate),
  36. // `rcpointer' = reference counted pointer.
  37. //
  38. // "garbage collectible" means that a reference count is maintained, and
  39. // when the reference count drops to 0, the object is freed. This is useful
  40. // for all kind of short- or long-lived objects.
  41. // "reference counted" means that a reference count is maintained, which
  42. // cannot drop to 0. This is useful for objects which are registered in a
  43. // global cache table, in order to know which objects can be thrown away
  44. // when the cache is cleaned. (If the cache were never cleaned, its objects
  45. // would never be freed, and we could get away with normal C pointers.)
  46. //
  47. // It is permissible to treat a `rcobject' as a `gcobject', and a `rcpointer'
  48. // as a `gcpointer', but this just increases the destructor and copy-constructor
  49. // overhead.
  50. // It is also permissible to treat a `gcpointer' as a `gcobject', and a
  51. // `rcpointer' as a `rcobject', but this just increases the destructor and
  52. // copy-constructor overhead.
  53. // Immediate data is a word, as wide as a pointer.
  54. typedef sintP cl_sint;
  55. typedef uintP cl_uint; // This ought to be called `cl_word'.
  56. #define cl_pointer_size intPsize
  57. // NB: (cl_pointer_size==64) implies defined(HAVE_FAST_LONGLONG)
  58. #if (cl_pointer_size==64)
  59. #define CL_WIDE_POINTERS
  60. #endif
  61. // Distinguish immediate data from pointers.
  62. inline bool cl_pointer_p (cl_uint word)
  63. {
  64. return (word & (cl_word_alignment-1)) == 0;
  65. }
  66. inline bool cl_immediate_p (cl_uint word)
  67. {
  68. return (word & (cl_word_alignment-1)) != 0;
  69. }
  70. // Immediate data: Fixnum, Short Float, maybe Single Float.
  71. // They have type tags.
  72. // |...............................|......|
  73. // cl_value cl_tag
  74. // Number of bits reserved for tagging information:
  75. #if (cl_word_alignment <= 4)
  76. #define cl_tag_len 2
  77. #else
  78. #define cl_tag_len 3
  79. #endif
  80. #define cl_tag_shift 0
  81. #define cl_value_shift (cl_tag_len+cl_tag_shift)
  82. #define cl_value_len (cl_pointer_size - cl_value_shift)
  83. #define cl_tag_mask (((1UL << cl_tag_len) - 1) << cl_tag_shift)
  84. #define cl_value_mask (((1UL << cl_value_len) - 1) << cl_value_shift)
  85. // Return the tag of a word.
  86. inline cl_uint cl_tag (cl_uint word)
  87. {
  88. return (word & cl_tag_mask) >> cl_tag_shift;
  89. }
  90. // Return the value (unsigned) of a word.
  91. inline cl_uint cl_value (cl_uint word)
  92. {
  93. // This assumes cl_value_shift + cl_value_len == cl_pointer_size.
  94. return word >> cl_value_shift;
  95. }
  96. // Return a word, combining a value and a tag.
  97. inline cl_uint cl_combine (cl_uint tag, cl_uint value)
  98. {
  99. return (value << cl_value_shift) + (tag << cl_tag_shift);
  100. }
  101. inline cl_uint cl_combine (cl_uint tag, cl_sint value)
  102. {
  103. // This assumes cl_value_shift + cl_value_len == cl_pointer_size.
  104. return (value << cl_value_shift) + (tag << cl_tag_shift);
  105. }
  106. // Keep the compiler happy.
  107. inline cl_uint cl_combine (cl_uint tag, unsigned int value)
  108. { return cl_combine(tag, (cl_uint)value); }
  109. inline cl_uint cl_combine (cl_uint tag, int value)
  110. { return cl_combine(tag, (cl_sint)value); }
  111. #ifdef HAVE_LONGLONG
  112. inline cl_uint cl_combine (cl_uint tag, unsigned long long value)
  113. { return cl_combine(tag, (cl_uint)value); }
  114. inline cl_uint cl_combine (cl_uint tag, long long value)
  115. { return cl_combine(tag, (cl_uint)value); }
  116. #endif
  117. // Definition of the tags.
  118. #if !defined(CL_WIDE_POINTERS)
  119. #if (cl_word_alignment == 2)
  120. #define cl_FN_tag 1
  121. #define cl_SF_tag 3 // must satisfy the cl_immediate_p predicate!
  122. #endif
  123. #if (cl_word_alignment == 4)
  124. #define cl_FN_tag 1
  125. #define cl_SF_tag 2
  126. #endif
  127. #else // CL_WIDE_POINTERS
  128. // Single Floats are immediate as well.
  129. #define cl_FN_tag 1
  130. #define cl_SF_tag 2
  131. #define cl_FF_tag 3
  132. #endif
  133. // Corresponding classes.
  134. extern const struct cl_class * cl_immediate_classes [1<<cl_tag_len];
  135. // Heap allocated data contains a header, for two purposes:
  136. // - dynamic typing,
  137. // - reference count (a portable alternative to garbage collection,
  138. // or the basis for a portable and interoperable garbage collection).
  139. struct cl_heap {
  140. int refcount; // reference count
  141. const struct cl_class * type; // type tag
  142. };
  143. // Function to destroy the contents of a heap object.
  144. typedef void (*cl_heap_destructor_function) (cl_heap* pointer);
  145. // Flags, may be ORed together.
  146. #define cl_class_flags_subclass_complex 1 // all instances belong to cl_N
  147. #define cl_class_flags_subclass_real 2 // all instances belong to cl_R
  148. #define cl_class_flags_subclass_float 4 // all instances belong to cl_F
  149. #define cl_class_flags_subclass_rational 8 // all instances belong to cl_RA
  150. #define cl_class_flags_number_ring 16 // all instances are rings whose
  151. // elements belong to cl_number
  152. #define cl_class_flags_modint_ring 32 // all instances are rings whose
  153. // elements belong to cl_MI
  154. #define cl_class_flags_univpoly_ring 64 // all instances are rings whose
  155. // elements belong to cl_UP
  156. // Function to print an object for debugging, to cerr.
  157. typedef void (*cl_heap_dprint_function) (cl_heap* pointer);
  158. struct cl_class {
  159. cl_heap_destructor_function destruct;
  160. int flags;
  161. cl_heap_dprint_function dprint;
  162. };
  163. // Free an object on heap.
  164. extern void cl_free_heap_object (cl_heap* pointer);
  165. // Debugging support for dynamic typing: Register a debugging print function.
  166. #define cl_register_type_printer(type,printer) \
  167. { extern cl_class type; type.dprint = (printer); }
  168. // cl_private_thing: An immediate value or a pointer into the heap.
  169. // This must be as wide as a `cl_uint'.
  170. // (Actually, this ought to be a union { void*; cl_uint; }, but using
  171. // a pointer type generates better code.)
  172. // Never throw away a cl_private_thing, or reference counts will be wrong!
  173. typedef struct cl_anything * cl_private_thing;
  174. // Increment the reference count.
  175. inline void cl_inc_pointer_refcount (cl_heap* pointer)
  176. {
  177. pointer->refcount++;
  178. }
  179. // Decrement the reference count of a garbage collected pointer.
  180. inline void cl_gc_dec_pointer_refcount (cl_heap* pointer)
  181. {
  182. if (--pointer->refcount == 0)
  183. cl_free_heap_object(pointer);
  184. }
  185. // Decrement the reference count of a reference counted pointer.
  186. inline void cl_rc_dec_pointer_refcount (cl_heap* pointer)
  187. {
  188. --pointer->refcount;
  189. }
  190. // Increment the reference count.
  191. // This must be a macro, not an inline function, because pointer_p() and
  192. // inc_pointer_refcount() are non-virtual member functions, so that the
  193. // compiler can optimize it.
  194. #define cl_inc_refcount(x) \
  195. if ((x).pointer_p()) \
  196. (x).inc_pointer_refcount(); \
  197. // Decrement the reference count.
  198. // This must be a macro, not an inline function, because pointer_p() and
  199. // dec_pointer_refcount() are non-virtual member functions, so that the
  200. // compiler can optimize it.
  201. #define cl_dec_refcount(x) \
  202. if ((x).pointer_p()) \
  203. (x).dec_pointer_refcount(); \
  204. // The declaration of a copy constructor.
  205. // Restriction: The base class's default constructor must do nothing or
  206. // initialize `pointer' to a constant expression.
  207. #define CL_DEFINE_COPY_CONSTRUCTOR1(_class_) \
  208. _CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_class_)
  209. #define _CL_DEFINE_COPY_CONSTRUCTOR1(_class_,_classname_) \
  210. inline _class_::_classname_ (const _class_& x) \
  211. { \
  212. cl_uint x_word = x.word; \
  213. cl_inc_refcount(x); \
  214. this->word = x_word; \
  215. }
  216. // The declaration of a copy constructor.
  217. // Restriction: The base class must have the usual `cl_private_thing'
  218. // constructor. Drawback: The base class must be known here.
  219. #define CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_baseclass_) \
  220. _CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_class_,_baseclass_)
  221. #define _CL_DEFINE_COPY_CONSTRUCTOR2(_class_,_classname_,_baseclass_) \
  222. inline _class_::_classname_ (const _class_& x) \
  223. : _baseclass_ (as_cl_private_thing(x)) {}
  224. // The declaration of an assignment operator.
  225. #define CL_DEFINE_ASSIGNMENT_OPERATOR(dest_class,src_class) \
  226. inline dest_class& dest_class::operator= (const src_class& x) \
  227. { \
  228. /* Be careful, we might be assigning x to itself. */ \
  229. cl_uint x_word = x.word; \
  230. cl_inc_refcount(x); \
  231. cl_dec_refcount(*this); \
  232. this->word = x_word; \
  233. return *this; \
  234. }
  235. // We have a small problem with destructors: The specialized destructor
  236. // of a leaf class such as `cl_SF' should be more efficient than the
  237. // general destructor for `cl_N'. Since (by C++ specs) destructing a cl_SF
  238. // would run the destructors for cl_SF, cl_F, cl_R, cl_N (in that order),
  239. // and in the last step the compiler does not know any more that the object
  240. // actually is a cl_SF, there is no way to optimize the destructor!
  241. // ("progn-reversed" method combination is evil.)
  242. // And if we define "mirror"/"shadow" classes with no destructors (such
  243. // that `cl_F' inherits from `cl_F_no_destructor' buts adds a destructor)
  244. // then we need to add explicit conversion operators cl_SF -> cl_F -> cl_R ...,
  245. // with the effect that calling an overloaded function like `as_cl_F'
  246. // (which has two signatures `as_cl_F(cl_number)' and `as_cl_F(cl_F)')
  247. // with a cl_SF argument gives an "call of overloaded function is ambiguous"
  248. // error.
  249. // There is no help: If we want overloaded functions to be callable in a way
  250. // that makes sense, `cl_SF' has to be a subclass of `cl_F', and then the
  251. // destructor of `cl_SF' will do at least as much computation as the `cl_F'
  252. // destructor. Praise C++ ! :-((
  253. // (Even making `pointer_p()' a virtual function would not help.)
  254. // This is obnoxious.
  255. template <class key1_type, class value_type> struct cl_htentry1;
  256. // The four concrete classes of all objects.
  257. class cl_gcobject {
  258. public: /* ugh */
  259. union {
  260. void* pointer;
  261. cl_heap* heappointer;
  262. cl_uint word;
  263. };
  264. public:
  265. // Default constructor. (Used for objects with no initializer.)
  266. cl_gcobject ();
  267. // Destructor. (Used when a variable goes out of scope.)
  268. ~cl_gcobject ();
  269. // Copy constructor.
  270. cl_gcobject (const cl_gcobject&);
  271. // Assignment operator.
  272. cl_gcobject& operator= (const cl_gcobject&);
  273. // Distinguish immediate data from pointer.
  274. bool pointer_p() const
  275. { return cl_pointer_p(word); }
  276. // Reference counting.
  277. void inc_pointer_refcount () const
  278. { cl_inc_pointer_refcount(heappointer); }
  279. void dec_pointer_refcount () const
  280. { cl_gc_dec_pointer_refcount(heappointer); }
  281. // Return the type tag of an immediate number.
  282. cl_uint nonpointer_tag () const
  283. { return cl_tag(word); }
  284. // Return the type tag of a heap-allocated number.
  285. const cl_class * pointer_type () const
  286. { return heappointer->type; }
  287. // Private pointer manipulations.
  288. cl_private_thing _as_cl_private_thing () const;
  289. // Private constructor.
  290. cl_gcobject (cl_private_thing p)
  291. #if !(defined(__alpha__) && !defined(__GNUC__))
  292. : pointer (p) {}
  293. #else
  294. { pointer = p; }
  295. #endif
  296. // Debugging output.
  297. void debug_print () const;
  298. // Ability to place an object at a given address.
  299. void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
  300. void* operator new (size_t size) { return ::operator new (size); }
  301. };
  302. inline cl_gcobject::cl_gcobject () {}
  303. inline cl_gcobject::~cl_gcobject () { cl_dec_refcount(*this); }
  304. CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcobject)
  305. CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcobject,cl_gcobject)
  306. class cl_gcpointer {
  307. public: /* ugh */
  308. union {
  309. void* pointer;
  310. cl_heap* heappointer;
  311. cl_uint word;
  312. };
  313. public:
  314. // Default constructor. (Used for objects with no initializer.)
  315. cl_gcpointer ();
  316. // Destructor. (Used when a variable goes out of scope.)
  317. ~cl_gcpointer ();
  318. // Copy constructor.
  319. cl_gcpointer (const cl_gcpointer&);
  320. // Assignment operator.
  321. cl_gcpointer& operator= (const cl_gcpointer&);
  322. // Distinguish immediate data from pointer.
  323. bool pointer_p() const
  324. { return true; }
  325. // Reference counting.
  326. void inc_pointer_refcount () const
  327. { cl_inc_pointer_refcount(heappointer); }
  328. void dec_pointer_refcount () const
  329. { cl_gc_dec_pointer_refcount(heappointer); }
  330. // Return the type tag of an immediate number.
  331. cl_uint nonpointer_tag () const
  332. { return cl_tag(word); }
  333. // Return the type tag of a heap-allocated number.
  334. const cl_class * pointer_type () const
  335. { return heappointer->type; }
  336. // Private pointer manipulations.
  337. cl_private_thing _as_cl_private_thing () const;
  338. // Private constructor.
  339. cl_gcpointer (cl_private_thing p)
  340. #if !(defined(__alpha__) && !defined(__GNUC__))
  341. : pointer (p) {}
  342. #else
  343. { pointer = p; }
  344. #endif
  345. // Debugging output.
  346. void debug_print () const;
  347. // Ability to place an object at a given address.
  348. void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
  349. void* operator new (size_t size) { return ::operator new (size); }
  350. };
  351. inline cl_gcpointer::cl_gcpointer () {}
  352. inline cl_gcpointer::~cl_gcpointer () { cl_dec_refcount(*this); }
  353. CL_DEFINE_COPY_CONSTRUCTOR1(cl_gcpointer)
  354. CL_DEFINE_ASSIGNMENT_OPERATOR(cl_gcpointer,cl_gcpointer)
  355. class cl_rcobject {
  356. public: /* ugh */
  357. union {
  358. void* pointer;
  359. cl_heap* heappointer;
  360. cl_uint word;
  361. };
  362. public:
  363. // Default constructor. (Used for objects with no initializer.)
  364. cl_rcobject ();
  365. // Destructor. (Used when a variable goes out of scope.)
  366. ~cl_rcobject ();
  367. // Copy constructor.
  368. cl_rcobject (const cl_rcobject&);
  369. // Assignment operator.
  370. cl_rcobject& operator= (const cl_rcobject&);
  371. // Distinguish immediate data from pointer.
  372. bool pointer_p() const
  373. { return cl_pointer_p(word); }
  374. // Reference counting.
  375. void inc_pointer_refcount () const
  376. { cl_inc_pointer_refcount(heappointer); }
  377. void dec_pointer_refcount () const
  378. { cl_rc_dec_pointer_refcount(heappointer); }
  379. // Return the type tag of an immediate number.
  380. cl_uint nonpointer_tag () const
  381. { return cl_tag(word); }
  382. // Return the type tag of a heap-allocated number.
  383. const cl_class * pointer_type () const
  384. { return heappointer->type; }
  385. // Private pointer manipulations.
  386. cl_private_thing _as_cl_private_thing () const;
  387. // Private constructor.
  388. cl_rcobject (cl_private_thing p)
  389. #if !(defined(__alpha__) && !defined(__GNUC__))
  390. : pointer (p) {}
  391. #else
  392. { pointer = p; }
  393. #endif
  394. // Debugging output.
  395. void debug_print () const;
  396. // Ability to place an object at a given address.
  397. void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
  398. void* operator new (size_t size) { return ::operator new (size); }
  399. };
  400. inline cl_rcobject::cl_rcobject () {}
  401. inline cl_rcobject::~cl_rcobject () { cl_dec_refcount(*this); }
  402. CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcobject)
  403. CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcobject,cl_rcobject)
  404. class cl_rcpointer {
  405. public: /* ugh */
  406. union {
  407. void* pointer;
  408. cl_heap* heappointer;
  409. cl_uint word;
  410. };
  411. public:
  412. // Default constructor. (Used for objects with no initializer.)
  413. cl_rcpointer ();
  414. // Destructor. (Used when a variable goes out of scope.)
  415. ~cl_rcpointer ();
  416. // Copy constructor.
  417. cl_rcpointer (const cl_rcpointer&);
  418. // Assignment operator.
  419. cl_rcpointer& operator= (const cl_rcpointer&);
  420. // Distinguish immediate data from pointer.
  421. bool pointer_p() const
  422. { return true; }
  423. // Reference counting.
  424. void inc_pointer_refcount () const
  425. { cl_inc_pointer_refcount(heappointer); }
  426. void dec_pointer_refcount () const
  427. { cl_rc_dec_pointer_refcount(heappointer); }
  428. // Return the type tag of an immediate number.
  429. cl_uint nonpointer_tag () const
  430. { return cl_tag(word); }
  431. // Return the type tag of a heap-allocated number.
  432. const cl_class * pointer_type () const
  433. { return heappointer->type; }
  434. // Private pointer manipulations.
  435. cl_private_thing _as_cl_private_thing () const;
  436. // Private constructor.
  437. cl_rcpointer (cl_private_thing p)
  438. #if !(defined(__alpha__) && !defined(__GNUC__))
  439. : pointer (p) {}
  440. #else
  441. { pointer = p; }
  442. #endif
  443. // Debugging output.
  444. void debug_print () const;
  445. // Ability to place an object at a given address.
  446. void* operator new (size_t size, void* ptr) { (void)size; return ptr; }
  447. void* operator new (size_t size) { return ::operator new (size); }
  448. };
  449. inline cl_rcpointer::cl_rcpointer () {}
  450. inline cl_rcpointer::~cl_rcpointer () { cl_dec_refcount(*this); }
  451. CL_DEFINE_COPY_CONSTRUCTOR1(cl_rcpointer)
  452. CL_DEFINE_ASSIGNMENT_OPERATOR(cl_rcpointer,cl_rcpointer)
  453. // Private pointer manipulations.
  454. inline cl_private_thing cl_gcobject::_as_cl_private_thing () const
  455. {
  456. cl_private_thing p = (cl_private_thing) pointer;
  457. cl_inc_refcount(*this);
  458. return p;
  459. }
  460. inline cl_private_thing as_cl_private_thing (const cl_gcobject& x)
  461. {
  462. return x._as_cl_private_thing();
  463. }
  464. inline cl_private_thing cl_gcpointer::_as_cl_private_thing () const
  465. {
  466. cl_private_thing p = (cl_private_thing) pointer;
  467. cl_inc_refcount(*this);
  468. return p;
  469. }
  470. inline cl_private_thing as_cl_private_thing (const cl_gcpointer& x)
  471. {
  472. return x._as_cl_private_thing();
  473. }
  474. inline cl_private_thing cl_rcobject::_as_cl_private_thing () const
  475. {
  476. cl_private_thing p = (cl_private_thing) pointer;
  477. cl_inc_refcount(*this);
  478. return p;
  479. }
  480. inline cl_private_thing as_cl_private_thing (const cl_rcobject& x)
  481. {
  482. return x._as_cl_private_thing();
  483. }
  484. inline cl_private_thing cl_rcpointer::_as_cl_private_thing () const
  485. {
  486. cl_private_thing p = (cl_private_thing) pointer;
  487. cl_inc_refcount(*this);
  488. return p;
  489. }
  490. inline cl_private_thing as_cl_private_thing (const cl_rcpointer& x)
  491. {
  492. return x._as_cl_private_thing();
  493. }
  494. // Note: When we define a function that returns a class object by value,
  495. // we normally return it as const value. The declarations
  496. // T func (...); (A)
  497. // and
  498. // const T func (...); (B)
  499. // behave identically and generate identical code, except that the code
  500. // func(...) = foo;
  501. // compiles fine with (A) but is an error (and yields a warning) with (B).
  502. // We want this warning.
  503. // Define a conversion operator from one object to another object of the
  504. // same size.
  505. #define CL_DEFINE_CONVERTER(target_class) \
  506. operator const target_class & () const \
  507. { \
  508. typedef int assert1 [2*(sizeof(target_class)==sizeof(*this))-1]; \
  509. return * (const target_class *) (void*) this; \
  510. }
  511. } // namespace cln
  512. #endif /* _CL_OBJECT_H */