ExtensionDirective.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 ExtensionDirective.cpp */
40 /* */
41 /* Primitive Translator Abstract Directive Code */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "ExtensionDirective.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 an ExtensionDirective.
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 ExtensionDirective::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);
81 }
82 
83 
84 /**
85  * The generalized object marking routine.
86  *
87  * @param reason The processing faze we're running the mark on.
88  */
90 {
91  memory_mark_general(this->nextInstruction); // must be first one marked (though normally null)
97 }
98 
99 
100 /**
101  * Flatten the directive instance.
102  *
103  * @param envelope The envelope we're flattening into.
104  */
106 {
108 
109  flatten_reference(newThis->nextInstruction, envelope);
110  flatten_reference(newThis->publicName, envelope);
111  flatten_reference(newThis->idName, envelope);
112  flatten_reference(newThis->inheritsClasses, envelope);
113  flatten_reference(newThis->instanceMethods, envelope);
114  flatten_reference(newThis->classMethods, envelope);
115  // by this time, we should be finished with this, and it should
116  // already be null. Make sure this is the case.
117 
119 }
120 
121 
122 /**
123  * Allocate a new requires directive.
124  *
125  * @param size The size of the object.
126  *
127  * @return The memory for the new object.
128  */
129 void *ExtensionDirective::operator new(size_t size)
130 {
131  return new_object(size, T_ExtensionDirective); /* Get new object */
132 }
133 
134 
135 /**
136  * Do install-time processing of the ::extension directive.
137  *
138  * @param activation The activation we're running under for the install.
139  */
141 {
142  // make this the current line for the error context
143  activation->setCurrent(this);
144 
145  RexxClass *classObject; // the class object we're extending
146 
147  // retrieve the class object to extend
148  classObject = source->findClass(idName);
149  if (classObject == OREF_NULL) /* not found? */
150  {
152  }
153 
154  if (inheritsClasses != OREF_NULL) /* have inherits to process? */
155  {
156  // now handle the multiple inheritance issues
157  for (size_t i = inheritsClasses->firstIndex(); i != LIST_END; i = inheritsClasses->nextIndex(i))
158  {
159  /* get the next inherits name */
160  RexxString *inheritsName = (RexxString *)inheritsClasses->getValue(i);
161  /* go resolve the entry */
162  RexxClass *mixin = source->findClass(inheritsName);
163  if (mixin == OREF_NULL) /* not found? */
164  {
165  /* not found in environment, error! */
167  }
168  /* do the actual inheritance */
169  classObject->sendMessage(OREF_INHERIT, mixin);
170  }
171  }
172 
173  RexxString *methodName;
174 
175  if (instanceMethods != OREF_NULL) /* have instance methods to add? */
176  {
177  /* define them to the class object */
178  for (HashLink i = instanceMethods->first(); (methodName = (RexxString *)instanceMethods->index(i)) != OREF_NULL; i = instanceMethods->next(i))
179  {
180  RexxMethod *method = (RexxMethod *)instanceMethods->value(i);
181  classObject->defineMethod(methodName, method);
182  }
183  }
184 
185  if (classMethods != OREF_NULL) /* have class methods to add? */
186  {
187  /* define them to the class object */
188  for (HashLink i = classMethods->first(); (methodName = (RexxString *)classMethods->index(i)) != OREF_NULL; i = classMethods->next(i))
189  {
190  RexxMethod *method = (RexxMethod *)classMethods->value(i);
191  classObject->defineClassMethod(methodName, method);
192  }
193  }
194 }
195 
196 
197 /**
198  * Add an inherits class to the class definition.
199  *
200  * @param name The name of the inherited class.
201  */
203 {
204  if (inheritsClasses == OREF_NULL)
205  {
206  OrefSet(this, this->inheritsClasses, new_list());
207  }
208  inheritsClasses->append(name);
209 }
210 
211 
212 /**
213  * Retrieve the class methods directory for this class.
214  *
215  * @return The class methods directory.
216  */
218 {
219  if (classMethods == OREF_NULL)
220  {
221  OrefSet(this, this->classMethods, new_table());
222  }
223  return classMethods;
224 }
225 
226 
227 /**
228  * Retrieve the instance methods directory for this class.
229  *
230  * @return The instance methods directory.
231  */
233 {
234  if (instanceMethods == OREF_NULL)
235  {
236  OrefSet(this, this->instanceMethods, new_table());
237  }
238  return instanceMethods;
239 }
240 
241 
242 /**
243  * Check for a duplicate method defined om this class.
244  *
245  * @param name The method name.
246  * @param classMethod
247  * Indicates whether we are checking for a class or instance method.
248  *
249  * @return true if this is a duplicate of the method type.
250  */
252 {
253  if (classMethod)
254  {
255  return getClassMethods()->get(name) != OREF_NULL;
256  }
257  else
258  {
259  return getInstanceMethods()->get(name) != OREF_NULL;
260  }
261 
262 }
263 
264 
265 /**
266  * Add a method to an extension definition.
267  *
268  * @param name The name to add.
269  * @param method The method object that maps to this name.
270  * @param classMethod
271  * Indicates whether this is a new class or instance method.
272  */
273 void ExtensionDirective::addMethod(RexxString *name, RexxMethod *method, bool classMethod)
274 {
275  if (classMethod)
276  {
277  getClassMethods()->put(method, name);
278  }
279  else
280  {
281  getInstanceMethods()->put(method, name);
282  }
283 }
284 
285 
286 /**
287  * Add a method to an extension definition.
288  *
289  * @param name The name to add.
290  * @param method The method object that maps to this name.
291  */
293 {
294  // this gets added as both a class and instance method
295  addMethod(name, method, false);
296  addMethod(name, method, true);
297 }
void reportException(wholenumber_t error)
@ T_ExtensionDirective
#define LIST_END
Definition: ListClass.hpp:60
RexxList * new_list()
Definition: ListClass.hpp:147
#define OREF_NULL
Definition: RexxCore.h:61
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define Error_Execution_noclass
size_t HashLink
#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
void addMethod(RexxString *name, RexxMethod *method, bool classMethod)
void liveGeneral(int reason)
RexxTable * getClassMethods()
ExtensionDirective(RexxString *, RexxString *, RexxClause *)
RexxTable * getInstanceMethods()
bool checkDuplicateMethod(RexxString *name, bool classMethod)
void addConstantMethod(RexxString *name, RexxMethod *method)
void addInherits(RexxString *name)
void flatten(RexxEnvelope *)
void install(RexxSource *source, RexxActivation *activation)
void setCurrent(RexxInstruction *v)
RexxObject * defineMethod(RexxString *, RexxMethod *)
Definition: ClassClass.cpp:653
RexxObject * defineClassMethod(RexxString *method_name, RexxMethod *newMethod)
Definition: ClassClass.cpp:772
RexxObject * value(HashLink pos)
HashLink next(HashLink pos)
virtual RexxObject * get(RexxObject *key)
RexxObject * index(HashLink pos)
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 &)
RexxClass * findClass(RexxString *)