1 /****************************************************************************
2 **
3 **  This file is part of GAP, a system for computational discrete algebra.
4 **
5 **  Copyright of GAP belongs to its developers, whose names are too numerous
6 **  to list here. Please refer to the COPYRIGHT file for details.
7 **
8 **  SPDX-License-Identifier: GPL-2.0-or-later
9 **
10 **  This file defines the functions of the objects package.
11 **
12 **  The objects package is the part that defines the 'Obj' type,  the objects
13 **  types  (i.e., the numbers  that  Gasman needs  to distinguish types), the
14 **  dispatcher for the printing of objects, etc.
15 */
16 
17 #ifndef GAP_OBJECTS_H
18 #define GAP_OBJECTS_H
19 
20 #include "gasman.h"
21 #include "intobj.h"
22 
23 #ifdef HPCGAP
24 #define USE_THREADSAFE_COPYING
25 #endif
26 
27 
28 /****************************************************************************
29 **
30 *t  Obj . . . . . . . . . . . . . . . . . . . . . . . . . . . type of objects
31 **
32 **  'Obj' is the type of objects.
33 **
34 **  The following is defined in "system.h"
35 **
36 #define Obj             Bag
37 */
38 
39 
40 /****************************************************************************
41 **
42 *F  IS_FFE( <o> ) . . . . . . . . test if an object is a finite field element
43 **
44 **  'IS_FFE'  returns 1  if the  object <o>  is  an  (immediate) finite field
45 **  element and 0 otherwise.
46 */
IS_FFE(Obj o)47 EXPORT_INLINE Int IS_FFE(Obj o)
48 {
49     return (Int)o & 0x02;
50 }
51 
52 
53 /****************************************************************************
54 **
55 *F  RegisterPackageTNUM( <name>, <typeObjFunc> )
56 **
57 **  Allocates a TNUM for use by a package. The parameters <name> and
58 **  <typeObjFunc> are used to initialize the relevant entries in the
59 **  InfoBags and TypeObjFuncs arrays.
60 **
61 **  If allocation fails (e.g. because no more TNUMs are available),
62 **  a negative value is returned.
63 */
64 Int RegisterPackageTNUM(const char * name, Obj (*typeObjFunc)(Obj obj));
65 
66 
67 /****************************************************************************
68 **
69 *F  NEXT_ENUM_EVEN( <id> )
70 *F  START_ENUM_RANGE_EVEN( <id> )
71 *F  END_ENUM_RANGE_ODD( <id> )
72 **
73 **  'NEXT_ENUM_EVEN' can be used in an enum to force <id> to use the next
74 **  available even integer value.
75 **
76 **  'START_ENUM_RANGE_EVEN' is a variant of 'START_ENUM_RANGE' which always
77 **  sets the value of <id> to the next even integer.
78 **
79 **  'END_ENUM_RANGE_ODD' is a variant of 'END_ENUM_RANGE' which always sets
80 **  the value of <id> to an odd integer.
81 */
82 #define NEXT_ENUM_EVEN(id)   \
83     _##id##_pre, \
84     id = _##id##_pre + (_##id##_pre & 1)
85 #define START_ENUM_RANGE_EVEN(id)   \
86     NEXT_ENUM_EVEN(id), \
87     _##id##_post = id - 1
88 #define END_ENUM_RANGE_ODD(id)   \
89     _##id##_pre, \
90     id = _##id##_pre - !(_##id##_pre & 1)
91 
92 
93 /****************************************************************************
94 **
95 */
96 enum {
97     IMMUTABLE = 1    // IMMUTABLE is not a TNUM, but rather a bitmask
98 };
99 
100 /****************************************************************************
101 **
102 *S  T_<name>  . . . . . . . . . . . . . . . . symbolic names for object types
103 *S  FIRST_CONSTANT_TNUM, LAST_CONSTANT_TNUM . . . . range of constant   types
104 *S  FIRST_RECORD_TNUM,   LAST_RECORD_TNUM . . . . . range of record     types
105 *S  FIRST_LIST_TNUM,     LAST_LIST_TNUM . . . . . . range of list       types
106 *S  FIRST_EXTERNAL_TNUM, LAST_EXTERNAL_TNUM . . . . range of external   types
107 *S  FIRST_REAL_TNUM,     LAST_REAL_TNUM . . . . . . range of real       types
108 *S  FIRST_IMM_MUT_TNUM,  LAST_IMM_MUT_TNUM  . . . . range of im/mutable types
109 **
110 **  For every type of objects there is a symbolic name defined for this type.
111 **
112 **  'FIRST_CONSTANT_TNUM'  is  the first   type  of constant  objects,  e.g.,
113 **  integers, booleans, and functions.  'LAST_CONSTANT_TNUM' is the last type
114 **  of constant objects.
115 **
116 **  'FIRST_RECORD_TNUM' is the first type of record objects,  currently  only
117 **  plain records.  'LAST_RECORD_TNUM' is the last type of record objects.
118 **
119 **  'FIRST_LIST_TNUM' is the first type of list objects, e.g.,  plain  lists,
120 **  ranges, boolean lists, and strings.  'LAST_LIST_TNUM' is the last type of
121 **  list objects.
122 **
123 **  'FIRST_EXTERNAL_TNUM' is the  first type  of external objects,  currently
124 **  only   component   objects,  positional   objects,    and data   objects.
125 **  'LAST_EXTERNAL_TNUM' is the last type of external objects.
126 **
127 **  'FIRST_REAL_TNUM' is the first  real  type, namely 'FIRST_CONSTANT_TNUM'.
128 **  'LAST_REAL_TNUM'  is the last   real  type, namely  'LAST_EXTERNAL_TNUM'.
129 **
130 **  'FIRST_IMM_MUT_TNUM'  is the first  real  internal type of objects  which
131 **  might be mutable, 'LAST_IMM_MUT_TNUM' is the last such type.
132 **
133 **  The types *must* be sorted in this order, i.e., first the constant types,
134 **  then the record types, then the list types,  then the external types, and
135 **  finally the virtual types.
136 */
137 enum TNUM {
138     START_ENUM_RANGE(FIRST_REAL_TNUM),
139 
140     START_ENUM_RANGE(FIRST_CONSTANT_TNUM),
141 
142         // The next range contains all constant TNUMs for which multiplication
143         // with an integer resp. powering by an integer makes sense
144         START_ENUM_RANGE(FIRST_MULT_TNUM),
145             T_INT,      // immediate
146             T_INTPOS,
147             T_INTNEG,
148             T_RAT,
149             T_CYC,
150             T_FFE,      // immediate
151             T_MACFLOAT,
152             T_PERM2,
153             T_PERM4,
154             T_TRANS2,
155             T_TRANS4,
156             T_PPERM2,
157             T_PPERM4,
158         END_ENUM_RANGE(LAST_MULT_TNUM),
159 
160         T_BOOL,
161         T_CHAR,
162 
163         T_FUNCTION,
164         T_BODY,     // the type of function body bags
165         T_FLAGS,
166         T_LVARS,
167         T_HVARS,
168     END_ENUM_RANGE(LAST_CONSTANT_TNUM),
169 
170     // first mutable/immutable TNUM
171     START_ENUM_RANGE_EVEN(FIRST_IMM_MUT_TNUM),
172 
173         // records
174         START_ENUM_RANGE_EVEN(FIRST_RECORD_TNUM),
175             T_PREC,
176         END_ENUM_RANGE_ODD(LAST_RECORD_TNUM),
177 
178         // lists
179         START_ENUM_RANGE_EVEN(FIRST_LIST_TNUM),
180 
181             // plists
182             START_ENUM_RANGE_EVEN(FIRST_PLIST_TNUM),
183                 NEXT_ENUM_EVEN(T_PLIST),
184                 NEXT_ENUM_EVEN(T_PLIST_NDENSE),
185                 NEXT_ENUM_EVEN(T_PLIST_DENSE),
186                 NEXT_ENUM_EVEN(T_PLIST_DENSE_NHOM),
187                 NEXT_ENUM_EVEN(T_PLIST_DENSE_NHOM_SSORT),
188                 NEXT_ENUM_EVEN(T_PLIST_DENSE_NHOM_NSORT),
189                 NEXT_ENUM_EVEN(T_PLIST_EMPTY),
190                 NEXT_ENUM_EVEN(T_PLIST_HOM),
191                 NEXT_ENUM_EVEN(T_PLIST_HOM_NSORT),
192                 NEXT_ENUM_EVEN(T_PLIST_HOM_SSORT),
193                 NEXT_ENUM_EVEN(T_PLIST_TAB),
194                 NEXT_ENUM_EVEN(T_PLIST_TAB_NSORT),
195                 NEXT_ENUM_EVEN(T_PLIST_TAB_SSORT),
196                 NEXT_ENUM_EVEN(T_PLIST_TAB_RECT),
197                 NEXT_ENUM_EVEN(T_PLIST_TAB_RECT_NSORT),
198                 NEXT_ENUM_EVEN(T_PLIST_TAB_RECT_SSORT),
199                 NEXT_ENUM_EVEN(T_PLIST_CYC),
200                 NEXT_ENUM_EVEN(T_PLIST_CYC_NSORT),
201                 NEXT_ENUM_EVEN(T_PLIST_CYC_SSORT),
202                 NEXT_ENUM_EVEN(T_PLIST_FFE),
203             END_ENUM_RANGE_ODD(LAST_PLIST_TNUM),
204 
205             // other kinds of lists
206             NEXT_ENUM_EVEN(T_RANGE_NSORT),
207             NEXT_ENUM_EVEN(T_RANGE_SSORT),
208             NEXT_ENUM_EVEN(T_BLIST),
209             NEXT_ENUM_EVEN(T_BLIST_NSORT),
210             NEXT_ENUM_EVEN(T_BLIST_SSORT),
211             NEXT_ENUM_EVEN(T_STRING),
212             NEXT_ENUM_EVEN(T_STRING_NSORT),
213             NEXT_ENUM_EVEN(T_STRING_SSORT),
214 
215         END_ENUM_RANGE_ODD(LAST_LIST_TNUM),
216 
217         // object sets and maps
218         START_ENUM_RANGE_EVEN(FIRST_OBJSET_TNUM),
219             NEXT_ENUM_EVEN(T_OBJSET),
220             NEXT_ENUM_EVEN(T_OBJMAP),
221         END_ENUM_RANGE_ODD(LAST_OBJSET_TNUM),
222 
223     // last mutable/immutable TNUM
224     END_ENUM_RANGE(LAST_IMM_MUT_TNUM),
225 
226     // external types
227     START_ENUM_RANGE(FIRST_EXTERNAL_TNUM),
228         T_COMOBJ,
229         T_POSOBJ,
230         T_DATOBJ,
231         T_WPOBJ,
232 #ifdef HPCGAP
233         T_ACOMOBJ,
234         T_APOSOBJ,
235 #endif
236 
237         // package TNUMs, for use by kernel extensions
238         //
239         // The value of LAST_REAL_TNUM must not exceed 254.
240         // This restricts the value for LAST_PACKAGE_TNUM indirectly. It is
241         // difficult to describe the largest possible value with a formula,
242         // as LAST_REAL_TNUM itself changes depending LAST_PACKAGE_TNUM, and
243         // the fact that some TNUMs are forced to be even causes additional
244         // jumps; increasing LAST_PACKAGE_TNUM by 1 can lead to
245         // LAST_REAL_TNUM growing by 2. So we simply hand-pick
246         // LAST_PACKAGE_TNUM as the largest value that does not trigger the
247         // GAP_STATIC_ASSERT following this enum.
248         FIRST_PACKAGE_TNUM,
249 #ifdef HPCGAP
250         LAST_PACKAGE_TNUM   = FIRST_PACKAGE_TNUM + 153,
251 #else
252         LAST_PACKAGE_TNUM   = FIRST_PACKAGE_TNUM + 167,
253 #endif
254 
255     END_ENUM_RANGE(LAST_EXTERNAL_TNUM),
256 
257 #ifdef HPCGAP
258     START_ENUM_RANGE(FIRST_SHARED_TNUM),
259         // primitive types
260         T_THREAD,
261         T_MONITOR,
262         T_REGION,
263         // user-programmable types
264         T_SEMAPHORE,
265         T_CHANNEL,
266         T_BARRIER,
267         T_SYNCVAR,
268         // atomic lists and records, thread local records
269     START_ENUM_RANGE(FIRST_ATOMIC_TNUM),
270     START_ENUM_RANGE(FIRST_ATOMIC_LIST_TNUM),
271         T_FIXALIST,
272         T_ALIST,
273     END_ENUM_RANGE(LAST_ATOMIC_LIST_TNUM),
274     START_ENUM_RANGE(FIRST_ATOMIC_RECORD_TNUM),
275         T_AREC,
276         T_AREC_INNER,
277         T_TLREC,
278         T_TLREC_INNER,
279     END_ENUM_RANGE(LAST_ATOMIC_RECORD_TNUM),
280     END_ENUM_RANGE(LAST_ATOMIC_TNUM),
281     END_ENUM_RANGE(LAST_SHARED_TNUM),
282 #endif
283 
284     END_ENUM_RANGE(LAST_REAL_TNUM),
285 
286 #if !defined(USE_THREADSAFE_COPYING)
287     T_COPYING,
288 #endif
289 };
290 
291 #if !defined(USE_THREADSAFE_COPYING)
292 GAP_STATIC_ASSERT(T_COPYING <= 254, "T_COPYING is too large");
293 #else
294 GAP_STATIC_ASSERT(LAST_REAL_TNUM <= 254, "LAST_REAL_TNUM is too large");
295 #endif
296 
297 
298 /****************************************************************************
299 **
300 *F  TEST_OBJ_FLAG(<obj>, <flag>) . . . . . . . . . . . . . . test object flag
301 *F  SET_OBJ_FLAG(<obj>, <flag>) . . . . . . . . . . . . . . . set object flag
302 *F  CLEAR_OBJ_FLAG(<obj>, <flag>) . . . . . . . . . . . . . clear object flag
303 **
304 **  These three functions test, set, and clear object flags, respectively.
305 **  For non-immediate objects, these are simply the bag flags, see
306 **  TEST_BAG_FLAG, SET_BAG_FLAG, CLEAR_BAG_FLAG.
307 **
308 **  For immediate objects, objects flags are always 0.
309 */
TEST_OBJ_FLAG(Obj obj,uint8_t flag)310 EXPORT_INLINE uint8_t TEST_OBJ_FLAG(Obj obj, uint8_t flag)
311 {
312     if (IS_BAG_REF(obj))
313         return TEST_BAG_FLAG(obj, flag);
314     else
315         return 0;
316 }
317 
SET_OBJ_FLAG(Obj obj,uint8_t flag)318 EXPORT_INLINE void SET_OBJ_FLAG(Obj obj, uint8_t flag)
319 {
320     if (IS_BAG_REF(obj))
321         SET_BAG_FLAG(obj, flag);
322 }
323 
CLEAR_OBJ_FLAG(Obj obj,uint8_t flag)324 EXPORT_INLINE void CLEAR_OBJ_FLAG(Obj obj, uint8_t flag)
325 {
326     if (IS_BAG_REF(obj))
327         CLEAR_BAG_FLAG(obj, flag);
328 }
329 
330 
331 /****************************************************************************
332 **
333 **  Object flags for use with SET_OBJ_FLAG() etc.
334 **
335 */
336 enum {
337     TESTING = (1 << 0),
338 #ifdef HPCGAP
339     TESTED  = (1 << 1),
340 #endif
341 };
342 
343 
344 /****************************************************************************
345 **
346 *F  TNUM_OBJ( <obj> ) . . . . . . . . . . . . . . . . . . . type of an object
347 **
348 **  'TNUM_OBJ' returns the type of the object <obj>.
349 */
TNUM_OBJ(Obj obj)350 EXPORT_INLINE UInt TNUM_OBJ(Obj obj)
351 {
352     if (IS_INTOBJ(obj))
353         return T_INT;
354     if (IS_FFE(obj))
355         return T_FFE;
356     return TNUM_BAG(obj);
357 }
358 
359 
360 /****************************************************************************
361 **
362 *F  TNAM_TNUM( <obj> ) . . . . . . . . . . . . . . . . . . . . name of a type
363 */
364 const Char * TNAM_TNUM(UInt tnum);
365 
366 
367 /****************************************************************************
368 **
369 *F  SET_TNAM_TNUM( <obj> ) . . . . . . . . . . . . . . set the name of a type
370 */
371 void SET_TNAM_TNUM(UInt tnum, const Char * name);
372 
373 
374 /****************************************************************************
375 **
376 *F  TNAM_OBJ( <obj> ) . . . . . . . . . . . . . name of the type of an object
377 */
TNAM_OBJ(Obj obj)378 EXPORT_INLINE const Char * TNAM_OBJ(Obj obj)
379 {
380     return TNAM_TNUM(TNUM_OBJ(obj));
381 }
382 
383 
384 /****************************************************************************
385 **
386 *F  SIZE_OBJ( <obj> ) . . . . . . . . . . . . . . . . . . . size of an object
387 **
388 **  'SIZE_OBJ' returns the size of the object <obj>.
389 */
SIZE_OBJ(Obj obj)390 EXPORT_INLINE UInt SIZE_OBJ(Obj obj)
391 {
392     return SIZE_BAG(obj);
393 }
394 
395 
396 /****************************************************************************
397 **
398 *F  ADDR_OBJ( <obj> ) . . . . . . . . . . . . . absolute address of an object
399 **
400 **  'ADDR_OBJ' returns the absolute address of the memory block of the object
401 **  <obj>.
402 */
ADDR_OBJ(Obj obj)403 EXPORT_INLINE Obj *ADDR_OBJ(Obj obj)
404 {
405     return PTR_BAG(obj);
406 }
407 
CONST_ADDR_OBJ(Obj obj)408 EXPORT_INLINE const Obj *CONST_ADDR_OBJ(Obj obj)
409 {
410     return CONST_PTR_BAG(obj);
411 }
412 
413 
414 /****************************************************************************
415 **
416 *S  POS_FAMILY_TYPE . . . . . . position where the family of a type is stored
417 *S  POS_FLAGS_TYPE . . . . . .  position where the flags of a type are stored
418 *S  POS_DATA_TYPE . . . . . . . . position where the data of a type is stored
419 *S  POS_NUMB_TYPE . . . . . . . position where the number of a type is stored
420 *S  POS_FIRST_FREE_TYPE . . . . .  first position that has no overall meaning
421 */
422 enum {
423     POS_FAMILY_TYPE = 1,
424     POS_FLAGS_TYPE = 2,
425     POS_DATA_TYPE = 3,
426     POS_NUMB_TYPE = 4,
427     POS_FIRST_FREE_TYPE = 5,
428 };
429 
430 
431 /****************************************************************************
432 **
433 *F  FAMILY_TYPE( <type> ) . . . . . . . . . . . . . . . . .  family of a type
434 **
435 **  'FAMILY_TYPE' returns the family of the type <type>.
436 */
437 #define FAMILY_TYPE(type)       ELM_PLIST( type, POS_FAMILY_TYPE )
438 
439 
440 /****************************************************************************
441 **
442 *F  FAMILY_OBJ( <obj> ) . . . . . . . . . . . . . . . . . family of an object
443 */
444 #define FAMILY_OBJ(obj)         FAMILY_TYPE( TYPE_OBJ(obj) )
445 
446 
447 /****************************************************************************
448 **
449 *F  FLAGS_TYPE( <type> ) . . . . . . . . . . . . flags boolean list of a type
450 **
451 **  'FLAGS_TYPE' returns the flags boolean list of the type <type>.
452 */
453 #define FLAGS_TYPE(type)        ELM_PLIST( type, POS_FLAGS_TYPE )
454 
455 
456 /****************************************************************************
457 **
458 *F  DATA_TYPE( <type> ) . . . . . . . . . . . . . . . . shared data of a type
459 **
460 **  'DATA_TYPE' returns the shared data of the type <type>.
461 **  Not used by the GAP kernel right now, but useful for kernel extensions.
462 */
463 #define DATA_TYPE(type)       ELM_PLIST( type, POS_DATA_TYPE )
464 
465 
466 /****************************************************************************
467 **
468 *F  ID_TYPE( <type> ) . . . . . . . . . . . . . . . . . . . . .  id of a type
469 **
470 **  'ID_TYPE' returns the ID of  a type.  Warning: if  GAP runs out of ID  it
471 **  will renumber all IDs.  Therefore the  corresponding routine must excatly
472 **  know where such numbers are stored.
473 */
474 #define ID_TYPE(type) ELM_PLIST(type, POS_NUMB_TYPE)
475 #define SET_ID_TYPE(type, val) SET_ELM_PLIST(type, POS_NUMB_TYPE, val)
476 
477 
478 /****************************************************************************
479 **
480 *F  TYPE_OBJ( <obj> ) . . . . . . . . . . . . . . . . . . . type of an object
481 **
482 **  'TYPE_OBJ' returns the type of the object <obj>.
483 */
484 extern Obj (*TypeObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
TYPE_OBJ(Obj obj)485 EXPORT_INLINE Obj TYPE_OBJ(Obj obj)
486 {
487     UInt tnum = TNUM_OBJ(obj);
488     return (*TypeObjFuncs[tnum])(obj);
489 }
490 
491 
492 /****************************************************************************
493 **
494 *F  SET_TYPE_OBJ( <obj>, <kind> ) . . . . . . . . . . . set kind of an object
495 **
496 **  'SET_TYPE_OBJ' sets the kind <kind>of the object <obj>.
497 */
498 extern void (*SetTypeObjFuncs[ LAST_REAL_TNUM+1 ]) ( Obj obj, Obj kind );
SET_TYPE_OBJ(Obj obj,Obj type)499 EXPORT_INLINE void SET_TYPE_OBJ(Obj obj, Obj type)
500 {
501     UInt tnum = TNUM_OBJ(obj);
502     (*SetTypeObjFuncs[tnum])(obj, type);
503 }
504 
505 
506 /****************************************************************************
507 **
508 *F  MUTABLE_TNUM( <type> )  . . . . . . . . . . mutable type of internal type
509 */
510 #define MUTABLE_TNUM(type) \
511     ( ( (type) < FIRST_IMM_MUT_TNUM ? (type) : \
512        ( LAST_IMM_MUT_TNUM < (type) ? (type) : \
513         ( ((((type)-T_PLIST)&(~IMMUTABLE))+T_PLIST) ) ) ) )
514 
515 
516 /****************************************************************************
517 **
518 *F  IMMUTABLE_TNUM( <type> )  . . . . . . . . immutable type of internal type
519 */
520 #define IMMUTABLE_TNUM(type) \
521     ( ( (type) < FIRST_IMM_MUT_TNUM ? (type) : \
522        ( LAST_IMM_MUT_TNUM < (type) ? (type) : \
523         ( ((((type)-T_PLIST)|IMMUTABLE)+T_PLIST) ) ) ) )
524 
525 /****************************************************************************
526 **
527 *F  MakeImmutable( <obj> ) . . . . . . . . . . . . . make an object immutable
528 */
529 void MakeImmutable(Obj obj);
530 
531 
532 /****************************************************************************
533 **
534 *F  MakeImmutableNoRecurse( <obj> ) . . set immutable flag on internal object
535 **
536 **  This is an unsafe helper function, for use in functions installed as
537 **  handlers in 'MakeImmutableObjFuncs' for internal objects tracking their
538 **  mutability, i.e., in the range FIRST_IMM_MUT_TNUM to LAST_IMM_MUT_TNUM.
539 **  It only modifies the TNUM, and does not make subobjects immutable.
540 */
MakeImmutableNoRecurse(Obj obj)541 EXPORT_INLINE void MakeImmutableNoRecurse(Obj obj)
542 {
543     UInt type = TNUM_OBJ(obj);
544     GAP_ASSERT((FIRST_IMM_MUT_TNUM <= type) && (type <= LAST_IMM_MUT_TNUM));
545     RetypeBag(obj, type | IMMUTABLE);
546 }
547 
548 
549 /****************************************************************************
550 **
551 *F  CheckedMakeImmutable( <obj> )  . . . . . . . . . make an object immutable
552 **
553 **  Same effect as MakeImmutable( <obj> ), but checks first that all
554 **  subobjects lie in a writable region.
555 */
556 
557 #ifdef HPCGAP
558 void CheckedMakeImmutable(Obj obj);
559 #endif
560 
561 /****************************************************************************
562 **
563 *F  IS_MUTABLE_OBJ( <obj> ) . . . . . . . . . . . . . .  is an object mutable
564 **
565 **  'IS_MUTABLE_OBJ' returns   1 if the object  <obj> is mutable   (i.e., can
566 **  change due to assignments), and 0 otherwise.
567 */
568 extern Int (*IsMutableObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
IS_MUTABLE_OBJ(Obj obj)569 EXPORT_INLINE Int IS_MUTABLE_OBJ(Obj obj)
570 {
571     UInt tnum = TNUM_OBJ(obj);
572     if (/*FIRST_CONSTANT_TNUM <= tnum &&*/ tnum <= LAST_CONSTANT_TNUM)
573         return 0;
574     if (FIRST_IMM_MUT_TNUM <= tnum && tnum <= LAST_IMM_MUT_TNUM)
575         return !(tnum & IMMUTABLE);
576     return ((*IsMutableObjFuncs[tnum])(obj));
577 }
578 
579 
580 /****************************************************************************
581 **
582 *F  IsInternallyMutableObj( <obj> ) . . . does an object have a mutable state
583 **
584 **  This function returns   1 if the object  <obj> has a mutable state, i.e.
585 **  if its internal representation can change even though its outwardly
586 **  visible properties do not, e.g. through code that transparently
587 **  reorganizes its structure.
588 */
589 
590 #ifdef HPCGAP
591 Int IsInternallyMutableObj(Obj obj);
592 #endif
593 
594 /****************************************************************************
595 **
596 *V  SaveObjFuncs[ <type> ]  . . . . . . . . . . . . functions to save objects
597 **
598 **  'SaveObjFuncs' is the dispatch table that  contains, for every type
599 **  of  objects, a pointer to the saving function for objects of that type
600 **  These should not handle the file directly, but should work via the
601 **  functions 'SaveObjRef', 'SaveUInt<n>' (<n> = 1,2,4 or 8), and others
602 **  to be determined. Their role is to identify the C types of the various
603 **  parts of the bag, and perhaps to leave out some information that does
604 **  not need to be saved. By the time this function is called, the bag
605 **  size and type have already been saved.
606 **  No saving function may allocate any bag.
607 */
608 
609 extern void (*SaveObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
610 
611 void SaveObjError(Obj obj);
612 
613 
614 /****************************************************************************
615 **
616 *V  LoadObjFuncs[ <type> ]  . . . . . . . . . . . . functions to load objects
617 **
618 **  'LoadObjFuncs' is the dispatch table that  contains, for every type
619 **  of  objects, a pointer to the loading function for objects of that type
620 **  These should not handle the file directly, but should work via the
621 **  functions 'LoadObjRef', 'LoadUInt<n>' (<n> = 1,2,4 or 8), and others
622 **  to be determined. Their role is to reinstall the information in the bag
623 **  and reconstruct anything that was left out. By the time this function is
624 **  called, the bag size and type have already been loaded and the bag argument
625 **  contains the bag in question.
626 **  No loading function may allocate any bag.
627 */
628 
629 extern void (*LoadObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
630 
631 void LoadObjError(Obj obj);
632 
633 /****************************************************************************
634 **
635 *F  IS_COPYABLE_OBJ( <obj> )  . . . . . . . . . . . . . is an object copyable
636 **
637 **  'IS_COPYABLE_OBJ' returns 1 if the object <obj> is copyable (i.e., can be
638 **  copied into a mutable object), and 0 otherwise.
639 */
640 extern Int (*IsCopyableObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
IS_COPYABLE_OBJ(Obj obj)641 EXPORT_INLINE Int IS_COPYABLE_OBJ(Obj obj)
642 {
643     UInt tnum = TNUM_OBJ(obj);
644     return (IsCopyableObjFuncs[tnum])(obj);
645 }
646 
647 
648 /****************************************************************************
649 **
650 *V  ShallowCopyObjFuncs[<type>] . . . . . . . . . .  shallow copier functions
651 *F  SHALLOW_COPY_OBJ( <obj> ) . . . . . . .  make a shallow copy of an object
652 **
653 **  'SHALLOW_COPY_OBJ' makes a shallow copy of the object <obj>.
654 */
655 extern Obj (*ShallowCopyObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
SHALLOW_COPY_OBJ(Obj obj)656 EXPORT_INLINE Obj SHALLOW_COPY_OBJ(Obj obj)
657 {
658     UInt tnum = TNUM_OBJ(obj);
659     return (ShallowCopyObjFuncs[tnum])(obj);
660 }
661 
662 
663 /****************************************************************************
664 **
665 *F  CopyObj( <obj> )  . . . . . . . . . . make a structural copy of an object
666 **
667 **  'CopyObj' returns a  structural (deep) copy  of the object <obj>, i.e., a
668 **  recursive copy that preserves the structure.
669 */
670 Obj CopyObj(Obj obj, Int mut);
671 
672 
673 /****************************************************************************
674 **
675 *F  COPY_OBJ(<obj>) . . . . . . . . . . . make a structural copy of an object
676 **
677 **  'COPY_OBJ'  implements  the first pass  of  'CopyObj', i.e., it makes the
678 **  structural copy of <obj> and marks <obj> as already copied.
679 **
680 **  'COPY_OBJ' must only be used from within CopyObjFuncs functions. To copy
681 **  an object from regular code, call 'CopyObj'.
682 */
683 #if !defined(USE_THREADSAFE_COPYING)
684 Obj COPY_OBJ(Obj obj, Int mut);
685 #endif
686 
687 /****************************************************************************
688 **
689 *F  PrepareCopy(<obj>,<copy>) . . .  helper for use in CopyObjFuncs functions
690 **
691 */
692 #if !defined(USE_THREADSAFE_COPYING)
693 void PrepareCopy(Obj obj, Obj copy);
694 #endif
695 
696 
697 /****************************************************************************
698 **
699 *F  CLEAN_OBJ(<obj>)  . . . . . . . . . . . . . clean up object after copying
700 **
701 **  'CLEAN_OBJ' implements the second pass of 'CopyObj', i.e., it removes the
702 **  mark from <obj>.
703 */
704 #if !defined(USE_THREADSAFE_COPYING)
705 void CLEAN_OBJ(Obj obj);
706 #endif
707 
708 
709 /****************************************************************************
710 **
711 *V  CopyObjFuncs[<type>]  . . . . . . . . . . . .  table of copying functions
712 **
713 **  A package implementing a nonconstant object type <type> must provide such
714 **  functions      and     install them     in    'CopyObjFuncs[<type>]'  and
715 **  'CleanObjFuncs[<type>]'.
716 **
717 **  The function called  by 'COPY_OBJ' should  first create a  copy of <obj>,
718 **  somehow mark   <obj> as having  already been  copied, leave  a forwarding
719 **  pointer  to  the  copy  in <obj>,   and  then  copy all  subobjects  with
720 **  'COPY_OBJ'  recursively.  If  called   for an already  marked  object, it
721 **  should simply return the value  of the forward  pointer.  It should *not*
722 **  clear the mark, this is the job of 'CLEAN_OBJ' later.
723 **
724 **  The function  called by 'CLEAN_OBJ' should   clear the mark  left by the
725 **  corresponding 'COPY_OBJ' function,   remove the forwarding  pointer, and
726 **  then call 'CLEAN_OBJ'  for all subobjects recursively.  If called for an
727 **  already unmarked object, it should simply return.
728 */
729 #if !defined(USE_THREADSAFE_COPYING)
730 extern Obj (*CopyObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj, Int mut );
731 #endif
732 
733 
734 /****************************************************************************
735 **
736 *V  CleanObjFuncs[<type>] . . . . . . . . . . . . table of cleaning functions
737 */
738 #if !defined(USE_THREADSAFE_COPYING)
739 extern void (*CleanObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
740 #endif
741 
742 
743 /****************************************************************************
744 **
745 *V  MakeImmutableObjFuncs[<type>] . . . . . . . . . . . .  table of functions
746 */
747 extern void (*MakeImmutableObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
748 
749 
750 /****************************************************************************
751 **
752 *F  PrintObj( <obj> ) . . . . . . . . . . . . . . . . . . . . print an object
753 **
754 **  'PrintObj' prints the object <obj>.
755 */
756 void PrintObj(Obj obj);
757 
758 extern Obj PrintObjOper;
759 
760 /****************************************************************************
761 **
762 **
763 */
764 UInt SetPrintObjState(UInt state); // returns the old state
765 void SetPrintObjIndex(Int index);
766 
767 
768 /****************************************************************************
769 **
770 *V  PrintObjFuncs[<type>] . . . . . . . .  printer for objects of type <type>
771 **
772 **  'PrintObjFuncs' is  the dispatch  table that  contains  for every type of
773 **  objects a pointer to the printer for objects of this  type.  The  printer
774 **  is the function '<func>(<obj>)' that should be called to print the object
775 **  <obj> of this type.
776 */
777 extern void (* PrintObjFuncs[LAST_REAL_TNUM+1]) ( Obj obj );
778 
779 
780 /****************************************************************************
781 **
782 *F  ViewObj( <obj> ) . . . . . . . . . . . . . . . . . . . . view an object
783 **
784 **  'ViewObj' views the object <obj>.
785 */
786 void ViewObj(Obj obj);
787 
788 
789 /****************************************************************************
790 **
791 *V  PrintPathFuncs[<type>]  . . . . . . printer for subobjects of type <type>
792 **
793 **  'PrintPathFuncs'  is   the   dispatch table  that     contains for  every
794 **  appropriate type of objects a pointer to  the path printer for objects of
795 **  that type.  The path  printer is the function '<func>(<obj>,<indx>)' that
796 **  should be  called  to print  the  selector   that selects  the  <indx>-th
797 **  subobject of the object <obj> of this type.
798 **
799 **  These are also used for viewing
800 */
801 extern void (* PrintPathFuncs[LAST_REAL_TNUM+1]) (
802     Obj                 obj,
803     Int                 indx );
804 
805 
806 /****************************************************************************
807 **
808 *F  IS_COMOBJ( <obj> )  . . . . . . . . . . . is an object a component object
809 */
IS_COMOBJ(Obj obj)810 EXPORT_INLINE Int IS_COMOBJ(Obj obj)
811 {
812     return TNUM_OBJ(obj) == T_COMOBJ;
813 }
814 
815 
816 /****************************************************************************
817 **
818 *F  TYPE_COMOBJ( <obj> )  . . . . . . . . . . . .  type of a component object
819 */
TYPE_COMOBJ(Obj obj)820 EXPORT_INLINE Obj TYPE_COMOBJ(Obj obj)
821 {
822     return CONST_ADDR_OBJ(obj)[0];
823 }
824 
825 
826 /****************************************************************************
827 **
828 *F  SET_TYPE_COMOBJ( <obj>, <val> ) . . .  set the type of a component object
829 */
SET_TYPE_COMOBJ(Obj obj,Obj val)830 EXPORT_INLINE void SET_TYPE_COMOBJ(Obj obj, Obj val)
831 {
832     ADDR_OBJ(obj)[0] = val;
833 }
834 
835 
836 /****************************************************************************
837 **
838 *F  AssComObj( <obj>, <rnam>, <val> )
839 *F  UnbComObj( <obj>, <rnam> )
840 *F  ElmComObj( <obj>, <rnam> )
841 *F  IsbComObj( <obj>, <rnam> )
842 */
843 void AssComObj(Obj obj, UInt rnam, Obj val);
844 void UnbComObj(Obj obj, UInt rnam);
845 Obj  ElmComObj(Obj obj, UInt rnam);
846 Int  IsbComObj(Obj obj, UInt rnam);
847 
848 
849 /****************************************************************************
850 **
851 *F  IS_POSOBJ( <obj> )  . . . . . . . . . .  is an object a positional object
852 */
IS_POSOBJ(Obj obj)853 EXPORT_INLINE Int IS_POSOBJ(Obj obj)
854 {
855     return TNUM_OBJ(obj) == T_POSOBJ;
856 }
857 
858 
859 /****************************************************************************
860 **
861 *F  TYPE_POSOBJ( <obj> )  . . . . . . . . . . . . type of a positional object
862 */
TYPE_POSOBJ(Obj obj)863 EXPORT_INLINE Obj TYPE_POSOBJ(Obj obj)
864 {
865     return CONST_ADDR_OBJ(obj)[0];
866 }
867 
868 
869 /****************************************************************************
870 **
871 *F  SET_TYPE_POSOBJ( <obj>, <val> ) . . . set the type of a positional object
872 */
SET_TYPE_POSOBJ(Obj obj,Obj val)873 EXPORT_INLINE void SET_TYPE_POSOBJ(Obj obj, Obj val)
874 {
875     ADDR_OBJ(obj)[0] = val;
876 }
877 
878 
879 /****************************************************************************
880 **
881 *F  AssPosbj( <obj>, <rnam>, <val> )
882 *F  UnbPosbj( <obj>, <rnam> )
883 *F  ElmPosbj( <obj>, <rnam> )
884 *F  IsbPosbj( <obj>, <rnam> )
885 */
886 void AssPosObj(Obj obj, Int idx, Obj val);
887 void UnbPosObj(Obj obj, Int idx);
888 Obj  ElmPosObj(Obj obj, Int idx);
889 Int  IsbPosObj(Obj obj, Int idx);
890 
891 
892 /****************************************************************************
893 **
894 *F  IS_DATOBJ( <obj> )  . . . . . . . . . . . . .  is an object a data object
895 */
IS_DATOBJ(Obj obj)896 EXPORT_INLINE Int IS_DATOBJ(Obj obj)
897 {
898     return TNUM_OBJ(obj) == T_DATOBJ;
899 }
900 
901 
902 /****************************************************************************
903 **
904 *F  TYPE_DATOBJ( <obj> )  . . . . . . . . . . . . . . . type of a data object
905 */
TYPE_DATOBJ(Obj obj)906 EXPORT_INLINE Obj TYPE_DATOBJ(Obj obj)
907 {
908     return CONST_ADDR_OBJ(obj)[0];
909 }
910 
911 
912 /****************************************************************************
913 **
914 *F  SetTypeDatobj( <obj>, <kind> ) . . . . . .  set the type of a data object
915 **
916 **  'SetTypeDatobj' sets the kind <kind> of the data object <obj>.
917 */
SET_TYPE_DATOBJ(Obj obj,Obj val)918 EXPORT_INLINE void SET_TYPE_DATOBJ(Obj obj, Obj val)
919 {
920     ADDR_OBJ(obj)[0] = val;
921 }
922 
923 void SetTypeDatObj(Obj obj, Obj type);
924 
925 
926 /****************************************************************************
927 **
928 *F  NewKernelBuffer( <size> )  . . . . . . . . . . return a new kernel buffer
929 **
930 **  Return a new T_DATOBJ of the specified <size>, with its type set to the
931 **  special value TYPE_KERNEL_OBJECT.
932 **
933 **  Note that <size> must include storage for the the first slot of the bag,
934 **  which points to the type object.
935 */
936 Obj NewKernelBuffer(UInt size);
937 
938 
939 /****************************************************************************
940 **
941 *F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
942 */
943 
944 
945 /****************************************************************************
946 **
947 *F  InitInfoObjects() . . . . . . . . . . . . . . . . table of init functions
948 */
949 StructInitInfo * InitInfoObjects ( void );
950 
951 
952 #endif // GAP_OBJECTS_H
953