/* storage.h - storage parameters.
 *  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/.
 */

#ifndef storage_h


// Parse/evaluation stack size. 
#define PSTACK 5

// Data storage size for numbers, strings, etc. Largest available must be < 1024.
#define DSIZE 1023
#if (DSIZE > 1023)
  #error DSIZE must be < 1024
#endif

// Program storage size.
#define ISIZE 1650
//#define ISIZE  500

// Symbol table size.
#define SSIZE 16

// For loop depth.
#define FORDEPTH 3



// The storage types - up to 8 allowed.
enum {
      DESC_INT,                      // 32 bit integer
      DESC_FLOAT,                    // 32 bit float
      DESC_STRING,                   // 0 terminated string.
      DESC_SYMBOL,                   // Symbol table entry.
      DESC_BYTEVECTOR,               // Small byte vectors.
      DESC_FLOATVECTOR               // Small float vectors.
};

#define GC_TAG    0x80



// The storage allocation for the free space is 24 bits, next and size. This allows up to
// 1K bytes of storage. The object as stored in various places is always the real world address
// of this value.
//      +--------+--------+--------+
//      |gtttssss|ssssssnn|nnnnnnnn|
//      +--------+--------+--------+
//  g    gc tag.
//  ttt  data type
//  ssssssssss   Size (0 - 1023) includes header.
//  nnnnnnnnnn   Byte offset to next element.


// Symbol table entries.
typedef struct {
  uint16_t  pname;               // Offset into D space.
  uint16_t  addr;                // Offset into D space or 0xFFFF if no value.
} SymtabEntry;


// We have 4 variables and abuse them many different ways.
typedef union {
  float    f;
  int32_t  i;
  struct {
    uint16_t i16a;
    uint16_t i16b;
  } i16;
  struct {
    uint8_t b8a;
    uint8_t b8b;
    uint8_t b8c;
    uint8_t b8d;
  } i8;
} floatOrInt;


// The program types. See the tables in program.c which must have the same order though multiple
// keywords can parse to the same value. We give the hexadecimal values here because that's how
// they show up in the I space dump.
enum {
      ZERO            = 0x00,
      ONE             = 0x01,
      INT32           = 0x02,
      FLOAT           = 0x03,
      STRING          = 0x04,
      TIMES           = 0x05,
      QUOTIENT        = 0x06,
      PLUS            = 0x07,
      DIFFERENCE      = 0x08,
      REMAINDER       = 0x09,
      ASSIGN          = 0x0A,
      LESSP           = 0x0B,
      LEQ             = 0x0C,
      GREATERP        = 0x0D,
      GEQ             = 0x0E,
      EQUAL           = 0x0F,
      NEQ             = 0x10,
      OR              = 0x11,
      AND             = 0x12,
      NOT             = 0x13,
      BOR             = 0x14,
      BAND            = 0x15,
      BNOT            = 0x16,
      LPAREN          = 0x17,
      RPAREN          = 0x18,
      LCBRACKET       = 0x19,
      RCBRACKET       = 0x1A,
      SEMICOLON       = 0x1B,
      COLON           = 0x1C,
      COMMA           = 0x1D,
      LSQB            = 0x1E,
      RSQB            = 0x1F,

      LET             = 0x20,                       
      IF              = 0x21,
      ELSE            = 0x22,
      FOR             = 0x23,
      TO              = 0x24,
      BY              = 0x25,
      SEND            = 0x26,
      PRINT           = 0x27,
      STOP            = 0x28,
      FREQUENCY       = 0x29,
      CHAIN           = 0x2A,
      WHILE           = 0x2B,

      CREATE          = 0x2C,
      OPEN            = 0x2D,
      READ            = 0x2E,
      WRITE           = 0x2F,
      CLOSE           = 0x30,

      DIRECTION       = 0x31,
      DIG0            = 0x32,
      DIG1            = 0x33,
      ANYCHAR         = 0x34,
      RED             = 0x35,
      YELLOW          = 0x36,
      GREEN           = 0x37,
      BLUE            = 0x38,
      IN              = 0x39,
      OUT             = 0x3A,
      PP              = 0x3B,
      OD              = 0x3C,
      A2DC0           = 0x3D,
      A2DC1           = 0x3E,
      RAWTEMP         = 0x3F,
      TEMP            = 0x40,

      PAUSE           = 0x41,
      SLEEP           = 0x42,
      MILLISECONDS    = 0x43,
      SECONDS         = 0x44,
      MINUTES         = 0x45,
      
      DITMS           = 0x46,
      SPACEDITS       = 0x47,

      BYTEVECTOR      = 0x48,
      FLOATVECTOR     = 0x49,

      // Functions.
      ISINT           = 0x4A,
      ISFLOAT         = 0x4B,
      ISSTRING        = 0x4C,
      ISBYTEVECTOR    = 0x4D,
      ISFLOATVECTOR   = 0x4E,
      SQRT            = 0x4F,
      ROUND           = 0x50,
      ABS             = 0x51,
      READCH          = 0x52,
      PUTCH           = 0x53,

      VARIABLE        = 0x54
};


enum {
      returnOK,
      returnStop,
      returnError
};

// FOR loop table.
typedef struct {
  uint16_t limit;                    // Limit value. Must be GC'd
  uint16_t increment;                // Increment value. Must be GC'd
  uint16_t restart;                  // I space offset. Must not be GC'd.
} forValues;


// See dmalloc.c
uint16_t next(void);
uint16_t size(void);
void setNext(uint16_t n);
void setSize(uint16_t s);
uint8_t tag(void);
void setTag(uint8_t t);
void setByte(uint8_t b);
void setIACC(void);
void getIACC(void);
void getIACCB(void);
void setFACC(void);
void getFACC(void);
void getFACCB(void);
void setFloat(uint32_t __xdata *f);
uint8_t getByte(void);
void initDynamic(void);
void gc(void);
uint16_t dmalloc(uint16_t sze);
void dumpRAM(void);

// Symbol table.
uint8_t lookupPName(char *q);
uint8_t createSymbol(void);
uint16_t newSymbol(uint8_t indx);
void initSymtab(void);

// ints.c
uint16_t newInt(int32_t v);
void initInts(void);

// floats.c
uint16_t newFloat(float f);
uint16_t newFloatAddr(uint32_t __xdata *ptr);

#endif


// EOF
