ClassDirective.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 ClassDirective.cpp */
40 /* */
41 /* Primitive Translator Abstract Directive Code */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "ClassDirective.hpp"
47 #include "Clause.hpp"
48 #include "DirectoryClass.hpp"
49 #include "TableClass.hpp"
50 #include "ListClass.hpp"
51 #include "RexxActivation.hpp"
52 
53 
54 
55 /**
56  * Construct a ClassDirective.
57  *
58  * @param n The name of the requires target.
59  * @param p The public name of the requires target.
60  * @param clause The source file clause containing the directive.
61  */
63 {
64  idName = n;
65  publicName = p;
66 }
67 
68 /**
69  * Normal garbage collecting live mark.
70  *
71  * @param liveMark The current live object mark.
72  */
73 void ClassDirective::live(size_t liveMark)
74 {
75  memory_mark(this->nextInstruction); // must be first one marked (though normally null)
76  memory_mark(this->publicName);
77  memory_mark(this->idName);
84 }
85 
86 
87 /**
88  * The generalized object marking routine.
89  *
90  * @param reason The processing faze we're running the mark on.
91  */
93 {
94  memory_mark_general(this->nextInstruction); // must be first one marked (though normally null)
103 }
104 
105 
106 /**
107  * Flatten the directive instance.
108  *
109  * @param envelope The envelope we're flattening into.
110  */
112 {
114 
115  flatten_reference(newThis->nextInstruction, envelope);
116  flatten_reference(newThis->publicName, envelope);
117  flatten_reference(newThis->idName, envelope);
118  flatten_reference(newThis->metaclassName, envelope);
119  flatten_reference(newThis->subclassName, envelope);
120  flatten_reference(newThis->inheritsClasses, envelope);
121  flatten_reference(newThis->instanceMethods, envelope);
122  flatten_reference(newThis->classMethods, envelope);
123  // by this time, we should be finished with this, and it should
124  // already be null. Make sure this is the case.
125  newThis->dependencies = OREF_NULL;
126 
128 }
129 
130 
131 /**
132  * Allocate a new requires directive.
133  *
134  * @param size The size of the object.
135  *
136  * @return The memory for the new object.
137  */
138 void *ClassDirective::operator new(size_t size)
139 {
140  return new_object(size, T_ClassDirective); /* Get new object */
141 }
142 
143 
144 /**
145  * Do install-time processing of the ::requires directive. This
146  * will resolve the directive and merge all of the public information
147  * from the resolved file into this program context.
148  *
149  * @param activation The activation we're running under for the install.
150  */
152 {
153  RexxClass *metaclass = OREF_NULL;
154  RexxClass *subclass = TheObjectClass;
155 
156  // make this the current line for the error context
157  activation->setCurrent(this);
158 
159  if (metaclassName != OREF_NULL)
160  {
161  /* resolve the class */
162  metaclass = source->findClass(metaclassName);
163  if (metaclass == OREF_NULL) /* nothing found? */
164  {
165  /* not found in environment, error! */
167  }
168  }
169 
170  if (subclassName != OREF_NULL) /* no subclass? */
171  {
172  /* resolve the class */
173  subclass = source->findClass(subclassName);
174  if (subclass == OREF_NULL) /* nothing found? */
175  {
176  /* not found in environment, error! */
178  }
179  }
180 
181  RexxClass *classObject; // the class object we're creating
182 
183  // create the class object using the appropriate mechanism
184  if (mixinClass)
185  {
186  classObject = subclass->mixinclass(idName, metaclass, classMethods);
187  }
188  else
189  {
190  /* doing a subclassing */
191  classObject = subclass->subclass(idName, metaclass, classMethods);
192  }
193  /* add the class to the directory */
194  source->addInstalledClass(publicName, classObject, publicClass);
195 
196  if (inheritsClasses != OREF_NULL) /* have inherits to process? */
197  {
198  // now handle the multiple inheritance issues
199  for (size_t i = inheritsClasses->firstIndex(); i != LIST_END; i = inheritsClasses->nextIndex(i))
200  {
201  /* get the next inherits name */
202  RexxString *inheritsName = (RexxString *)inheritsClasses->getValue(i);
203  /* go resolve the entry */
204  RexxClass *mixin = source->findClass(inheritsName);
205  if (mixin == OREF_NULL) /* not found? */
206  {
207  /* not found in environment, error! */
209  }
210  /* do the actual inheritance */
211  classObject->sendMessage(OREF_INHERIT, mixin);
212  }
213  }
214 
215  if (instanceMethods != OREF_NULL) /* have instance methods to add? */
216  {
217  /* define them to the class object */
218  classObject->defineMethods(instanceMethods);
219  }
220  // the source needs this at the end so it call call the activate methods
221  return classObject;
222 }
223 
224 
225 /**
226  * Check if a dependency this class has is based off of a
227  * class co-located in the same class package.
228  *
229  * @param name The class name.
230  * @param class_directives
231  * The global local classes list.
232  */
234 {
235  if (name != OREF_NULL)
236  {
237  // if this is in install? */
238  if (class_directives->entry(name) != OREF_NULL)
239  {
240  if (dependencies == OREF_NULL)
241  {
242  OrefSet(this, this->dependencies, new_directory());
243  }
244  /* add to our pending list */
245  dependencies->setEntry(name, name);
246  }
247  }
248 }
249 
250 
251 /**
252  * Check our class dependencies against the locally defined class
253  * list to develop a cross dependency list.
254  *
255  * @param class_directives
256  * The global set of defined classes in this package.
257  */
259 {
260  // now for each of our dependent classes, if this is defined locally, we
261  // an entry to our dependency list to aid the class ordering
262 
263  checkDependency(metaclassName, class_directives);
264  checkDependency(subclassName, class_directives);
265  // process each inherits item the same way
266  if (inheritsClasses != OREF_NULL)
267  {
268  for (size_t i = inheritsClasses->firstIndex(); i != LIST_END; i = inheritsClasses->nextIndex(i))
269  {
270  /* get the next inherits name */
271  RexxString *inheritsName = (RexxString *)inheritsClasses->getValue(i);
272  checkDependency(inheritsName, class_directives);
273  }
274  }
275 }
276 
277 
278 /**
279  * Check if this class has any additional in-package dependencies.
280  *
281  * @return true if all in-package dependencies have been resolved already.
282  */
284 {
285  return dependencies == OREF_NULL;
286 }
287 
288 
289 /**
290  * Remove a class from the dependency list.
291  *
292  * @param name The name of the class that's next in the ordering.
293  */
295 {
296  // if we have a dependency list, remove this name from the
297  // list. If this is our last dependency item, we can junk
298  // the list entirely.
299  if (dependencies != OREF_NULL)
300  {
301  dependencies->remove(name);
302  if (dependencies->items() == 0)
303  {
304  OrefSet(this, this->dependencies, OREF_NULL);
305  }
306  }
307 }
308 
309 
310 /**
311  * Add an inherits class to the class definition.
312  *
313  * @param name The name of the inherited class.
314  */
316 {
317  if (inheritsClasses == OREF_NULL)
318  {
319  OrefSet(this, this->inheritsClasses, new_list());
320  }
321  inheritsClasses->append(name);
322 }
323 
324 
325 /**
326  * Retrieve the class methods directory for this class.
327  *
328  * @return The class methods directory.
329  */
331 {
332  if (classMethods == OREF_NULL)
333  {
334  OrefSet(this, this->classMethods, new_table());
335  }
336  return classMethods;
337 }
338 
339 
340 /**
341  * Retrieve the instance methods directory for this class.
342  *
343  * @return The instance methods directory.
344  */
346 {
347  if (instanceMethods == OREF_NULL)
348  {
349  OrefSet(this, this->instanceMethods, new_table());
350  }
351  return instanceMethods;
352 }
353 
354 
355 /**
356  * Check for a duplicate method defined om this class.
357  *
358  * @param name The method name.
359  * @param classMethod
360  * Indicates whether we are checking for a class or instance method.
361  *
362  * @return true if this is a duplicate of the method type.
363  */
365 {
366  if (classMethod)
367  {
368  return getClassMethods()->get(name) != OREF_NULL;
369  }
370  else
371  {
372  return getInstanceMethods()->get(name) != OREF_NULL;
373  }
374 
375 }
376 
377 
378 /**
379  * Add a method to a class definition.
380  *
381  * @param name The name to add.
382  * @param method The method object that maps to this name.
383  * @param classMethod
384  * Indicates whether this is a new class or instance method.
385  */
386 void ClassDirective::addMethod(RexxString *name, RexxMethod *method, bool classMethod)
387 {
388  if (classMethod)
389  {
390  getClassMethods()->put(method, name);
391  }
392  else
393  {
394  getInstanceMethods()->put(method, name);
395  }
396 }
397 
398 
399 /**
400  * Add a method to a class definition.
401  *
402  * @param name The name to add.
403  * @param method The method object that maps to this name.
404  */
406 {
407  // this gets added as both a class and instance method
408  addMethod(name, method, false);
409  addMethod(name, method, true);
410 }
void reportException(wholenumber_t error)
@ T_ClassDirective
RexxDirectory * new_directory()
#define LIST_END
Definition: ListClass.hpp:60
RexxList * new_list()
Definition: ListClass.hpp:147
#define OREF_NULL
Definition: RexxCore.h:60
#define TheObjectClass
Definition: RexxCore.h:158
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define Error_Execution_nometaclass
#define Error_Execution_noclass
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:431
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:493
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:446
#define cleanUpFlatten
Definition: RexxMemory.hpp:479
#define setUpFlatten(type)
Definition: RexxMemory.hpp:473
RexxTable * new_table()
Definition: TableClass.hpp:76
#define KEYWORD_CLASS
Definition: Token.hpp:196
RexxString * subclassName
RexxString * metaclassName
void live(size_t)
void addInherits(RexxString *name)
ClassDirective(RexxString *, RexxString *, RexxClause *)
RexxList * inheritsClasses
void removeDependency(RexxString *name)
bool checkDuplicateMethod(RexxString *name, bool classMethod)
RexxClass * install(RexxSource *source, RexxActivation *activation)
void flatten(RexxEnvelope *)
RexxString * idName
void addConstantMethod(RexxString *name, RexxMethod *method)
RexxTable * classMethods
RexxTable * getInstanceMethods()
void addMethod(RexxString *name, RexxMethod *method, bool classMethod)
bool dependenciesResolved()
RexxString * publicName
void checkDependency(RexxString *name, RexxDirectory *class_directives)
RexxTable * getClassMethods()
RexxDirectory * dependencies
void addDependencies(RexxDirectory *class_directives)
RexxTable * instanceMethods
void liveGeneral(int reason)
void setCurrent(RexxInstruction *v)
RexxObject * defineMethods(RexxTable *)
Definition: ClassClass.cpp:695
RexxClass * mixinclass(RexxString *, RexxClass *, RexxTable *)
RexxClass * subclass(RexxString *, RexxClass *, RexxTable *)
RexxObject * setEntry(RexxString *, RexxObject *)
RexxObject * entry(RexxString *)
RexxObject * remove(RexxString *)
virtual RexxObject * get(RexxObject *key)
virtual RexxObject * put(RexxObject *, RexxObject *)
RexxInstruction * nextInstruction
RexxObject * append(RexxObject *)
Definition: ListClass.cpp:538
size_t firstIndex()
Definition: ListClass.hpp:84
size_t nextIndex(size_t i)
Definition: ListClass.cpp:804
RexxObject * getValue(size_t i)
Definition: ListClass.cpp:276
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
void addInstalledClass(RexxString *name, RexxClass *classObject, bool publicClass)
RexxClass * findClass(RexxString *)