ClassClass.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel */
40 /* */
41 /* Primitive Class Class */
42 /* */
43 /******************************************************************************/
44 
45 #include <stdarg.h>
46 #include <string.h>
47 #include "RexxCore.h"
48 #include "StringClass.hpp"
49 #include "ListClass.hpp"
50 #include "TableClass.hpp"
51 #include "DirectoryClass.hpp"
52 #include "ArrayClass.hpp"
53 #include "SupplierClass.hpp"
54 #include "ClassClass.hpp"
55 #include "MethodClass.hpp"
56 #include "RexxActivity.hpp"
57 #include "ActivityManager.hpp"
58 #include "ProtectedObject.hpp"
59 #include "WeakReferenceClass.hpp"
60 
61 
62 // singleton class instance
64 
65 
66 void RexxClass::live(size_t liveMark)
67 /******************************************************************************/
68 /* Function: Normal garbage collection live marking */
69 /******************************************************************************/
70 {
71  memory_mark(this->objectVariables);
72  memory_mark(this->id);
76  memory_mark(this->baseClass);
77  memory_mark(this->metaClass);
82  memory_mark(this->subClasses);
83 }
84 
85 void RexxClass::liveGeneral(int reason)
86 /******************************************************************************/
87 /* Function: Generalized object marking */
88 /******************************************************************************/
89 {
90  memory_mark_general(this->objectVariables);
91  memory_mark_general(this->id);
102 }
103 
105 /******************************************************************************/
106 /* Function: Flatten an object */
107 /******************************************************************************/
108 {
109  ;
110 }
111 
113 /******************************************************************************/
114 /* Function: unflaatten an object */
115 /******************************************************************************/
116 {
117  return this;
118 }
119 
121 /******************************************************************************/
122 /* Function: Make a proxy object */
123 /******************************************************************************/
124 {
125 
126  /* Following code is pulled from */
127  /* object_primitive, to get class id*/
128  /* as a string object. */
129  /* get the class id */
130  return new_proxy(this->id->getStringData());
131 }
132 
133 
134 /**
135  * Hash a class object. Because behaviors don't always get set
136  * up properly with this, we'll always use the primitive one for
137  * class objects.
138  *
139  * @return A "hashed hash" that can be used by the map collections.
140  */
142 {
143  // always, always, always return the hash value, which will be the
144  // hash value of our id string. This is important, since we need to
145  // have a hash value that will be the same before and after the image save
146  return getHashValue();
147 }
148 
149 
150 /**
151  * Get the primitive hash value of this String object.
152  *
153  * @return The calculated string hash for the string.
154  */
156 {
157  // always, always, always return the hash value, which will be the
158  // hash value of our id string. This is important, since we need to
159  // have a hash value that will be the same before and after the image save
160  return id->getHashValue();
161 }
162 
163 
165  RexxObject *other) /* other comparison object */
166 /******************************************************************************/
167 /* Function: Compare two classes */
168 /******************************************************************************/
169 {
170  return this->equal(other); /* this is direct object equality */
171 }
172 
174  RexxObject *other) /* other comparison object */
175 /******************************************************************************/
176 /* Function: Compare two class objects as a strict compare (==) */
177 /******************************************************************************/
178 {
179  /* If a non-copied (Primitive) */
180  /*behaviour Then we can directly */
181  /*call primitive method */
182  if (this->behaviour->isPrimitive())
183  {
184  /* can compare at primitive level */
185  return this->equal(other) == TheTrueObject;
186  }
187  else
188  {
189  ProtectedObject r;
190  /* other wise giveuser version a */
191  /*chance */
192  this->sendMessage(OREF_STRICT_EQUAL, other, r);
193  if ((RexxObject *)r == OREF_NULL)
194  {
196  }
197  return((RexxObject *)r)->truthValue(Error_Logical_value_method);
198  }
199 }
200 
202  RexxObject *other) /* other comparison object */
203 /******************************************************************************/
204 /* Function: Compare two classes */
205 /******************************************************************************/
206 {
207  requiredArgument(other, OREF_positional, ARG_ONE); /* must have the other argument */
208  /* this is direct object equality */
209 
210  /* comparing string/int/numstr to */
211  /* string/int/numstr? */
212  if ((this == TheStringClass || this == TheIntegerClass || this == TheNumberStringClass) &&
213  (other == (RexxObject *)TheStringClass || other == (RexxObject *)TheIntegerClass || other == (RexxObject *)TheNumberStringClass))
214  {
215  return TheTrueObject; /* YES, then equal.... */
216  }
217  else /* other wise, do a direct compare */
218  {
219  return((this == other) ? TheTrueObject: TheFalseObject);
220  }
221 }
222 
224  RexxObject *other) /* other comparison object */
225 /******************************************************************************/
226 /* Function: Compare two classes */
227 /******************************************************************************/
228 {
229  requiredArgument(other, OREF_positional, ARG_ONE); /* must have the other argument */
230  /* this is direct object equality */
231 
232  /* comparing string/int/numstr to */
233  /* string/int/numstr? */
234  if ((this == TheStringClass || this == TheIntegerClass || this == TheNumberStringClass) &&
235  (other == (RexxObject *)TheStringClass || other == (RexxObject *)TheIntegerClass || other == (RexxObject *)TheNumberStringClass))
236  {
237  return TheFalseObject; /* YES, then equal.... */
238  }
239  else /* other wise, do a direct compare */
240  {
241  return((this != other) ? TheTrueObject: TheFalseObject);
242  }
243 }
244 
246 /*****************************************************************************/
247 /* Function: To check if class_info MIXIN has been set */
248 /*****************************************************************************/
249 {
250  /* return true/false indicator */
251  return this->isMixinClass() ? TheTrueObject : TheFalseObject;
252 }
253 
255 /*****************************************************************************/
256 /* Function: Return the ID for the class */
257 /*****************************************************************************/
258 {
259  return this->id;
260 }
261 
263 /*****************************************************************************/
264 /* Function: Set a class as a Rexx defined class */
265 /*****************************************************************************/
266 {
267  this->classFlags |= REXX_DEFINED; /* flag the class */
268  return OREF_NULL;
269 }
270 
272 /*****************************************************************************/
273 /* Function: Return the classes base class */
274 /*****************************************************************************/
275 {
276  return this->baseClass; /* return the base class for this */
277 }
278 
280 /*****************************************************************************/
281 /* Function: return the classes metaclass */
282 /*****************************************************************************/
283 {
284  if (this->isPrimitiveClass()) /* primitive class? */
285  {
286  return TheClassClass; /* this is always .class */
287  }
288  else /* return first member of the list */
289  {
290  return(RexxClass *)this->metaClass->get(1);
291  }
292 }
293 
295  RexxBehaviour *b) /* new instance behaviour */
296 /*****************************************************************************/
297 /* Function: Give a class a new instance behaviour */
298 /*****************************************************************************/
299 {
300  OrefSet(this, this->instanceBehaviour, b);
301 }
302 
304 /*****************************************************************************/
305 /* Function: Return the first superclass in the superclass list */
306 /*****************************************************************************/
307 {
308  // object has no superclasses
309  if (this == TheObjectClass)
310  {
311  return (RexxClass *)TheNilObject;
312  }
313  // get the first item from the immediate list.
314  return (RexxClass *)this->instanceSuperClasses->get(1);
315 }
316 
317 
319 /*****************************************************************************/
320 /* Function: Return an array of the superclasses */
321 /*****************************************************************************/
322 {
323  /* return a copy of the list */
324  return (RexxArray *)this->instanceSuperClasses->copy();
325 }
326 
327 
329 /*****************************************************************************/
330 /* Function: Return an array of the subclasses */
331 /*****************************************************************************/
332 {
333  // remove any gc classes from the list now, and return the array
334  return subClasses->weakReferenceArray();
335 }
336 
338 /*****************************************************************************/
339 /* Function: Add a subclass to a class */
340 /*****************************************************************************/
341 {
342  // wrap a weak reference around the subclass
343  WeakReference *ref = new WeakReference(subClass);
344  // add this to the front of the subclass list
345  subClasses->addFirst((RexxObject *)ref);
346 }
347 
349  RexxTable *newMethods) /* methods to add */
350 /*****************************************************************************/
351 /* Function: Add a table of methods to a primitive class behaviour */
352 /*****************************************************************************/
353 {
354  /* loop through the list of methods */
355  for (HashLink i = newMethods->first(); newMethods->available(i); i = newMethods->next(i))
356  {
357  /* get the method name */
358  RexxString *method_name = (RexxString *)newMethods->index(i);
359  /* add this method to the classes */
360  /* class behaviour */
361 
362  // if this is the Nil object, that's an override. Make it OREF_NULL.
363  RexxObject *_method = (RexxMethod *)newMethods->value(i);
364  if (_method == TheNilObject)
365  {
366  _method = OREF_NULL;
367  }
368 
369  this->behaviour->define(method_name, OREF_NULL);
370  }
371 }
372 
374 /******************************************************************************/
375 /* Function: retrieve a classes default name value */
376 /******************************************************************************/
377 {
378  RexxString *defaultname = this->id; /* use the id directly */
379  /* prefix with "The" */
380  defaultname = defaultname->concatToCstring("The ");
381  ProtectedObject p(defaultname);
382  /* add on "class" */
383  defaultname = defaultname->concatWithCstring(" class");
384  return defaultname; /* return that value */
385 }
386 
388 /*****************************************************************************/
389 /* Function: Return the instance behaviour's method dictionary */
390 /*****************************************************************************/
391 {
392  /* get the method dictionary */
393  RexxTable *methodTable = this->instanceBehaviour->getMethodDictionary();
394  if (methodTable == OREF_NULL) /* no methods defined yet? */
395  {
396  return new_table(); /* create a new method table */
397  }
398  else
399  {
400  /* just copy the method dictionary */
401  return(RexxTable *)methodTable->copy();
402  }
403 }
404 
406 /*****************************************************************************/
407 /* Function: Return the class behaviour's method dictionary */
408 /*****************************************************************************/
409 {
410  /* get the method dictionary */
411  RexxTable *methodTable = this->behaviour->getMethodDictionary();
412  if (methodTable == OREF_NULL) /* no methods defined yet? */
413  {
414  return new_table(); /* create a new method table */
415  }
416  else
417  {
418  /* just copy the method dictionary */
419  return(RexxTable *)methodTable->copy();
420  }
421 }
422 
423 
424 /**
425  * Initialize a base Rexx class.
426  *
427  * @param restricted Whether we should turn the RexxRestricted flag on at this time.
428  * Some classes get additional customization after initial
429  * creation, so we delay setting this attribute until the
430  * class is fully constructed.
431  */
432 void RexxClass::subClassable(bool restricted)
433 {
434  /* get a copy of the class instance */
435  /* behaviour mdict before the merge */
436  /* with OBJECT. This unmerged mdict */
437  /* is kept in this class's */
438  /* class_instance_mdict field. */
440  /* Add OBJECT to the behaviour scope */
441  /* table */
443  if (this != TheObjectClass) /* if this isn't the OBJECT class */
444  {
445  /* Add OBJECT to the behaviour scope */
446  /* table */
448  /* and merge this class's instance */
449  /* behaviour with that of OBJECT's */
451  }
452  /* add self to the scope table */
453  this->instanceBehaviour->addScope(this);
454  /* get a copy of the class behaviour */
455  /* mdict before the merge with the */
456  /* CLASS instance behaviour. This */
457  /* unmerged mdict is kept in the */
458  /* class_mdict field */
460  /* The merge of the mdict's is order */
461  /* specific. By processing OBJECT */
462  /* first then CLASS and then the */
463  /* rest of the subclassable classes */
464  /* the mdict's will be set up */
465  /* correctly. */
466  /* In this way merging the CLASS */
467  /* behaviour will only be the CLASS */
468  /* instance methods when OBJECT is */
469  /* processed, but will be CLASS's */
470  /* and OBJECT's after CLASS is */
471  /* processed */
473  /* now add the scope levels to this */
474  /* class behaviour */
475  /* If this isn't OBJECT put OBJECT */
476  /* in first */
477  if (this != TheObjectClass)
478  {
480  }
481  /* if this is OBJECT - merge the */
482  /* object instance methods with the */
483  /* object class methods */
484  else
485  {
487  /* and put them into the class mdict */
488  /* so all the classes will inherit */
490  }
491  /* if this isn't CLASS put CLASS in */
492  /* next */
493  if (this != TheClassClass)
494  {
496  }
497  this->behaviour->addScope(this); /* put self into the scope table */
498  /* That finishes the class behaviour */
499  /* initialization. */
500  /* Now fill in the state data */
501 
502  if (TheObjectClass != this )
503  {
504  /* set up the new metaclass list */
505  OrefSet(this, this->metaClass, new_array(TheClassClass));
506  /* the metaclass mdict list */
507  OrefSet(this, this->metaClassMethodDictionary, new_array(TheClassClass->instanceMethodDictionary->copy()));
508  /* and the metaclass scopes list */
509  OrefSet(this, this->metaClassScopes, (RexxIdentityTable *)TheClassClass->behaviour->getScopes()->copy());
510  }
511 
512  /* The Baseclass for non-mixin classes*/
513  /* is self */
514  OrefSet(this, this->baseClass, this);
515  /* The class superclasses list for */
516  /* OBJECT is an empty list. */
517  OrefSet(this, this->classSuperClasses, new_array((size_t)0));
518  /* as is the instance superclasses */
519  /* list. */
520  OrefSet(this, this->instanceSuperClasses, new_array((size_t)0));
521  // create the subclasses list
522  OrefSet(this, this->subClasses, new_list());
523  if (this != TheObjectClass) /* not .object? */
524  {
525  /* add object to the list */
527  /* The instance superclasses for all */
528  /* except OBJECT is OBJECT */
530  /* and for OBJECT we need to add all */
531  /* the other classes */
532  /* except integer and numberstring */
533  if (this != TheIntegerClass && this != TheNumberStringClass)
534  {
535  TheObjectClass->addSubClass(this);
536  }
537  }
538  /* and point the instance behaviour */
539  /* back to this class */
540  this->instanceBehaviour->setOwningClass(this);
541  /* and the class behaviour to CLASS */
543  /* these are primitive classes */
544  this->classFlags |= PRIMITIVE_CLASS;
545 
546  if (this == TheClassClass) /* mark CLASS as a meta class */
547  {
548  this->setMetaClass();
549  }
550 }
551 
552 
553 /**
554  * Initialize a base Rexx class that inherits from a primitive
555  * class other than Object.
556  *
557  * @param superClass The immediate superclass of the created
558  * class.
559  * @param restricted Whether we should turn the RexxRestricted flag on at this time.
560  * Some classes get additional customization after initial
561  * creation, so we delay setting this attribute until the
562  * class is fully constructed.
563  */
564 void RexxClass::subClassable(RexxClass *superClass, bool restricted)
565 {
566  // get a copy of the class instance behaviour mdict before the merge
567  // with OBJECT. This unmerged mdict is kept in this class's
568  // class_instance_mdict field.
570 
571  // set up the superclass/subclass relationships
572  OrefSet(this, this->classSuperClasses, new_array(superClass));
573  OrefSet(this, this->instanceSuperClasses, new_array(superClass));
574  // create the subclasses list
575  OrefSet(this, this->subClasses, new_list());
576  // and add this as a subclass to our superclass
577  superClass->addSubClass(this);
578 
579  // create the merged method dictionary for the instancebehavior
580  // and update all of the scopes.
582 
583  /* add self to the scope table */
584  this->instanceBehaviour->addScope(this);
585 
586  // get a copy of the class behaviour mdict before the merge with the
587  // CLASS instance behaviour. This unmerged mdict is kept in the
588  // class_mdict field
590  // The merge of the mdict's is order specific. By processing OBJECT
591  // first then CLASS and then the rest of the subclassable classes
592  // the mdict's will be set up correctly.In this way merging the CLASS
593  // behaviour will only be the CLASS instance methods when OBJECT is
594  // processed, but will be CLASS's and OBJECT's after CLASS is
595  // processed */
597  // now add the scope levels to this class behaviour
599  // add the class scope levels
601  // and finally the new class.
602  this->behaviour->addScope(this);
603 
604  // now fill in some state data for the class object.
605  // set up the new metaclass list
606  OrefSet(this, this->metaClass, new_array(TheClassClass));
607  // the metaclass mdict list
608  OrefSet(this, this->metaClassMethodDictionary, new_array(TheClassClass->instanceMethodDictionary->copy()));
609  // and the metaclass scopes list
610  OrefSet(this, this->metaClassScopes, (RexxIdentityTable *)TheClassClass->behaviour->getScopes()->copy());
611 
612  // The Baseclass for non-mixin classes is self
613  OrefSet(this, this->baseClass, this);
614  // and point the instance behaviour back to this class
615  this->instanceBehaviour->setOwningClass(this);
616  // and the class behaviour to CLASS
618  // these are primitive classes
619  this->classFlags |= PRIMITIVE_CLASS;
620 }
621 
622 
624  RexxString * method_name, /*define method name */
625  RexxMethod *method_object) /* returned method object */
626 /*****************************************************************************/
627 /* Function: Define an instance method on this class object */
628 /*****************************************************************************/
629 {
630 #if 0
631  /* check if this is a rexx class */
632  if ( this->isRexxDefined())
633  {
634  /* report as a nomethod condition */
636  }
637 #endif
638  /* make sure there is at least one */
639  /* parameter */
640  method_name = stringArgument(method_name, OREF_positional, ARG_ONE)->upper();
641  ProtectedObject p_method_name(method_name);
642  ProtectedObject p_method_object(method_object);
643  if ( OREF_NULL == method_object) /* 2nd arg omitted? */
644  {
645  /* Yes, remove all message with this */
646  /* name from our instanceMdict */
647  /* (method lookup) */
648  /* done by defining the method */
649  /* to be .nil at this class level, so*/
650  /* when message lookup is attempted */
651  /* we get .nil, telling us not found */
652  method_object = (RexxMethod *)TheNilObject;
653  }
654  /* not a method type already? */
655  /* and not TheNilObject */
656  else if (TheNilObject != method_object && !isOfClass(Method, method_object))
657  {
658  /* make one from a string */
659  method_object = RexxMethod::newMethodObject(method_name, method_object, IntegerTwo, OREF_NULL);
660  }
661  if (TheNilObject != method_object) /* if the method is not TheNilObject */
662  {
663  /* set the scope of the method to self*/
664  method_object = method_object->newScope(this);
665  /* Installing UNINIT? */
666  if (method_name->strCompare(CHAR_UNINIT))
667  {
668  this->setHasUninitDefined(); /* and turn on uninit if so */
669  }
670  }
671  p_method_object = method_object;
672 
673  /* make a copy of the instance */
674  /* behaviour so any previous objects */
675  /* aren't enhanced */
676  //JLF OrefSet(this, this->instanceBehaviour, (RexxBehaviour *)this->instanceBehaviour->copy());
677  /* add method to the instance mdict */
678  this->instanceMethodDictionary->stringPut((RexxObject *)method_object, method_name);
679  /* any subclasses that we have need */
680  /* to redo their instance behaviour */
681  /* this also updates our own */
682  this->updateInstanceSubClasses(); /* behaviour table */
683 
684  // .nil not updated when defining a method on the class Object.
685  // probably because the class of .nil is the special class RexxNilObject...
686  // Use the same technique than in setup.cpp: call defMethod
687  if (this == TheObjectClass)
688  {
689  TheNilObject->defMethod(method_name, method_object);
690  }
691 
692  return OREF_NULL; /* returns nothing */
693 }
694 
696  RexxTable * newMethods) /* new table of methods to define */
697 /*****************************************************************************/
698 /* Function: Define instance methods on this class object */
699 /*****************************************************************************/
700 {
701  RexxString * index; /* method name */
702  /* loop thru the methods setting the */
703  /* method scopes to SELF and then */
704  /* adding them to SELF's instance */
705  /* mdict */
706  for (HashLink i = newMethods->first(); (index = (RexxString *)newMethods->index(i)) != OREF_NULL; i = newMethods->next(i))
707  {
708  /* get the method */
709  RexxMethod *newMethod = (RexxMethod *)newMethods->value(i);
710  if (isOfClass(Method, newMethod)) /* if this is a method object */
711  {
712  newMethod->setScope(this); /* change the scope */
713  }
714  /* add method to the instance mdict */
715  this->instanceMethodDictionary->stringPut(newMethod, index);
716  /* Installing UNINIT? */
717  if (index->strCompare(CHAR_UNINIT))
718  {
719  this->setHasUninitDefined(); /* and turn on uninit if so */
720  }
721  }
722  /* create the instance behaviour from */
723  /* the instance superclass list */
727 
728  return OREF_NULL; /* returns nothing */
729 }
730 
731 /**
732  * special method to allow a class method to be added
733  * to a primitive class during image build.
734  * New JLF : also used for ::EXTENSION
735  *
736  * @param method_name
737  * The name of the new method.
738  * @param newMethod The method object to add
739  *
740  * @return always returns OREF_NULL
741  */
743 {
744  // validate the arguments
745  method_name = stringArgument(method_name, OREF_positional, ARG_ONE)->upper();
746  ProtectedObject p(method_name);
747  requiredArgument(newMethod, OREF_positional, ARG_TWO);
748  newMethod->newScope(this); // change the scope to the class // JLF newScope instead of setScope
749  /* now add this to the behaviour */
750  this->behaviour->getMethodDictionary()->stringPut(newMethod, method_name);
751  this->classMethodDictionary->stringAdd(newMethod, method_name);
752 
753  // propagate to all subclasses (JLF : don't know why it was not done, maybe not needed during image build ?)
754  RexxArray *subclass_list = this->getSubClasses();
755  for (size_t i = 1; i < subclass_list->size(); i++)
756  {
757  ((RexxClass *)subclass_list->get(i))->defineClassMethod(method_name, newMethod);
758  }
759 
760  return OREF_NULL; /* returns nothing */
761 }
762 
763 /**
764  * Remove a class method from a class and all of its class methods.
765  *
766  * @param method_name
767  * The target method name.
768  */
770 {
771  // remove from our behaviour
772  this->behaviour->deleteMethod(method_name);
773 
774  // propagate to all subclasses
775  RexxArray *subclass_list = getSubClasses();
776  for (size_t i = 1; i < subclass_list->size(); i++)
777  {
778  ((RexxClass *)subclass_list->get(i))->removeClassMethod(method_name);
779  }
780 }
781 
782 
784  RexxString *method_name) /* deleted method name */
785 /*****************************************************************************/
786 /* Function: Delete an instance method on this class object */
787 /*****************************************************************************/
788 {
789  if (this->isRexxDefined()) /* check if this is a rexx class */
790  {
791  /* report as a nomethod condition */
793  }
794  /* and that it can be a string */
795  method_name = stringArgument(method_name, OREF_positional, ARG_ONE)->upper();
796  ProtectedObject p(method_name);
797  /* make a copy of the instance */
798  /* behaviour so any previous objects */
799  /* aren't enhanced */
800  //JLF OrefSet(this, this->instanceBehaviour, (RexxBehaviour *)this->instanceBehaviour->copy());
801  /* if there is a method to remove */
802  /* from the instance mdict */
803  /* remove it */
804  if (OREF_NULL != this->instanceMethodDictionary->remove(method_name))
805  {
806  /* and update our instance behaviour */
807  this->updateInstanceSubClasses(); /* along with our subclasses */
808  }
809  return OREF_NULL; /* returns nothing */
810 }
811 
813  RexxString *method_name)
814 /*****************************************************************************/
815 /* Function: Return the method object for the method name */
816 /*****************************************************************************/
817 {
818  /* make sure we have a proper name */
819  method_name = stringArgument(method_name, OREF_positional, ARG_ONE)->upper();
820  ProtectedObject p(method_name);
821  RexxMethod *method_object = (RexxMethod *)this->instanceBehaviour->getMethodDictionary()->stringGet(method_name);
822  /* check if it is in the mdict */
823  if ( OREF_NULL == method_object)
824  {
825  /* if not return an error */
826  reportException(Error_No_method_name, this, method_name);
827  }
828  return method_object; /* if it was - return the value */
829 }
830 
832  RexxClass *class_object) /* target class object */
833 /*****************************************************************************/
834 /* Function: If no qualification parameter entered */
835 /* return all the methods that an instance of this class */
836 /* will inherit */
837 /* If TheNilObject is the qualification parameter */
838 /* return just the methods introduced at this class scope */
839 /* For any other qualification parameter */
840 /* return just the methods introduced at that class scope */
841 /*****************************************************************************/
842 {
843  /* if no parameter specified */
844  /* return my behaviour mdict as a */
845  /* supplier object */
846  if (class_object == OREF_NULL)
847  {
849  }
850  /* if TheNilObject specified */
851  /* return my instance mdict as a */
852  /* supplier object */
853  if (class_object == TheNilObject)
854  {
855  return this->instanceMethodDictionary->supplier();
856  }
857  /* if not one of the above */
858  /* check if it is a superclass */
859  if (this->behaviour->checkScope(class_object))
860  {
861  /* let the class specified return */
862  /* it's own methods */
863  ProtectedObject r;
864  class_object->sendMessage(OREF_METHODS, TheNilObject, r);
865  return(RexxSupplier *)(RexxObject *)r;
866  }
867  /* or just return a null supplier */
868  return(RexxSupplier *)TheNullArray->supplier();
869 }
870 
872 /******************************************************************************/
873 /* Function: Update my behaviours and call each subclass to do the same */
874 /******************************************************************************/
875 {
876  /* start out the class mdict with */
877  /* a clear mdict and scopes tables */
879  this->behaviour->setScopes(OREF_NULL);
880  /* create the instance behaviour from*/
881  /* the instance superclass list */
885  // This time, we update the class behaviour
886  // after building the instance behaviour
887  // because the added methods may have an
888  // impact on metaclasses.
889  this->createClassBehaviour(this->behaviour);
890 
891  RexxArray *subClassList = this->getSubClasses(); /* get the subclasses list */
892  ProtectedObject p(subClassList);
893  /* loop thru the subclass doing the */
894  /* same for each of them */
895  for (size_t index = 1; index <= subClassList->size(); index++)
896  {
897  /* get the next subclass */
898  /* and recursively update them */
899  ((RexxClass *)subClassList->get(index))->updateSubClasses();
900  }
901 }
902 
904 /******************************************************************************/
905 /* Function: Update my instance behaviour and have the subclasses do the same */
906 /******************************************************************************/
907 {
908  /* create the instance behaviour from*/
909  /* the instance superclass list */
913  RexxArray *subClassList = this->getSubClasses(); /* get the subclasses list */
914  ProtectedObject p(subClassList);
915  /* loop thru the subclass doing the */
916  /* same for each of them */
917  for (size_t index = 1; index <= subClassList->size(); index++)
918  {
919  /* get the next subclass */
920  /* recursively update these */
921  ((RexxClass *)subClassList->get(index))->updateInstanceSubClasses();
922  }
923 }
924 
926  RexxBehaviour *target_class_behaviour)
927 /*****************************************************************************/
928 /* Funcion: To call the superclasses and have them update this classes */
929 /* class behaviour mdict and scopes table */
930 /*****************************************************************************/
931 {
932  RexxClass * superclass; /* superclass being called */
933  RexxClass * metaclass; /* metaclass to use */
934 
935 
936  /* Call each of the superclasses in */
937  /* this superclass list starting from*/
938  /* the last to the first */
939  for (HashLink index = this->classSuperClasses->size(); index > 0; index--)
940  {
941  /* get the next superclass */
942  superclass = (RexxClass *)this->classSuperClasses->get(index);
943  /* if there is a superclass and */
944  /* it hasn't been added into this */
945  /* behaviour yet, call and have it */
946  /* add itself */
947  if (superclass != TheNilObject && !target_class_behaviour->checkScope(superclass))
948  {
949  superclass->createClassBehaviour(target_class_behaviour);
950  }
951  }
952  /* If this class mdict has not been */
953  /* merged into this target behaviour */
954  if (!target_class_behaviour->checkScope(this))
955  {
956  if (TheObjectClass != this) /* if this isn't OBJECT */
957  {
958  // we only process the first item in the metaclass list, since it
959  // will properly pull in the scopes for all of the rest, in the correct order.
960  metaclass = (RexxClass *)this->metaClass->get(1);
961  /* add which ever metaclasses have */
962  /* not been added yet */
963  if (metaclass != TheNilObject && !target_class_behaviour->checkScope(metaclass))
964  {
965  /* merge in the meta class mdict */
966  target_class_behaviour->methodDictionaryMerge(metaclass->instanceBehaviour->getMethodDictionary());
967  // now we need to merge in the scopes. For each metaclass, starting
968  // from the bottom of the hierarchy down, merge in each of the scope
969  // values.
970  RexxArray *addedScopes = metaclass->behaviour->getScopes()->allAt(TheNilObject);
971  ProtectedObject p(addedScopes);
972 
973  // these need to be processed in reverse order
974  for (size_t i = addedScopes->size(); i > 0; i--)
975  {
976  RexxClass *scope = (RexxClass *)addedScopes->get(i);
977  target_class_behaviour->mergeScope(scope);
978  }
979  }
980  }
981  /* only merge the mdict for CLASS */
982  /* if this is a capable of being a */
983  /* metaclass */
984  if ((this != TheClassClass) || (this == TheClassClass && this->isMetaClass()))
985  {
986  /* Merge this class mdict with the */
987  /* target behaviour class mdict */
988  target_class_behaviour->methodDictionaryMerge(this->classMethodDictionary);
989  }
990  /* And update the target behaviour */
991  /* scopes table with this class */
992  if (this != TheClassClass && !target_class_behaviour->checkScope(this))
993  {
994  target_class_behaviour->addScope(this);
995  }
996  }
997 }
998 
999 
1001  /* target behaviour to create */
1002  RexxBehaviour *target_instance_behaviour)
1003 /*****************************************************************************/
1004 /* Funcion: To call the superclasses and have them update this classes */
1005 /* instance behaviour mdict and scopes table */
1006 /*****************************************************************************/
1007 {
1008  /* Call each of the superclasses in */
1009  /* this superclass list starting from*/
1010  /* the last going to the first */
1011  for (HashLink index = this->instanceSuperClasses->size(); index > 0; index--)
1012  {
1013  /* get the next super class */
1014  RexxClass *superclass = (RexxClass *)this->instanceSuperClasses->get(index);
1015  /* if there is a superclass and */
1016  /* it hasn't been added into this */
1017  /* behaviour yet, call and have it */
1018  /* add itself */
1019  if (superclass != TheNilObject && !target_instance_behaviour->checkScope(superclass))
1020  {
1021  superclass->createInstanceBehaviour(target_instance_behaviour);
1022  }
1023  }
1024  /* If this class mdict has not been */
1025  /* merged into this target behaviour */
1026  if (!target_instance_behaviour->checkScope(this))
1027  {
1028  /* Merge this class mdict with the */
1029  /* target behaviour class mdict */
1030  target_instance_behaviour->methodDictionaryMerge(this->instanceMethodDictionary);
1031  /* And update the target behaviour */
1032  /* scopes table with this class */
1033  target_instance_behaviour->addScope(this);
1034  }
1035 }
1036 
1037 
1038 /**
1039  * Merge the scopes from the superclasses into a target primitive class.
1040  *
1041  * @param target_instance_behaviour
1042  * The target behavior to update.
1043  */
1044 void RexxClass::mergeSuperClassScopes(RexxBehaviour *target_instance_behaviour)
1045 {
1046  // Call each of the superclasses in this superclass list starting from
1047  // the last going to the first
1048  for (HashLink index = this->instanceSuperClasses->size(); index > 0; index--)
1049  {
1050  RexxClass *superclass = (RexxClass *)this->instanceSuperClasses->get(index);
1051  // if there is a superclass and it hasn't been added into this
1052  // behaviour yet, call and have it add itself */
1053  if (superclass != TheNilObject && !target_instance_behaviour->checkScope(superclass))
1054  {
1055  superclass->mergeSuperClassScopes(target_instance_behaviour);
1056  }
1057  }
1058  // now add in the scope for this class, if still needed.
1059  if (!target_instance_behaviour->checkScope(this))
1060  {
1061  /* Merge this class mdict with the */
1062  /* target behaviour class mdict */
1063  target_instance_behaviour->merge(this->instanceBehaviour);
1064  /* And update the target behaviour */
1065  /* scopes table with this class */
1066  target_instance_behaviour->addScope(this);
1067  }
1068 }
1069 
1071  RexxTable *source_mdict, /* source method dictionary */
1072  RexxTable *target_mdict) /* target method dictionary */
1073 /*****************************************************************************/
1074 /* Function: Merge the source mdict methods into the target mdict after */
1075 /* getting copies of the methods with a new scope */
1076 /* After this merge the method search order will find the source */
1077 /* mdict methods prior to the target methods */
1078 /*****************************************************************************/
1079 {
1080  if (source_mdict == OREF_NULL) /* check for a source mdict */
1081  {
1082  return; /* there isn't anything to do */
1083  }
1084  /* just loop through the entries */
1085  for (HashLink i = source_mdict->first(); source_mdict->available(i); i = source_mdict->next(i))
1086  {
1087  /* get the method name */
1088  RexxString *method_name = REQUEST_STRING(source_mdict->index(i));
1089  ProtectedObject p(method_name);
1090  /* get the method */
1091  RexxMethod *method_instance = (RexxMethod *)source_mdict->value(i);
1092  /* add the method to the target mdict */
1093  target_mdict->stringAdd(method_instance, method_name);
1094  /* check if the method that was added */
1095  /* is the uninit method */
1096  if ( method_name->strCompare(CHAR_UNINIT))
1097  {
1098  this->setHasUninitDefined(); /* and turn on uninit if so */
1099  }
1100  }
1101 }
1102 
1104  RexxTable *sourceCollection, /* source method collection */
1105  RexxClass *scope ) /* required method scope */
1106 /*****************************************************************************/
1107 /* Function: Process a collection of methods that will be added to a class */
1108 /* as class methods, or will be added to an enhanced object. In */
1109 /* either case, this is an arbitrary collection of objects that */
1110 /* may need conversion into method objects and given a scope. */
1111 /*****************************************************************************/
1112 {
1113  RexxTable *newDictionary = new_table(); /* get a new table for this */
1114  ProtectedObject p(newDictionary);
1115  /* loop thru the supplier object */
1116  /* obtained from the source mdict */
1117  ProtectedObject p2;
1118  sourceCollection->sendMessage(OREF_SUPPLIERSYM, p2);
1119  RexxSupplier *supplier = (RexxSupplier *)(RexxObject *)p2;
1120  for (; supplier->available() == TheTrueObject; supplier->next())
1121  {
1122  /* get the method name (uppercased) */
1123  RexxString *method_name = REQUEST_STRING(supplier->index())->upper();
1124  ProtectedObject p(method_name);
1125  /* get the method */
1126  RexxMethod *newMethod = (RexxMethod *)supplier->value();
1127  /* if the method is not TheNilObject */
1128  if (newMethod != (RexxMethod *)TheNilObject)
1129  {
1130  /* and it isn't a primitive method */
1131  if (!isOfClass(Method, newMethod)) /* object */
1132  {
1133  /* make it into a method object */
1134  newMethod = RexxMethod::newMethodObject(method_name, newMethod, IntegerOne, OREF_NULL);
1135  newMethod->setScope(scope); /* and set the scope to the given */
1136  }
1137  else
1138  {
1139  /* if it is a primitive method object */
1140  /* let the newscope method copy it */
1141  newMethod = newMethod->newScope(scope);
1142  }
1143  }
1144  /* add the method to the target mdict */
1145  newDictionary->stringAdd(newMethod, method_name);
1146  }
1147  return newDictionary; /* and return the new version */
1148 }
1149 
1150 
1152  RexxClass *mixin_class, /* target class */
1153  RexxClass *position) /* target inherit position */
1154 /*****************************************************************************/
1155 /* Function: To add the mixin class (parameter one) to the superclass */
1156 /* hierarchy of the receiver class (this), at the last position */
1157 /* or the specified position (parameter two). */
1158 /*****************************************************************************/
1159 {
1160 #if 0
1161  /* make sure this isn't a rexx */
1162  if (this->isRexxDefined()) /* defined class being changed */
1163  {
1164  /* report as a nomethod condition */
1166  }
1167 #endif
1168  requiredArgument(mixin_class, OREF_positional, ARG_ONE); /* make sure it was passed in */
1169 
1170  /* check the mixin class is really a */
1171  /* good class for this */
1172  if (!mixin_class->isInstanceOf(TheClassClass) || !mixin_class->isMixinClass())
1173  {
1174  /* if it isn't raise an error */
1176  }
1177 
1178  /* if the mixin class is also the */
1179  if (this == mixin_class ) /* reciever class */
1180  {
1181  /* raise an error */
1183  }
1184  /* check that the mixin class is not */
1185  /* a superclass of the reciever */
1186  if (this->behaviour->checkScope(mixin_class))
1187  {
1188  /* if it is raise an error */
1190  }
1191  /* check if the reciever class is a */
1192  /* superclass of the mixin class */
1193  if (mixin_class->behaviour->checkScope(this))
1194  {
1195  /* if it is it's an error */
1197  }
1198 
1199  /* Now ensure the mixin class */
1200  /* baseclass is in the reciever's */
1201  /* class superclass hierarchy */
1202  if (!this->behaviour->checkScope(mixin_class->getBaseClass()))
1203  {
1204  /* if it isn't raise an error */
1205  reportException(Error_Execution_baseclass, this, mixin_class, mixin_class->getBaseClass());
1206  }
1207 
1208  /* and the reciever's */
1209  /* instance superclass hierarchy */
1210  if (!this->instanceBehaviour->checkScope(mixin_class->getBaseClass()))
1211  {
1212  /* if it isn't raise an error */
1213  reportException(Error_Execution_baseclass, this, mixin_class, mixin_class->getBaseClass());
1214  }
1215  if ( position == OREF_NULL ) /* if position was not specified */
1216  {
1217  /* insert the mixin class last in the*/
1218  /* reciever's superclasses list */
1219  this->classSuperClasses->addLast(mixin_class);
1220  this->instanceSuperClasses->addLast(mixin_class);
1221  }
1222  else /* if it was specified */
1223  {
1224  /* check that it's a valid superclass*/
1225  /* in the class superclasses list */
1226  /* and the reciever's */
1227  /* instance superclasses list */
1228  HashLink class_index = this->classSuperClasses->indexOf(position);
1229  HashLink instance_index = this->instanceSuperClasses->indexOf(position);
1230  if (class_index == 0 || instance_index == 0)
1231  {
1232  /* if it isn't raise an error */
1233  reportException(Error_Execution_uninherit, this, position);
1234  }
1235  /* insert the mixin class into the */
1236  /* superclasses list's */
1237  this->classSuperClasses->insertAfter(mixin_class, class_index);
1238  this->instanceSuperClasses->insertAfter(mixin_class, instance_index);
1239  }
1240 
1241  /* update the mixin class subclass */
1242  mixin_class->addSubClass(this); /* list to reflect this class */
1243  /* any subclasses that we have need */
1244  /* to redo their behaviour's */
1245  /* this also updates our own */
1246  /* behaviour tables. */
1247  this->updateSubClasses();
1248  /* If the mixin class has an uninit defined, the new class must have one, too */
1249  if (mixin_class->hasUninitDefined() || mixin_class->parentHasUninitDefined())
1250  {
1251  this->setParentHasUninitDefined();
1252  }
1253  return OREF_NULL; /* returns nothing */
1254 }
1255 
1257  RexxClass *mixin_class) /* target subclass to remove */
1258 /*****************************************************************************/
1259 /* Function: To remove a mixin class (parameter one) from the superclass */
1260 /* hierarchy of the receiver class (this). */
1261 /*****************************************************************************/
1262 {
1263  HashLink class_index; /* index for class superclasses list */
1264  HashLink instance_index; /* index for instance superclasses */
1265  /* make sure this isn't rexx defined */
1266  if (this->isRexxDefined()) /* class that is being changed */
1267  {
1268  /* report as a nomethod condition */
1270  }
1271  requiredArgument(mixin_class, OREF_positional, ARG_ONE); /* make sure it was passed in */
1272 
1273  /* check that the mixin class is a */
1274  /* superclass of the receiver class */
1275  /* and not the superclass */
1276  if ( ((class_index = this->classSuperClasses->indexOf(mixin_class)) > 1) &&
1277  ((instance_index = this->instanceSuperClasses->indexOf(mixin_class)) > 1))
1278  {
1279  /* and remove it */
1280  this->classSuperClasses->deleteItem(class_index);
1281  this->instanceSuperClasses->deleteItem(instance_index);
1282  }
1283  else
1284  {
1285  /* else raise an error */
1286  reportException(Error_Execution_uninherit, this, mixin_class);
1287  }
1288  /* update the mixin class subclass */
1289  /* list to not have this class */
1290  removeSubclass(mixin_class);
1291  /* any subclasses that we have need */
1292  /* to redo their behaviour's */
1293  /* this also updates our own behaviour*/
1294  this->updateSubClasses(); /* tables. */
1295  return OREF_NULL; /* returns nothing */
1296 }
1297 
1298 
1299 /**
1300  * Remove a subclass from the uninherit list after an uninherit
1301  * operation.
1302  *
1303  * @param c The class to remove.
1304  */
1306 {
1307  size_t index = subClasses->firstIndex();
1308  // scan the subclasses list looking for the removed class
1309  while (index != LIST_END)
1310  {
1311  WeakReference *ref = (WeakReference *)subClasses->getValue(index);
1312  RexxObject *sc = ref->get();
1313  if (sc == c)
1314  {
1315  subClasses->removeIndex(index);
1316  return;
1317  }
1318  index = subClasses->nextIndex(index);
1319  }
1320 }
1321 
1323  RexxObject **args, /* enhanced arguments */
1324  size_t argCount, /* the number of positional arguments*/
1325  size_t named_argCount) /* the number of named arguments */
1326 /*****************************************************************************/
1327 /* Function: Create a new object that is an instance of the receiver class */
1328 /* object that has had it's instance mdict enhanced. */
1329 /*****************************************************************************/
1330 {
1331  if (argCount == 0) /* make sure an arg was passed in */
1332  {
1333  /* if not report an error */
1335  }
1336  /* get the value of the arg */
1337  RexxTable *enhanced_instance_mdict = (RexxTable *)args[0];
1338  /* make sure it was a real value */
1339  requiredArgument(enhanced_instance_mdict, OREF_positional, ARG_ONE);
1340  /* subclass the reciever class */
1341  RexxClass *dummy_subclass = this->subclass(new_string("Enhanced Subclass"), OREF_NULL, OREF_NULL);
1342  ProtectedObject p(dummy_subclass);
1343  /* turn into a real method dictionary*/
1344  enhanced_instance_mdict = dummy_subclass->methodDictionaryCreate(enhanced_instance_mdict, (RexxClass *)TheNilObject);
1345  ProtectedObject p1(enhanced_instance_mdict);
1346  /* enhance the instance behaviour */
1347  dummy_subclass->methodDictionaryMerge(enhanced_instance_mdict, dummy_subclass->instanceMethodDictionary);
1348  /* and record the changes in behavior*/
1349  dummy_subclass->instanceBehaviour->setInstanceMethodDictionary(enhanced_instance_mdict);
1350  /* recreate the instance behaviour */
1352  dummy_subclass->instanceBehaviour->setScopes(OREF_NULL);
1353  dummy_subclass->createInstanceBehaviour(dummy_subclass->instanceBehaviour);
1354  ProtectedObject r;
1355  /* get an instance of the enhanced */
1356  /* subclass */
1357  dummy_subclass->sendMessage(OREF_NEW, args + 1, argCount - 1, named_argCount, r);
1358  RexxObject *enhanced_object = (RexxObject *)r;
1359  /* change the create_class in the */
1360  /* instance behaviour to point to the*/
1361  /* original class object */
1362  enhanced_object->behaviour->setOwningClass(this);
1363  /* remember it was enhanced */
1364  enhanced_object->behaviour->setEnhanced();
1365 
1366  return enhanced_object; /* send back the new improved version*/
1367 }
1368 
1370  RexxString * mixin_id, /* ID name of the class */
1371  RexxClass * meta_class, /* source meta class */
1372  /* extra class methods */
1373  RexxTable * enhancing_class_methods)
1374 /*****************************************************************************/
1375 /* Function: Create a new class object containng class and instance methods */
1376 /* to be used for multiple inheritance . */
1377 /*****************************************************************************/
1378 {
1379  /* call subclass with the parameters */
1380  RexxClass *mixin_subclass = this->subclass(mixin_id, meta_class, enhancing_class_methods);
1381  mixin_subclass->setMixinClass(); /* turn on the mixin info */
1382  /* change the base class to the base */
1383  /* class of the reciever */
1384  OrefSet(mixin_subclass, mixin_subclass->baseClass, this->baseClass);
1385  /* If the mixin's parent class has an uninit defined, the new mixin class must have one, too */
1386  if (this->hasUninitDefined() || this->parentHasUninitDefined())
1387  {
1388  mixin_subclass->setParentHasUninitDefined();
1389  }
1390  return mixin_subclass; /* return the new mixin class */
1391 }
1392 
1393 
1395  RexxString * class_id, /* ID name of the class */
1396  RexxClass * meta_class, /* source meta class */
1397  /* extra class methods */
1398  RexxTable * enhancing_class_methods)
1399 /*****************************************************************************/
1400 /* Function: Create a new class object that is a subclass of this class */
1401 /* object. */
1402 /*****************************************************************************/
1403 {
1404  if (meta_class == OREF_NULL) /* if there is no metaclass specified*/
1405  {
1406  meta_class = this->getMetaClass(); /* use the default metaclass */
1407  }
1408 
1409  /* check that it is a meta class */
1410  if (!meta_class->isInstanceOf(TheClassClass) || !meta_class->isMetaClass())
1411  {
1413  }
1414  ProtectedObject p;
1415  /* get a copy of the metaclass class */
1416  meta_class->sendMessage(OREF_NEW, class_id, p);
1417  RexxClass *new_class = (RexxClass *)(RexxObject *)p;
1418  if (this->isMetaClass()) /* if the superclass is a metaclass */
1419  {
1420  new_class->setMetaClass(); /* mark the new class as a meta class*/
1421  /* and if the metaclass lists haven't */
1422  /* been updated yet */
1423  if (new_class->metaClassScopes->get(this) == OREF_NULL)
1424  {
1425  /* add the class instance info to the */
1426  /* metaclass lists */
1427  new_class->metaClass->addFirst(this);
1428  /* the metaclass mdict list */
1430  /* and the metaclass scopes list */
1431  /* this is done by adding all the */
1432  /* scope information of the new class */
1433  new_class->metaClassScopes->add(this, TheNilObject);
1434  /* add the scope list for this scope */
1435  new_class->metaClassScopes->add(new_class->metaClassScopes->allAt(TheNilObject), this);
1436  }
1437  }
1438  /* set up the new_class behaviour */
1439  /* to match the subclass reciever */
1440  new_class->instanceBehaviour->subclass(this->instanceBehaviour);
1441  /* set this class as the superclass */
1442  /* for the new class' */
1443  /* class_superclasses list */
1444  OrefSet(new_class, new_class->classSuperClasses, new_array(this));
1445  /* make the receiver class the */
1446  /* superclass for the instance behav */
1447  OrefSet(new_class, new_class->instanceSuperClasses, new_array(this));
1448  /* if there was enhancing methods */
1449  /* specified */
1450  if (enhancing_class_methods != OREF_NULL && enhancing_class_methods != TheNilObject)
1451  {
1452  /* convert into a real method dict. */
1453  enhancing_class_methods = new_class->methodDictionaryCreate(enhancing_class_methods, new_class);
1454  ProtectedObject p(enhancing_class_methods);
1455  /* merge them into the class mdict */
1456  new_class->methodDictionaryMerge(enhancing_class_methods, new_class->classMethodDictionary);
1457  }
1458  /* start out the class behaviour clean*/
1460  new_class->behaviour->setScopes(OREF_NULL);
1461  /* create the class behaviour from */
1462  /* the class superclass list */
1463  new_class->createClassBehaviour(new_class->behaviour);
1464  /* set the class behaviour created */
1465  /* class to the meta class */
1466  new_class->behaviour->setOwningClass(meta_class);
1467  /* create the instance behaviour from */
1468  /* the instance superclass list */
1470  new_class->instanceBehaviour->setScopes(OREF_NULL);
1471  new_class->createInstanceBehaviour(new_class->instanceBehaviour);
1472  /* set the instance behaviour created */
1473  /* class to the reciever class */
1474  new_class->instanceBehaviour->setOwningClass(new_class);
1475  /* update the receiver class' subclass*/
1476 
1477  this->addSubClass(new_class); /* list to reflect the new class */
1478  /* if the class object has an UNINIT method defined, make sure we */
1479  /* add this to the table of classes to be processed. */
1480  if (new_class->hasUninitMethod())
1481  {
1482  new_class->hasUninit();
1483  }
1484  new_class->sendMessage(OREF_INIT); /* now drive any user INIT methods */
1485  /* now the new class object should */
1486  /* If the parent class has an uninit defined, the new child class must have one, too */
1487  if (this->hasUninitDefined() || this->parentHasUninitDefined())
1488  {
1489  new_class->setParentHasUninitDefined();
1490  }
1491  /* notify activity this object has an UNINIT that needs to be called
1492  when collecting the object */
1493  if (new_class->hasUninitDefined())
1494  {
1495  new_class->setHasUninitDefined();
1496  }
1497 
1498  return new_class; /* return the new class */
1499 }
1500 
1502  RexxClass *new_metaClass ) /* new meta class to add */
1503 /******************************************************************************/
1504 /* Function: Set a metaclass for a class */
1505 /******************************************************************************/
1506 {
1507  OrefSet(this, this->metaClass, new_array(TheClassClass));
1508  this->metaClass->addFirst(new_metaClass);
1509  /* the metaclass mdict list */
1510  OrefSet(this, this->metaClassMethodDictionary, new_array(TheClassClass->instanceMethodDictionary->copy()));
1512  /* and the metaclass scopes list */
1513  OrefSet(this, this->metaClassScopes, (RexxIdentityTable *)TheClassClass->behaviour->getScopes()->copy());
1514  /* add the scope list for this scope */
1515  this->metaClassScopes->add(new_metaClass, TheNilObject);
1516  this->metaClassScopes->add(this->metaClassScopes->allAt(TheNilObject), new_metaClass);
1517 }
1518 
1519 
1520 /**
1521  * Test if the target class is a "compatible" with the argument
1522  * class. To be compatible, the target class must either A)
1523  * be the same class, B) be a direct subclass of the argument
1524  * class, or C) inherit the argument class as a mixin. This
1525  * rule gets applied recursively down the hierarchy.
1526  *
1527  * @param other The comparison class.
1528  *
1529  * @return True if the two classes are compatible, false otherwise.
1530  */
1532 {
1533  // if asking for a match here, this is true
1534  if (other == this)
1535  {
1536  return true;
1537  }
1538 
1539  // if this is .object, there are no superclasses. Otherwise, ask each of the superclasses
1540  // the same question.
1542  {
1543  for (size_t i = 1; i <= instanceSuperClasses->size(); i++)
1544  {
1545  if (((RexxClass *)instanceSuperClasses->get(i))->isCompatibleWith(other))
1546  {
1547  return true;
1548  }
1549  }
1550  }
1551  return false;
1552 }
1553 
1554 
1555 /**
1556  * A stub to test compatibility of two classes.
1557  *
1558  * @param other The class for the superclass test.
1559  *
1560  * @return True if the class is a subclass of the argument class (or IS
1561  * the argument class).
1562  */
1564 {
1565  requiredArgument(other, OREF_positional, ARG_ONE); // must have the other argument
1566  return isCompatibleWith(other) ? TheTrueObject : TheFalseObject;
1567 }
1568 
1570 /******************************************************************************/
1571 /* Function: Exported access to an object virtual function */
1572 /******************************************************************************/
1573 {
1574  return this->defaultName(); /* forward to the virtual function */
1575 }
1576 
1577 
1578 void *RexxClass::operator new(size_t size,
1579  size_t size1, /* additional size */
1580  const char *className, // The id string of the class
1581  RexxBehaviour *class_behaviour, /* new class behaviour */
1582  RexxBehaviour *instanceBehaviour) /* instance behaviour info */
1583 /*****************************************************************************/
1584 /* Function: Create a new primitive class */
1585 /* for the subclassable classes the rest of the class information */
1586 /* will be filled in when oksetup.c is run */
1587 /*****************************************************************************/
1588 {
1589  RexxClass *new_class; /* newly create class */
1590 
1591  if (size1 == 0) /* want the default? */
1592  {
1593  /* Get new class object */
1594  new_class = (RexxClass *)new_object(size);
1595  }
1596  else
1597  {
1598  /* use the specified size */
1599  new_class = (RexxClass *)new_object(size1);
1600  }
1601  // set this value immediately
1602  new_class->id = new_string(className);
1603  /* set the class specific behaviour */
1604  new_class->setBehaviour(class_behaviour);
1605  /* set the class into the behaviour */
1606  new_class->behaviour->setOwningClass(new_class);
1607  /* set the instance behaviour */
1608  OrefSet(new_class, new_class->instanceBehaviour, instanceBehaviour);
1609  /* and the class of this behaviour */
1610  new_class->instanceBehaviour->setOwningClass(new_class);
1611  /* tell the mobile support to just */
1612  new_class->makeProxiedObject(); /* make a proxy for this class */
1613  return(void *)new_class; /* should be ready */
1614 }
1615 
1616 RexxClass *RexxClass::newRexx(RexxObject **args, size_t argCount, size_t named_argCount)
1617 /*****************************************************************************/
1618 /* Function: Create a new class for a rexx class */
1619 /* A copy of this class object is made */
1620 /* This class' behaviour, class_mdict, metaclass, and class_info */
1621 /* are used in the new class. All the rest of the object state */
1622 /* data is updated to reflect a new class object */
1623 /*****************************************************************************/
1624 {
1625  if (argCount == 0) /* make sure an arg was passed in */
1626  {
1627  /* if not report an error */
1629  }
1630  RexxString *class_id = (RexxString *)args[0]; /* get the id parameter */
1631  class_id = stringArgument(class_id, OREF_positional, ARG_ONE); /* and that it can be a string */
1632  ProtectedObject p1(class_id);
1633  /* get a copy of this class object */
1634  RexxClass *new_class = (RexxClass *)this->clone();
1635 
1636  // NOTE: we do this before save() is called. The class object hash value
1637  // is based off of the string name, so we need to set this before we
1638  // attempt putting this into a hash collection.
1639  OrefSet(new_class, new_class->id, class_id);
1640  /* update cloned hashvalue */
1641  ProtectedObject p(new_class); /* better protect this */
1642  /* make this into an instance of the */
1643  /* meta class */
1644  OrefSet(new_class, new_class->behaviour, (RexxBehaviour *)new_class->instanceBehaviour->copy());
1645  /* don't give access to this class' */
1646  /* class mdict */
1647  OrefSet(new_class, new_class->classMethodDictionary, new_table());
1648  /* make this class the superclass */
1649  OrefSet(new_class, new_class->classSuperClasses, new_array(this));
1650  new_class->behaviour->setOwningClass(this);/* and set the behaviour class */
1651  /* if this is a primitive class then */
1652  /* there isn't any metaclass info */
1653  if (this->isPrimitiveClass()) /* set up yet */
1654  {
1655  /* set up the new metaclass list */
1656  OrefSet(new_class, new_class->metaClass, new_array(TheClassClass));
1657  /* the metaclass mdict list */
1658  OrefSet(new_class, new_class->metaClassMethodDictionary, new_array(TheClassClass->instanceMethodDictionary->copy()));
1659  /* and the metaclass scopes list */
1660  OrefSet(new_class, new_class->metaClassScopes, (RexxIdentityTable *)TheClassClass->behaviour->getScopes()->copy());
1661  }
1662  else
1663  {
1664  /* add this class to the new class */
1665  /* metaclass list */
1666  OrefSet(new_class, new_class->metaClass, (RexxArray *)new_class->metaClass->copy());
1667  new_class->metaClass->addFirst(this);
1668  /* the metaclass mdict list */
1669  OrefSet(new_class, new_class->metaClassMethodDictionary, (RexxArray *)new_class->metaClassMethodDictionary->copy());
1671  /* and the metaclass scopes list */
1672  /* this is done by adding all the */
1673  /* scope information of the new class */
1674  OrefSet(new_class, new_class->metaClassScopes, (RexxIdentityTable *)new_class->metaClassScopes->copy());
1675  /* and update the scopes to include */
1676  /* the metaclass scopes */
1677  new_class->metaClassScopes->add(this, TheNilObject);
1678  new_class->metaClassScopes->add(this->behaviour->getScopes()->allAt(TheNilObject), this);
1679  }
1680 
1681  // create the subclasses list
1682  OrefSet(new_class, new_class->subClasses, new_list());
1683  /* set up the instance behaviour with */
1684  /* object's instance methods */
1685  OrefSet(new_class, new_class->instanceBehaviour, (RexxBehaviour *)TheObjectClass->instanceBehaviour->copy());
1686  /* don't give access to this class' */
1687  /* instance mdict */
1688  OrefSet(new_class, new_class->instanceMethodDictionary, new_table());
1689  /* make the instance_superclass list */
1690  /* with OBJECT in it */
1691  OrefSet(new_class, new_class->instanceSuperClasses, new_array(TheObjectClass));
1692  /* and set the behaviour class */
1694  /* and the instance behaviour scopes */
1696  /* set the scoping info */
1698  /* don't give access to this class' */
1699  /* ovd's */
1700  OrefSet(new_class, new_class->objectVariables, OREF_NULL);
1701  /* set the new class as it's own */
1702  /* baseclass */
1703  OrefSet(new_class, new_class->baseClass, new_class);
1704  /* clear the info area except for */
1705  /* uninit */
1706  new_class->setInitialFlagState();
1707  /* if the class object has an UNINIT method defined, make sure we */
1708  /* add this to the table of classes to be processed. */
1709  if (new_class->hasUninitDefined())
1710  {
1711  new_class->setHasUninitDefined();
1712  }
1713  new_class->sendMessage(OREF_INIT, args + 1, argCount - 1, named_argCount);
1714  return new_class; /* return the new class */
1715 }
1716 
1718 /******************************************************************************/
1719 /* Function: Create the initial class object */
1720 /******************************************************************************/
1721 {
1722  /* create a class object */
1724  /* set the instance behaviour */
1725  TheClassClass->setBehaviour(TheClassClassBehaviour);
1726  /* set the instance behaviour */
1727  TheClassClass->setInstanceBehaviour(TheClassBehaviour);
1728 
1729  // the initial class needs to have an ID before it can be used for
1730  // other purposes.
1731  TheClassClass->id = new_string("Class");
1732 
1733  /* tell the mobile support to just */
1734  /* make a proxy for this class */
1735  TheClassClass->makeProxiedObject();
1736  new (TheClassClass) RexxClass;
1737 }
1738 
1739 
1741  RexxObject **arg_array, /* source argument array */
1742  size_t argCount, /* size of the argument array */
1743  RexxObject***init_args, /* remainder arguments */
1744  size_t *remainderSize, /* remaining count of arguments */
1745  size_t required, /* number of arguments we require */
1746  RexxObject **argument1, /* first returned argument */
1747  RexxObject **argument2 ) /* second return argument */
1748 /******************************************************************************/
1749 /* Function: Divide up a class new arglist into new arguments and init args */
1750 /******************************************************************************/
1751 {
1752  *argument1 = OREF_NULL; /* clear the first argument */
1753  if (argCount >= 1) /* have at least one argument? */
1754  {
1755  *argument1 = arg_array[0]; /* get the first argument */
1756  }
1757  if (required == 2)
1758  { /* processing two arguments? */
1759  if (argCount >= 2) /* get at least 2? */
1760  {
1761  *argument2 = arg_array[1]; /* get the second argument */
1762  }
1763  else
1764  {
1765  *argument2 = OREF_NULL; /* clear the second argument */
1766  }
1767  }
1768  /* get the init args part */
1769  *init_args = arg_array + required;
1770  /* if we have at least the required arguments, reduce the count. */
1771  /* Otherwise, set this to zero. */
1772  if (argCount >= required)
1773  {
1774  *remainderSize = argCount - required;
1775  }
1776  else
1777  {
1778  *remainderSize = 0;
1779  }
1780 }
void reportNomethod(RexxString *message, RexxObject *receiver)
void reportException(wholenumber_t error)
RexxString * lastMessageName()
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
RexxIdentityTable * new_identity_table()
#define LIST_END
Definition: ListClass.hpp:60
RexxList * new_list()
Definition: ListClass.hpp:147
size_t HashCode
Definition: ObjectClass.hpp:77
#define TheClassBehaviour
#define TheClassClassBehaviour
#define TheObjectBehaviour
#define OREF_NULL
Definition: RexxCore.h:60
RexxString * stringArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:303
#define TheObjectClass
Definition: RexxCore.h:158
#define TheNullArray
Definition: RexxCore.h:183
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:283
#define IntegerOne
Definition: RexxCore.h:190
#define TheClassClass
Definition: RexxCore.h:148
#define TheStringClass
Definition: RexxCore.h:161
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define TheTrueObject
Definition: RexxCore.h:186
const int ARG_TWO
Definition: RexxCore.h:81
#define TheIntegerClass
Definition: RexxCore.h:150
#define IntegerTwo
Definition: RexxCore.h:191
#define isOfClass(t, r)
Definition: RexxCore.h:212
#define TheNilObject
Definition: RexxCore.h:181
#define TheFalseObject
Definition: RexxCore.h:185
const int ARG_ONE
Definition: RexxCore.h:80
#define TheNumberStringClass
Definition: RexxCore.h:157
void requiredArgument(RexxObject *object, RexxString *kind, size_t position)
Definition: RexxCore.h:291
#define Error_Logical_value_method
#define Error_Execution_mixinclass
#define Error_No_result_object_message
#define Error_Translation_bad_metaclass
#define Error_Execution_uninherit
#define Error_Incorrect_method_minarg
#define Error_No_method_name
#define Error_Execution_recursive_inherit
#define Error_Execution_baseclass
size_t HashLink
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:431
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
RexxString * new_proxy(const char *name)
RexxString * new_string(const char *s, stringsizeB_t bl, sizeC_t cl=-1)
RexxTable * new_table()
Definition: TableClass.hpp:76
size_t addFirst(RexxObject *item)
Definition: ArrayClass.hpp:199
size_t insertAfter(RexxObject *item, size_t index)
Definition: ArrayClass.hpp:200
RexxObject * copy()
Definition: ArrayClass.cpp:122
size_t indexOf(RexxObject *)
size_t size()
Definition: ArrayClass.hpp:202
size_t addLast(RexxObject *item)
Definition: ArrayClass.hpp:198
RexxObject * deleteItem(size_t index)
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
RexxTable * getMethodDictionary()
void merge(RexxBehaviour *)
RexxObject * mergeScope(RexxObject *)
RexxObject * addScope(RexxObject *)
void methodDictionaryMerge(RexxTable *)
RexxObject * define(RexxString *, RexxMethod *)
RexxObject * copy()
void setMethodDictionary(RexxTable *m)
RexxObject * deleteMethod(RexxString *)
RexxObject * setScopes(RexxIdentityTable *)
bool checkScope(RexxObject *)
RexxIdentityTable * getScopes()
void subclass(RexxBehaviour *)
void setInstanceMethodDictionary(RexxTable *m)
void setOwningClass(RexxClass *c)
void removeSubclass(RexxClass *c)
void createClassBehaviour(RexxBehaviour *)
Definition: ClassClass.cpp:925
void setHasUninitDefined()
Definition: ClassClass.hpp:118
RexxClass * newRexx(RexxObject **args, size_t argCount, size_t named_argCount)
void setInstanceBehaviour(RexxBehaviour *)
Definition: ClassClass.cpp:294
RexxObject * deleteMethod(RexxString *)
Definition: ClassClass.cpp:783
RexxClass * getSuperClass()
Definition: ClassClass.cpp:303
uint32_t classFlags
Definition: ClassClass.hpp:170
RexxTable * methodDictionaryCreate(RexxTable *, RexxClass *)
static void createInstance()
void mergeSuperClassScopes(RexxBehaviour *target_instance_behaviour)
void addSubClass(RexxClass *)
Definition: ClassClass.cpp:337
static RexxClass * classInstance
Definition: ClassClass.hpp:136
bool isRexxDefined()
Definition: ClassClass.hpp:114
void updateInstanceSubClasses()
Definition: ClassClass.cpp:903
void methodDictionaryMerge(RexxTable *, RexxTable *)
RexxClass * baseClass
Definition: ClassClass.hpp:158
void setInitialFlagState()
Definition: ClassClass.hpp:121
RexxTable * instanceMethodDictionary
Definition: ClassClass.hpp:157
RexxMethod * method(RexxString *)
Definition: ClassClass.cpp:812
void setMetaClass(RexxClass *)
RexxClass * getMetaClass()
Definition: ClassClass.cpp:279
RexxArray * instanceSuperClasses
Definition: ClassClass.hpp:167
RexxTable * getInstanceBehaviourDictionary()
Definition: ClassClass.cpp:387
bool isPrimitiveClass()
Definition: ClassClass.hpp:124
static void processNewArgs(RexxObject **, size_t, RexxObject ***, size_t *, size_t, RexxObject **, RexxObject **)
RexxObject * inherit(RexxClass *, RexxClass *)
void defmeths(RexxTable *)
Definition: ClassClass.cpp:348
RexxString * defaultNameRexx()
RexxObject * notEqual(RexxObject *)
Definition: ClassClass.cpp:223
RexxArray * getSubClasses()
Definition: ClassClass.cpp:328
void liveGeneral(int reason)
Definition: ClassClass.cpp:85
RexxIdentityTable * metaClassScopes
Definition: ClassClass.hpp:162
void removeClassMethod(RexxString *method_name)
Definition: ClassClass.cpp:769
RexxClass * getBaseClass()
Definition: ClassClass.cpp:271
RexxTable * classMethodDictionary
Definition: ClassClass.hpp:153
RexxObject * defineMethod(RexxString *, RexxMethod *)
Definition: ClassClass.cpp:623
RexxArray * getSuperClasses()
Definition: ClassClass.cpp:318
RexxObject * isSubclassOf(RexxClass *other)
RexxObject * enhanced(RexxObject **, size_t, size_t)
RexxObject * unflatten(RexxEnvelope *)
Definition: ClassClass.cpp:112
void updateSubClasses()
Definition: ClassClass.cpp:871
RexxInteger * queryMixinClass()
Definition: ClassClass.cpp:245
RexxTable * getBehaviourDictionary()
Definition: ClassClass.cpp:405
RexxObject * equal(RexxObject *)
Definition: ClassClass.cpp:201
void setParentHasUninitDefined()
Definition: ClassClass.hpp:123
bool parentHasUninitDefined()
Definition: ClassClass.hpp:122
RexxObject * defineMethods(RexxTable *)
Definition: ClassClass.cpp:695
RexxObject * setRexxDefined()
Definition: ClassClass.cpp:262
bool isCompatibleWith(RexxClass *other)
RexxObject * defineClassMethod(RexxString *method_name, RexxMethod *newMethod)
Definition: ClassClass.cpp:742
RexxSupplier * methods(RexxClass *)
Definition: ClassClass.cpp:831
RexxArray * metaClass
Definition: ClassClass.hpp:159
void flatten(RexxEnvelope *)
Definition: ClassClass.cpp:104
RexxBehaviour * instanceBehaviour
Definition: ClassClass.hpp:155
bool hasUninitDefined()
Definition: ClassClass.hpp:117
RexxObject * strictEqual(RexxObject *)
Definition: ClassClass.cpp:164
RexxList * subClasses
Definition: ClassClass.hpp:172
bool isEqual(RexxObject *)
Definition: ClassClass.cpp:173
RexxObject * uninherit(RexxClass *)
RexxClass * mixinclass(RexxString *, RexxClass *, RexxTable *)
void setMetaClass()
Definition: ClassClass.hpp:128
RexxArray * classSuperClasses
Definition: ClassClass.hpp:164
RexxString * id
Definition: ClassClass.hpp:150
RexxString * getId()
Definition: ClassClass.cpp:254
bool isMixinClass()
Definition: ClassClass.hpp:115
HashCode getHashValue()
Definition: ClassClass.cpp:155
RexxString * defaultName()
Definition: ClassClass.cpp:373
RexxClass * subclass(RexxString *, RexxClass *, RexxTable *)
HashCode hash()
Definition: ClassClass.cpp:141
void live(size_t)
Definition: ClassClass.cpp:66
void createInstanceBehaviour(RexxBehaviour *)
RexxObject * makeProxy(RexxEnvelope *)
Definition: ClassClass.cpp:120
RexxArray * metaClassMethodDictionary
Definition: ClassClass.hpp:161
void subClassable(bool)
Definition: ClassClass.cpp:432
void setMixinClass()
Definition: ClassClass.hpp:125
bool isMetaClass()
Definition: ClassClass.hpp:116
bool available(HashLink pos)
RexxObject * value(HashLink pos)
HashLink next(HashLink pos)
virtual RexxObject * remove(RexxObject *key)
RexxObject * index(HashLink pos)
RexxSupplier * supplier()
RexxArray * allAt(RexxObject *key)
virtual RexxObject * get(RexxObject *key)
virtual RexxObject * add(RexxObject *, RexxObject *)
void setBehaviour(RexxBehaviour *b)
RexxObject * clone()
RexxBehaviour * behaviour
RexxObject * removeIndex(size_t i)
Definition: ListClass.hpp:113
size_t firstIndex()
Definition: ListClass.hpp:84
size_t nextIndex(size_t i)
Definition: ListClass.cpp:804
RexxArray * weakReferenceArray()
Definition: ListClass.cpp:1158
RexxObject * getValue(size_t i)
Definition: ListClass.cpp:276
void addFirst(RexxObject *value)
Definition: ListClass.cpp:486
void setScope(RexxClass *)
static RexxMethod * newMethodObject(RexxString *, RexxObject *, RexxObject *, RexxSource *a, bool isBlock=false)
RexxMethod * newScope(RexxClass *)
bool hasUninitMethod()
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
bool isInstanceOf(RexxClass *)
const char * getStringData()
RexxString * concatWithCstring(const char *)
RexxString * concatToCstring(const char *)
bool strCompare(const char *s)
RexxString * upper()
RexxObject * next()
RexxInteger * available()
RexxObject * value()
RexxObject * index()
RexxObject * stringAdd(RexxObject *, RexxString *)
Definition: TableClass.cpp:94
RexxObject * stringPut(RexxObject *, RexxString *)
Definition: TableClass.cpp:113
RexxObject * stringGet(RexxString *key)
Definition: TableClass.hpp:67
RexxObject * get()