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 (isMixinClass())
185  {
186  classObject = subclass->mixinclass(source->getPackage(), idName, metaclass, classMethods);
187  }
188  else
189  {
190  /* doing a subclassing */
191  classObject = subclass->subclass(source->getPackage(), idName, metaclass, classMethods);
192  }
193  /* add the class to the directory */
194  source->addInstalledClass(publicName, classObject, isPublic());
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 
221  // ooRexx5
222  // if we had the abstract keyword specified, mark the class as abstract.
223  if (isAbstract())
224  {
225  classObject->makeAbstract();
226  }
227 
228  // the source needs this at the end so it call call the activate methods
229  return classObject;
230 }
231 
232 
233 /**
234  * Check if a dependency this class has is based off of a
235  * class co-located in the same class package.
236  *
237  * @param name The class name.
238  * @param class_directives
239  * The global local classes list.
240  */
242 {
243  if (name != OREF_NULL)
244  {
245  // if this is in install? */
246  if (class_directives->entry(name) != OREF_NULL)
247  {
248  if (dependencies == OREF_NULL)
249  {
250  OrefSet(this, this->dependencies, new_directory());
251  }
252  /* add to our pending list */
253  dependencies->setEntry(name, name);
254  }
255  }
256 }
257 
258 
259 /**
260  * Check our class dependencies against the locally defined class
261  * list to develop a cross dependency list.
262  *
263  * @param class_directives
264  * The global set of defined classes in this package.
265  */
267 {
268  // now for each of our dependent classes, if this is defined locally, we
269  // an entry to our dependency list to aid the class ordering
270 
271  checkDependency(metaclassName, class_directives);
272  checkDependency(subclassName, class_directives);
273  // process each inherits item the same way
274  if (inheritsClasses != OREF_NULL)
275  {
276  for (size_t i = inheritsClasses->firstIndex(); i != LIST_END; i = inheritsClasses->nextIndex(i))
277  {
278  /* get the next inherits name */
279  RexxString *inheritsName = (RexxString *)inheritsClasses->getValue(i);
280  checkDependency(inheritsName, class_directives);
281  }
282  }
283 }
284 
285 
286 /**
287  * Check if this class has any additional in-package dependencies.
288  *
289  * @return true if all in-package dependencies have been resolved already.
290  */
292 {
293  return dependencies == OREF_NULL;
294 }
295 
296 
297 /**
298  * Remove a class from the dependency list.
299  *
300  * @param name The name of the class that's next in the ordering.
301  */
303 {
304  // if we have a dependency list, remove this name from the
305  // list. If this is our last dependency item, we can junk
306  // the list entirely.
307  if (dependencies != OREF_NULL)
308  {
309  dependencies->remove(name);
310  if (dependencies->items() == 0)
311  {
312  OrefSet(this, this->dependencies, OREF_NULL);
313  }
314  }
315 }
316 
317 
318 /**
319  * Add an inherits class to the class definition.
320  *
321  * @param name The name of the inherited class.
322  */
324 {
325  if (inheritsClasses == OREF_NULL)
326  {
327  OrefSet(this, this->inheritsClasses, new_list());
328  }
329  inheritsClasses->append(name);
330 }
331 
332 
333 /**
334  * Retrieve the class methods directory for this class.
335  *
336  * @return The class methods directory.
337  */
339 {
340  if (classMethods == OREF_NULL)
341  {
342  OrefSet(this, this->classMethods, new_table());
343  }
344  return classMethods;
345 }
346 
347 
348 /**
349  * Retrieve the instance methods directory for this class.
350  *
351  * @return The instance methods directory.
352  */
354 {
355  if (instanceMethods == OREF_NULL)
356  {
357  OrefSet(this, this->instanceMethods, new_table());
358  }
359  return instanceMethods;
360 }
361 
362 
363 /**
364  * Check for a duplicate method defined om this class.
365  *
366  * @param name The method name.
367  * @param classMethod
368  * Indicates whether we are checking for a class or instance method.
369  *
370  * @return true if this is a duplicate of the method type.
371  */
373 {
374  if (classMethod)
375  {
376  return getClassMethods()->get(name) != OREF_NULL;
377  }
378  else
379  {
380  return getInstanceMethods()->get(name) != OREF_NULL;
381  }
382 
383 }
384 
385 
386 /**
387  * Add a method to a class definition.
388  *
389  * @param name The name to add.
390  * @param method The method object that maps to this name.
391  * @param classMethod
392  * Indicates whether this is a new class or instance method.
393  */
394 void ClassDirective::addMethod(RexxString *name, RexxMethod *method, bool classMethod)
395 {
396  if (classMethod)
397  {
398  getClassMethods()->put(method, name);
399  }
400  else
401  {
402  getInstanceMethods()->put(method, name);
403  }
404 }
405 
406 
407 /**
408  * Add a method to a class definition.
409  *
410  * @param name The name to add.
411  * @param method The method object that maps to this name.
412  */
414 {
415  // this gets added as both a class and instance method
416  addMethod(name, method, false);
417  addMethod(name, method, true);
418 }
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:61
#define TheObjectClass
Definition: RexxCore.h:166
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define Error_Execution_nometaclass
#define Error_Execution_noclass
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
RexxObject * new_object(size_t s)
Definition: RexxMemory.hpp:436
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:498
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
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:725
void makeAbstract()
RexxClass * subclass(PackageClass *, RexxString *, RexxClass *, RexxTable *)
RexxClass * mixinclass(PackageClass *, 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)
PackageClass * getPackage()
RexxClass * findClass(RexxString *)