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 
111 /**
112  * Check for a label match on a block instruction.
113  *
114  * @param name The target block name.
115  *
116  * @return True if this is a name match, false otherwise.
117  */
119 {
120  return label == name;
121 }
122 
123 /**
124  * Get the label for this block instruction.
125  *
126  * @return The label for the loop. Returns OREF_NULL if there is no label.
127  */
129 {
130  return label;
131 }
132 
133 /**
134  * Tests to see if this is a loop instruction.
135  *
136  * @return True if this is a repetitive loop, false otherwise.
137  */
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  ProtectedObject p_result;
465  RexxObject *_initial; /* initial variable value */
466  RexxObject *object; /* original result object (for error)*/
467  ProtectedObject p_object;
468  wholenumber_t count; /* for count */
469 
470  /* evaluate the initial expression */
471  _initial = this->initial->evaluate(context, stack);
472  /* force rounding */
473  _initial = callOperatorMethod(_initial, OPERATOR_PLUS, OREF_NULL);
474  /* process each of the expressions */
475  for (i = 0; i < 3 && this->expressions[i] != 0; i++)
476  {
477  switch (this->expressions[i]) /* process various keywords */
478  {
479 
480  case EXP_TO: /* TO expression */
481  { /* get the expression value */
482  result = this->to->evaluate(context, stack);
483  p_result = result;
484  /* force rounding */
485  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
486  p_result = result;
487  /* if the result is a string, see if we can convert this to */
488  /* an integer value. This is very common in loops, and can */
489  /* save us a lot of processing on each loop iteration. */
490  RexxObject *temp = result->integerValue(number_digits());
491  if (temp != TheNilObject)
492  {
493  result = temp;
494  }
495  doblock->setTo(result); /* save the new value */
496  break;
497  }
498 
499  case EXP_BY: /* BY expression */
500  /* get the expression value */
501  result = this->by->evaluate(context, stack);
502  p_result = result;
503  /* force rounding */
504  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
505  doblock->setBy(result); /* save the new value */
506  /* if the BY is negative */
508  {
509  /* comparison is for less than */
510  /* the termination value */
511  doblock->setCompare(OPERATOR_LESSTHAN);
512  }
513  else
514  {
515  /* comparison is for greater than */
516  /* the termination value */
518  }
519  break;
520 
521  case EXP_FOR: /* FOR expression */
522  /* get the expression value */
523  result = this->forcount->evaluate(context, stack);
524  p_result = result;
525  object = result; /* save for error reporting */
526  p_object = object;
527  /* an integer value already, and */
528  /* we're dealing with a "normal */
529  /* NUMERIC DIGITS setting */
530  if (isOfClass(Integer, result) && context->digits() >= Numerics::DEFAULT_DIGITS)
531  {
532  /* get the value directly */
533  count = ((RexxInteger *)result)->getValue();
534  context->traceResult(result);/* trace if necessary */
535  }
536  else
537  {
538  /* get this as a number string, */
539  /* which should force string */
540  /* conversion also */
541  result = REQUEST_STRING(result);
542  p_result = result;
543  /* force rounding */
544  result = callOperatorMethod(result, OPERATOR_PLUS, OREF_NULL);
545  p_result = result;
546  context->traceResult(result);/* trace if necessary */
547  /* convert the value */
548  if (!result->requestNumber(count, number_digits()))
549  {
550  /* report an exception */
552  }
553  }
554  /* bad value, too small or too big? */
555  if (count < 0)
556  {
557  /* report an exception */
559  }
560  doblock->setFor(count); /* save the new value */
561  break;
562  }
563  }
564  if (this->by == OREF_NULL) /* no BY expression? */
565  {
566  doblock->setBy(IntegerOne); /* use an increment of 1 */
567  /* comparison is for greater than */
568  /* the termination value */
570  }
571  /* do the initial assignment */
572  this->control->assign(context, stack, _initial);
573 }
574 
576  RexxActivation *context, /* current activation context */
577  RexxExpressionStack *stack, /* evaluation stack */
578  RexxDoBlock *doblock ) /* stacked DO execution block */
579 /******************************************************************************/
580 /* Function: Process an iterationn of an OVER loop */
581 /******************************************************************************/
582 {
583  size_t over_position; /* position of DO_OVER iteration */
584  RexxArray *over_array; /* DO OVER value array */
585  RexxObject *result; /* process the result */
586  over_position = doblock->getFor(); /* get the current position */
587  /* get the value array */
588  over_array = (RexxArray *)doblock->getTo();
589  /* reached the end? */
590  if (over_array->size() < over_position)
591  {
592  return false; // time to get out of here.
593  }
594  /* get the next element */
595  result = over_array->get(over_position);
596  if (result == OREF_NULL) /* empty for some reason? */
597  {
598  result = TheNilObject; /* use .nil instead */
599  }
600  /* do the initial assignment */
601  this->control->assign(context, stack, result);
602  context->traceResult(result); /* trace if necessary */
603  doblock->setFor(over_position + 1);/* set position for next time */
604  return true;
605 }
606 
607 
609  RexxActivation *context, /* current activation context */
610  RexxExpressionStack *stack, /* evaluation stack */
611  RexxDoBlock *doblock, /* stacked DO execution block */
612  bool increment ) /* increment control variable test */
613 /******************************************************************************/
614 /* Function: Step and check the value of a control variable against the */
615 /* terminating value */
616 /******************************************************************************/
617 {
618  RexxObject *result; /* increment result */
619  /* get the control variable value */
620  result = this->control->getValue(context);
621  context->traceResult(result); /* trace if necessary */
622  if (increment)
623  { /* not the first time through? */
624  /* perform the addition */
625  result = callOperatorMethod(result, OPERATOR_PLUS, doblock->getBy());
626  /* increment the control variable */
627  /* value and assign new value */
628  this->control->set(context, result);
629  context->traceResult(result); /* trace if necessary */
630  }
631  if (this->to != OREF_NULL)
632  { /* have a termination condition? */
633  /* do the comparison */
634  if (callOperatorMethod(result, doblock->getCompare(), doblock->getTo()) == TheTrueObject)
635  {
636  return false; // time to stop if this is true
637  }
638  }
639  if (this->forcount != OREF_NULL) /* have a for count to check? */
640  {
641  if (doblock->testFor()) /* hit the end condition? */
642  {
643  return false; // done looping
644  }
645  }
646  return true; // still looping
647 }
648 
649 
651  RexxActivation *context, /* current activation context */
652  RexxExpressionStack *stack, /* evaluation stack */
653  RexxDoBlock *doblock ) /* stacked DO execution block */
654 /******************************************************************************/
655 /* Function: Handle a re-execution of a DO loop (every iteration by the */
656 /* first. */
657 /******************************************************************************/
658 {
659  /* set for the top of the loop */
660  context->setNext(this->nextInstruction);
661  context->traceInstruction(this); /* trace if necessary */
662  context->indent(); /* now indent again */
663 
664  switch (this->type) /* process each DO seperately */
665  {
666 
667  case DO_FOREVER: /* DO FOREVER loop */
668  return; /* nothing to do at all */
669 
670  case DO_OVER: /* DO name OVER collection loop */
671  /* go process the loop */
672  if (this->checkOver(context, stack, doblock))
673  {
674  return; /* finish quickly */
675  }
676  break;
677 
678  case DO_OVER_UNTIL: /* DO name OVER coll. UNTIL cond. */
679  /* go process the loop */
680  /* fail the control check or */
681  /* the UNTIL check? */
682  if (!this->untilCondition(context, stack) && this->checkOver(context, stack, doblock))
683  {
684  return; /* finish quickly */
685  }
686  break;
687 
688  case DO_OVER_WHILE: /* DO name OVER coll. WHILE cond. */
689  /* go process the loop */
690  /* fail the control check or */
691  /* the WHILE check? */
692  if (this->checkOver(context, stack, doblock) && this->whileCondition(context, stack))
693  {
694  return; /* finish quickly */
695  }
696  break;
697 
698  case DO_UNTIL: /* DO UNTIL condition */
699  /* evaluate the condition */
700  if (!this->untilCondition(context, stack))
701  return; /* finish quickly */
702  break;
703 
704  case DO_COUNT: /* DO expr */
705  if (!doblock->testFor()) /* have we reached 0? */
706  {
707  return; /* finish quickly */
708  }
709  break;
710 
711  case DO_COUNT_WHILE: /* DO expr WHILE expr */
712  /* have we reached 0? */
713  if (!doblock->testFor() && this->whileCondition(context, stack))
714  {
715  return; /* finish quickly */
716  }
717  break;
718 
719  case DO_COUNT_UNTIL: /* DO expr UNTIL expr */
720  /* have we reached 0? */
721  if (!this->untilCondition(context, stack) && !doblock->testFor())
722  {
723  return; /* finish quickly */
724  }
725  break;
726 
727  case DO_WHILE: /* DO WHILE condition */
728  /* evaluate the condition */
729  if (this->whileCondition(context, stack))
730  {
731  return; /* finish quickly */
732  }
733  break;
734 
735  case CONTROLLED_DO: /* DO i=expr TO expr BY expr FOR expr*/
736  /* fail the termination check? */
737  if (this->checkControl(context, stack, doblock, true))
738  {
739  return; /* finish quickly */
740  }
741  break;
742 
743  case CONTROLLED_UNTIL: /* DO i=expr ... UNTIL condition */
744  /* fail the control check or */
745  /* the UNTIL check? */
746  if (!this->untilCondition(context, stack) && this->checkControl(context, stack, doblock, true))
747  {
748  return; /* finish quickly */
749  }
750  break;
751 
752  case CONTROLLED_WHILE: /* DO i=expr ... WHILE condition */
753  /* fail the control check or */
754  /* the WHILE check? */
755  if (this->checkControl(context, stack, doblock, true) && this->whileCondition(context, stack))
756  {
757  return; /* finish quickly */
758  }
759  break;
760  }
761  context->popBlock(); /* cause termination cleanup */
762  context->removeBlock(); /* remove the execution nest */
763  /* jump to the loop end */
764  context->setNext(this->end->nextInstruction);
765  context->unindent(); /* step back trace indentation */
766 }
767 
769  RexxActivation *context, /* current activation context */
770  RexxExpressionStack *stack ) /* evaluation stack */
771 /******************************************************************************/
772 /* Function: Evaluate the result of a WHILE or UNTIL condition */
773 /******************************************************************************/
774 {
775  /* get the expression value */
776  RexxObject *result = this->conditional->evaluate(context, stack);
777  context->traceResult(result); /* trace if necessary */
778 
779  /* most comparisons return either true or false directly, so we */
780  /* can optimize this check. UNTIL conditions are more likely to */
781  /* evaluate to false, so we'll check that first */
782  if (result == TheFalseObject)
783  {
784  return false;
785  }
786  else if (result == TheTrueObject)
787  {
788  return true;
789  }
790  /* This is some sort of computed boolean, so we need to do a real */
791  /* validation on this */
792  return result->truthValue(Error_Logical_value_until);
793 }
794 
796  RexxActivation *context, /* current activation context */
797  RexxExpressionStack *stack ) /* evaluation stack */
798 /******************************************************************************/
799 /* Function: Evaluate the result of a WHILE or UNTIL condition */
800 /******************************************************************************/
801 {
802  /* get the expression value */
803  RexxObject *result = this->conditional->evaluate(context, stack);
804  context->traceResult(result); /* trace if necessary */
805 
806  /* most comparisons return either true or false directly, so we */
807  /* can optimize this check. WHILE conditions are more likely to */
808  /* evaluate to true, so we'll check that first */
809  if (result == TheTrueObject)
810  {
811  return true;
812  }
813  else if (result == TheFalseObject)
814  {
815  return false;
816  }
817  /* This is some sort of computed boolean, so we need to do a real */
818  /* validation on this */
819  return result->truthValue(Error_Logical_value_while);
820 }
void reportException(wholenumber_t error)
RexxArray * new_array(size_t s)
Definition: ArrayClass.hpp:259
#define DO_COUNT
#define DO_OVER_WHILE
#define EXP_TO
#define CONTROLLED_UNTIL
#define SIMPLE_DO
#define DO_OVER_UNTIL
#define DO_COUNT_WHILE
#define DO_FOREVER
#define DO_WHILE
#define DO_UNTIL
#define EXP_BY
#define DO_OVER
#define DO_COUNT_UNTIL
#define EXP_FOR
#define CONTROLLED_WHILE
#define CONTROLLED_DO
#define DO_BLOCK
#define LABELED_DO_BLOCK
#define LOOP_BLOCK
RexxInteger * new_integer(wholenumber_t v)
size_t number_digits()
Definition: Numerics.hpp:155
#define OREF_NULL
Definition: RexxCore.h:60
RexxArray * REQUEST_ARRAY(RexxObject *obj)
Definition: RexxCore.h:469
RexxString * REQUEST_STRING(RexxObject *object)
Definition: RexxCore.h:283
#define IntegerOne
Definition: RexxCore.h:190
#define OrefSet(o, r, v)
Definition: RexxCore.h:94
#define TheTrueObject
Definition: RexxCore.h:186
#define isOfClass(t, r)
Definition: RexxCore.h:212
#define TheNilObject
Definition: RexxCore.h:181
#define TheFalseObject
Definition: RexxCore.h:185
RexxObject * callOperatorMethod(RexxObject *object, size_t methodOffset, RexxObject *argument)
Definition: RexxCore.h:533
#define IntegerZero
Definition: RexxCore.h:189
#define Error_Logical_value_while
#define Error_Execution_noarray
#define Error_Unexpected_end_nocontrol
#define Error_Unexpected_end_control
#define Error_Invalid_whole_number_repeat
#define Error_Invalid_whole_number_for
#define Error_Logical_value_until
#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
#define OPERATOR_PLUS
Definition: Token.hpp:110
#define OPERATOR_LESSTHAN
Definition: Token.hpp:124
#define OPERATOR_GREATERTHAN
Definition: Token.hpp:122
static const size_t DEFAULT_DIGITS
Definition: Numerics.hpp:66
int conditionalPauseInstruction()
void newDo(RexxDoBlock *block)
void traceResult(RexxObject *v)
void traceInstruction(RexxInstruction *v)
void terminateBlock(size_t _indent)
void setNext(RexxInstruction *v)
size_t size()
Definition: ArrayClass.hpp:202
RexxArray * makeArray()
RexxObject * get(size_t pos)
Definition: ArrayClass.hpp:203
int getCompare()
Definition: DoBlock.hpp:65
RexxObject * getBy()
Definition: DoBlock.hpp:66
RexxObject * getTo()
Definition: DoBlock.hpp:63
void setFor(wholenumber_t value)
Definition: DoBlock.hpp:71
wholenumber_t getFor()
Definition: DoBlock.hpp:64
void setTo(RexxObject *value)
Definition: DoBlock.hpp:68
void setCompare(int value)
Definition: DoBlock.hpp:70
bool testFor()
Definition: DoBlock.hpp:72
size_t getIndent()
Definition: DoBlock.hpp:73
void setBy(RexxObject *value)
Definition: DoBlock.hpp:69
void flatten(RexxEnvelope *)
bool checkOver(RexxActivation *, RexxExpressionStack *, RexxDoBlock *)
void reExecute(RexxActivation *, RexxExpressionStack *, RexxDoBlock *)
void matchEnd(RexxInstructionEnd *, RexxSource *)
void matchLabel(RexxInstructionEnd *end, RexxSource *source)
RexxVariableBase * control
RexxInstruction * end
void terminate(RexxActivation *, RexxDoBlock *)
bool isLabel(RexxString *name)
RexxString * label
bool whileCondition(RexxActivation *, RexxExpressionStack *)
RexxObject * forcount
void liveGeneral(int reason)
void execute(RexxActivation *, RexxExpressionStack *)
RexxObject * initial
uint8_t expressions[3]
RexxObject * conditional
bool checkControl(RexxActivation *, RexxExpressionStack *, RexxDoBlock *, bool)
bool untilCondition(RexxActivation *, RexxExpressionStack *)
RexxString * getLabel()
void controlSetup(RexxActivation *, RexxExpressionStack *, RexxDoBlock *)
void setStyle(size_t type)
const SourceLocation & getLocation()
RexxInstruction * nextInstruction
virtual RexxObject * evaluate(RexxActivation *, RexxExpressionStack *)
virtual RexxObject * getValue(RexxActivation *)
RexxInteger * integerValue(size_t)
bool requestNumber(wholenumber_t &, size_t)
bool truthValue(int)
void error(int)
virtual void set(RexxActivation *, RexxObject *)
virtual void assign(RexxActivation *, RexxExpressionStack *, RexxObject *)
ssize_t wholenumber_t
Definition: rexx.h:230