ooRexx  4.2.0-source
About: ooRexx (Open Object Rexx) is a free implementation of Object Rexx. Object Rexx is an enhancement of the classic Rexx interpreter; a full-featured programming language with a human-oriented syntax.
  Fossies Dox: ooRexx-4.2.0-source.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

DoInstruction.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 Do Parse Class */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "StringClass.hpp"
47 #include "ArrayClass.hpp"
48 #include "RexxActivation.hpp"
49 #include "RexxActivity.hpp"
50 #include "DoInstruction.hpp"
51 #include "DoBlock.hpp"
52 #include "EndInstruction.hpp"
53 #include "Token.hpp"
54 #include "SourceFile.hpp"
56 
58  RexxInstructionEnd *_end, /* end to match up */
59  RexxSource *source ) /* parsed source file (for errors) */
60 /******************************************************************************/
61 /* Function: Verify that the name on an END and the END statement match */
62 /******************************************************************************/
63 {
64  RexxString *name = _end->name; /* get then END name */
65  SourceLocation location = _end->getLocation(); /* get location of END instruction */
66 
67  if (name != OREF_NULL) /* was a name given? */
68  {
69  size_t lineNum = this->getLineNumber(); /* Instruction line number */
70  RexxString *myLabel = getLabel();
71  if (myLabel == OREF_NULL) /* name given on non-control form? */
72  {
73  /* have a mismatched end */
74  source->error(Error_Unexpected_end_nocontrol, location, new_array(name, new_integer(lineNum)));
75  }
76  else if (name != getLabel()) /* not the same name? */
77  {
78  source->error(Error_Unexpected_end_control, location, new_array(name, myLabel, new_integer(lineNum)));
79  }
80  }
81 }
82 
84  RexxInstructionEnd *partner, /* partner END instruction for block */
85  RexxSource *source ) /* parsed source file (for errors) */
86 /******************************************************************************/
87 /* Make sure we have a match between and END and a DO */
88 /******************************************************************************/
89 {
90  this->matchLabel(partner, source); /* match up the names */
91  OrefSet(this, this->end, partner); /* match up with the END instruction */
92  if (this->type != SIMPLE_DO) /* not a simple DO form? */
93  {
94  partner->setStyle(LOOP_BLOCK); /* this is a loop form */
95  }
96  else
97  {
98  // for a simple DO, we need to check if this has a label
99  if (getLabel() != OREF_NULL)
100  {
101  partner->setStyle(LABELED_DO_BLOCK);
102  }
103  else
104  {
105  partner->setStyle(DO_BLOCK);
106  }
107  }
108 }
109 
110 
119 {
120  return label == name;
121 }
122 
129 {
130  return label;
131 }
132 
139 {
140  return this->type != SIMPLE_DO;
141 }
142 
143 
144 void RexxInstructionDo::live(size_t liveMark)
145 /******************************************************************************/
146 /* Function: Normal garbage collection live marking */
147 /******************************************************************************/
148 {
149  memory_mark(this->nextInstruction); /* must be first one marked */
150  memory_mark(this->initial);
151  memory_mark(this->to);
152  memory_mark(this->by);
153  memory_mark(this->forcount);
154  memory_mark(this->control);
155  memory_mark(this->label);
156  memory_mark(this->conditional);
157  memory_mark(this->end);
158 }
159 
161 /******************************************************************************/
162 /* Function: Generalized object marking */
163 /******************************************************************************/
164 {
165  /* must be first one marked */
168  memory_mark_general(this->to);
169  memory_mark_general(this->by);
172  memory_mark_general(this->label);
174  memory_mark_general(this->end);
175 }
176 
178 /******************************************************************************/
179 /* Function: Flatten an object */
180 /******************************************************************************/
181 {
183 
184  flatten_reference(newThis->nextInstruction, envelope);
185  flatten_reference(newThis->initial, envelope);
186  flatten_reference(newThis->to, envelope);
187  flatten_reference(newThis->by, envelope);
188  flatten_reference(newThis->forcount, envelope);
189  flatten_reference(newThis->control, envelope);
190  flatten_reference(newThis->label, envelope);
191  flatten_reference(newThis->conditional, envelope);
192  flatten_reference(newThis->end, envelope);
193 
195 }
196 
198  RexxActivation *context, /* current execution context */
199  RexxDoBlock *doblock ) /* active do block */
200 /******************************************************************************/
201 /* Function: Terminate an active do loop */
202 /******************************************************************************/
203 {
204  /* perform cleanup */
205  context->terminateBlock(doblock->getIndent());
206  /* jump to the loop end */
207  context->setNext(this->end->nextInstruction);
208 }
209 
211  RexxActivation *context, /* current activation context */
212  RexxExpressionStack *stack) /* evaluation stack */
213 /******************************************************************************/
214 /* Function: Execute a REXX DO instruction */
215 /******************************************************************************/
216 {
217  RexxDoBlock *doblock = OREF_NULL; /* active DO block */
218  RexxObject *result; /* expression evaluation result */
219  RexxArray *array; /* converted collection object */
220  wholenumber_t count; /* count for repetitive or FOR loops */
221  RexxObject *object; /* result object (for error)*/
222 
223  context->traceInstruction(this); /* trace if necessary */
224  if (this->type != SIMPLE_DO) /* a real loop instruction? */
225  {
226  /* create an active DO block */
227  doblock = new RexxDoBlock (this, context->getIndent());
228  context->newDo(doblock); /* set the new block */
229 
230  switch (this->type) /* process each DO seperately */
231  {
232 
233  case DO_FOREVER: /* DO FOREVER loop */
234  case DO_UNTIL: /* DO UNTIL - no checks first time */
235  break; /* just quit */
236 
237  case DO_OVER: /* DO name OVER collection */
238  case DO_OVER_UNTIL: /* same as DO_OVER on first pass */
239  /* get the collection object */
240  result = this->initial->evaluate(context, stack);
241  doblock->setTo(result); /* Anchor result in doBlock to keep */
242  /* from GC. */
243  context->traceResult(result); /* trace if necessary */
244  if (isOfClass(Array, result)) /* already an array item? */
245  {
246  /* get the non-sparse version */
247  array = ((RexxArray *)result)->makeArray();
248  }
249  else /* some other type of collection */
250  {
251  /* get the array version of this */
252  array = REQUEST_ARRAY(result);
253  /* didn't convert ok? */
254  if (array == TheNilObject || !isOfClass(Array, array) )
255  {
256  /* raise an error */
258  }
259  }
260  doblock->setTo(array); /* save this as the "TO" value */
261  doblock->setFor(1); /* set the initial position */
262  /* go process the loop */
263  if (!this->checkOver(context, stack, doblock))
264  {
265  /* cause termination cleanup */
266  this->terminate(context, doblock);
267  }
268  break;
269 
270  case DO_OVER_WHILE: /* DO name OVER collection WHILE cond*/
271  /* get the collection object */
272  result = this->initial->evaluate(context, stack);
273  /* Anchor result in doBlock to keep */
274  doblock->setTo(result); /* from GC. */
275  context->traceResult(result); /* trace if necessary */
276  if (isOfClass(Array, result)) /* already an array item? */
277  {
278  /* get the non-sparse version */
279  array = ((RexxArray *)result)->makeArray();
280  }
281  else /* some other type of collection */
282  {
283  /* get the array version of this */
284  array = REQUEST_ARRAY(result);
285  /* didn't convert ok? */
286  if (array == TheNilObject || !isOfClass(Array, array) )
287  {
288  /* raise an error */
290  }
291  }
292  doblock->setTo(array); /* save this as the "TO" value */
293  doblock->setFor(1); /* set the initial position */
294  /* go process the loop */
295  if (!this->checkOver(context, stack, doblock) || !this->whileCondition(context, stack))
296  {
297  /* cause termination cleanup */
298  this->terminate(context, doblock);
299  }
300  break;
301 
302  case DO_COUNT: /* DO expr */
303  case DO_COUNT_UNTIL: /* DO expr UNTIL foo */
304  /* get the expression value */
305  result = this->forcount->evaluate(context, stack);
306  object = result; /* save for error reporting */
307  /* an integer value already, and */
308  /* we're dealing with a "normal */
309  /* NUMERIC DIGITS setting */
310  if (isOfClass(Integer, result) && context->digits() >= Numerics::DEFAULT_DIGITS)
311  {
312  /* get the value directly */
313  count = ((RexxInteger *)result)->getValue();
314  context->traceResult(result);/* trace if necessary */
315  }
316  else
317  {
318  /* get this as a number string, */
319  /* which should force string */
320  /* conversion also */
321  result = REQUEST_STRING(result);
322  /* force rounding */
323  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
324  context->traceResult(result);/* trace if necessary */
325  /* convert the value */
326  if (!result->requestNumber(count, number_digits()))
327  {
328  /* report an exception */
330  }
331  }
332  /* bad value, too small or too big? */
333  if (count < 0)
334  {
335  /* report an exception */
337  }
338  doblock->setFor(count); /* save the new value */
339  if (doblock->testFor()) /* is this DO 0? */
340  {
341  /* cause termination cleanup */
342  this->terminate(context, doblock);
343  }
344  break;
345 
346  case DO_COUNT_WHILE: /* DO expr WHILE foo */
347  /* get the expression value */
348  result = this->forcount->evaluate(context, stack);
349  object = result; /* save for error reporting */
350  /* an integer value already, and */
351  /* we're dealing with a "normal */
352  /* NUMERIC DIGITS setting */
353  if (isOfClass(Integer, result) && context->digits() >= Numerics::DEFAULT_DIGITS)
354  {
355  /* get the value directly */
356  count = ((RexxInteger *)result)->getValue();
357  context->traceResult(result);/* trace if necessary */
358  }
359  else
360  {
361  /* get this as a number string, */
362  /* which should force string */
363  /* conversion also */
364  result = REQUEST_STRING(result);
365  /* force rounding */
366  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
367  context->traceResult(result);/* trace if necessary */
368  /* convert the value */
369  if (!result->requestNumber(count, number_digits()))
370  {
371  /* report an exception */
373  }
374  }
375  /* bad value, too small or too big? */
376  if (count < 0)
377  {
378  /* report an exception */
380  }
381  doblock->setFor(count); /* save the new value */
382  /* is this DO 0? */
383  if (doblock->testFor() || !this->whileCondition(context, stack))
384  {
385  /* cause termination cleanup */
386  this->terminate(context, doblock);
387  }
388  break;
389 
390  case DO_WHILE: /* DO WHILE condition */
391  /* evaluate the condition */
392  if (!this->whileCondition(context, stack))
393  {
394  /* cause termination cleanup */
395  this->terminate(context, doblock);
396  }
397  break;
398 
399  case CONTROLLED_DO: /* DO i=expr TO expr BY expr FOR expr*/
400  case CONTROLLED_UNTIL: /* DO i=expr ... UNTIL condition */
401  /* do initial controlled loop setup */
402  this->controlSetup(context, stack, doblock);
403  /* fail the initial check? */
404  if (!this->checkControl(context, stack, doblock, false))
405  {
406  /* cause termination cleanup */
407  this->terminate(context, doblock);
408  }
409  break;
410 
411  case CONTROLLED_WHILE: /* DO i=expr ... WHILE condition */
412  /* do initial controlled loop setup */
413  this->controlSetup(context, stack, doblock);
414  /* fail the initial check or */
415  /* the WHILE check? */
416  if (!this->checkControl(context, stack, doblock, false) || !this->whileCondition(context, stack))
417  {
418  /* cause termination cleanup */
419  this->terminate(context, doblock);
420  }
421  break;
422  }
423  }
424  else /* just a simple do */
425  {
426  if (getLabel() != OREF_NULL)
427  {
428  /* create an active DO block */
429  doblock = new RexxDoBlock (this, context->getIndent());
430  context->newDo(doblock); /* set the new block */
431  }
432  else
433  {
434  context->addBlock(); /* step the nesting level */
435  }
436  }
437  /* do debug pause if necessary */
438  /* have to re-execute? */
439  if (context->conditionalPauseInstruction())
440  {
441  if (doblock != OREF_NULL)
442  {
443  this->terminate(context, doblock); /* cause termination cleanup */
444  }
445  else
446  {
447  context->removeBlock(); /* cause termination cleanup */
448  }
449  context->setNext(this); /* make this the new next instruction*/
450  }
451 }
452 
453 
455  RexxActivation *context, /* current activation context */
456  RexxExpressionStack *stack, /* evaluation stack */
457  RexxDoBlock *doblock ) /* stacked DO execution block */
458 /******************************************************************************/
459 /* Function: Setup for use of a control variable */
460 /******************************************************************************/
461 {
462  size_t i; /* loop control variable */
463  RexxObject *result; /* expression result */
464  RexxObject *_initial; /* initial variable value */
465  RexxObject *object; /* original result object (for error)*/
466  wholenumber_t count; /* for count */
467 
468  /* evaluate the initial expression */
469  _initial = this->initial->evaluate(context, stack);
470  /* force rounding */
471  _initial = callOperatorMethod(_initial, OPERATOR_PLUS, OREF_NULL);
472  /* process each of the expressions */
473  for (i = 0; i < 3 && this->expressions[i] != 0; i++)
474  {
475  switch (this->expressions[i]) /* process various keywords */
476  {
477 
478  case EXP_TO: /* TO expression */
479  { /* get the expression value */
480  result = this->to->evaluate(context, stack);
481  /* force rounding */
482  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
483  /* if the result is a string, see if we can convert this to */
484  /* an integer value. This is very common in loops, and can */
485  /* save us a lot of processing on each loop iteration. */
486  RexxObject *temp = result->integerValue(number_digits());
487  if (temp != TheNilObject)
488  {
489  result = temp;
490  }
491  doblock->setTo(result); /* save the new value */
492  break;
493  }
494 
495  case EXP_BY: /* BY expression */
496  /* get the expression value */
497  result = this->by->evaluate(context, stack);
498  /* force rounding */
499  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
500  doblock->setBy(result); /* save the new value */
501  /* if the BY is negative */
503  {
504  /* comparison is for less than */
505  /* the termination value */
506  doblock->setCompare(OPERATOR_LESSTHAN);
507  }
508  else
509  {
510  /* comparison is for greater than */
511  /* the termination value */
513  }
514  break;
515 
516  case EXP_FOR: /* FOR expression */
517  /* get the expression value */
518  result = this->forcount->evaluate(context, stack);
519  object = result; /* save for error reporting */
520  /* an integer value already, and */
521  /* we're dealing with a "normal */
522  /* NUMERIC DIGITS setting */
523  if (isOfClass(Integer, result) && context->digits() >= Numerics::DEFAULT_DIGITS)
524  {
525  /* get the value directly */
526  count = ((RexxInteger *)result)->getValue();
527  context->traceResult(result);/* trace if necessary */
528  }
529  else
530  {
531  /* get this as a number string, */
532  /* which should force string */
533  /* conversion also */
534  result = REQUEST_STRING(result);
535  /* force rounding */
536  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
537  context->traceResult(result);/* trace if necessary */
538  /* convert the value */
539  if (!result->requestNumber(count, number_digits()))
540  {
541  /* report an exception */
543  }
544  }
545  /* bad value, too small or too big? */
546  if (count < 0)
547  {
548  /* report an exception */
550  }
551  doblock->setFor(count); /* save the new value */
552  break;
553  }
554  }
555  if (this->by == OREF_NULL) /* no BY expression? */
556  {
557  doblock->setBy(IntegerOne); /* use an increment of 1 */
558  /* comparison is for greater than */
559  /* the termination value */
561  }
562  /* do the initial assignment */
563  this->control->assign(context, stack, _initial);
564 }
565 
567  RexxActivation *context, /* current activation context */
568  RexxExpressionStack *stack, /* evaluation stack */
569  RexxDoBlock *doblock ) /* stacked DO execution block */
570 /******************************************************************************/
571 /* Function: Process an iterationn of an OVER loop */
572 /******************************************************************************/
573 {
574  size_t over_position; /* position of DO_OVER iteration */
575  RexxArray *over_array; /* DO OVER value array */
576  RexxObject *result; /* process the result */
577  over_position = doblock->getFor(); /* get the current position */
578  /* get the value array */
579  over_array = (RexxArray *)doblock->getTo();
580  /* reached the end? */
581  if (over_array->size() < over_position)
582  {
583  return false; // time to get out of here.
584  }
585  /* get the next element */
586  result = over_array->get(over_position);
587  if (result == OREF_NULL) /* empty for some reason? */
588  {
589  result = TheNilObject; /* use .nil instead */
590  }
591  /* do the initial assignment */
592  this->control->assign(context, stack, result);
593  context->traceResult(result); /* trace if necessary */
594  doblock->setFor(over_position + 1);/* set position for next time */
595  return true;
596 }
597 
598 
600  RexxActivation *context, /* current activation context */
601  RexxExpressionStack *stack, /* evaluation stack */
602  RexxDoBlock *doblock, /* stacked DO execution block */
603  bool increment ) /* increment control variable test */
604 /******************************************************************************/
605 /* Function: Step and check the value of a control variable against the */
606 /* terminating value */
607 /******************************************************************************/
608 {
609  RexxObject *result; /* increment result */
610  /* get the control variable value */
611  result = this->control->getValue(context);
612  context->traceResult(result); /* trace if necessary */
613  if (increment)
614  { /* not the first time through? */
615  /* perform the addition */
616  result = callOperatorMethod(result, OPERATOR_PLUS, doblock->getBy());
617  /* increment the control variable */
618  /* value and assign new value */
619  this->control->set(context, result);
620  context->traceResult(result); /* trace if necessary */
621  }
622  if (this->to != OREF_NULL)
623  { /* have a termination condition? */
624  /* do the comparison */
625  if (callOperatorMethod(result, doblock->getCompare(), doblock->getTo()) == TheTrueObject)
626  {
627  return false; // time to stop if this is true
628  }
629  }
630  if (this->forcount != OREF_NULL) /* have a for count to check? */
631  {
632  if (doblock->testFor()) /* hit the end condition? */
633  {
634  return false; // done looping
635  }
636  }
637  return true; // still looping
638 }
639 
640 
642  RexxActivation *context, /* current activation context */
643  RexxExpressionStack *stack, /* evaluation stack */
644  RexxDoBlock *doblock ) /* stacked DO execution block */
645 /******************************************************************************/
646 /* Function: Handle a re-execution of a DO loop (every iteration by the */
647 /* first. */
648 /******************************************************************************/
649 {
650  /* set for the top of the loop */
651  context->setNext(this->nextInstruction);
652  context->traceInstruction(this); /* trace if necessary */
653  context->indent(); /* now indent again */
654 
655  switch (this->type) /* process each DO seperately */
656  {
657 
658  case DO_FOREVER: /* DO FOREVER loop */
659  return; /* nothing to do at all */
660 
661  case DO_OVER: /* DO name OVER collection loop */
662  /* go process the loop */
663  if (this->checkOver(context, stack, doblock))
664  {
665  return; /* finish quickly */
666  }
667  break;
668 
669  case DO_OVER_UNTIL: /* DO name OVER coll. UNTIL cond. */
670  /* go process the loop */
671  /* fail the control check or */
672  /* the UNTIL check? */
673  if (!this->untilCondition(context, stack) && this->checkOver(context, stack, doblock))
674  {
675  return; /* finish quickly */
676  }
677  break;
678 
679  case DO_OVER_WHILE: /* DO name OVER coll. WHILE cond. */
680  /* go process the loop */
681  /* fail the control check or */
682  /* the WHILE check? */
683  if (this->checkOver(context, stack, doblock) && this->whileCondition(context, stack))
684  {
685  return; /* finish quickly */
686  }
687  break;
688 
689  case DO_UNTIL: /* DO UNTIL condition */
690  /* evaluate the condition */
691  if (!this->untilCondition(context, stack))
692  return; /* finish quickly */
693  break;
694 
695  case DO_COUNT: /* DO expr */
696  if (!doblock->testFor()) /* have we reached 0? */
697  {
698  return; /* finish quickly */
699  }
700  break;
701 
702  case DO_COUNT_WHILE: /* DO expr WHILE expr */
703  /* have we reached 0? */
704  if (!doblock->testFor() && this->whileCondition(context, stack))
705  {
706  return; /* finish quickly */
707  }
708  break;
709 
710  case DO_COUNT_UNTIL: /* DO expr UNTIL expr */
711  /* have we reached 0? */
712  if (!this->untilCondition(context, stack) && !doblock->testFor())
713  {
714  return; /* finish quickly */
715  }
716  break;
717 
718  case DO_WHILE: /* DO WHILE condition */
719  /* evaluate the condition */
720  if (this->whileCondition(context, stack))
721  {
722  return; /* finish quickly */
723  }
724  break;
725 
726  case CONTROLLED_DO: /* DO i=expr TO expr BY expr FOR expr*/
727  /* fail the termination check? */
728  if (this->checkControl(context, stack, doblock, true))
729  {
730  return; /* finish quickly */
731  }
732  break;
733 
734  case CONTROLLED_UNTIL: /* DO i=expr ... UNTIL condition */
735  /* fail the control check or */
736  /* the UNTIL check? */
737  if (!this->untilCondition(context, stack) && this->checkControl(context, stack, doblock, true))
738  {
739  return; /* finish quickly */
740  }
741  break;
742 
743  case CONTROLLED_WHILE: /* DO i=expr ... WHILE condition */
744  /* fail the control check or */
745  /* the WHILE check? */
746  if (this->checkControl(context, stack, doblock, true) && this->whileCondition(context, stack))
747  {
748  return; /* finish quickly */
749  }
750  break;
751  }
752  context->popBlock(); /* cause termination cleanup */
753  context->removeBlock(); /* remove the execution nest */
754  /* jump to the loop end */
755  context->setNext(this->end->nextInstruction);
756  context->unindent(); /* step back trace indentation */
757 }
758 
760  RexxActivation *context, /* current activation context */
761  RexxExpressionStack *stack ) /* evaluation stack */
762 /******************************************************************************/
763 /* Function: Evaluate the result of a WHILE or UNTIL condition */
764 /******************************************************************************/
765 {
766  /* get the expression value */
767  RexxObject *result = this->conditional->evaluate(context, stack);
768  context->traceResult(result); /* trace if necessary */
769 
770  /* most comparisons return either true or false directly, so we */
771  /* can optimize this check. UNTIL conditions are more likely to */
772  /* evaluate to false, so we'll check that first */
773  if (result == TheFalseObject)
774  {
775  return false;
776  }
777  else if (result == TheTrueObject)
778  {
779  return true;
780  }
781  /* This is some sort of computed boolean, so we need to do a real */
782  /* validation on this */
783  return result->truthValue(Error_Logical_value_until);
784 }
785 
787  RexxActivation *context, /* current activation context */
788  RexxExpressionStack *stack ) /* evaluation stack */
789 /******************************************************************************/
790 /* Function: Evaluate the result of a WHILE or UNTIL condition */
791 /******************************************************************************/
792 {
793  /* get the expression value */
794  RexxObject *result = this->conditional->evaluate(context, stack);
795  context->traceResult(result); /* trace if necessary */
796 
797  /* most comparisons return either true or false directly, so we */
798  /* can optimize this check. WHILE conditions are more likely to */
799  /* evaluate to true, so we'll check that first */
800  if (result == TheTrueObject)
801  {
802  return true;
803  }
804  else if (result == TheFalseObject)
805  {
806  return false;
807  }
808  /* This is some sort of computed boolean, so we need to do a real */
809  /* validation on this */
810  return result->truthValue(Error_Logical_value_while);
811 }
RexxActivation::newDo
void newDo(RexxDoBlock *block)
Definition: RexxActivation.hpp:339
RexxActivation::getIndent
size_t getIndent()
Definition: RexxActivation.hpp:347
RexxDoBlock::setBy
void setBy(RexxObject *value)
Definition: DoBlock.hpp:69
new_array
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:250
RexxExpressionStack
Definition: ExpressionStack.hpp:53
DO_COUNT_UNTIL
#define DO_COUNT_UNTIL
Definition: DoInstruction.hpp:61
RexxArray
Definition: ArrayClass.hpp:100
RexxInternalObject::evaluate
virtual RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
Definition: ObjectClass.hpp:269
RexxInstructionDo::by
RexxObject * by
Definition: DoInstruction.hpp:100
RexxInstruction::getLocation
const SourceLocation & getLocation()
Definition: RexxInstruction.hpp:68
RexxObject::truthValue
bool truthValue(int)
Definition: ObjectClass.cpp:468
TheFalseObject
#define TheFalseObject
Definition: RexxCore.h:184
RexxVariableBase::set
virtual void set(RexxActivation *, RexxObject *)
Definition: ExpressionBaseVariable.hpp:51
RexxInstructionDo::checkOver
bool checkOver(RexxActivation *, RexxExpressionStack *, RexxDoBlock *)
Definition: DoInstruction.cpp:566
DO_COUNT_WHILE
#define DO_COUNT_WHILE
Definition: DoInstruction.hpp:60
new_integer
RexxInteger * new_integer(wholenumber_t v)
Definition: IntegerClass.hpp:198
RexxInstructionDo::matchLabel
void matchLabel(RexxInstructionEnd *end, RexxSource *source)
Definition: DoInstruction.cpp:57
memory_mark_general
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:437
DO_OVER_UNTIL
#define DO_OVER_UNTIL
Definition: DoInstruction.hpp:59
RexxActivation.hpp
OrefSet
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
RexxActivation::terminateBlock
void terminateBlock(size_t _indent)
Definition: RexxActivation.hpp:337
RexxInstructionDo::isLabel
bool isLabel(RexxString *name)
Definition: DoInstruction.cpp:118
EXP_FOR
#define EXP_FOR
Definition: DoInstruction.hpp:65
RexxInstructionDo::live
void live(size_t)
Definition: DoInstruction.cpp:144
RexxDoBlock::getCompare
int getCompare()
Definition: DoBlock.hpp:65
RexxDoBlock::setFor
void setFor(wholenumber_t value)
Definition: DoBlock.hpp:71
RexxInstructionDo::forcount
RexxObject * forcount
Definition: DoInstruction.hpp:105
RexxInstructionDo::to
RexxObject * to
Definition: DoInstruction.hpp:99
RexxInstructionDo::untilCondition
bool untilCondition(RexxActivation *, RexxExpressionStack *)
Definition: DoInstruction.cpp:759
OPERATOR_GREATERTHAN
#define OPERATOR_GREATERTHAN
Definition: Token.hpp:114
RexxInstructionDo::controlSetup
void controlSetup(RexxActivation *, RexxExpressionStack *, RexxDoBlock *)
Definition: DoInstruction.cpp:454
RexxArray::size
size_t size()
Definition: ArrayClass.hpp:200
RexxActivation::traceResult
void traceResult(RexxObject *v)
Definition: RexxActivation.hpp:392
RexxInstructionDo::matchEnd
void matchEnd(RexxInstructionEnd *, RexxSource *)
Definition: DoInstruction.cpp:83
EXP_BY
#define EXP_BY
Definition: DoInstruction.hpp:64
reportException
void reportException(wholenumber_t error)
Definition: ActivityManager.hpp:136
SourceLocation
Definition: SourceLocation.hpp:48
RexxInstructionDo
Definition: DoInstruction.hpp:67
RexxInstructionDo::flatten
void flatten(RexxEnvelope *)
Definition: DoInstruction.cpp:177
RexxInstructionDo::type
uint8_t type
Definition: DoInstruction.hpp:106
DoBlock.hpp
RexxInstructionDo::expressions
uint8_t expressions[3]
Definition: DoInstruction.hpp:107
TheTrueObject
#define TheTrueObject
Definition: RexxCore.h:185
DO_BLOCK
#define DO_BLOCK
Definition: EndInstruction.hpp:49
RexxInstructionDo::execute
void execute(RexxActivation *, RexxExpressionStack *)
Definition: DoInstruction.cpp:210
DO_COUNT
#define DO_COUNT
Definition: DoInstruction.hpp:50
RexxEnvelope
Definition: RexxEnvelope.hpp:53
OPERATOR_PLUS
#define OPERATOR_PLUS
Definition: Token.hpp:102
RexxDoBlock::setCompare
void setCompare(int value)
Definition: DoBlock.hpp:70
IntegerZero
#define IntegerZero
Definition: RexxCore.h:188
RexxArray::get
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:201
REQUEST_ARRAY
RexxArray * REQUEST_ARRAY(RexxObject *obj)
Definition: RexxCore.h:433
CONTROLLED_WHILE
#define CONTROLLED_WHILE
Definition: DoInstruction.hpp:55
RexxInstructionDo::reExecute
void reExecute(RexxActivation *, RexxExpressionStack *, RexxDoBlock *)
Definition: DoInstruction.cpp:641
CONTROLLED_UNTIL
#define CONTROLLED_UNTIL
Definition: DoInstruction.hpp:56
isOfClass
#define isOfClass(t, r)
Definition: RexxCore.h:211
RexxInstructionDo::initial
RexxObject * initial
Definition: DoInstruction.hpp:98
RexxInstructionDo::label
RexxString * label
Definition: DoInstruction.hpp:102
CONTROLLED_DO
#define CONTROLLED_DO
Definition: DoInstruction.hpp:54
RexxObject::integerValue
RexxInteger * integerValue(size_t)
Definition: ObjectClass.cpp:1008
RexxSource
Definition: SourceFile.hpp:131
RexxInstruction::nextInstruction
RexxInstruction * nextInstruction
Definition: RexxInstruction.hpp:85
RexxDoBlock::getIndent
size_t getIndent()
Definition: DoBlock.hpp:73
RexxObject::requestNumber
bool requestNumber(wholenumber_t &, size_t)
Definition: ObjectClass.cpp:1352
RexxActivation::unindent
void unindent()
Definition: RexxActivation.hpp:345
OREF_NULL
#define OREF_NULL
Definition: RexxCore.h:60
OPERATOR_LESSTHAN
#define OPERATOR_LESSTHAN
Definition: Token.hpp:116
ArrayClass.hpp
ExpressionBaseVariable.hpp
RexxInstruction::getLineNumber
size_t getLineNumber()
Definition: RexxInstruction.hpp:79
callOperatorMethod
RexxObject * callOperatorMethod(RexxObject *object, size_t methodOffset, RexxObject *argument)
Definition: RexxCore.h:442
RexxInstructionEnd::setStyle
void setStyle(size_t type)
Definition: EndInstruction.hpp:71
flatten_reference
#define flatten_reference(oref, envel)
Definition: RexxMemory.hpp:440
DoInstruction.hpp
cleanUpFlatten
#define cleanUpFlatten
Definition: RexxMemory.hpp:432
RexxInstructionDo::getLabel
RexxString * getLabel()
Definition: DoInstruction.cpp:128
Error_Unexpected_end_control
#define Error_Unexpected_end_control
Definition: RexxErrorCodes.h:86
StringClass.hpp
RexxActivation::removeBlock
void removeBlock()
Definition: RexxActivation.hpp:340
RexxInstructionEnd::name
RexxString * name
Definition: EndInstruction.hpp:72
RexxVariableBase::assign
virtual void assign(RexxActivation *, RexxExpressionStack *, RexxObject *)
Definition: ExpressionBaseVariable.hpp:53
RexxInstructionDo::control
RexxVariableBase * control
Definition: DoInstruction.hpp:101
DO_OVER_WHILE
#define DO_OVER_WHILE
Definition: DoInstruction.hpp:58
IntegerOne
#define IntegerOne
Definition: RexxCore.h:189
DO_FOREVER
#define DO_FOREVER
Definition: DoInstruction.hpp:51
Numerics::DEFAULT_DIGITS
static const size_t DEFAULT_DIGITS
Definition: Numerics.hpp:66
LABELED_DO_BLOCK
#define LABELED_DO_BLOCK
Definition: EndInstruction.hpp:55
Error_Logical_value_until
#define Error_Logical_value_until
Definition: RexxErrorCodes.h:269
RexxDoBlock::getFor
wholenumber_t getFor()
Definition: DoBlock.hpp:64
memory_mark
#define memory_mark(oref)
Definition: RexxMemory.hpp:436
RexxDoBlock::getBy
RexxObject * getBy()
Definition: DoBlock.hpp:66
Error_Logical_value_while
#define Error_Logical_value_while
Definition: RexxErrorCodes.h:268
RexxArray::makeArray
RexxArray * makeArray()
Definition: ArrayClass.cpp:1443
REQUEST_STRING
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:276
RexxActivation::indent
void indent()
Definition: RexxActivation.hpp:344
RexxActivation
Definition: RexxActivation.hpp:156
Token.hpp
wholenumber_t
ssize_t wholenumber_t
Definition: rexx.h:229
Error_Unexpected_end_nocontrol
#define Error_Unexpected_end_nocontrol
Definition: RexxErrorCodes.h:87
RexxDoBlock::testFor
bool testFor()
Definition: DoBlock.hpp:72
RexxActivation::addBlock
void addBlock()
Definition: RexxActivation.hpp:341
DO_OVER
#define DO_OVER
Definition: DoInstruction.hpp:57
RexxInstructionDo::terminate
void terminate(RexxActivation *, RexxDoBlock *)
Definition: DoInstruction.cpp:197
RexxInternalObject::getValue
virtual RexxObject * getValue(RexxActivation *)
Definition: ObjectClass.hpp:270
RexxActivation::digits
size_t digits()
Definition: RexxActivation.cpp:1913
number_digits
size_t number_digits()
Definition: Numerics.hpp:147
EXP_TO
#define EXP_TO
Definition: DoInstruction.hpp:63
RexxDoBlock::getTo
RexxObject * getTo()
Definition: DoBlock.hpp:63
RexxActivation::traceInstruction
void traceInstruction(RexxInstruction *v)
Definition: RexxActivation.hpp:396
EndInstruction.hpp
setUpFlatten
#define setUpFlatten(type)
Definition: RexxMemory.hpp:427
DO_WHILE
#define DO_WHILE
Definition: DoInstruction.hpp:52
LOOP_BLOCK
#define LOOP_BLOCK
Definition: EndInstruction.hpp:52
TheNilObject
#define TheNilObject
Definition: RexxCore.h:180
RexxInstructionDo::conditional
RexxObject * conditional
Definition: DoInstruction.hpp:103
RexxInstructionDo::whileCondition
bool whileCondition(RexxActivation *, RexxExpressionStack *)
Definition: DoInstruction.cpp:786
RexxInstructionDo::end
RexxInstruction * end
Definition: DoInstruction.hpp:104
RexxActivity.hpp
Error_Invalid_whole_number_repeat
#define Error_Invalid_whole_number_repeat
Definition: RexxErrorCodes.h:222
DO_UNTIL
#define DO_UNTIL
Definition: DoInstruction.hpp:53
Error_Invalid_whole_number_for
#define Error_Invalid_whole_number_for
Definition: RexxErrorCodes.h:223
RexxInstructionDo::checkControl
bool checkControl(RexxActivation *, RexxExpressionStack *, RexxDoBlock *, bool)
Definition: DoInstruction.cpp:599
RexxCore.h
RexxDoBlock::setTo
void setTo(RexxObject *value)
Definition: DoBlock.hpp:68
RexxSource::error
void error(int)
Definition: SourceFile.cpp:5483
Error_Execution_noarray
#define Error_Execution_noarray
Definition: RexxErrorCodes.h:532
RexxInstructionDo::liveGeneral
void liveGeneral(int reason)
Definition: DoInstruction.cpp:160
RexxDoBlock
Definition: DoBlock.hpp:49
RexxInstructionEnd
Definition: EndInstruction.hpp:57
RexxInteger
Definition: IntegerClass.hpp:56
RexxActivation::setNext
void setNext(RexxInstruction *v)
Definition: RexxActivation.hpp:361
RexxActivation::conditionalPauseInstruction
int conditionalPauseInstruction()
Definition: RexxActivation.hpp:402
RexxActivation::popBlock
void popBlock()
Definition: RexxActivation.hpp:335
RexxInstructionDo::isLoop
bool isLoop()
Definition: DoInstruction.cpp:138
SourceFile.hpp
RexxObject
Definition: ObjectClass.hpp:311
SIMPLE_DO
#define SIMPLE_DO
Definition: DoInstruction.hpp:49
RexxString
Definition: StringClass.hpp:119