#include "symtab.h"

#include <search.h>
#include <string.h>
#include <stdlib.h>

#include "../global.h"
#include "../util/util.h"

enum 
{
    capacityInc = 10
};


typedef struct
{
    char        *name;
    uint16_t    address;
    unsigned      nParams;
    ExprType    *paramType;     /* nParams elements */
    ExprType    returnType;
} FunInfo;

typedef struct
{
    FunInfo *info;
    unsigned nFunctions;
    unsigned capacity;
} FunInfoTab;
   
extern FunInfoTab gs_functions; /* symbol table for functions */
int st_findFun(void const *key, void const *funInfo);


typedef struct
{
    char        *name;
    uint16_t       value;
    ExprType    type;
} VarInfo;

typedef struct
{
    VarInfo *info;
    unsigned nVars;
    unsigned capacity;
} VarTab;

typedef struct
{
    unsigned *index;
    unsigned nVars;
    unsigned capacity;
} VarIndices;
   
typedef struct
{
    VarTab *varTab;             /* points to global [0] or local [1] vars */

    unsigned nParams;             /* the number of parameters of the function 
                                    currently being defined */
    VarIndices *varIndices;     /* level 0 holds indices of global vars */
    unsigned nLevels;             /* at least 1: the global level */
    unsigned capacity;
} VarRef;


extern VarTab *gs_compareTable; /* set by st_findVar for st_compareVars 
                                        to gs_global or gs_local    */

extern VarRef gs_vars;     /* 
                                    OLD:
                                   VarRef objects per nesting level. At
                                    each nesting level a new VarRef is
                                    used allowing access  to the VarInfo
                                    records of variables that are defined at
                                    that level.
                                   At the end of a function gs_level is reset,
                                    and gs_local contains the info of all
                                    variables that are locally defined,
                                    allowing the frame to be constructed
                                */


unsigned st_nextFunIdx(void);      /* idx of an uninitialized record of a 
                                    function */

FunInfo *st_lastFunInfo();      /* ptr to the last FunInfo record */

unsigned       st_nestingOffset(void);

VarIndices  *st_topLevel(void);

VarTab      *st_varTab(unsigned nesting); /* vartab to use, given nestinglevel */

int st_compareVars(void const *key, void const *idxPtr);    /* compare key 
                                                to entry in gs_compareTable */

int         st_findVar(unsigned nesting); /* find util_string() in vars indexed
                                            at gs_vars.indices[nesting].
                                            return idx in VarTab.info or -1 */

VarIndex st_addVar(ExprType type);   /* add variable to the topmost symbol 
                                            table */

unsigned st_nextVarIdx(VarInfo **vi); /* return idx of next variable, and set
                                        a ptr to its record using RBA */

ExprType st_paramType(unsigned idx);  /* returns type of parameter idx */

unsigned *st_newIdxPtr(void);   /* pointer to the next available index[] */

unsigned st_newVarIdx(void);    /* idx of an uninitialized record of a new 
                                        variable */

VarTab *st_varTab(unsigned nesting); /* return the variable table matching the 
                                   currrent nesting level (global or local) */

void st_deleteVars(VarTab *varTab); /* delete all info allocated by VarInfo
                                        objects */

