/* floatvector.c - single-precision floating point vectors.
 *  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"


extern __bit               errorThrown;
extern __bit               doit;
extern __xdata floatOrInt  IACC;
extern __xdata floatOrInt  IACCB;
extern uint16_t            DREG;
extern __xdata uint8_t     D[];
extern __xdata SymtabEntry S[];




void runFloatVector(void)
//  FLOATVECTOR <variable>[<expression>];
{
  uint8_t sym;
  
  incPC();
  if (getPByte() != VARIABLE)
  {
    putstring("FLOATVECTOR missing variable\n");
    errorThrown = 1;
    return;
  }
  incPC();
  sym = getPByte();
  //  putstring("FV symbol "); putbyte(sym); terpri();

  incPC();
  if (getPByte() != LSQB)
  {
    putstring("FLOATVECTOR missing [\n");
    errorThrown = 1;
    return;
  }

  incPC();
  parseExpression();
  if (getPByte() != RSQB)
  {
    putstring("BYtEVECTOR missing ]\n");
    errorThrown = 1;
    return;
  }
  incPC();

  // If skipping, then just return, we've finished parsing.
  if (!doit) return;
  
  DREG = popST();
  if (tag() != DESC_INT)
  {
    putstring("FLOATVECTOR size not integer\n");
    errorThrown = 1;
    return;
  }

  // Get the size.
  getIACCB();
  if (IACCB.i < 1 || IACCB.i > 255)
  {
    putstring("FLOATVECTOR [");
    putint32(IACCB.i);
    putstring("] illegal\n");
    errorThrown = 1;
    return;
  }

  // Allocate the storage.
  DREG = dmalloc(1 + 4 * (uint16_t) IACCB.i);
  D[DREG + 3] = (uint8_t) IACCB.i;
  setTag(DESC_FLOATVECTOR);

  // Store it in the symbol table.
  S[sym].addr = DREG;
  //   putstring("FV ["); putbyte(sym); putstring("] "); puthex16(DREG); terpri();
}



void getFloatVector(uint8_t s)
//     Retrieve an element from a FloatVector symbol s. Error check subscript.
//   DREG index of vector allocation.
//   doit already checked, actually executing.
{

  // Loads IACCB.i with subscript value.
  subscriptCheck(s);
  if (errorThrown) return;

  DREG = S[s].addr;
  IACCB.i = 4 * (IACCB.i + 1);
  pushST(newFloatAddr((uint32_t __xdata *) &D[DREG + IACCB.i]));
}


// EOF
