/* while.c - while loop.
 *  Copyright (C) 2022 by Jed Marti
 *   This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see https://www.gnu.org/licenses/.
 */


#include <C8051F380.h>
#include <stdint.h>

#include "lfxmit.h"
#include "serial.h"
#include "storage.h"

// We use the FOR loop table, even if it wastes space.
extern __xdata forValues  FRT[];
extern __xdata uint8_t    FINDEX;
extern __xdata uint16_t   PC;

extern __bit              errorThrown;
extern __bit              doit;
extern __bit              stopBit;

extern uint16_t           DREG;
extern __xdata floatOrInt IACC;



void runWhile(void)
//     Keep evaluating the statement while the expression is integer non-zero.
//       while expression <statement>;
//   We use the FOR loop table so the maximum depth includes FOR's as well. 
{
  incPC();

  // Save the return spot in the FOR table.
  if (FINDEX >= FORDEPTH)
  {
    putstring("WHILE exceeds loop depth\n");
    errorThrown = 1;
    return;
  }
  FRT[FINDEX].restart = PC;
  ++FINDEX;

 loop:
  parseExpression();
  if (errorThrown) return;

  // If we're skipping the loop, then let runStatement do the work.
  if (!doit)
  {
    runStatement();
    return;
  }

  // Check result.
  DREG = popST();
  if (tag() == DESC_INT)
  {
    getIACC();
    if (IACC.f != 0)
    {
      runStatement();
      if (errorThrown || stopBit) return;
      PC = FRT[FINDEX - 1].restart;
      goto loop;
    }

    // We're done, skip over statement but don't execute it.
    doit = 0;
    runStatement();
    doit = 1;

    // Pop loop stack.
    --FINDEX;
    return;
  }
  putstring("WHILE not Int\n");
  errorThrown = 1;
  return;
}



// EOF
