BlockClass.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.ibm.com/developerworks/oss/CPLv1.0.htm */
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 #include "RexxCore.h"
40 #include "BlockClass.hpp"
41 #include "RexxActivation.hpp"
42 #include "PackageClass.hpp"
43 #include "DirectoryClass.hpp"
44 
45 
46 /******************************************************************************/
47 /* REXX Kernel */
48 /* */
49 /* Primitive Rexx source literal */
50 /* */
51 /******************************************************************************/
52 
53 /*
54 About OrefSet
55 This class is internal, so candidate to OrefSet.
56 But according the doc in ooRexx5 RexxCore.h, it's not needed for the attributes
57 initialized by a constructor. Belt and suspenders, I still decide to use OrefSet.
58 */
59 
60 /**
61  * Allocate a new RexxSourceLiteral object
62  *
63  * @param size The size of the object.
64  *
65  * @return The newly allocated object.
66  */
67 void *RexxSourceLiteral::operator new(size_t size)
68 {
69  /* Get new object */
70  return new_object(size, T_SourceLiteral);
71 }
72 
73 
74 void RexxSourceLiteral::live(size_t liveMark)
75 /******************************************************************************/
76 /* Function: Normal garbage collection live marking */
77 /******************************************************************************/
78 {
79  memory_mark(this->source);
80  memory_mark(this->package);
81  memory_mark(this->kind);
83 }
84 
86 /******************************************************************************/
87 /* Function: Generalized object marking */
88 /******************************************************************************/
89 {
94 }
95 
97 /******************************************************************************/
98 /* Function: Flatten an object */
99 /******************************************************************************/
100 {
102 
103  OrefSet(newThis, newThis->source, OREF_NULL); // this never should be getting flattened, so sever the connection
104  OrefSet(newThis, newThis->package, OREF_NULL); // idem
105  OrefSet(newThis, newThis->kind, OREF_NULL); // idem
106  OrefSet(newThis, newThis->rawExecutable, OREF_NULL); // idem
107 
109 }
110 
111 
113 {
114  ProtectedObject pThis(this);
115  RexxArray *sa = s->makeArrayRexx(NULL); // use default separator \n
116  OrefSet(this, this->source, sa);
117  OrefSet(this, this->package, p);
118  RexxArray *sourceArray = (RexxArray *)sa->copy();
119  ProtectedObject pSourceArray(sourceArray);
120 
121  // clauser = .Clauser~new(sourceArray)
122  // The clauser will have a direct impact on sourceArray :
123  // - The message KIND returns the kind of the source after removing the keyword(s) that declares the kind of the source.
124  // - The message TRANSFORMSOURCE updates directly the sourceArray.
125  RexxObject *clauserClass = TheEnvironment->at(OREF_CLAUSER);
126  RexxObject *clauser = clauserClass->sendMessage(OREF_NEW, (RexxObject *)sourceArray); // must cast sourceArray, otherwise taken as array of arguments
127  ProtectedObject pClauser(clauser);
128 
129  // kind = clauser~kind(remove: .true)
130  RexxObject *arguments[0 + (1*2)]; // 0 positional arg, 1 named arg
131  arguments[0] = OREF_REMOVE; // named arg name
132  arguments[1] = TheTrueObject; // named arg value
133  OrefSet(this, this->kind, (RexxString *)clauser->sendMessage(OREF_KIND, arguments, 0, 1));
134 
135  // clauser~transformSource(clauseBefore, clauseAfter)
136  // Transform the source to accept auto named arguments, and to return implicitely the result of the last evaluated expression
137  RexxString *clauseBefore = new_string("use auto named arg ; options \"NOCOMMANDS\"");
138  ProtectedObject pClauseBefore(clauseBefore);
139  RexxString *clauseAfter = new_string("if var(\"result\") then return result");
140  ProtectedObject pClauseAfter(clauseAfter);
141  clauser->sendMessage(OREF_TRANSFORMSOURCE, clauseBefore, clauseAfter);
142 
143  // rawExecutable = .Clauser~rawExecutable(kind, sourceArray, package)
144  OrefSet(this, this->rawExecutable, clauserClass->sendMessage(OREF_RAWEXECUTABLE, this->kind, sourceArray, this->package));
145  this->closure = (0 == strncmp(this->kind->getStringData(), "cl", 2));
146 }
147 
148 
150  RexxActivation *context, /* current activation context */
151  RexxExpressionStack *stack ) /* evaluation stack */
152 {
153  RexxContext *rexxContext = (RexxContext *)context->getContextObject();
154  RexxObject *value = new RexxBlock(this, rexxContext);
155  stack->push(value); /* place on the evaluation stack */
156  /* trace if necessary */
157  context->traceIntermediate(value, TRACE_PREFIX_LITERAL);
158 
159  // The encoding of a block is equal to the encoding of its definition package
160  PackageClass *package = context->getPackage();
161  ProtectedObject result;
162  // OREF_SETENCODING instead of OREF_ENCODING:
163  // With a single message, force the package's encoding to be stored, if not already done, and retrieve its encoding
164  bool messageUnderstood = package->messageSend(OREF_SETENCODING, OREF_NULL, 0, 0, result, false);
165  if (messageUnderstood && (RexxObject *)result != OREF_NULL) // the package has an encoding
166  {
167  RexxObject *packageEncoding = (RexxObject *)result;
168  RexxObject *args[1];
169  args[0] = packageEncoding; // positional argument
170  messageUnderstood = value->messageSend(OREF_SETENCODING, args, 1, 0, result, false);
171  }
172 
173  return value; /* also return the result */
174 }
175 
176 
177 /******************************************************************************/
178 /* REXX Kernel */
179 /* */
180 /* Primitive Rexx contextual source */
181 /* */
182 /******************************************************************************/
183 
184 RexxClass *RexxBlock::classInstance = OREF_NULL; // singleton class instance
185 
186 /**
187  * Create initial bootstrap objects
188  */
190 {
191  CLASS_CREATE(RexxBlock, "RexxBlock", RexxClass);
192 }
193 
194 
195 /**
196  * Allocate a new RexxBlock object
197  *
198  * @param size The size of the object.
199  *
200  * @return The newly allocated object.
201  */
202 void *RexxBlock::operator new(size_t size)
203 {
204  /* Get new object */
205  return new_object(size, T_RexxBlock);
206 }
207 
208 
209 /**
210  * Constructor for a RexxBlock object.
211  *
212  * @param s The source literal.
213  * @param c The context.
214  */
216 {
217  OrefSet(this, this->sourceLiteral, s);
218  OrefSet(this, this->variables, (RexxDirectory *)TheNilObject);
219 
220  // c->getVariables will create a directory : see RexxVariableDictionary::getAllVariables
221  // So a GC may happen, must protect this.
222  ProtectedObject p(this);
223  if (s->isClosure()) OrefSet(this, this->variables, (RexxDirectory *)c->getVariables());
224 
225  // Normally, next lines are done from RexxBlock::newRexx
226  // But I don't allow to create a new block from Rexx code.
227  // On the other hand, I want to extend the RexxBlock class and initialize some variables,
228  // hence the sendMessage OREF_INIT.
229 
230 #if 0 // To rework... this code is wrong (crash)
231  // override the behaviour in case this is a subclass
232  RexxBehaviour *behaviour = ((RexxClass *)this)->getInstanceBehaviour();
233  if (behaviour != NULL) this->setBehaviour(behaviour);
234  if (((RexxClass *)this)->hasUninitDefined())
235  {
236  this->hasUninit();
237  }
238 #endif
239  this->sendMessage(OREF_INIT);
240 }
241 
242 
243 /**
244  * The Rexx accessible class NEW method. This raises an
245  * error because RexxBlock objects can only be created
246  * by the internal interpreter.
247  *
248  * @param args The NEW args
249  * @param argc The count of positional arguments
250  * @param named_argc The count of named arguments
251  *
252  * @return Never returns.
253  */
254 RexxObject *RexxBlock::newRexx(RexxObject **args, size_t argc, size_t named_argc)
255 {
256  // we do not allow these to be allocated from Rexx code...
258  return TheNilObject;
259 }
260 
261 
262 /**
263  * An override for the copy method to keep RexxBlock
264  * objects from being copied.
265  *
266  * @return Never returns.
267  */
269 {
270  // we do not allow these to be allocated from Rexx code...
272  return TheNilObject;
273 }
274 
275 
276 void RexxBlock::live(size_t liveMark)
277 /******************************************************************************/
278 /* Function: Normal garbage collection live marking */
279 /******************************************************************************/
280 {
281  memory_mark(this->objectVariables);
282  memory_mark(this->sourceLiteral);
283  memory_mark(this->variables);
284 }
285 
286 void RexxBlock::liveGeneral(int reason)
287 /******************************************************************************/
288 /* Function: Generalized object marking */
289 /******************************************************************************/
290 {
291  memory_mark_general(this->objectVariables);
292  memory_mark_general(this->sourceLiteral);
293  memory_mark_general(this->variables);
294 }
295 
297 /******************************************************************************/
298 /* Function: Flatten an object */
299 /******************************************************************************/
300 {
302 
303  flatten_reference(newThis->objectVariables, envelope);
304  OrefSet(newThis, newThis->sourceLiteral, OREF_NULL); // this never should be getting flattened, so sever the connection
305  OrefSet(newThis, newThis->variables, OREF_NULL); // idem
306 
308 }
void reportException(wholenumber_t error)
@ T_SourceLiteral
@ T_RexxBlock
@ TRACE_PREFIX_LITERAL
#define OREF_NULL
Definition: RexxCore.h:61
#define TheEnvironment
Definition: RexxCore.h:183
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define TheTrueObject
Definition: RexxCore.h:196
#define TheNilObject
Definition: RexxCore.h:191
#define Error_Unsupported_copy_method
#define Error_Unsupported_new_method
#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 CLASS_CREATE(name, id, className)
Definition: RexxMemory.hpp:503
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
#define cleanUpFlatten
Definition: RexxMemory.hpp:484
#define setUpFlatten(type)
Definition: RexxMemory.hpp:478
RexxString * new_string(const char *s, stringsize_t l)
RexxObject * getContextObject()
void traceIntermediate(RexxObject *v, int p)
RexxObject * copy()
Definition: ArrayClass.cpp:122
void flatten(RexxEnvelope *)
Definition: BlockClass.cpp:296
static void createInstance()
Definition: BlockClass.cpp:189
RexxBlock(RexxSourceLiteral *, RexxContext *)
Definition: BlockClass.cpp:215
void liveGeneral(int reason)
Definition: BlockClass.cpp:286
RexxObject * newRexx(RexxObject **args, size_t argc, size_t named_argc)
Definition: BlockClass.cpp:254
static RexxClass * classInstance
Definition: BlockClass.hpp:109
RexxObject * copyRexx()
Definition: BlockClass.cpp:268
void live(size_t)
Definition: BlockClass.cpp:276
RexxObject * getVariables()
void push(RexxObject *value)
void setBehaviour(RexxBehaviour *b)
RexxBehaviour * behaviour
void sendMessage(RexxString *, RexxArray *, RexxDirectory *, ProtectedObject &)
bool messageSend(RexxString *, RexxObject **, size_t, size_t, ProtectedObject &, bool processUnknown=true, bool dynamicTarget=true)
RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
Definition: BlockClass.cpp:149
void flatten(RexxEnvelope *)
Definition: BlockClass.cpp:96
void live(size_t)
Definition: BlockClass.cpp:74
RexxArray * source
Definition: BlockClass.hpp:76
RexxSourceLiteral(RexxString *, PackageClass *, size_t)
Definition: BlockClass.cpp:112
void liveGeneral(int reason)
Definition: BlockClass.cpp:85
PackageClass * package
Definition: BlockClass.hpp:77
RexxObject * rawExecutable
Definition: BlockClass.hpp:79
RexxString * kind
Definition: BlockClass.hpp:78
RexxArray * makeArrayRexx(RexxString *)
const char * getStringData()