ExpressionMessage.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 Translator */
40 /* */
41 /* Primitive Message Instruction Parse Class */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "StringClass.hpp"
47 #include "QueueClass.hpp"
48 #include "RexxActivation.hpp"
49 #include "ExpressionMessage.hpp"
50 #include "Token.hpp"
51 #include "SourceFile.hpp"
52 #include "ProtectedObject.hpp"
53 
55  RexxObject *_target, /* message send target */
56  RexxString *name, /* message name */
57  RexxObject *_super, /* message super class */
58  size_t argCount, /* count of positional arguments */
59  RexxQueue *arglist, /* message positional argument list */
60  size_t namedArgCount, /* count of named arguments */
61  RexxQueue *namedArglist, /* message named argument list */
62  bool double_form) /* type of message send */
63 /******************************************************************************/
64 /* Function: Create a new message expression object */
65 /******************************************************************************/
66 {
67  /* also make sure name is cleared */
68  /* name doubles as hash so ClearObjec*/
69  this->messageName = OREF_NULL; /* doesn't clear hash field. */
70 
71  OrefSet(this, this->target, _target); /* fill in the target */
72  /* the message name */
73  OrefSet(this, this->messageName, name->upper());
74  OrefSet(this, this->super, _super); /* the super class target */
75  doubleTilde = double_form; // set the argument form
76 
77  /* get the count of positional arguments */
78  this->argumentCount = argCount;
79  while (argCount > 0) /* now copy the argument pointers */
80  {
81  /* in reverse order */
82  OrefSet(this, this->arguments[--argCount], arglist->pop());
83  }
84 
85  // The named arguments are stored after the positional argument
86  // Each named argument has 2 entries : name, expression
87  // named_argument_count = the number of named arguments
88  this->namedArgumentCount = namedArgCount;
89  while (namedArgCount > 0) /* now copy the argument pointers */
90  {
91  /* in reverse order */
92  --namedArgCount;
93  OrefSet(this, this->arguments[this->argumentCount + (2 * namedArgCount) + 1], namedArglist->pop()); // expression
94  OrefSet(this, this->arguments[this->argumentCount + (2 * namedArgCount) + 0], namedArglist->pop()); // name
95  }
96 }
97 
99  RexxActivation *context, /* current activation context */
100  RexxExpressionStack *stack ) /* evaluation stack */
101 /******************************************************************************/
102 /* Function: Evaluate a message send in an expression */
103 /******************************************************************************/
104 {
105  ProtectedObject result; /* message expression result */
106  RexxObject *_super; /* target super class */
107  size_t argcount; /* count of positional arguments */
108  size_t namedArgcount; /* count of named arguments */
109  RexxObject *_target; /* message target */
110  size_t i; /* loop counter */
111 
112  /* evaluate the target */
113  _target = this->target->evaluate(context, stack);
114  if (this->super != OREF_NULL) /* have a message lookup override? */
115  {
116 #if 0
117  if (_target != context->getReceiver()) /* sender and receiver different? */
118  {
119  /* this is an error */
121  }
122 #endif
123  /* get the variable value */
124  _super = this->super->evaluate(context, stack);
125  stack->toss(); /* pop the top item */
126  }
127  else
128  {
129  _super = OREF_NULL; /* use the default lookup */
130  }
131 
132  // Positional arguments
133  argcount = this->argumentCount; /* get the argument count */
134  /* loop through the argument list */
135  for (i = 0; i < (size_t)argcount; i++)
136  {
137  /* real argument? */
138  if (this->arguments[i] != OREF_NULL)
139  {
140  /* evaluate the expression */
141  RexxObject *resultArg = this->arguments[i]->evaluate(context, stack);
142  /* trace if necessary */
143  context->traceIntermediate(resultArg, TRACE_PREFIX_ARGUMENT);
144  }
145  else
146  {
147  stack->push(OREF_NULL); /* push an non-existent argument */
148  /* trace if necessary */
149  context->traceIntermediate(OREF_NULLSTRING, TRACE_PREFIX_ARGUMENT);
150  }
151  }
152 
153  // Named arguments
154  namedArgcount = this->namedArgumentCount;
155  for (i = argcount; i < argcount + (2 * namedArgcount); i+=2)
156  {
157  // Argument name: string literal
158  RexxObject *name = this->arguments[i];
159  stack->push(name); // a string
161 
162  // Argument expression
163  RexxObject *argResult = this->arguments[i+1]->evaluate(context, stack);
164  context->traceIntermediate(argResult, TRACE_PREFIX_ARGUMENT);
165  }
166 
167  if (_super == OREF_NULL) /* no super class override? */
168  {
169  /* issue the fast message */
170  stack->send(this->messageName, argcount, namedArgcount, result);
171  }
172  else
173  {
174  /* evaluate the message w/override */
175  stack->send(this->messageName, _super, argcount, namedArgcount, result);
176  }
177  stack->popn(argcount + (2 * namedArgcount)); /* remove any arguments */
178 
179  if (this->doubleTilde) /* double twiddle form? */
180  {
181  result = _target; /* get the target element */
182  }
183  else
184  {
185  stack->prefixResult(result); /* replace top element on stack */
186  }
187 
188  if ((RexxObject *)result == OREF_NULL) /* in an expression and need a result*/
189  {
190  /* need to raise an exception */
192  }
193  /* trace if necessary */
194  context->traceMessage(messageName, (RexxObject *)result);
195  return(RexxObject *)result; /* return the result */
196 }
197 
198 void RexxExpressionMessage::live(size_t liveMark)
199 /******************************************************************************/
200 /* Function: Normal garbage collection live marking */
201 /******************************************************************************/
202 {
203  size_t i; /* loop counter */
204  size_t count; /* argument count */
205 
206  memory_mark(this->messageName);
207  memory_mark(this->target);
208  memory_mark(this->super);
209  for (i = 0, count = this->argumentCount + (2 * this->namedArgumentCount); i < count; i++)
210  {
211  memory_mark(this->arguments[i]);
212  }
213 }
214 
216 /******************************************************************************/
217 /* Function: Generalized object marking */
218 /******************************************************************************/
219 {
220  size_t i; /* loop counter */
221  size_t count; /* argument count */
222 
225  memory_mark_general(this->super);
226  for (i = 0, count = this->argumentCount + (2 * this->namedArgumentCount); i < count; i++)
227  {
228  memory_mark_general(this->arguments[i]);
229  }
230 }
231 
233 /******************************************************************************/
234 /* Function: Flatten an object */
235 /******************************************************************************/
236 {
237  size_t i; /* loop counter */
238  size_t count; /* argument count */
239 
241 
242  flatten_reference(newThis->messageName, envelope);
243  flatten_reference(newThis->target, envelope);
244  flatten_reference(newThis->super, envelope);
245  for (i = 0, count = this->argumentCount + (2 * this->namedArgumentCount); i < count; i++)
246  {
247  flatten_reference(newThis->arguments[i], envelope);
248  }
249 
251 }
252 
253 void *RexxExpressionMessage::operator new(size_t size,
254  size_t argCount) /* count of arguments */
255 /******************************************************************************/
256 /* Function: Create a new translator object */
257 /******************************************************************************/
258 {
259  /* Get new object */
260  return new_object(size + (argCount - 1) * sizeof(RexxObject *), T_MessageSendTerm);
261 }
262 
264  RexxActivation *context, /* current activation context */
265  RexxExpressionStack *stack, /* current evaluation stack */
266  RexxObject *value ) /* new value to assign */
267 /******************************************************************************/
268 /* Function: Emulate a variable assignment using a method */
269 /******************************************************************************/
270 {
271  // evaluate the target
272  RexxObject *_target = this->target->evaluate(context, stack);
273  RexxObject *_super = OREF_NULL;
274  // message override?
275  if (this->super != OREF_NULL)
276  {
277  // in this context, the value needs to be SELF
278  if (_target != context->getReceiver())
279  {
281  }
282  // evaluate the superclass override
283  _super = this->super->evaluate(context, stack);
284  stack->toss();
285  }
286  // push the assignment value on to the stack as the argument
287  stack->push(value);
288  // now push the rest of the arguments. This might be something like a[1,2,3,4] as
289  // an assignment term. The assignment value is the first argument, followed by
290  // any other arguments that are part of the encoded message term.
291  size_t argcount = (size_t)this->argumentCount;
292 
293  for (size_t i = 0; i < argcount; i++)
294  {
295  // non-omitted argument?
296  if (this->arguments[i] != OREF_NULL)
297  {
298  // evaluate and potentiall trace
299  RexxObject *resultArg = this->arguments[i]->evaluate(context, stack);
300  context->traceResult(resultArg);
301  }
302  else
303  {
304  // non existant arg....we may still need to trace that
305  stack->push(OREF_NULL);
306  context->traceResult(OREF_NULLSTRING);
307  }
308  }
309 
310  // Named arguments
311  size_t namedArgcount = this->namedArgumentCount;
312  for (size_t i = argcount; i < argcount + (2 * namedArgcount); i+=2)
313  {
314  // Argument name: string literal
315  RexxObject *name = this->arguments[i];
316  stack->push(name); // a string
318 
319  // Argument expression
320  RexxObject *argResult = this->arguments[i+1]->evaluate(context, stack);
321  context->traceIntermediate(argResult, TRACE_PREFIX_ARGUMENT);
322  }
323 
324  ProtectedObject result;
325 
326  // now send the message the appropriate way
327  if (_super == OREF_NULL)
328  {
329  // normal message send
330  stack->send(this->messageName, argcount + 1, namedArgcount, result);
331  }
332  else
333  {
334  // send with an override
335  stack->send(this->messageName, _super, argcount + 1, namedArgcount, result);
336  }
337  /* trace if necessary */
338  context->traceAssignment(messageName, (RexxObject *)result);
339  // remove all arguments (arguments + target + assignment value)
340  // and all named arguments
341  stack->popn((argcount + 2) + ((2 * namedArgcount)));
342 }
343 
344 
345 
346 /**
347  * Convert a message into an assignment message by adding "="
348  * to the end of the message name.
349  *
350  * @param source The current source context.
351  */
353 {
354  // add an equal sign to the name
355  messageName = source->commonString(messageName->concat(OREF_EQUAL));
356 }
357 
void reportException(wholenumber_t error)
@ T_MessageSendTerm
@ TRACE_PREFIX_NAMED_ARGUMENT
@ TRACE_PREFIX_ARGUMENT
#define OREF_NULL
Definition: RexxCore.h:61
#define OrefSet(o, r, v)
Definition: RexxCore.h:101
#define Error_Execution_super
#define Error_No_result_object_message
#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
void traceAssignment(RexxString *n, RexxObject *v, bool quoteValue=true)
virtual RexxObject * getReceiver()
void traceResult(RexxObject *v)
void traceMessage(RexxString *n, RexxObject *v)
void traceIntermediate(RexxObject *v, int p)
void liveGeneral(int reason)
RexxExpressionMessage(RexxObject *, RexxString *, RexxObject *, size_t, RexxQueue *, size_t, RexxQueue *, bool)
RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
void makeAssignment(RexxSource *source)
void assign(RexxActivation *, RexxExpressionStack *, RexxObject *)
void flatten(RexxEnvelope *)
void push(RexxObject *value)
void prefixResult(RexxObject *value)
void send(RexxString *message, RexxObject *scope, size_t count, size_t namedCount, ProtectedObject &result)
virtual RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
RexxObject * pop()
Definition: QueueClass.hpp:80
RexxString * commonString(RexxString *)
RexxString * concat(RexxString *)
RexxString * upper()