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