1 /*  Part of XPCE --- The SWI-Prolog GUI toolkit
2 
3     Author:        Jan Wielemaker and Anjo Anjewierden
4     E-mail:        jan@swi.psy.uva.nl
5     WWW:           http://www.swi.psy.uva.nl/projects/xpce/
6     Copyright (c)  1985-2002, University of Amsterdam
7     All rights reserved.
8 
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions
11     are met:
12 
13     1. Redistributions of source code must retain the above copyright
14        notice, this list of conditions and the following disclaimer.
15 
16     2. Redistributions in binary form must reproduce the above copyright
17        notice, this list of conditions and the following disclaimer in
18        the documentation and/or other materials provided with the
19        distribution.
20 
21     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32     POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #include <h/kernel.h>
36 #include <h/trace.h>
37 #include <h/graphics.h>
38 #include <h/interface.h>
39 #include <rel/proto.h>
40 
41 static int	check_object(Any, BoolObj, HashTable, int);
42 static status	makeTempObject(Any obj);
43 
44 		 /*******************************
45 		 *	  DELETE OBJECTS	*
46 		 *******************************/
47 
48 void
unreferencedObject(Any obj)49 unreferencedObject(Any obj)
50 { Instance i = obj;
51 
52   if ( noRefsObj(i) )
53   { if ( isFreedObj(i) )
54     { DEBUG(NAME_free,
55 	    Cprintf("Doing (code-)deferred unalloc on %s\n", pp(i)));
56       unallocObject(i);
57       deferredUnalloced--;
58     }
59   } else
60   { if ( onFlag(i, F_CREATING|F_FREEING|F_FREED) )
61       errorPce(PCE, NAME_negativeRefCountInCreate, i);
62     else
63       errorPce(PCE, NAME_negativeRefCount, i);
64   }
65 }
66 
67 
68 		/********************************
69 		*        SLOT ASSIGNMENT	*
70 		********************************/
71 
72 inline void
addRefObject(Any from,Any to)73 addRefObject(Any from, Any to)
74 { if ( inBoot || classOfObject(from)->un_answer == ON )
75     deleteAnswerObject(to);
76 
77   addRefObj(to);
78 
79   if ( onFlag(to, F_INSPECT) )
80   { addCodeReference(from);
81     changedObject(to, NAME_addReference, from, EAV);
82     delCodeReference(from);
83   }
84 }
85 
86 
87 inline void
delRefObject(Any from,Any to)88 delRefObject(Any from, Any to)
89 { if ( onFlag(to, F_INSPECT) )
90   { addCodeReference(to);
91     addCodeReference(from);
92     delRefObj(to);
93     changedObject(to, NAME_delReference, from, EAV);
94     delCodeReference(from);
95     delCodeReference(to);
96   } else
97   { delRefObj(to);
98     checkDeferredUnalloc(to);
99   }
100   freeableObj(to);
101 }
102 
103 
104 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
105 This function is responsible  for assignments to  an instance variable
106 (slot) of any object.  It is a wrapper arround  C's assignment to take
107 care of reference counts and the garbage collection issues.
108 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
109 
110 
111 void
assignField(Instance instance,Any * field,Any value)112 assignField(Instance instance, Any *field, Any value)
113 { Any old;
114 
115   if ((old = *field) == value)		/* no change */
116     return;
117 
118   if ( PCEdebugging && !onFlag(instance, F_CREATING|F_FREEING) )
119   { int offset = field - &instance->slots[0];
120     Class class = classOfObject(instance);
121     Variable v = getElementVector(class->instance_variables, toInt(offset));
122 
123     if ( v && DebuggingProgramObject(v, D_TRACE) )
124       writef("V %O ->%s: %O --> %O\n", instance, v->name, old, value);
125   }
126 
127   *field = value;
128   if ( isObject(value) && !isProtectedObj(value) )
129     addRefObject(instance, value);
130   if ( isObject(old) && !isProtectedObj(old) )
131     delRefObject(instance, old);
132 
133   if ( onFlag(instance, F_INSPECT) )
134     (*(classOfObject(instance))->changedFunction)(instance, field);
135 }
136 
137 
138 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
139 			  CREATING OBJECTS
140 
141 PCE objects are created by  C-functions.  Some   objects  are  used as a
142 temporary argument to a  method   (e.g.  send(@box, move, point(30,30)).
143 Others are created as an `end-point' object (e.g. new(@box, box(50,50)))
144 and yet others are  stored  as  an   attribute  to  other  objects (e.g.
145 send(@sheet, size, size(50,50))).
146 
147 To deal with this problem, the following schemas may be used:
148 
149 (1)	someFunction()
150 	{ Any obj = globalObject(Name, Class, ....);
151 
152 	  .....
153 	}
154 
155 This schema is to be used if the object will be used as an `end-point'
156 object.  The object will be locked  againts  the garbage collector and
157 does not have a reference.
158 
159 (2)	someFunction(me)
160 	{ assign(me, field, newObject(....));
161 
162 	  .....
163 	}
164 
165 This schema is  to be used if  the object is  immediately connected to
166 another object.  This will give the object a reference and preserve it
167 until it is detached from its last object.
168 
169 
170 (3)	someFunction()
171 	{ .....
172 
173 	  answer( answerObject(...) );
174 	}
175 
176 This  construct   is  used  if the    return  value  of some  function
177 (method) is a new object.  It  indicates nobody has declared itself
178 responsible for  the object.  The object is  marked  with the F_ANSWER
179 flag and added to the   answerTable.   If the   object is assigned  to
180 another object, it  will become  a normal attribute  object.  If it is
181 locked,  it will become an object  under  program control.   If non of
182 these  happens, it will be considered  garbage as soon  as the garbage
183 collector  is activated.  Status `answer'   is  also used for  objects
184 created from the host language.
185 
186 
187 (4)	someFunction()
188 	{ Any obj = tempObject(....);
189 
190 	  .....
191 
192 	  considerPreserveObject(obj);
193 	}
194 
195 This schema is to be used for objects that are created to be passed as
196 an argument to some method.   The object will  be given a reference
197 to avoid drop-out.    The function   considerPreserveObject()  acts as
198 follows:
199 
200    First it lowers the reference count by 1, next:
201 
202 	1) If the object is locked, it does nothing (`end-point')
203 	2) If the object has references, it does nothing (attribute)
204 	3) Otherwise the object is freed (argument)
205 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
206 
207 #undef offset
208 #define offset(t, f) ((uintptr_t)(&((struct t *)0)->f))
209 
210 static status
hasClassVariableVariable(Variable v,Class class)211 hasClassVariableVariable(Variable v, Class class)
212 { for( ; notNil(class); class=class->super_class )
213   { Cell cell;
214 
215     for_cell(cell, class->class_variables)
216     { ClassVariable cv = cell->value;
217 
218       if ( cv->name == v->name )
219 	succeed;
220     }
221   }
222 
223   fail;
224 }
225 
226 
227 
228 static void
updateInstanceProtoClass(Class class)229 updateInstanceProtoClass(Class class)
230 { int slots = valInt(class->slots);
231   int size = valInt(class->instance_size);
232   Variable *var = (Variable *) &class->instance_variables->elements[0];
233   Any *field;
234   Instance obj;
235   Name init_variables = NAME_static;
236 
237   class->proto = alloc(offset(instance_proto, proto) + size);
238   class->proto->size = size;
239   obj = (Instance) &class->proto->proto;
240   initHeaderObj(obj, class);
241 
242   field = &obj->slots[0];
243   for( ; --slots >= 0; var++, field++)
244   { Variable v = *var;
245 
246     if ( hasClassVariableVariable(v, class) )
247     { *field = CLASSDEFAULT;
248       setFlag(obj, F_OBTAIN_CLASSVARS);
249       DEBUG(NAME_classVariable,
250 	    Cprintf("Set %s-%s to @class_default\n",
251 		    pp(class->name), pp(v->name)));
252     } else
253     { *field = v->alloc_value;
254 
255       if ( init_variables != NAME_function )
256       { if ( isFunction(v->init_function) )
257 	  init_variables = NAME_function;
258 	else if ( notNil(v->init_function) )
259 	  init_variables = NAME_value;
260       }
261     }
262   }
263 
264   assign(class, init_variables, init_variables);
265 }
266 
267 
268 void
unallocInstanceProtoClass(Class class)269 unallocInstanceProtoClass(Class class)
270 { if ( class->proto )
271   { unalloc(offset(instance_proto, proto) + class->proto->size, class->proto);
272     class->proto = NULL;
273   }
274 }
275 
276 
277 Any
allocObject(Class class,int funcs)278 allocObject(Class class, int funcs)
279 { Instance obj;
280   int size;
281 
282 again:
283   if ( class->proto )
284   { size = class->proto->size;
285     obj = alloc(size);
286     cpdata((Any)obj, (Any)&class->proto->proto, Any, size/sizeof(Any));
287 
288     return obj;
289   }
290 
291   if ( class->boot )
292   { int size = valInt(class->instance_size);
293     int slots = (size - offset(instance, slots[0])) / sizeof(Any);
294     int i;
295 
296     obj = alloc(size);
297     initHeaderObj(obj, class);
298 
299     for (i = 0; i < slots; i++)
300       obj->slots[i] = ((i < class->boot) ? NIL : (Any) NULL);
301 
302     return obj;
303   } else
304   { updateInstanceProtoClass(class);
305     goto again;
306   }
307 }
308 
309 
310 static inline status
init_slots(Instance obj,int slots,Variable * var,Any * field)311 init_slots(Instance obj, int slots, Variable *var, Any *field)
312 { for( ; --slots >= 0; var++, field++)
313   { Any value;
314     Function f = (*var)->init_function;
315 
316     if ( notNil(f) )
317     { if ( !(value = expandCodeArgument(f)) ||
318 	   !sendVariable(*var, obj, value) ) 		/* assignField? */
319 	return errorPce(*var, NAME_initVariableFailed, obj);
320     }
321   }
322 
323   succeed;
324 }
325 
326 
327 status
initialiseObject(Instance obj)328 initialiseObject(Instance obj)
329 { Class class = classOfObject(obj);
330   status rval = SUCCEED;
331 
332   if ( class->init_variables != NAME_static )
333   { int slots = valInt(class->slots);
334     Variable *var = (Variable *) &class->instance_variables->elements[0];
335     Any *field = &obj->slots[0];
336 
337     if ( class->init_variables == NAME_function )
338     { withReceiver(obj, classOfObject(obj),
339 		   rval = init_slots(obj, slots, var, field));
340     } else
341       rval = init_slots(obj, slots, var, field);
342   }
343 
344   return rval;
345 }
346 
347 
348 Any
createObjectv(Name assoc,Class class,int argc,const Any argv[])349 createObjectv(Name assoc, Class class, int argc, const Any argv[])
350 { Any rval;
351 
352 					/* Resolve the class (caller?) */
353   if ( !instanceOfObject(class, ClassClass) )
354   { Class c2;
355 
356     if ( (c2 = getMemberHashTable(classTable, class)) ||
357 	 (c2 = checkType(class, TypeClass, NIL)) )
358     { class = c2;
359     } else
360     { errorPce(class, NAME_noClass);
361       fail;
362     }
363   }
364 					/* Prepare the class */
365   if ( class->realised != ON )
366     realiseClass(class);
367   if ( isDefault(class->lookup_method) ||
368        isDefault(class->initialise_method) )
369     bindNewMethodsClass(class);
370 
371 
372 					/* Try lookup of existing object */
373   if ( notNil(class->lookup_method) )
374   { if ( (rval = getGetGetMethod(class->lookup_method,
375 				 class, argc, argv)) )
376       answer(rval);
377   }
378 
379 					/* Check assoc redefinition */
380   if ( notNil(assoc) )
381   { if ( getObjectAssoc(assoc) )
382       exceptionPce(PCE, NAME_redefinedAssoc, assoc, EAV);
383     if ( getObjectAssoc(assoc) )
384     { errorPce(PCE, NAME_redefinedAssoc, assoc, 0);
385       fail;
386     }
387   }
388 
389 					/* Allocate the object */
390   rval = allocObject(class, TRUE);
391   addCodeReference(rval);		/* avoid drop-out */
392   if ( notNil(assoc) )			/* Create name association */
393     newAssoc(assoc, rval);
394 
395   if ( class->init_variables != NAME_static )
396   { if ( !initialiseObject(rval) )
397       goto failed;
398   }
399 					/* Initialise the object */
400   if ( sendSendMethod(class->initialise_method, rval, argc, argv) )
401   { createdClass(class, rval, NAME_new);
402     delCodeReference(rval);
403 
404     answer(rval);
405   }
406 
407 failed:
408   { ArgVector(av, argc+1);
409     int ac = 0, i = 0;
410 
411     av[ac++] = rval;			/* @arg1 */
412     for(; i<argc; i++)
413       av[ac++] = argv[i];
414 
415     exceptionPcev(PCE, NAME_initialiseFailed, ac, av);
416     deleteAssoc(rval);
417     unallocObject(rval);
418     fail;
419   }
420 }
421 
422 
423 Any
newObjectv(Class class,int argc,const Any argv[])424 newObjectv(Class class, int argc, const Any argv[])
425 { return createObjectv(NIL, class, argc, argv);
426 }
427 
428 
429 static Any
globalObjectv(Name assoc,Class class,int argc,const Any argv[])430 globalObjectv(Name assoc, Class class, int argc, const Any argv[])
431 { Any rval;
432 
433   DEBUG_BOOT(Cprintf("globalObject @%s ... ", pp(assoc)));
434   rval = createObjectv(assoc, class, argc, argv);
435   DEBUG_BOOT(Cprintf("ok\n"););
436 
437   return rval;
438 }
439 
440 
441 static status
makeTempObject(Any obj)442 makeTempObject(Any obj)
443 { if ( isObject(obj) )
444     addCodeReference(obj);
445 
446   succeed;
447 }
448 
449 
450 status
considerPreserveObject(Any obj)451 considerPreserveObject(Any obj)
452 { if ( isObject(obj) && !isFreedObj(obj) )
453   { if ( ((Instance)obj)->references < ONE_CODE_REF )
454       errorPce(obj, NAME_negativeCodeReferenceCount);
455     delCodeReference(obj);
456     freeableObj(obj);
457   }
458 
459   succeed;
460 }
461 
462 
463 Any
answerObjectv(Class class,int argc,const Any * argv)464 answerObjectv(Class class, int argc, const Any *argv)
465 { Any rval = newObjectv(class, argc, argv);
466 
467   if ( rval != FAIL )
468     pushAnswerObject(rval);
469 
470   return rval;
471 }
472 
473 
474 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
475 			       VARARGS VERSIONS
476 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
477 
478 Any
newObject(Class class,...)479 newObject(Class class, ...)
480 { va_list args;
481   Any argv[VA_PCE_MAX_ARGS];
482   int argc;
483 
484   va_start(args, class);
485   for(argc=0; (argv[argc] = va_arg(args, Any)) != NULL; argc++)
486     assert(argc < VA_PCE_MAX_ARGS );
487   va_end(args);
488 
489   return newObjectv(class, argc, argv);
490 }
491 
492 Any
tempObject(Class class,...)493 tempObject(Class class, ...)
494 { va_list args;
495   Any argv[VA_PCE_MAX_ARGS];
496   int argc;
497   Any rval;
498 
499   va_start(args, class);
500   for(argc=0; (argv[argc] = va_arg(args, Any)) != NULL; argc++)
501     assert(argc <= VA_PCE_MAX_ARGS);
502   va_end(args);
503 
504   rval = newObjectv(class, argc, argv);
505   makeTempObject(rval);
506 
507   return rval;
508 }
509 
510 
511 Any
globalObject(Name assoc,Class class,...)512 globalObject(Name assoc, Class class, ...)
513 { va_list args;
514   Any argv[VA_PCE_MAX_ARGS];
515   int argc;
516 
517   va_start(args, class);
518   for(argc=0; (argv[argc] = va_arg(args, Any)) != NULL; argc++)
519     assert(argc < VA_PCE_MAX_ARGS);
520   va_end(args);
521 
522   return globalObjectv(assoc, class, argc, argv);
523 }
524 
525 
526 Any
answerObject(Class class,...)527 answerObject(Class class, ...)
528 { va_list args;
529   Any argv[VA_PCE_MAX_ARGS];
530   int argc;
531   Any rval;
532 
533   va_start(args, class);
534   for(argc=0; (argv[argc] = va_arg(args, Any)) != NULL; argc++)
535     assert(argc < VA_PCE_MAX_ARGS);
536   va_end(args);
537 
538   rval = newObjectv(class, argc, argv);
539   if ( rval )
540     pushAnswerObject(rval);
541 
542   return rval;
543 }
544 
545 
546 static inline void
unlinkHypersObject(Any obj)547 unlinkHypersObject(Any obj)
548 { if ( onFlag(obj, F_HYPER) )
549   { Chain ch = getAllHypersObject(obj, ON);
550     Hyper h;
551 
552     clearFlag(obj, F_HYPER);
553     for_chain(ch, h,
554 	      { if ( !onFlag(h, F_FREED|F_FREEING) )
555 		{ if ( h->from == obj )
556 		    sendv(h, NAME_unlinkFrom, 0, NULL);
557 		  else
558 		    sendv(h, NAME_unlinkTo, 0, NULL);
559 
560 		  if ( !isFreedObj(h) )	/* ensure it has gone! */
561 		    freeObject(h);
562 		}
563 	      });
564     deleteHashTable(ObjectHyperTable, obj);
565   }
566 }
567 
568 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
569 unlinkObject()
570 
571 Disconnect the object from its environment.   The  first loop resets all
572 instance-variables to NIL that  do  not   contain  integers  of reusable
573 objects. This process could be  optimised   a  little  further by closer
574 examination of the variable properties  of   the  class  and adding this
575 information (for example) to the prototype used in createObject().
576 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
577 
578 static inline void
unlinkObject(Any obj)579 unlinkObject(Any obj)
580 { Instance  inst  = obj;
581   Class     class = classOfObject(obj);
582   Variable *var   = (Variable *)class->instance_variables->elements;
583   Any      *field = inst->slots;
584   int i;
585 
586   for(i=valInt(class->slots); --i >= 0; var++, field++)
587   { if ( var[0]->type->kind != NAME_alien )
588     { if ( isObject(*field) && !isProtectedObj(*field) )
589       { Any old = *field;
590 
591 	*field = NIL;
592 	delRefObject(inst, old);
593       }
594     }
595   }
596 
597   if ( onFlag(obj, F_ATTRIBUTE|F_CONSTRAINT|F_SENDMETHOD|
598 	           F_GETMETHOD|F_RECOGNISER) )
599   { if ( onFlag(obj, F_CONSTRAINT) )
600     { Chain ch = getAllConstraintsObject(obj, ON);
601       Constraint c;
602 
603       clearFlag(obj, F_CONSTRAINT);
604       for_chain(ch, c, freeObject(c));
605       deleteHashTable(ObjectConstraintTable, obj);
606     }
607     if ( onFlag(obj, F_ATTRIBUTE) )
608     { clearFlag(obj, F_ATTRIBUTE);
609       deleteHashTable(ObjectAttributeTable, obj);
610     }
611     if ( onFlag(obj, F_SENDMETHOD) )
612     { clearFlag(obj, F_SENDMETHOD);
613       deleteHashTable(ObjectSendMethodTable, obj);
614     }
615     if ( onFlag(obj, F_GETMETHOD) )
616     { clearFlag(obj, F_GETMETHOD);
617       deleteHashTable(ObjectGetMethodTable, obj);
618     }
619     if ( onFlag(obj, F_RECOGNISER) )
620     { clearFlag(obj, F_RECOGNISER);
621       deleteHashTable(ObjectRecogniserTable, obj);
622     }
623   }
624 }
625 
626 
627 status
freeObject(Any obj)628 freeObject(Any obj)
629 { Instance inst = obj;
630   Class class;
631 
632   if ( nonObject(inst) || onFlag(inst, F_FREED|F_FREEING) )
633     succeed;
634   if ( isProtectedObj(inst) )		/* cannot be freed */
635     fail;
636 
637   class = classOfObject(inst);
638   freedClass(class, inst);
639 
640   unlockObj(inst);			/* release possible lock */
641   deleteAnswerObject(inst);		/* delete from AnswerStack */
642   setFreeingObj(inst);			/* mark */
643 
644   if ( !qadSendv(inst, NAME_unlink, 0, NULL) )
645     errorPce(inst, NAME_unlinkFailed);
646 
647   if ( onFlag(obj, F_ASSOC) )
648     deleteAssoc(inst);			/* delete name association */
649 
650   unlinkHypersObject(inst);
651 
652   unlinkObject(inst);
653   setFreedObj(inst);			/* freeing finished */
654 
655   if ( noRefsObj(inst) )
656     unallocObject(inst);
657   else
658   { deferredUnalloced++;
659     DEBUG(NAME_free,
660 	  Cprintf("%s has %ld.%ld refs.  Deferring unalloc\n",
661 		  pp(inst), refsObject(inst), codeRefsObject(inst)));
662   }
663 
664   succeed;
665 }
666 
667 
668 static status
unlinkingObject(Any obj)669 unlinkingObject(Any obj)
670 { if ( isFreeingObj(obj) )
671     succeed;
672 
673   fail;
674 }
675 
676 
677 status
createdObject(Any obj,Name how)678 createdObject(Any obj, Name how)
679 { Class class;
680 
681   if ( (class = classOfObject(obj)) )
682     createdClass(class, obj, how);
683 
684   succeed;
685 }
686 
687 
688 status
succeedObject(Any obj,...)689 succeedObject(Any obj, ...)
690 { succeed;
691 }
692 
693 
694 status
failObject(Any obj,...)695 failObject(Any obj, ...)
696 { fail;
697 }
698 
699 
700 Any
getFailObject(Any obj)701 getFailObject(Any obj)
702 { fail;
703 }
704 
705 
706 status
virtualObject(Any obj)707 virtualObject(Any obj)
708 { fail;
709 }
710 
711 
712 status
virtualObject1(Any obj,Any a1)713 virtualObject1(Any obj, Any a1)
714 { fail;
715 }
716 
717 
718 status
virtualObject2(Any obj,Any a1,Any a2)719 virtualObject2(Any obj, Any a1, Any a2)
720 { fail;
721 }
722 
723 
724 Any
getVirtualObject(Any obj)725 getVirtualObject(Any obj)
726 { fail;
727 }
728 
729 
730 Any
getVirtualObject1(Any obj,Any a1)731 getVirtualObject1(Any obj, Any a1)
732 { fail;
733 }
734 
735 
736 Any
getVirtualObject2(Any obj,Any a1,Any a2)737 getVirtualObject2(Any obj, Any a1, Any a2)
738 { fail;
739 }
740 
741 
742 Int
getReferencesObject(Any obj)743 getReferencesObject(Any obj)
744 { answer(toInt(refsObject(obj)));
745 }
746 
747 
748 static Int
getCodeReferencesObject(Any obj)749 getCodeReferencesObject(Any obj)
750 { answer(toInt(codeRefsObject(obj)));
751 }
752 
753 
754 Name
getFlagsObject(Any obj)755 getFlagsObject(Any obj)
756 { char tmp[100];
757   char *s = tmp;
758 
759 #define DoFlag(f, c)	*s++ = (onFlag(obj, f) ? c : '-')
760   DoFlag(F_PROTECTED, 'P');
761   DoFlag(F_LOCKED,    'L');
762   DoFlag(F_ANSWER,    'A');
763   *s = EOS;
764 #undef DoFlag
765 
766   answer(CtoName(tmp));
767 }
768 
769 
770 status
protectObject(Any obj)771 protectObject(Any obj)
772 { deleteAnswerObject(obj);		/* status is clear now */
773 
774   setProtectedObj(obj);
775   succeed;
776 }
777 
778 
779 static BoolObj
getProtectObject(Any obj)780 getProtectObject(Any obj)
781 { answer(isProtectedObj(obj) ? ON : OFF);
782 }
783 
784 
785 status
doneObject(Any obj)786 doneObject(Any obj)
787 { deleteAnswerObject(obj);
788   freeableObj(obj);
789 
790   succeed;
791 }
792 
793 
794 status
lockObject(Any obj,BoolObj val)795 lockObject(Any obj, BoolObj val)
796 { if (val == ON)
797   { deleteAnswerObject(obj);		/* status is clear now */
798     lockObj(obj);
799   } else
800   { unlockObj(obj);
801     freeableObj(obj);
802   }
803   succeed;
804 }
805 
806 
807 static Any
getUnlockObject(Any obj)808 getUnlockObject(Any obj)
809 { unlockObj(obj);
810   pushAnswerObject(obj);
811 
812   answer(obj);
813 }
814 
815 
816 static BoolObj
getLockObject(Any obj)817 getLockObject(Any obj)
818 { answer(lockedObj(obj) ? ON : OFF);
819 }
820 
821 
822 #ifndef O_RUNTIME
823 status
inspectObject(Any obj,BoolObj val)824 inspectObject(Any obj, BoolObj val)
825 { if ( val == ON )
826   { setFlag(obj, F_INSPECT);
827   } else
828   { clearFlag(obj, F_INSPECT);
829   }
830 
831   succeed;
832 }
833 
834 
835 BoolObj
getInspectObject(Any obj)836 getInspectObject(Any obj)
837 { answer(onFlag(obj, F_INSPECT) ? ON : OFF);
838 }
839 #endif /*O_RUNTIME*/
840 
841 
842 Name
getClassNameObject(Any obj)843 getClassNameObject(Any obj)
844 { answer(classOfObject(obj)->name);
845 }
846 
847 
848 Class
getClassObject(Any obj)849 getClassObject(Any obj)
850 { answer(classOfObject(obj));
851 }
852 
853 
854 Any
getSelfObject(Any obj)855 getSelfObject(Any obj)
856 { answer(obj);
857 }
858 
859 
860 /*
861 instanceOfObject(obj, super)
862 Any obj;
863 Class super;
864 { if ( isObject(obj) )
865   { Class class = classOfObject(obj);
866 
867     return class == super || (class->tree_index >= super->tree_index &&
868 			      class->tree_index <  super->neighbour_index);
869   }
870 
871   fail;
872 }
873 */
874 
875 status
setSlotInstance(Any obj,Variable var,Any value)876 setSlotInstance(Any obj, Variable var, Any value)
877 { Instance inst = obj;
878 
879   assignField(inst, &inst->slots[valInt(var->offset)], value);
880   succeed;
881 }
882 
883 
884 static status
sameClassObject(Any obj1,Any obj2)885 sameClassObject(Any obj1, Any obj2)
886 { if ( classOfObject(obj1) == classOfObject(obj2))
887     succeed;
888   fail;
889 }
890 
891 
892 status
nameReferenceObject(Any obj,Name name)893 nameReferenceObject(Any obj, Name name)
894 { Any old;
895 
896   if ( (old = getObjectAssoc(name)) == obj )
897     succeed;
898   if ( old )
899     exceptionPce(PCE, NAME_redeclaredReference, name, EAV);
900   if ( (old = getObjectAssoc(name)) )
901     errorPce(obj, NAME_redeclaredReference, name);
902 
903   deleteAssoc(obj);
904   if ( notNil(name) )
905     newAssoc(name, obj);
906 
907   succeed;
908 }
909 
910 
911 static Any
getObjectReferenceObject(Any obj)912 getObjectReferenceObject(Any obj)
913 { Name name;
914 
915   if ( (name = getNameAssoc(obj)) != FAIL )
916     answer(name);
917 
918   answer(PointerToInt(obj));
919 }
920 
921 
922 		/********************************
923 		*       OBJECT-EXTENSIONS	*
924 		********************************/
925 
926 
927 status
constraintObject(Any obj,Constraint c)928 constraintObject(Any obj, Constraint c)
929 { Chain ch = getAllConstraintsObject(obj, ON);
930 
931   return addChain(ch, c);
932 }
933 
934 
935 status
deleteConstraintObject(Any obj,Constraint c)936 deleteConstraintObject(Any obj, Constraint c)
937 { Chain ch;
938 
939   TRY(ch = getAllConstraintsObject(obj, OFF));
940 
941   return deleteChain(ch, c);
942 }
943 
944 
945 static status
sendMethodObject(Any obj,Method m)946 sendMethodObject(Any obj, Method m)
947 { Chain ch = getAllSendMethodsObject(obj, ON);
948 
949   return prependChain(ch, m);
950 }
951 
952 static status
getMethodObject(Any obj,Method m)953 getMethodObject(Any obj, Method m)
954 { Chain ch = getAllGetMethodsObject(obj, ON);
955 
956   return prependChain(ch, m);
957 }
958 
959 
960 status
attachHyperObject(Any obj,Hyper h,Any to)961 attachHyperObject(Any obj, Hyper h, Any to)
962 { Chain ch = getAllHypersObject(obj, ON);
963 
964   return addChain(ch, h);
965 }
966 
967 
968 static status
deleteHyperObject(Any obj,Hyper h)969 deleteHyperObject(Any obj, Hyper h)
970 { Chain ch;
971 
972   TRY(ch = getAllHypersObject(obj, OFF));
973   if ( deleteChain(ch, h) )
974   { if ( emptyChain(ch) )
975     { deleteHashTable(ObjectHyperTable, obj);
976       clearFlag(obj, F_HYPER);
977     }
978 
979     succeed;
980   }
981 
982   fail;
983 }
984 
985 
986 status
attributeObject(Any obj,Any name,Any value)987 attributeObject(Any obj, Any name, Any value)
988 { Chain ch = getAllAttributesObject(obj, ON);
989   Cell cell;
990 
991   if ( instanceOfObject(name, ClassAttribute) )
992   { Attribute att = (Attribute) name;
993 
994     for_cell(cell, ch)
995     { Attribute a = cell->value;
996 
997       if ( a->name == att->name )
998       { assign(a, value, att->value);
999 	succeed;
1000       }
1001     }
1002 
1003     if ( getInstanceVariableClass(classOfObject(obj), att->name) )
1004       return errorPce(obj, NAME_classHasVariable, att->name);
1005 
1006     return appendChain(ch, att);
1007   } else /* if instanceOfObject(att, ClassName) */
1008   { for_cell(cell, ch)
1009     { Attribute a = cell->value;
1010 
1011       if ( a->name == name )
1012       { assign(a, value, value);
1013 	succeed;
1014       }
1015     }
1016 
1017     if ( getInstanceVariableClass(classOfObject(obj), name) )
1018       return errorPce(obj, NAME_classHasVariable, name);
1019 
1020     return appendChain(ch, newObject(ClassAttribute, name, value, EAV));
1021   }
1022 }
1023 
1024 
1025 status
deleteAttributeObject(Any obj,Any att)1026 deleteAttributeObject(Any obj, Any att)
1027 { Chain ch;
1028   status rval = FAIL;
1029 
1030   TRY(ch = getAllAttributesObject(obj, OFF));
1031 
1032   if ( instanceOfObject(att, ClassAttribute) )
1033     rval = deleteChain(ch, att);
1034   else
1035   { Cell cell;
1036 
1037     for_cell(cell, ch)
1038     { Attribute a = cell->value;
1039 
1040       if ( a->name == att )
1041       { rval = deleteChain(ch, a);
1042 	break;
1043       }
1044     }
1045   }
1046 
1047   if ( rval && emptyChain(ch) )
1048   { deleteHashTable(ObjectAttributeTable, obj);
1049     clearFlag(obj, F_ATTRIBUTE);
1050   }
1051 
1052   return rval;
1053 }
1054 
1055 
1056 Any
getAttributeObject(Any obj,Name name)1057 getAttributeObject(Any obj, Name name)
1058 { Chain ch;
1059   Cell cell;
1060 
1061   TRY(ch = getAllAttributesObject(obj, OFF));
1062 
1063   for_cell(cell, ch)
1064   { Attribute a = cell->value;
1065 
1066     if ( a->name == name )
1067       answer(a->value);
1068   }
1069 
1070   fail;
1071 }
1072 
1073 		 /*******************************
1074 		 *          CONSTRAINTS		*
1075 		 *******************************/
1076 
1077 status
updateConstraintsObject(Any obj)1078 updateConstraintsObject(Any obj)
1079 { if ( onFlag(obj, F_CONSTRAINT) && !isFreedObj(obj) )
1080   { Chain constraints = getAllConstraintsObject(obj, ON);
1081     Cell cell;
1082 
1083     DEBUG(NAME_constraint,
1084 	  Cprintf("Called %s->update_constraints\n", pp(obj)));
1085 
1086     for_cell(cell, constraints)
1087       lockConstraint(cell->value, obj);
1088 
1089     for_cell(cell, constraints)
1090       executeConstraint(cell->value, obj);
1091 
1092     for_cell(cell, constraints)
1093       unlockConstraint(cell->value, obj);
1094   }
1095 
1096   succeed;
1097 }
1098 
1099 
1100 		/********************************
1101 		*       RESOLVING METHODS	*
1102 		********************************/
1103 
1104 Tuple
getSendMethodObject(Any obj,Name selector)1105 getSendMethodObject(Any obj, Name selector)
1106 { Any m, rec;
1107 
1108   TRY( m = resolveSendMethodObject(obj, NULL, selector, &rec) );
1109 
1110   answer(answerObject(ClassTuple, rec, m, EAV));
1111 }
1112 
1113 
1114 Tuple
getGetMethodObject(Any obj,Name selector)1115 getGetMethodObject(Any obj, Name selector)
1116 { Any m, rec;
1117 
1118   TRY( m = resolveGetMethodObject(obj, NULL, selector, &rec) );
1119 
1120   answer(answerObject(ClassTuple, rec, m, EAV));
1121 }
1122 
1123 
1124 status
hasSendMethodObject(Any obj,Name selector)1125 hasSendMethodObject(Any obj, Name selector)
1126 { Any m, rec;
1127 
1128   TRY(m = resolveSendMethodObject(obj, NULL, selector, &rec));
1129   succeed;
1130 }
1131 
1132 
1133 status
hasGetMethodObject(Any obj,Name selector)1134 hasGetMethodObject(Any obj, Name selector)
1135 { Any m, rec;
1136 
1137   TRY(m = resolveGetMethodObject(obj, NULL, selector, &rec));
1138   succeed;
1139 }
1140 
1141 
1142 static int
isSendInitialise(PceGoal g,Any obj)1143 isSendInitialise(PceGoal g, Any obj)
1144 { if ( g->receiver == obj &&
1145        instanceOfObject(g->implementation, ClassSendMethod) )
1146   { SendMethod sm = g->implementation;
1147     if ( sm->name == NAME_initialise )
1148       succeed;
1149   }
1150 
1151   fail;
1152 }
1153 
1154 
1155 
1156 Any
getCreateContextObject(Any obj,Code cond)1157 getCreateContextObject(Any obj, Code cond)
1158 { if ( onFlag(obj, F_CREATING) )
1159   { PceGoal g = CurrentGoal;
1160 
1161     for( ; g; g=g->parent )
1162     { if ( isSendInitialise(g, obj) )
1163       {					/* skip send_super() */
1164 	for( g=g->parent; g && isSendInitialise(g, obj); g = g->parent)
1165 	  ;
1166 					/* goal created by new/2 */
1167 	if ( g && isNil(g->implementation) )
1168 	  g = g->parent;
1169 
1170 	if ( notDefault(cond) )
1171 	{ while( g &&
1172 		 !forwardReceiverCode(cond, obj,
1173 				      g->receiver, g->implementation, EAV) )
1174 	    g = g->parent;
1175 	}
1176 
1177 	if ( g && instanceOfObject(g->implementation, ClassMethod) )
1178 	{ answer(g->receiver);
1179 	}
1180 
1181 	fail;
1182       }
1183     }
1184   }
1185 
1186   fail;
1187 }
1188 
1189 
1190 		 /*******************************
1191 		 *	  COLLECT METHODS	*
1192 		 *******************************/
1193 
1194 static void
mergeMethod(Chain rval,Any m,HashTable done,Code cond)1195 mergeMethod(Chain rval, Any m, HashTable done, Code cond)
1196 { Behaviour b = m;
1197 
1198   if ( !getMemberHashTable(done, b->name) )
1199   { appendHashTable(done, b->name, b);
1200     if ( isDefault(cond) || forwardCodev(cond, 1, &m) )
1201       appendChain(rval, m);
1202   }
1203 }
1204 
1205 
1206 static void
mergeMethods(Chain rval,Chain mts,HashTable done,Code cond)1207 mergeMethods(Chain rval, Chain mts, HashTable done, Code cond)
1208 { Cell cell;
1209 
1210   for_cell(cell, mts)
1211     mergeMethod(rval, cell->value, done, cond);
1212 }
1213 
1214 
1215 
1216 static void
mergeSendMethodsObject(Any obj,Chain ch,HashTable done,Code cond)1217 mergeSendMethodsObject(Any obj, Chain ch, HashTable done, Code cond)
1218 { Chain methods;
1219   Class class;
1220   Cell cell;
1221 
1222   if ( (methods = getAllSendMethodsObject(obj, OFF)) )
1223     mergeMethods(ch, methods, done, cond);
1224   if ( (methods = getAllAttributesObject(obj, OFF)) )
1225     mergeMethods(ch, methods, done, cond);
1226 
1227   for(class = classOfObject(obj); notNil(class); class = class->super_class)
1228   { Variable var;
1229 
1230     mergeMethods(ch, getSendMethodsClass(class), done, cond);
1231     for_vector(class->instance_variables, var,
1232 	       if ( sendAccessVariable(var) )
1233 	         mergeMethod(ch, var, done, cond));
1234   }
1235 
1236   for_cell(cell, classOfObject(obj)->delegate)
1237   { Variable var = cell->value;
1238     Any val;
1239 
1240     if ( (val = getGetVariable(var, obj)) )
1241       mergeSendMethodsObject(val, ch, done, cond);
1242   }
1243 }
1244 
1245 
1246 static Chain
getFindAllSendMethodsObject(Any obj,Code cond)1247 getFindAllSendMethodsObject(Any obj, Code cond)
1248 { Chain ch = answerObject(ClassChain, EAV);
1249   static HashTable done = NULL;
1250 
1251   if ( !done )
1252     done = createHashTable(toInt(32), NAME_none);
1253 
1254   mergeSendMethodsObject(obj, ch, done, cond);
1255   clearHashTable(done);
1256 
1257   answer(ch);
1258 }
1259 
1260 
1261 		/********************************
1262 		*        OBJECT ATTRIBUTES	*
1263 		********************************/
1264 
1265 Chain
getAllConstraintsObject(Any obj,BoolObj create)1266 getAllConstraintsObject(Any obj, BoolObj create)
1267 { if ( onFlag(obj, F_CONSTRAINT) )
1268     answer(getMemberHashTable(ObjectConstraintTable, obj));
1269 
1270   if ( create == ON )
1271   { Chain ch = newObject(ClassChain, EAV);
1272 
1273     setFlag(obj, F_CONSTRAINT);
1274     appendHashTable(ObjectConstraintTable, obj, ch);
1275 
1276     answer(ch);
1277   }
1278 
1279   fail;
1280 }
1281 
1282 
1283 Chain
getAllHypersObject(Any obj,BoolObj create)1284 getAllHypersObject(Any obj, BoolObj create)
1285 { if ( onFlag(obj, F_HYPER) )
1286     answer(getMemberHashTable(ObjectHyperTable, obj));
1287 
1288   if ( create == ON )
1289   { Chain ch = newObject(ClassChain, EAV);
1290 
1291     setFlag(obj, F_HYPER);
1292     appendHashTable(ObjectHyperTable, obj, ch);
1293 
1294     answer(ch);
1295   }
1296 
1297   fail;
1298 }
1299 
1300 
1301 Chain
getAllAttributesObject(Any obj,BoolObj create)1302 getAllAttributesObject(Any obj, BoolObj create)
1303 { if ( onFlag(obj, F_ATTRIBUTE) )
1304     answer(getMemberHashTable(ObjectAttributeTable, obj));
1305 
1306   if ( create == ON )
1307   { Chain ch = newObject(ClassChain, EAV);
1308 
1309     setFlag(obj, F_ATTRIBUTE);
1310     appendHashTable(ObjectAttributeTable, obj, ch);
1311 
1312     answer(ch);
1313   }
1314 
1315   fail;
1316 }
1317 
1318 
1319 Chain
getAllSendMethodsObject(Any obj,BoolObj create)1320 getAllSendMethodsObject(Any obj, BoolObj create)
1321 { if ( onFlag(obj, F_SENDMETHOD) )
1322     answer(getMemberHashTable(ObjectSendMethodTable, obj));
1323 
1324   if ( create == ON )
1325   { Chain ch = newObject(ClassChain, EAV);
1326 
1327     setFlag(obj, F_SENDMETHOD);
1328     appendHashTable(ObjectSendMethodTable, obj, ch);
1329 
1330     answer(ch);
1331   }
1332 
1333   fail;
1334 }
1335 
1336 
1337 Chain
getAllGetMethodsObject(Any obj,BoolObj create)1338 getAllGetMethodsObject(Any obj, BoolObj create)
1339 { if ( onFlag(obj, F_GETMETHOD) )
1340     answer(getMemberHashTable(ObjectGetMethodTable, obj));
1341 
1342   if ( create == ON )
1343   { Chain ch = newObject(ClassChain, EAV);
1344 
1345     setFlag(obj, F_GETMETHOD);
1346     appendHashTable(ObjectGetMethodTable, obj, ch);
1347 
1348     answer(ch);
1349   }
1350 
1351   fail;
1352 }
1353 
1354 
1355 		/********************************
1356 		*           KLONING		*
1357 		********************************/
1358 
1359 typedef struct clone_field *CloneField;
1360 
1361 struct clone_field
1362 { Any		instance;
1363   Any	       *field;
1364   Any		old_value;
1365   unsigned long flags;
1366   CloneField	next;
1367 };
1368 
1369 static	HashTable	CloneTable;
1370 static  CloneField     	CloneFields;
1371 
1372 static void
addCloneField(Any obj,unsigned long flags,Any * field,Any old)1373 addCloneField(Any obj, unsigned long flags, Any *field, Any old)
1374 { CloneField kf = alloc(sizeof(struct clone_field));
1375 
1376   kf->instance  = obj;
1377   kf->field     = field;
1378   kf->old_value = old;
1379   kf->flags     = flags;
1380   kf->next      = CloneFields;
1381   CloneFields   = kf;
1382 }
1383 
1384 static void
destroyCloneFields()1385 destroyCloneFields()
1386 { while(CloneFields != NULL)
1387   { CloneField kf = CloneFields;
1388     CloneFields = kf->next;
1389     unalloc(sizeof(struct clone_field), kf);
1390   }
1391 }
1392 
1393 
1394 Any
getCloneObject(Any obj)1395 getCloneObject(Any obj)
1396 { Any clone;
1397   CloneField kf;
1398 
1399   if ( CloneTable == NULL )
1400     CloneTable = createHashTable(toInt(32), NAME_none);
1401 
1402   clearHashTable(CloneTable);		/* security for handling reset */
1403   CloneFields = NULL;
1404 
1405   clone = getClone2Object(obj);
1406   for(kf = CloneFields; kf != NULL; kf = kf->next)
1407   { Any kl;
1408 
1409     if ( kf->flags & D_CLONE_REFCHAIN )
1410     { Cell cell;
1411       Chain clch = newObject(ClassChain, EAV);
1412 
1413       assignField(kf->instance, kf->field, clch);
1414       for_cell(cell, (Chain)kf->old_value)
1415       { if ( (kl = getMemberHashTable(CloneTable, cell->value)) )
1416 	  appendChain(clch, kl);
1417       }
1418     } else
1419     { if ( (kl = getMemberHashTable(CloneTable, kf->old_value)) != FAIL )
1420 	assignField(kf->instance, kf->field, kl);
1421     }
1422   }
1423 
1424   clearHashTable(CloneTable);
1425   destroyCloneFields();
1426 
1427   pushAnswerObject(clone);
1428   answer(clone);
1429 }
1430 
1431 
1432 status
clonePceSlots(Any org,Any Clone)1433 clonePceSlots(Any org, Any Clone)
1434 { Instance clone = Clone;
1435   Instance me = org;
1436   Class class = classOfObject(org);
1437   int i;
1438 
1439   for_vector(class->instance_variables, Variable var,
1440 	     i = valInt(var->offset);
1441 	     if ( onDFlag(var, D_CLONE_RECURSIVE) )
1442 	     { assign(clone, slots[i], getClone2Object(me->slots[i]));
1443 	     } else if ( onDFlag(var, D_CLONE_REFERENCE) )
1444 	     { assign(clone, slots[i], me->slots[i]);
1445 	       addCloneField(clone, D_CLONE_REFERENCE,
1446 			     &clone->slots[i], me->slots[i]);
1447 	     } else if ( onDFlag(var, D_CLONE_VALUE) )
1448 	     { assign(clone, slots[i], me->slots[i]);
1449 	     } else if ( onDFlag(var, D_CLONE_ALIEN) )
1450 	     { clone->slots[i] = me->slots[i];
1451 	     } else if ( onDFlag(var, D_CLONE_NIL) )
1452 	     { assign(clone, slots[i], NIL);
1453 	       addCloneField(clone, D_CLONE_NIL,
1454 			     &clone->slots[i], me->slots[i]);
1455 	     } else if ( onDFlag(var, D_CLONE_REFCHAIN) )
1456 	     { addCloneField(clone, D_CLONE_REFCHAIN,
1457 			     &clone->slots[i], me->slots[i]);
1458 	     });
1459 
1460   succeed;
1461 }
1462 
1463 
1464 static void
cloneExtenstions(Any me,Any clone)1465 cloneExtenstions(Any me, Any clone)
1466 { Chain ch;
1467 
1468   if ( (ch = getAllConstraintsObject(me, OFF)) )
1469   { Chain ch2 = getClone2Object(ch);
1470 
1471     setFlag(clone, F_CONSTRAINT);
1472     appendHashTable(ObjectConstraintTable, clone, ch2);
1473   }
1474   if ( (ch = getAllHypersObject(me, OFF)) )
1475   { Chain ch2 = getClone2Object(ch);
1476 
1477     setFlag(clone, F_HYPER);
1478     appendHashTable(ObjectHyperTable, clone, ch2);
1479   }
1480   if ( (ch = getAllAttributesObject(me, OFF)) )
1481   { Chain ch2 = getClone2Object(ch);
1482 
1483     setFlag(clone, F_ATTRIBUTE);
1484     appendHashTable(ObjectAttributeTable, clone, ch2);
1485   }
1486   if ( (ch = getAllSendMethodsObject(me, OFF)) )
1487   { Chain ch2 = getClone2Object(ch);
1488 
1489     setFlag(clone, F_SENDMETHOD);
1490     appendHashTable(ObjectSendMethodTable, clone, ch2);
1491   }
1492   if ( (ch = getAllGetMethodsObject(me, OFF)) )
1493   { Chain ch2 = getClone2Object(ch);
1494 
1495     setFlag(clone, F_GETMETHOD);
1496     appendHashTable(ObjectGetMethodTable, clone, ch2);
1497   }
1498   if ( (ch = getAllRecognisersGraphical(me, OFF)) )
1499   { Chain ch2 = getClone2Object(ch);
1500 
1501     setFlag(clone, F_RECOGNISER);
1502     appendHashTable(ObjectRecogniserTable, clone, ch2);
1503   }
1504 }
1505 
1506 
1507 Any
getClone2Object(Any obj)1508 getClone2Object(Any obj)
1509 { Class class;
1510   Instance clone;
1511   Instance me;
1512 
1513   if ( nonObject(obj) )
1514     answer(obj);			/* untyped data-structures */
1515 
1516   if ( (clone = getMemberHashTable(CloneTable, obj)) )
1517   { DEBUG(NAME_clone, Cprintf("%s already cloned into %s\n",
1518 			      pp(obj), pp(clone)));
1519     answer(clone);
1520   }
1521 
1522   me = obj;
1523   class = classOfObject(me);
1524 
1525   if ( class->cloneStyle == NAME_none )
1526     answer(me);
1527   if ( class->cloneStyle == NAME_nil )
1528     answer(NIL);
1529 
1530   clone = (Instance) allocObject(class, FALSE);
1531   if ( offFlag(obj, F_OBTAIN_CLASSVARS) )
1532     clearFlag(clone, F_OBTAIN_CLASSVARS);
1533   DEBUG(NAME_clone, Cprintf("%s cloned into %s\n", pp(me), pp(clone)));
1534   appendHashTable(CloneTable, me, clone);
1535 
1536   cloneExtenstions(me, clone);
1537 
1538   if ( class->cloneFunction != NULL )
1539     (*class->cloneFunction)(me, clone);
1540   else
1541     clonePceSlots(me, clone);
1542 
1543   createdClass(class, clone, NAME_clone);
1544   answer(clone);
1545 }
1546 
1547 
1548 Int
getArityObject(Any obj)1549 getArityObject(Any obj)
1550 { Class class = classOfObject(obj);
1551 
1552   if ( isNil(class->term_names) )
1553     fail;
1554 
1555   answer(class->term_names->size);
1556 }
1557 
1558 
1559 Name
getFunctorObject(Any obj)1560 getFunctorObject(Any obj)
1561 { answer(classOfObject(obj)->name);
1562 }
1563 
1564 
1565 Any
getArgObject(Any obj,Int arg)1566 getArgObject(Any obj, Int arg)
1567 { Class class = classOfObject(obj);
1568   Name selector;
1569 
1570   if ( isNil(class->term_names) )
1571     fail;
1572 
1573   if ( isName(selector = getElementVector(class->term_names, arg)) )
1574     answer( get(obj, selector, EAV) );
1575 
1576   fail;
1577 }
1578 
1579 
1580 Any
getSlotObject(Any obj,Any which)1581 getSlotObject(Any obj, Any which)
1582 { Class class = classOfObject(obj);
1583   Variable var;
1584   Instance inst = (Instance) obj;
1585 
1586   if ( (var = getInstanceVariableClass(class, which)) )
1587   { if ( var->type->kind == NAME_alien &&
1588 	 var->name != CtoName("alien:Any") )
1589       answer(toInt((intptr_t)inst->slots[valInt(var->offset)]));
1590     else
1591       answer(getGetVariable(var, obj));
1592   }
1593 
1594   fail;
1595 }
1596 
1597 
1598 status
slotObject(Any obj,Any which,Any value)1599 slotObject(Any obj, Any which, Any value)
1600 { Variable var;
1601 
1602   if ( (var = getInstanceVariableClass(classOfObject(obj), which)) )
1603     return sendVariable(var, obj, value);
1604 
1605   return errorPce(obj, NAME_noVariable, which);
1606 }
1607 
1608 
1609 static status
isOnObject(Any obj,Name selector)1610 isOnObject(Any obj, Name selector)
1611 { if ( get(obj, selector, EAV) == ON)
1612     succeed;
1613   fail;
1614 }
1615 
1616 
1617 static status
isOffObject(Any obj,Name selector)1618 isOffObject(Any obj, Name selector)
1619 { if ( get(obj, selector, EAV) == OFF)
1620     succeed;
1621   fail;
1622 }
1623 
1624 
1625 static status
hasValueObject(Any obj,Name selector,Any value)1626 hasValueObject(Any obj, Name selector, Any value)
1627 { if (get(obj, selector, EAV) == value)
1628     succeed;
1629   fail;
1630 }
1631 
1632 
1633 static status
notHasValueObject(Any obj,Name selector,Any value)1634 notHasValueObject(Any obj, Name selector, Any value)
1635 { if (get(obj, selector, EAV) != value)
1636     succeed;
1637   fail;
1638 }
1639 
1640 		/********************************
1641 		*           EQUALITY		*
1642 		********************************/
1643 
1644 status
equalObject(Any o1,Any o2)1645 equalObject(Any o1, Any o2)
1646 { return o1 == o2;
1647 }
1648 
1649 
1650 status
sameReferenceObject(Any o1,Any o2)1651 sameReferenceObject(Any o1, Any o2)
1652 { return o1 == o2;
1653 }
1654 
1655 		/********************************
1656 		*         SPECIAL SENDS		*
1657 		********************************/
1658 
1659 static status
sendSubObject(Any obj,Name selector,int argc,Any * argv)1660 sendSubObject(Any obj, Name selector, int argc, Any *argv)
1661 { if ( obj == RECEIVER->value )
1662   { return sendv(obj, selector, argc, argv);
1663   } else
1664     return errorPce(obj, NAME_mustBeToReceiver, RECEIVER->value);
1665 }
1666 
1667 
1668 static Any
getGetSubObject(Any obj,Name selector,int argc,Any * argv)1669 getGetSubObject(Any obj, Name selector, int argc, Any *argv)
1670 { if ( obj == RECEIVER->value )
1671     return getv(obj, selector, argc, argv);
1672 
1673   errorPce(obj, NAME_mustBeToReceiver, RECEIVER->value);
1674   fail;
1675 }
1676 
1677 
1678 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1679 Object ->send_super: Selector, ...
1680 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1681 
1682 status
sendSuperObject(Any obj,Name selector,int argc,const Any argv[])1683 sendSuperObject(Any obj, Name selector, int argc, const Any argv[])
1684 { if ( obj == RECEIVER->value )
1685   { Class current = RECEIVER_CLASS->value;
1686     status rval;
1687 
1688     RECEIVER_CLASS->value = current->super_class;
1689     if ( notNil(RECEIVER_CLASS->value) )
1690       rval = vm_send(obj, selector, RECEIVER_CLASS->value, argc, argv);
1691     else
1692       rval = FAIL;
1693     RECEIVER_CLASS->value = current;
1694 
1695     return rval;
1696   }
1697 
1698   errorPce(obj, NAME_mustBeToReceiver, RECEIVER->value);
1699   fail;
1700 }
1701 
1702 
1703 static Any
getGetSuperObject(Any obj,Name selector,int argc,const Any argv[])1704 getGetSuperObject(Any obj, Name selector, int argc, const Any argv[])
1705 { if ( obj == RECEIVER->value )
1706   { Class current = RECEIVER_CLASS->value;
1707     Any rval;
1708 
1709     RECEIVER_CLASS->value = current->super_class;
1710     rval = vm_get(obj, selector, RECEIVER_CLASS->value, argc, argv);
1711     RECEIVER_CLASS->value = current;
1712 
1713     return rval;
1714   }
1715 
1716   errorPce(obj, NAME_mustBeToReceiver, RECEIVER->value);
1717   fail;
1718 }
1719 
1720 
1721 static status
sendClassObject(Any obj,Name selector,int argc,Any * argv)1722 sendClassObject(Any obj, Name selector, int argc, Any *argv)
1723 { if ( obj == RECEIVER->value )
1724   { Class current = RECEIVER_CLASS->value;
1725     status rval;
1726 
1727     RECEIVER_CLASS->value = classOfObject(obj);
1728     rval = vm_send(obj, selector, RECEIVER_CLASS->value, argc, argv);
1729     RECEIVER_CLASS->value = current;
1730 
1731     return rval;
1732   }
1733 
1734   errorPce(obj, NAME_mustBeToReceiver, RECEIVER->value);
1735   fail;
1736 }
1737 
1738 
1739 static Any
getGetClassObject(Any obj,Name selector,int argc,Any * argv)1740 getGetClassObject(Any obj, Name selector, int argc, Any *argv)
1741 { if ( obj == RECEIVER->value )
1742   { Class current = RECEIVER_CLASS->value;
1743     Any rval;
1744 
1745     RECEIVER_CLASS->value = classOfObject(obj);
1746     rval = vm_get(obj, selector, RECEIVER_CLASS->value, argc, argv);
1747     RECEIVER_CLASS->value = current;
1748 
1749     return rval;
1750   }
1751 
1752   errorPce(obj, NAME_mustBeToReceiver, RECEIVER->value);
1753   fail;
1754 }
1755 
1756 
1757 static status
sendVectorObject(Any obj,int argc,Any * argv)1758 sendVectorObject(Any obj, int argc, Any *argv)
1759 { Any a;
1760   Vector v;
1761   int shift;
1762   int args;
1763 
1764   if ( argc == 0 )
1765     goto usage;
1766   if ( argc >= 2 && isInteger(argv[argc-1]) )
1767   { a = argv[argc-2];
1768     shift = valInt(argv[argc-1]);
1769     args = argc-2;
1770   } else
1771   { a = argv[argc-1];
1772     shift = 0;
1773     args = argc-1;
1774   }
1775 
1776   if ( !(v = checkType(a, TypeVector, NIL)) )
1777   { if ( a == name_nil )
1778     { Name sel;
1779 
1780       if ( args >= 1 && (sel = checkType(argv[0], TypeName, NIL)) )
1781         return sendv(obj, sel, args-1, argv+1);
1782       fail;
1783     }
1784     goto usage;
1785   } else
1786   { int argn = args+valInt(v->size)-shift;
1787     ArgVector(av, argn);
1788     int i, n;
1789 
1790     for(i=0; i<args; i++)
1791       av[i] = argv[i];
1792     for(n=shift; n<valInt(v->size); n++)
1793       av[i++] = v->elements[n];
1794 
1795     if ( argn >= 1 )
1796     { Name sel;
1797 
1798       if ( (sel = checkType(av[0], TypeName, NIL)) )
1799 	return sendv(obj, sel, argn-1, av+1);
1800       goto usage;
1801     }
1802 
1803     fail;
1804   }
1805 
1806 usage:
1807   return errorPce(obj, NAME_badVectorUsage);
1808 }
1809 
1810 
1811 static Any
getVectorObject(Any obj,int argc,Any * argv)1812 getVectorObject(Any obj, int argc, Any *argv)
1813 { Any a;
1814   Vector v;
1815   int shift;
1816   int args;
1817 
1818   if ( argc == 0 )
1819     goto usage;
1820   if ( argc >= 2 && isInteger(argv[argc-1]) )
1821   { a = argv[argc-2];
1822     shift = valInt(argv[argc-1]);
1823     args = argc-2;
1824   } else
1825   { a = argv[argc-1];
1826     shift = 0;
1827     args = argc-1;
1828   }
1829 
1830   if ( !(v = checkType(a, TypeVector, NIL)) )
1831   { if ( a == name_nil )
1832     { if ( args >= 1 )
1833 	return getv(obj, (Name) argv[0], args-1, argv+1);
1834       fail;
1835     }
1836     goto usage;
1837   } else
1838   { int argn = args+valInt(v->size)-shift;
1839     ArgVector(av, argn);
1840     int i, n;
1841 
1842     for(i=0; i<args; i++)
1843       av[i] = argv[i];
1844     for(n=shift; n<valInt(v->size); n++)
1845       av[i++] = v->elements[n];
1846 
1847     if ( argn >= 1 )
1848       return getv(obj, (Name) av[0], argn-1, av+1);
1849     fail;
1850   }
1851 
1852 usage:
1853   errorPce(obj, NAME_badVectorUsage);
1854   fail;
1855 }
1856 
1857 
1858 static status
sendSuperVectorObject(Any obj,int argc,Any * argv)1859 sendSuperVectorObject(Any obj, int argc, Any *argv)
1860 { Vector v;
1861   int shift;
1862   int args;
1863 
1864   if ( argc == 0 )
1865     goto usage;
1866   if ( argc >= 2 && isInteger(argv[argc-1]) )
1867   { v = argv[argc-2];
1868     shift = valInt(argv[argc-1]);
1869     args = argc-2;
1870   } else
1871   { v = argv[argc-1];
1872     shift = 0;
1873     args = argc-1;
1874   }
1875 
1876   if ( !instanceOfObject(v, ClassVector) )
1877     goto usage;
1878   else
1879   { int argn = args+valInt(v->size)-shift;
1880     ArgVector(av, argn);
1881     int i, n;
1882 
1883     for(i=0; i<args; i++)
1884       av[i] = argv[i];
1885     for(n=shift; n<valInt(v->size); n++)
1886       av[i++] = v->elements[n];
1887 
1888     if ( argn >= 1 )
1889       return sendSuperObject(obj, (Name) av[0], argn-1, av+1);
1890     fail;
1891   }
1892 
1893 usage:
1894   return errorPce(obj, NAME_badVectorUsage);
1895 }
1896 
1897 
1898 static status
sendHyperObject(Any obj,Name hname,Name selector,int argc,Any * argv)1899 sendHyperObject(Any obj, Name hname, Name selector, int argc, Any *argv)
1900 { Chain ch;
1901   status rval = FAIL;
1902 
1903   if ( (ch = getAllHypersObject(obj, OFF)) )
1904   { Hyper h;
1905 
1906     for_chain(ch, h,
1907 	      { if ( h->from == obj )
1908 		{ if ( (hname == h->forward_name || isDefault(hname)) &&
1909 		       sendv(h->to, selector, argc, argv) )
1910 		    rval = SUCCEED;
1911 		} else
1912 		{ if ( (hname == h->backward_name || isDefault(hname)) &&
1913 		       sendv(h->from, selector, argc, argv) )
1914 		    rval = SUCCEED;
1915 		}
1916 	      });
1917   }
1918 
1919   return rval;
1920 }
1921 
1922 
1923 static Any
getHyperObject(Any obj,Name hname,Name selector,int argc,Any * argv)1924 getHyperObject(Any obj, Name hname, Name selector, int argc, Any *argv)
1925 { Chain ch;
1926 
1927   if ( (ch = getAllHypersObject(obj, OFF)) )
1928   { Hyper h;
1929     Any rval;
1930 
1931     for_chain(ch, h,
1932 	      { if ( h->from == obj )
1933 		{ if ( (hname == h->forward_name || isDefault(hname)) &&
1934 		       (rval = getv(h->to, selector, argc, argv)) )
1935 		    answer(rval);
1936 		} else
1937 		{ if ( (hname == h->backward_name || isDefault(hname)) &&
1938 		       (rval = getv(h->from, selector, argc, argv)) )
1939 		    answer(rval);
1940 		}
1941 	      });
1942   }
1943 
1944   fail;
1945 }
1946 
1947 
1948 Any
getFindHyperObject(Any obj,Name hname,Code cond)1949 getFindHyperObject(Any obj, Name hname, Code cond)
1950 { Chain ch;
1951 
1952   if ( (ch = getAllHypersObject(obj, OFF)) )
1953   { Cell cell;
1954 
1955     for_cell(cell, ch)
1956     { Hyper h = cell->value;
1957 
1958       if ( h->from == obj )
1959       { if ( (hname == h->forward_name || isDefault(hname)) &&
1960 	     (isDefault(cond) || forwardCode(cond, h->from, h, h->to, EAV)) )
1961 	  answer(h);
1962       } else
1963       { if ( (hname == h->backward_name || isDefault(hname)) &&
1964 	     (isDefault(cond) || forwardCode(cond, h->to, h, h->from, EAV)) )
1965 	  answer(h);
1966       }
1967     }
1968   }
1969 
1970   fail;
1971 }
1972 
1973 
1974 Any
getHyperedObject(Any obj,Name hname,Code cond)1975 getHyperedObject(Any obj, Name hname, Code cond)
1976 { Hyper h;
1977 
1978   if ( (h = getFindHyperObject(obj, hname, cond)) )
1979     answer(h->from == obj ? h->to : h->from);
1980 
1981   fail;
1982 }
1983 
1984 
1985 status
freeHypersObject(Any obj,Name hname,Code cond)1986 freeHypersObject(Any obj, Name hname, Code cond)
1987 { Chain ch;
1988 
1989   if ( (ch = getAllHypersObject(obj, OFF)) )
1990   { Hyper h;
1991 
1992     for_chain(ch, h,
1993 	      { if ( h->from == obj )
1994 		{ if ( (hname == h->forward_name || isDefault(hname)) &&
1995 		       (isDefault(cond) ||
1996 			forwardCode(cond, h->from, h, h->to, EAV)) )
1997 		    freeObject(h);
1998 		} else
1999 		{ if ( (hname == h->backward_name || isDefault(hname)) &&
2000 		       (isDefault(cond) ||
2001 			forwardCode(cond, h->to, h, h->from, EAV)) )
2002 		    freeObject(h);
2003 		}
2004 	      });
2005   }
2006 
2007   succeed;
2008 }
2009 
2010 
2011 		/********************************
2012 		*        TRAPPING CHANGES	*
2013 		********************************/
2014 
2015 static inline status
_changedObject(Any obj,va_list args)2016 _changedObject(Any obj, va_list args)
2017 { Class class = classOfObject(obj);
2018 
2019   if ( notNil(class->changed_messages) && !onFlag(obj, F_FREEING|F_CREATING) )
2020   { Cell cell;
2021     Any argv[VA_PCE_MAX_ARGS];
2022     int argc;
2023 
2024     if ( changedLevel )
2025     { errorPce(obj, NAME_changedLoop);
2026       succeed;
2027     }
2028 
2029     changedLevel++;
2030 
2031     argv[0] = obj;
2032     for(argc = 1; (argv[argc] = va_arg(args, Any)) != NULL; argc++)
2033       ;
2034     for_cell(cell, class->changed_messages)
2035       forwardCodev(cell->value, argc, argv);
2036 
2037     changedLevel--;
2038   }
2039 
2040   succeed;
2041 }
2042 
2043 
2044 status
changedObject(Any obj,...)2045 changedObject(Any obj, ...)
2046 { va_list args;
2047   status rval;
2048 
2049   if ( onFlag(obj, F_INSPECT) )
2050   { va_start(args, obj);
2051     rval = _changedObject(obj, args);
2052     va_end(args);
2053 
2054     return rval;
2055   } else
2056     succeed;
2057 }
2058 
2059 
2060 status
changedFieldObject(Any obj,Any * field)2061 changedFieldObject(Any obj, Any *field)
2062 { if ( onFlag(obj, F_INSPECT) )
2063   { Class class = classOfObject(obj);
2064 
2065     if ( notNil(class->changed_messages) &&
2066 	 !onFlag(obj, F_CREATING|F_FREEING) )
2067     { Instance inst = obj;
2068       int offset = field - &inst->slots[0];
2069       Variable v = getInstanceVariableClass(class, (Any) toInt(offset));
2070 
2071       if ( v != FAIL )
2072       { Cell cell;
2073 
2074 	if ( changedLevel )
2075 	{ errorPce(obj, NAME_changedLoop);
2076 	  succeed;
2077 	}
2078 	changedLevel++;
2079 	for_cell(cell, class->changed_messages)
2080 	  forwardCode(cell->value, obj, v->name, EAV);
2081 	changedLevel--;
2082       }
2083     }
2084   }
2085 
2086   succeed;
2087 }
2088 
2089 		/********************************
2090 		*           RESOURCES		*
2091 		********************************/
2092 
2093 Any
getClassVariableValueObject(Any obj,Name name)2094 getClassVariableValueObject(Any obj, Name name)
2095 { if ( !isObject(obj) )
2096     fail;
2097 
2098   answer(getClassVariableValueClass(classOfObject(obj), name));
2099 }
2100 
2101 
2102 status
obtainClassVariablesObject(Any obj)2103 obtainClassVariablesObject(Any obj)
2104 { if ( onFlag(obj, F_OBTAIN_CLASSVARS) )
2105   { Instance inst = obj;
2106     Class class = classOfObject(obj);
2107     int slots = valInt(class->slots);
2108     int i;
2109     status rval = SUCCEED;
2110 
2111     for(i=0; i<slots; i++)
2112     { if ( isClassDefault(inst->slots[i]) )
2113       { Variable var = class->instance_variables->elements[i];
2114 	Any value;
2115 
2116 	if ( (value = getClassVariableValueObject(obj, var->name)) )
2117 	{ Any v2;
2118 
2119 	  if ( (v2 = checkType(value, var->type, obj)) )
2120 	    assignField(inst, &inst->slots[i], v2);
2121 	  else
2122 	  { errorPce(var, NAME_incompatibleResource);
2123 	    rval = FAIL;
2124 	  }
2125 	} else
2126 	{ errorPce(var, NAME_noClassVariable);
2127 	  rval = FAIL;
2128 	}
2129       }
2130     }
2131 
2132     clearFlag(obj, F_OBTAIN_CLASSVARS);
2133     return rval;
2134   }
2135 
2136   succeed;
2137 }
2138 
2139 
2140 		/********************************
2141 		*         MISCELLANEOUS		*
2142 		********************************/
2143 
2144 status
convertLoadedObjectObject(Any obj,Int oldversion,Int currentversion)2145 convertLoadedObjectObject(Any obj, Int oldversion, Int currentversion)
2146 { succeed;
2147 }
2148 
2149 
2150 static status
initialiseNewSlotObject(Any obj,Variable var)2151 initialiseNewSlotObject(Any obj, Variable var)
2152 { if ( validateType(var->type, NIL, obj) )
2153     succeed;
2154   if ( validateType(var->type, DEFAULT, obj) )
2155     return sendVariable(var, obj, DEFAULT);
2156 
2157   fail;
2158 }
2159 
2160 
2161 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2162 Translates text of the form
2163 
2164   <blank>*@<blank>*<digit>+		integer reference
2165   <blank>*@<blank>*<alnum>+		atomic reference
2166 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2167 
2168 Any
getConvertObject(Any ctx,Any x)2169 getConvertObject(Any ctx, Any x)
2170 { char *s;
2171   Any rval = FAIL;
2172 
2173   if ( isInteger(x) )
2174     rval = answerObject(ClassNumber, x, EAV);
2175 
2176   if ( (s = toCharp(x)) )
2177   { char *start;
2178 
2179     for( ; *s && isblank(*s); s++)	/* skip leading blanks */
2180       ;
2181     if ( s[0] != '@' )			/* verify starting '@' */
2182       fail;
2183     for( s++ ; *s && isblank(*s); s++)	/* skip blanks */
2184       ;
2185     start = s;
2186 
2187 					/* check for @35435623 */
2188     for( ; isdigit(*s); s++ )
2189       ;
2190     if ( *s == EOS )
2191       rval = getObjectFromReferencePce(PCE, toInt(atol(start)));
2192     else
2193     {					/* check for @name (exception?) */
2194       for( s=start; iscsym(*s); s++ )
2195 	;
2196       if ( *s == EOS )
2197 	rval = getObjectAssoc(CtoKeyword(start));
2198     }
2199   }
2200 
2201   answer(rval);
2202 }
2203 
2204 
2205 		/********************************
2206 		*           CHECK		*
2207 		********************************/
2208 
2209 static int
checkExtensonsObject(Any obj,BoolObj recursive,HashTable done,int errs)2210 checkExtensonsObject(Any obj, BoolObj recursive, HashTable done, int errs)
2211 { Any val;
2212 
2213 #define CheckExt(att, get, attname) \
2214   { if ( onFlag(obj, att) ) \
2215     { if ( !(val = get(obj, OFF)) ) \
2216       { errorPce(obj, NAME_noExtension, attname); \
2217 	errs++; \
2218       } \
2219       errs = check_object(val, recursive, done, errs); \
2220     } \
2221   }
2222 
2223   if ( onFlag(obj, F_CONSTRAINT|F_ATTRIBUTE|F_SENDMETHOD|F_GETMETHOD|
2224 	           F_HYPER|F_RECOGNISER) )
2225   { CheckExt(F_CONSTRAINT, getAllConstraintsObject, NAME_allConstraints);
2226     CheckExt(F_ATTRIBUTE,  getAllAttributesObject,  NAME_allAttributes);
2227     CheckExt(F_SENDMETHOD, getAllSendMethodsObject, NAME_allSendMethods);
2228     CheckExt(F_GETMETHOD,  getAllGetMethodsObject,  NAME_allGetMethods);
2229     CheckExt(F_HYPER,      getAllHypersObject,      NAME_allHypers);
2230     CheckExt(F_RECOGNISER, getAllRecognisersGraphical, NAME_allRecognisers);
2231   }
2232 #undef CheckExtension
2233 
2234   return errs;
2235 }
2236 
2237 
2238 static int
check_object(Any obj,BoolObj recursive,HashTable done,int errs)2239 check_object(Any obj, BoolObj recursive, HashTable done, int errs)
2240 { Instance inst = obj;
2241   Class class;
2242   int slots;
2243   int i;
2244 
2245   if ( recursive == ON )
2246   { if ( getMemberHashTable(done, obj) )
2247       return errs;
2248     appendHashTable(done, obj, NIL);
2249   }
2250 
2251   if ( !isProperObject(obj) )
2252   { errorPce(CtoName(pp(obj)), NAME_noProperObject);
2253     return errs + 1;
2254   }
2255 
2256   if ( isCreatingObj(obj) )
2257   { if ( instanceOfObject(obj, ClassClass) )	/* HACK: see typeClass() */
2258       return errs;
2259 
2260     errorPce(obj, NAME_creating);
2261     errs++;
2262   }
2263 
2264   if ( onFlag(obj, F_OBTAIN_CLASSVARS) )
2265     errorPce(obj, NAME_classVariablesNotObtained);
2266 
2267   DEBUG(NAME_codeReferences,
2268 	if ( codeRefsObject(obj) != 0 )
2269 	  writef("\t%s has %d code references\n",
2270 		 obj,
2271 		 toInt(codeRefsObject(obj))));
2272 
2273   class = classOfObject(inst);
2274   slots = valInt(class->slots);
2275 
2276 #define Test(x) if ( isObject(x) ) \
2277 		     (errs = check_object(x, recursive, done, errs))
2278 
2279   for(i=0; i<slots; i++)
2280   { if ( isPceSlot(class, i) )
2281     { Variable var = getInstanceVariableClass(class, toInt(i));
2282       Any value = inst->slots[i];
2283 
2284       if ( var == FAIL )
2285       { errorPce(obj, NAME_noVariable, toInt(i));
2286       	continue;
2287       }
2288 
2289       if ( isClassDefault(value) &&
2290 	   getClassVariableClass(class, var->name) )
2291 	continue;
2292       if ( isClassDefault(value) &&
2293 	   instanceOfObject(obj, ClassClass) &&
2294 	   ((Class)obj)->realised != ON )
2295 	continue;
2296 
2297       if ( !validateType(var->type, value, obj) )
2298       { errorPce(obj, NAME_badSlotValue, var, value);
2299 	errs++;
2300       } else if ( isObject(value) )
2301       { if ( isFreedObj(value) )
2302 	{ errorPce(obj, NAME_freedSlotValue, var, CtoName(pp(value)));
2303 	  errs++;
2304 	} else if ( recursive == ON && isObject(value) )
2305 	{ if ( !isProperObject(value) )
2306 	  { errorPce(obj, NAME_badSlotValue, var, CtoName(pp(value)));
2307 	    errs++;
2308 	  } else
2309 	    Test(value);
2310 	}
2311       }
2312     }
2313   }
2314 
2315   errs = checkExtensonsObject(obj, recursive, done, errs);
2316 
2317   if ( instanceOfObject(obj, ClassChain) )
2318   { Cell cell;
2319     int i = 1;
2320 
2321     for_cell(cell, (Chain) obj)
2322     { if ( isObject(cell->value) )
2323       { if ( isFreedObj(cell->value) )
2324 	{ errorPce(obj, NAME_freedCellValue,
2325 		   toInt(i), CtoName(pp(cell->value)));
2326 	  errs++;
2327 	} else if ( recursive == ON && isObject(cell->value) )
2328 	{ if ( !isProperObject(cell->value) )
2329 	  { errorPce(obj, NAME_badCellCalue,
2330 		     toInt(i), CtoName(pp(cell->value)));
2331 	    errs++;
2332 	  } else
2333 	    Test(cell->value);
2334 	}
2335       }
2336       i++;
2337     }
2338   } else if ( instanceOfObject(obj, ClassVector) )
2339   { for_vector((Vector) obj, Any value,
2340 	       if ( isObject(value) )
2341 	       { if ( isFreedObj(value) )
2342 		 { errorPce(obj, NAME_freedElementValue,
2343 			    toInt(_iv), CtoName(pp(value)));
2344 		   errs++;
2345 		 } else if ( recursive == ON && isObject(value) )
2346 		 { if ( !isProperObject(value) )
2347 		   { errorPce(obj, NAME_badElementValue,
2348 			      toInt(_iv), CtoName(pp(value)));
2349 		     errs++;
2350 		   } else
2351 		     Test(value);
2352 		 }
2353 	       });
2354   } else if ( instanceOfObject(obj, ClassHashTable) )
2355   { HashTable ht = (HashTable)obj;
2356 
2357     if ( (valInt(ht->size) * 4) > 3 * ht->buckets)
2358     { errorPce(ht, NAME_tooFewBuckets, ht->size, ht->buckets);
2359       errs++;
2360     }
2361 
2362     for_hash_table(ht, s,
2363 		   { if ( isObject(s->name) )
2364 		     { if ( isFreedObj(s->name) )
2365 		       { errorPce(ht, NAME_freedKeyValue,
2366 				  CtoName(pp(s->name)), s->value);
2367 			 errs++;
2368 		       } else if ( recursive == ON && isObject(s->name) )
2369 		       { if ( !isProperObject(s->name) )
2370 			 { errorPce(ht, NAME_badKeyValue,
2371 				    CtoName(pp(s->name)), s->value);
2372 			   errs++;
2373 			 } else
2374 			   Test(s->name);
2375 		       }
2376 		     }
2377 		     if ( isObject(s->value) )
2378 		     { if ( isFreedObj(s->value) )
2379 		       { errorPce(ht, NAME_freedValueValue,
2380 				  s->name, CtoName(pp(s->value)));
2381 			 errs++;
2382 		       } else if ( recursive == ON && isObject(s->value) )
2383 		       { if ( !isProperObject(s->value) )
2384 			 { errorPce(ht, NAME_badValueValue,
2385 				    s->name, CtoName(pp(s->value)));
2386 			   errs++;
2387 			 } else
2388 			   Test(s->value);
2389 		       }
2390 		     }
2391 		   });
2392   }
2393 #undef Test
2394 
2395   return errs;
2396 }
2397 
2398 
2399 status
CheckObject(Any obj,BoolObj recursive)2400 CheckObject(Any obj, BoolObj recursive)
2401 { HashTable done = NIL;
2402   int errs;
2403 
2404   if ( isDefault(recursive) )
2405     recursive = ON;
2406 
2407   if ( recursive == ON )
2408   { checkNames(TRUE);
2409     done = createHashTable(toInt(200), NAME_none);
2410   }
2411 
2412   errs = check_object(obj, recursive, done, 0);
2413 
2414   if ( notNil(done) )
2415   { errorPce(obj, NAME_checkedObjects, done->size);
2416     freeHashTable(done);
2417   }
2418 
2419   return errs ? FAIL : SUCCEED;
2420 }
2421 
2422 
2423 static status
for_slot_reference_object(Any obj,Code msg,BoolObj recursive,HashTable done)2424 for_slot_reference_object(Any obj, Code msg, BoolObj recursive, HashTable done)
2425 { Instance inst = obj;
2426   Class class;
2427   int slots;
2428   int i;
2429 
2430   if ( !isProperObject(obj) )
2431   { errorPce(CtoName(pp(obj)), NAME_noProperObject);
2432     fail;
2433   }
2434 
2435   class = classOfObject(inst);
2436   slots = valInt(class->slots);
2437 
2438   if ( recursive == ON )
2439   { if ( getMemberHashTable(done, obj) != FAIL )
2440       succeed;
2441     appendHashTable(done, obj, NIL);
2442   }
2443 
2444   for(i=0; i<slots; i++)
2445   { if ( isPceSlot(class, i) )
2446     { Variable var = getInstanceVariableClass(class, (Any) toInt(i));
2447       Any value = inst->slots[i];
2448 
2449       if ( var == FAIL )
2450       { errorPce(obj, NAME_noVariable, toInt(i));
2451       	continue;
2452       }
2453 
2454       if ( isDefault(value) && getClassVariableClass(class, var->name) )
2455 	value = getGetVariable(var, inst);
2456 
2457       forwardCode(msg, inst, NAME_slot, var->name, value, EAV);
2458       if ( recursive == ON && isObject(value) )
2459 	for_slot_reference_object(value, msg, recursive, done);
2460     }
2461   }
2462 
2463   if ( instanceOfObject(obj, ClassChain) )
2464   { Cell cell;
2465     int n = 1;
2466 
2467     for_cell(cell, (Chain) obj)
2468     { forwardCode(msg, obj, NAME_cell, toInt(n), cell->value, EAV);
2469 
2470       if ( recursive == ON && isObject(cell->value) )
2471 	for_slot_reference_object(cell->value, msg, recursive, done);
2472       n++;
2473     }
2474   } else if ( instanceOfObject(obj, ClassVector) )
2475   { for_vector((Vector) obj, Any value,
2476 	       forwardCode(msg, NAME_element, obj, toInt(_iv), value, EAV);
2477 	       if ( recursive == ON && isObject(value) )
2478 		 for_slot_reference_object(value, msg, recursive, done););
2479   } else if ( instanceOfObject(obj, ClassHashTable) )
2480   { for_hash_table((HashTable) obj, s,
2481 		   { forwardCode(msg, obj, NAME_key, s->name, s->value, EAV);
2482 
2483 		     if ( recursive == ON )
2484 		     { if ( isObject(s->name) )
2485 			 for_slot_reference_object(s->name, msg,
2486 						   recursive, done);
2487 		       if ( isObject(s->value) )
2488 			 for_slot_reference_object(s->value, msg,
2489 						   recursive, done);
2490 		     }
2491 		   });
2492   }
2493 
2494   succeed;
2495 }
2496 
2497 
2498 static status
forSlotReferenceObject(Any obj,Code msg,BoolObj recursive)2499 forSlotReferenceObject(Any obj, Code msg, BoolObj recursive)
2500 { HashTable done = NULL;
2501 
2502   if ( isDefault(recursive) )
2503     recursive = ON;
2504   if ( recursive == ON )
2505     done = createHashTable(toInt(200), NAME_none);
2506 
2507   for_slot_reference_object(obj, msg, recursive, done);
2508 
2509   if ( notNil(done) )
2510     freeHashTable(done);
2511 
2512   succeed;
2513 }
2514 
2515 
2516 		/********************************
2517 		*       ERRORS/FEEDBACK		*
2518 		********************************/
2519 
2520 status
errorObjectv(Any obj,Error e,int argc,Any * argv)2521 errorObjectv(Any obj, Error e, int argc, Any *argv)
2522 { if ( e->kind == NAME_ignored )
2523     fail;
2524 
2525   assign(PCE, last_error, e->id);
2526 
2527   if ( !catchedErrorPce(PCE, e->id) || e->kind == NAME_fatal )
2528   { ArgVector(av, argc+1);
2529     PceGoal g = CurrentGoal;
2530     int i;
2531 
2532     av[0] = obj;
2533     for(i=0; i<argc; i++)
2534       av[i+1] = argv[i];
2535 
2536     for(i=0; i++ < 1 && isProperGoal(g); ) /* go one up for the real error */
2537       g = g->parent;
2538 
2539     if ( e->kind == NAME_error && isProperGoal(g) )
2540     { g->flags |= PCE_GF_EXCEPTION;
2541       g->errcode = PCE_ERR_ERROR;
2542       g->errc1   = e;
2543       g->errc2   = createCodeVectorv(argc+1, av);
2544     }
2545 
2546     if ( e->feedback == NAME_throw && e->kind != NAME_fatal )
2547     {					/* See if host wants to catch */
2548 					/* the error.  If so, put it into */
2549 					/* the goal and return silently */
2550       for( ; isProperGoal(g); g = g->parent )
2551       { if ( g->flags & PCE_GF_CATCH )
2552 	{ g->flags |= PCE_GF_THROW;
2553 	  g->errcode = PCE_ERR_ERROR;
2554 	  g->errc1   = e->id;
2555 	  g->errc2   = createCodeVectorv(argc+1, av);
2556 
2557 	  fail;
2558 	}
2559       }
2560     }
2561 
2562     sendv(e, NAME_display, argc+1, av);
2563   }
2564 
2565   fail;
2566 }
2567 
2568 
2569 static Any
getReportToObject(Any obj)2570 getReportToObject(Any obj)
2571 { if ( notNil(EVENT->value) )		/* associate to @event?receiver */
2572     answer(getReceiverEvent(EVENT->value));
2573 
2574   fail;
2575 }
2576 
2577 
2578 status
printReportObject(Any obj,Name kind,CharArray fmt,int argc,Any * argv)2579 printReportObject(Any obj, Name kind, CharArray fmt, int argc, Any *argv)
2580 { string msg;
2581   Any av[2];
2582 
2583   if ( isDefault(fmt) )
2584     fmt = (CharArray) (kind == NAME_done ? NAME_done : NAME_);
2585   str_writefv(&msg, fmt, argc, argv);
2586   av[0] = kind;
2587   av[1] = StringToTempString(&msg);
2588   formatPcev(PCE,
2589 	     (CharArray) CtoName(kind == NAME_progress ? "[PCE: %I%s ... " :
2590 				 kind == NAME_done     ? "%I%s]\n" :
2591 							 "[PCE: %s: %s]\n"),
2592 	     2, av);
2593   if ( kind == NAME_progress )
2594     Cflush();
2595   considerPreserveObject(av[1]);
2596   str_unalloc(&msg);
2597 
2598   succeed;
2599 }
2600 
2601 
2602 static status
reportObject(Any obj,Name kind,CharArray fmt,int argc,Any * argv)2603 reportObject(Any obj, Name kind, CharArray fmt, int argc, Any *argv)
2604 { Any to;
2605 
2606   if ( !(to = get(obj, NAME_reportTo, EAV)) )
2607   {
2608 #ifdef O_RUNTIME
2609     to = CurrentDisplay(NIL);
2610 #else
2611     if ( PCE->trap_errors == OFF )	/* Separate flag? */
2612       to = CurrentDisplay(NIL);
2613     else if ( obj != PCE )
2614       to = PCE;
2615 #endif
2616   }
2617 
2618   if ( to && notNil(to) )
2619   { ArgVector(av, argc + 2);
2620 
2621     av[0] = kind;
2622     av[1] = fmt;
2623     copyArgs(argc, argv, &av[2]);
2624 
2625     return sendv(to, NAME_report, argc+2, av);
2626   } else				/* no event: print it */
2627   { return printReportObject(obj, kind, fmt, argc, argv);
2628   }
2629 }
2630 
2631 
2632 		/********************************
2633 		*        MANUAL SUPPORT		*
2634 		********************************/
2635 
2636 #ifndef O_RUNTIME
2637 Name
getManIdObject(Any obj)2638 getManIdObject(Any obj)
2639 { Name name;
2640 
2641   if ( isName(name = getObjectReferenceObject(obj)) )
2642   { char buf[LINESIZE];
2643 
2644     sprintf(buf, "O.%s", strName(name));
2645     answer(CtoName(buf));
2646   }
2647 
2648   fail;
2649 }
2650 
2651 
2652 static Name
getManIndicatorObject(Any obj)2653 getManIndicatorObject(Any obj)
2654 { answer(CtoName("O"));
2655 }
2656 #endif
2657 
2658 
2659 static CharArray
getPrintNameObject(Any obj)2660 getPrintNameObject(Any obj)
2661 { CharArray name;
2662 
2663   if ( hasGetMethodObject(obj, NAME_name) &&
2664        (name = get(obj, NAME_name, EAV)) &&
2665        (name = checkType(name, TypeCharArray, NIL)) )
2666     answer(name);
2667   else
2668     answer((CharArray) CtoString(pp(obj)));
2669 }
2670 
2671 		 /*******************************
2672 		 *	 CLASS DECLARATION	*
2673 		 *******************************/
2674 
2675 /* Public Type declaractions */
2676 
2677 char *T_report[] =
2678         { "kind={status,inform,progress,done,warning,error,fatal}",
2679 	  "format=[char_array]",
2680 	  "argument=any ..."
2681 	};
2682 
2683 /* Type declaractions */
2684 
2685 static char *T_forSlotReference[] =
2686         { "action=code", "recursive=[bool]" };
2687 static char *T_attribute[] =
2688         { "attribute|name", "value=[any]" };
2689 static char *T_error[] =
2690         { "error=error", "context=unchecked ..." };
2691 static char *T_hyper_nameADnameD_selectorAname_argumentAunchecked_XXX[] =
2692         { "hyper_name=[name]", "selector=name", "argument=unchecked ..." };
2693 static char *T_hyper_nameADnameD_testADcodeD[] =
2694         { "hyper_name=[name]", "test=[code]" };
2695 static char *T_attachHyper[] =
2696         { "hyper", "object" };
2697 static char *T_deleteHypers[] =
2698         { "name=[name]", "condition=[code]" };
2699 static char *T_slot[] =
2700         { "name|int", "unchecked" };
2701 static char *T_name_any[] =
2702         { "name", "any" };
2703 static char *T_convertLoadedObject[] =
2704         { "old_version=int", "current_version=int" };
2705 static char *T_relayed_invocation[] =
2706         { "selector=name", "argument=unchecked ..." };
2707 
2708 /* Instance Variables */
2709 
2710 #define var_object NULL
2711 /*
2712 vardecl var_object[] =
2713 {
2714 };
2715 */
2716 
2717 /* Send Methods */
2718 
2719 static senddecl send_object[] =
2720 { SM(NAME_equal, 1, "to=any", equalObject,
2721      NAME_compare, "Test if i'm equal to the argument"),
2722   SM(NAME_sameReference, 1, "to=any", sameReferenceObject,
2723      NAME_compare, "Test if i'm the same object as the argument"),
2724   SM(NAME_forSlotReference, 2, T_forSlotReference, forSlotReferenceObject,
2725      NAME_debugging, "Run code on object-slot-value references"),
2726   SM(NAME_convertLoadedObject, 2, T_convertLoadedObject, convertLoadedObjectObject,
2727      NAME_file, "Called by File <-object if conversion might be required"),
2728   SM(NAME_initialiseNewSlot, 1, "new=variable", initialiseNewSlotObject,
2729      NAME_file, "Called by File <-object if a new slot is found"),
2730   SM(NAME_saveInFile, 1, "file", saveInFileObject,
2731      NAME_file, "Save object and it's context in a file"),
2732   SM(NAME_Free, 0, NULL, freeObject,
2733      NAME_function, "Equivalent to ->free"),
2734 #ifndef O_RUNTIME
2735   SM(NAME_Inspect, 1, "bool", inspectObject,
2736      NAME_function, "Equivalent to ->inspect"),
2737 #endif
2738   SM(NAME_InstanceOf, 1, "class", instanceOfObject,
2739      NAME_function, "Equivalent to ->instance_of"),
2740   SM(NAME_SameReference, 1, "to=unchecked", sameReferenceObject,
2741      NAME_function, "Equivalent to ->same_reference"),
2742   SM(NAME_hasGetMethod, 1, "selector=name", hasGetMethodObject,
2743      NAME_meta, "Test if object defines get_method"),
2744   SM(NAME_hasSendMethod, 1, "selector=name", hasSendMethodObject,
2745      NAME_meta, "Test if object defines send_method"),
2746   SM(NAME_done, 0, NULL, doneObject,
2747      NAME_oms, "Indicate I'm done with some answer"),
2748   SM(NAME_free, 0, NULL, freeObject,
2749      NAME_oms, "Delete object from the object-base"),
2750   SM(NAME_initialise, 0, NULL, succeedObject,
2751      NAME_oms, "Initialise a new instance"),
2752   SM(NAME_lockObject, 1, "bool", lockObject,
2753      NAME_oms, "Lock object for incremental garbage collection"),
2754   SM(NAME_protect, 0, NULL, protectObject,
2755      NAME_oms, "Lock object for destruction with ->free"),
2756   SM(NAME_unlink, 0, NULL, succeedObject,
2757      NAME_oms, "Unlink from environment"),
2758   SM(NAME_unlinking, 0, NULL, unlinkingObject,
2759      NAME_oms, "Try if ->unlink is in progress"),
2760   SM(NAME_getMethod, 1, "get_method|chain", getMethodObject,
2761      NAME_programming, "Add an object-level get_method"),
2762   SM(NAME_sendClass, 2, T_relayed_invocation, sendClassObject,
2763      NAME_programming, "Send using method of class of object"),
2764   SM(NAME_sendMethod, 1, "send_method|chain", sendMethodObject,
2765      NAME_programming, "Add an object-level send_method"),
2766   SM(NAME_sendSub, 2, T_relayed_invocation, sendSubObject,
2767      NAME_programming, "Send using method of subclass"),
2768   SM(NAME_sendSuper, 2, T_relayed_invocation, sendSuperObject,
2769      NAME_programming, "Send using method of super-class"),
2770   SM(NAME_sendSuperVector, 1, "unchecked ...", sendSuperVectorObject,
2771      NAME_programming, "Varargs: any ..., vector, [int]"),
2772   SM(NAME_sendVector, 1, "unchecked ...", sendVectorObject,
2773      NAME_programming, "Varargs: any ..., vector, [int]"),
2774   SM(NAME_slot, 2, T_slot, slotObject,
2775      NAME_programming, "Set value of an instance variable"),
2776   SM(NAME_nameReference, 1, "name*", nameReferenceObject,
2777      NAME_reference, "Change named (atomic) reference"),
2778   SM(NAME_attachHyper, 2, T_attachHyper, attachHyperObject,
2779      NAME_relation, "Attach a hyper to an object"),
2780   SM(NAME_deleteHyper, 1, "hyper", deleteHyperObject,
2781      NAME_relation, "Detach a hyper from an object"),
2782   SM(NAME_deleteHypers, 2, T_deleteHypers, freeHypersObject,
2783      NAME_relation, "Delete all matching hypers"),
2784   SM(NAME_sendHyper, 3, T_hyper_nameADnameD_selectorAname_argumentAunchecked_XXX, sendHyperObject,
2785      NAME_relation, "Send message using named hypers"),
2786   SM(NAME_error, 2, T_error, errorObjectv,
2787      NAME_report, "Initiate an error: id, context ..."),
2788   SM(NAME_report, 3, T_report, reportObject,
2789      NAME_report, "Report message (send to @event <-receiver)"),
2790   SM(NAME_obtainClassVariables, 0, NULL, obtainClassVariablesObject,
2791      NAME_resource, "Obtain class-variable values for @default-valued slots"),
2792   SM(NAME_attribute, 2, T_attribute, attributeObject,
2793      NAME_storage, "Append/change object-level attribute"),
2794   SM(NAME_deleteAttribute, 1, "name|attribute", deleteAttributeObject,
2795      NAME_storage, "Delete object-level attribute"),
2796   SM(NAME_hasValue, 2, T_name_any, hasValueObject,
2797      NAME_test, "Test if Obj <-name equals 2nd argument"),
2798   SM(NAME_isOff, 1, "name", isOffObject,
2799      NAME_test, "Test if Obj <-name returns @off"),
2800   SM(NAME_isOn, 1, "name", isOnObject,
2801      NAME_test, "Test if Obj <-name returns @on"),
2802   SM(NAME_notHasValue, 2, T_name_any, notHasValueObject,
2803      NAME_test, "Test if Obj <-name not-equal 2nd argument"),
2804   SM(NAME_instanceOf, 1, "class", instanceOfObject,
2805      NAME_type, "Test of object is an instance of class"),
2806   SM(NAME_sameClass, 1, "object", sameClassObject,
2807      NAME_type, "Is object of the same class as argument"),
2808   SM(NAME_updateConstraints, 0, NULL, updateConstraintsObject,
2809      NAME_constraint, "Execute all constraints")
2810 #ifndef O_RUNTIME
2811   ,
2812   SM(NAME_inspect, 1, "bool", inspectObject,
2813      NAME_debugging, "Forward changes via classes' changed_messages"),
2814   SM(NAME_Check, 1, "recursive=[bool]", CheckObject,
2815      NAME_debugging, "Check types for all instance-variables of object")
2816 #endif /*O_RUNTIME*/
2817 };
2818 
2819 /* Get Methods */
2820 
2821 static getdecl get_object[] =
2822 { GM(NAME_clone, 0, "object", NULL, getCloneObject,
2823      NAME_copy, "New object that is a (recursive) copy)"),
2824   GM(NAME_Flags, 0, "name", NULL, getFlagsObject,
2825      NAME_debugging, "Name width {P, L and A} flags"),
2826   GM(NAME_codeReferences, 0, "int", NULL, getCodeReferencesObject,
2827      NAME_debugging, "Number of code-references to this object"),
2828   GM(NAME_references, 0, "int", NULL, getReferencesObject,
2829      NAME_debugging, "Number of references to this object"),
2830   GM(NAME_storageReference, 0, "any", NULL, getFailObject,
2831      NAME_file, "Description name for ->save_in_file"),
2832   GM(NAME_Class, 0, "class", NULL, getClassObject,
2833      NAME_function, "Equivalent to <-class"),
2834   GM(NAME_ClassName, 0, "name", NULL, getClassNameObject,
2835      NAME_function, "Equivalent to <-class_name"),
2836   GM(NAME_References, 0, "int", NULL, getReferencesObject,
2837      NAME_function, "Equivalent to <-references"),
2838   GM(NAME_Slot, 1, "unchecked", "name|int", getSlotObject,
2839      NAME_function, "Equivalent to <-slot"),
2840   GM(NAME_allAttributes, 1, "chain", "create=[bool]", getAllAttributesObject,
2841      NAME_meta, "Chain with object-level attributes"),
2842   GM(NAME_allConstraints, 1, "chain", "create=[bool]", getAllConstraintsObject,
2843      NAME_meta, "Chain with all constraints"),
2844   GM(NAME_allGetMethods, 1, "chain", "create=[bool]", getAllGetMethodsObject,
2845      NAME_meta, "Chain with all get methods"),
2846   GM(NAME_allHypers, 1, "chain", "create=[bool]", getAllHypersObject,
2847      NAME_meta, "Chain with all hypers"),
2848   GM(NAME_allSendMethods, 1, "chain", "create=[bool]", getAllSendMethodsObject,
2849      NAME_meta, "Chain with all send methods"),
2850   GM(NAME_findAllSendMethods, 1, "chain", "condition=[code]", getFindAllSendMethodsObject,
2851      NAME_meta, "New chain with all send-methods satisfying code"),
2852   GM(NAME_getMethod, 1, "tuple", "name", getGetMethodObject,
2853      NAME_meta, "Tuple containing receiver and implementing object"),
2854   GM(NAME_sendMethod, 1, "tuple", "name", getSendMethodObject,
2855      NAME_meta, "Tuple containing receiver and implementing object"),
2856   GM(NAME_createContext, 1, "object", "condition=[code]",
2857      getCreateContextObject,
2858      NAME_meta, "Find object creating me"),
2859   GM(NAME_convert, 1, "object", "int|char_array", getConvertObject,
2860      NAME_oms, "Convert '@reference' into object"),
2861   GM(NAME_unlock, 0, "unchecked", NULL, getUnlockObject,
2862      NAME_oms, "Unlock object and return <-self"),
2863   GM(NAME_lockObject, 0, "bool", NULL, getLockObject,
2864      NAME_oms, "Boolean to indicate locked for GC"),
2865   GM(NAME_protect, 0, "bool", NULL, getProtectObject,
2866      NAME_oms, "Boolean to indicate locked for ->free"),
2867   GM(NAME_self, 0, "object", NULL, getSelfObject,
2868      NAME_oms, "Returns itself"),
2869   GM(NAME_getClass, 2, "unchecked", T_relayed_invocation, getGetClassObject,
2870      NAME_programming, "Get, using method of class of object"),
2871   GM(NAME_getSub, 2, "unchecked", T_relayed_invocation, getGetSubObject,
2872      NAME_programming, "Get, using method of sub-class"),
2873   GM(NAME_getSuper, 2, "unchecked", T_relayed_invocation, getGetSuperObject,
2874      NAME_programming, "Get, using method of super-class"),
2875   GM(NAME_getVector, 1, "unchecked", "unchecked ...", getVectorObject,
2876      NAME_programming, "Varargs: any ..., vector, [int]"),
2877   GM(NAME_slot, 1, "unchecked", "name|int", getSlotObject,
2878      NAME_programming, "Get value of a slot"),
2879   GM(NAME_objectReference, 0, "name|int", NULL, getObjectReferenceObject,
2880      NAME_reference, "Name of the object (e.g. @pce)"),
2881   GM(NAME_findHyper, 2, "hyper", T_hyper_nameADnameD_testADcodeD, getFindHyperObject,
2882      NAME_relation, "Find hyper-relation object"),
2883   GM(NAME_getHyper, 3, "unchecked", T_hyper_nameADnameD_selectorAname_argumentAunchecked_XXX, getHyperObject,
2884      NAME_relation, "Get-operation using named hypers"),
2885   GM(NAME_hypered, 2, "object", T_hyper_nameADnameD_testADcodeD, getHyperedObject,
2886      NAME_relation, "Find hyper-related object"),
2887   GM(NAME_reportTo, 0, "object", NULL, getReportToObject,
2888      NAME_report, "Object for ->report (@event <-receiver)"),
2889   GM(NAME_classVariableValue, 1, "any", "name", getClassVariableValueObject,
2890      NAME_default, "Get value of associated Default"),
2891   GM(NAME_attribute, 1, "unchecked", "name", getAttributeObject,
2892      NAME_storage, "Get value of a object-level attribute"),
2893   GM(NAME_Arg, 1, "unchecked", "int", getArgObject,
2894      NAME_term, "Nth-1 argument of term description"),
2895   GM(NAME_Arity, 0, "int", NULL, getArityObject,
2896      NAME_term, "Number of arguments of term description"),
2897   GM(NAME_functor, 0, "name", NULL, getFunctorObject,
2898      NAME_term, "Functor (name) of term description"),
2899   GM(NAME_printName, 0, "text=char_array", NULL, getPrintNameObject,
2900      NAME_textual, "Calls <-name"),
2901   GM(NAME_class, 0, "class", NULL, getClassObject,
2902      NAME_type, "Class the object belongs to"),
2903   GM(NAME_className, 0, "name", NULL, getClassNameObject,
2904      NAME_type, "Name of the class the object belongs to")
2905 #ifndef O_RUNTIME
2906   ,
2907   GM(NAME_inspect, 0, "bool", NULL, getInspectObject,
2908      NAME_debugging, "Boolean to indicate changes forwarding"),
2909   GM(NAME_Inspect, 0, "bool", NULL, getInspectObject,
2910      NAME_function, "Equivalent to <-inspect"),
2911   GM(NAME_ManId, 0, "name", NULL, getManIdObject,
2912      NAME_function, "Equivalent to <-man_id"),
2913   GM(NAME_manId, 0, "name", NULL, getManIdObject,
2914      NAME_manual, "Card Id for global object"),
2915   GM(NAME_manIndicator, 0, "name", NULL, getManIndicatorObject,
2916      NAME_manual, "Manual type indicator (`O')")
2917 #endif /*O_RUNTIME*/
2918 };
2919 
2920 /* Resources */
2921 
2922 #define rc_object NULL
2923 /*
2924 static classvardecl rc_object[] =
2925 {
2926 };
2927 */
2928 
2929 /* Class Declaration */
2930 
2931 ClassDecl(object_decls,
2932           var_object, send_object, get_object, rc_object,
2933           0, NULL,
2934           "$Rev$");
2935 
2936 
2937 status
makeClassObject(Class class)2938 makeClassObject(Class class)
2939 { declareClass(class, &object_decls);
2940   setChangedFunctionClass(class, changedFieldObject);
2941 
2942 
2943   succeed;
2944 }
2945 
2946 
2947