MessageInstruction.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 "RexxActivation.hpp"
49 #include "MessageInstruction.hpp"
50 #include "ExpressionMessage.hpp"
51 #include "ProtectedObject.hpp"
52 
54  RexxExpressionMessage *message) /* templace message to process */
55 /******************************************************************************/
56 /* Function: Initialize a message instruction */
57 /******************************************************************************/
58 {
59  RexxObject **argument_pointer; /* pointer to message args */
60  size_t i; /* loop counter */
61 
62  /* copy the message info */
63  OrefSet(this, this->target, message->target);
64  OrefSet(this, this->super, message->super);
65  /* get the name */
66  OrefSet(this, this->name, message->messageName);
67  /* get the argument count */
68  argumentCount = message->argumentCount;
70  /* and pointer to arguments */
71  argument_pointer = (RexxObject **)message->arguments;
72  /* copy each argument */
73  for (i = 0; i < (argumentCount + (2 * namedArgumentCount)); i++)
74  {
75  /* into the message instruction */
76  OrefSet(this, this->arguments[i], argument_pointer[i]);
77  }
78  if (message->doubleTilde) /* double twiddle form? */
79  {
80  instructionFlags |= message_i_double; /* turn this on */
81  }
82 }
83 
85  RexxExpressionMessage *message, /* templace message to process */
86  RexxObject *expression) /* associated expression */
87 /******************************************************************************/
88 /* Function: Initialize an assignment message instruction */
89 /******************************************************************************/
90 {
91  RexxObject **argument_pointer; /* pointer to message args */
92  size_t i; /* loop counter */
93 
94  /* copy the message info */
95  OrefSet(this, this->target, message->target);
96  OrefSet(this, this->super, message->super);
97  OrefSet(this, this->name, message->messageName); /* get the name */
98  /* get the argument count */
99  argumentCount = message->argumentCount + 1;
101  /* and the argument pointer */
102  argument_pointer = (RexxObject **)message->arguments;
103  /* make the expression the first */
104  OrefSet(this, this->arguments[0], expression);
105  /* copy each argument */
106  for (i = 1; i < (argumentCount + (2 * namedArgumentCount)); i++)
107  {
108  /* into the message instruction */
109  OrefSet(this, this->arguments[i], argument_pointer[i - 1]);
110  }
111  if (message->doubleTilde) /* double twiddle form? */
112  {
113  instructionFlags |= message_i_double; /* turn this on */
114  }
115 }
116 
117 void RexxInstructionMessage::live(size_t liveMark)
118 /******************************************************************************/
119 /* Function: Normal garbage collection live marking */
120 /******************************************************************************/
121 {
122  size_t i; /* loop counter */
123  size_t count; /* argument count */
124 
125  memory_mark(this->nextInstruction); /* must be first one marked */
126  memory_mark(this->name);
127  memory_mark(this->target);
128  memory_mark(this->super);
129  for (i = 0, count = argumentCount + (2 * namedArgumentCount); i < count; i++)
130  {
131  memory_mark(this->arguments[i]);
132  }
133 }
134 
136 /******************************************************************************/
137 /* Function: Generalized object marking */
138 /******************************************************************************/
139 {
140  size_t i; /* loop counter */
141  size_t count; /* argument count */
142 
143  /* must be first one marked */
145  memory_mark_general(this->name);
147  memory_mark_general(this->super);
148  for (i = 0, count = argumentCount + (2 * namedArgumentCount); i < count; i++)
149  {
150  memory_mark_general(this->arguments[i]);
151  }
152 }
153 
155 /******************************************************************************/
156 /* Function: Flatten an object */
157 /******************************************************************************/
158 {
159  size_t i; /* loop counter */
160  size_t count; /* argument count */
161 
163 
164  flatten_reference(newThis->nextInstruction, envelope);
165  flatten_reference(newThis->name, envelope);
166  flatten_reference(newThis->target, envelope);
167  flatten_reference(newThis->super, envelope);
168  for (i = 0, count = argumentCount + (2 * namedArgumentCount); i < count; i++)
169  {
170  flatten_reference(newThis->arguments[i], envelope);
171  }
172 
174 }
175 
177  RexxActivation *context, /* current activation context */
178  RexxExpressionStack *stack ) /* evaluation stack */
179 /****************************************************************************/
180 /* Function: Execute a REXX THEN instruction */
181 /****************************************************************************/
182 {
183  ProtectedObject result; /* message expression result */
184  RexxObject *_super; /* target super class */
185  size_t argcount; /* count of arguments */
186  size_t namedArgcount; /* count of arguments */
187  RexxObject *_target; /* message target */
188  size_t i; /* loop counter */
189 
190  context->traceInstruction(this); /* trace if necessary */
191  /* evaluate the target */
192  _target = this->target->evaluate(context, stack);
193  if (this->super != OREF_NULL) /* have a message lookup override? */
194  {
195 #if 0
196  if (_target != context->getReceiver()) /* sender and receiver different? */
197  {
198  /* this is an error */
200  }
201 #endif
202  /* get the variable value */
203  _super = this->super->evaluate(context, stack);
204  stack->toss(); /* pop the top item */
205  }
206  else
207  {
208  _super = OREF_NULL; /* use the default lookup */
209  }
210 
211  argcount = argumentCount; /* get the argument count */
212  for (i = 0; i < argcount; i++) /* loop through the argument list */
213  {
214  /* real argument? */
215  if (this->arguments[i] != OREF_NULL)
216  {
217  /* evaluate the expression */
218  result = this->arguments[i]->evaluate(context, stack);
219  /* trace if necessary */
220  context->traceIntermediate(result, TRACE_PREFIX_ARGUMENT);
221  }
222  else
223  {
224  stack->push(OREF_NULL); /* push an non-existent argument */
225  /* trace if necessary */
226  context->traceIntermediate(OREF_NULLSTRING, TRACE_PREFIX_ARGUMENT);
227  }
228  }
229 
230  // Named arguments
231  namedArgcount = this->namedArgumentCount;
232  for (i = argcount; i < argcount + (2 * namedArgcount); i+=2)
233  {
234  // Argument name: string literal
235  RexxObject *name = this->arguments[i];
236  stack->push(name); // a string
238 
239  // Argument expression
240  RexxObject *argResult = this->arguments[i+1]->evaluate(context, stack);
241  context->traceIntermediate(argResult, TRACE_PREFIX_ARGUMENT);
242  }
243 
244  if (super == OREF_NULL) /* no super class override? */
245  {
246  /* issue the fast message */
247  stack->send(this->name, argcount, namedArgcount, result);
248  }
249  else
250  {
251  /* evaluate the message w/override */
252  stack->send(this->name, _super, argcount, namedArgcount, result);
253  }
254  stack->popn(argcount + (2 * namedArgcount)); /* remove any arguments */
255  if (instructionFlags&message_i_double) /* double twiddle form? */
256  {
257  result = _target; /* get the target element */
258  }
259  if ((RexxObject *)result != OREF_NULL) /* result returned? */
260  {
261  context->traceResult((RexxObject *)result); /* trace if necessary */
262  /* set the RESULT variable to the */
263  /* message return value */
264  context->setLocalVariable(OREF_RESULT, VARIABLE_RESULT, (RexxObject *)result);
265  }
266  else /* drop the variable RESULT */
267  {
268  context->dropLocalVariable(OREF_RESULT, VARIABLE_RESULT);
269  }
270  context->pauseInstruction(); /* do debug pause if necessary */
271 }
272 
void reportException(wholenumber_t error)
#define message_i_double
@ TRACE_PREFIX_NAMED_ARGUMENT
@ TRACE_PREFIX_ARGUMENT
#define OREF_NULL
Definition: RexxCore.h:60
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define Error_Execution_super
#define VARIABLE_RESULT
#define memory_mark(oref)
Definition: RexxMemory.hpp:445
#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
virtual RexxObject * getReceiver()
void setLocalVariable(RexxString *name, size_t index, RexxObject *value)
void traceResult(RexxObject *v)
void traceInstruction(RexxInstruction *v)
void dropLocalVariable(RexxString *name, size_t index)
void traceIntermediate(RexxObject *v, int p)
void push(RexxObject *value)
void send(RexxString *message, RexxObject *scope, size_t count, size_t namedCount, ProtectedObject &result)
uint16_t instructionFlags
RexxInstruction * nextInstruction
RexxInstructionMessage(RexxExpressionMessage *)
void flatten(RexxEnvelope *)
void execute(RexxActivation *, RexxExpressionStack *)
virtual RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)