#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "semantics.h"
#define NEW(type) ((type *)malloc(sizeof(type)))
#ifdef CIBIC_DEBUG
CTable_t ctable_create(Hashfunc_t hfunc, Printfunc_t pfunc) {
CTable_t ct = NEW(CTable);
memset(ct->head, 0, sizeof(CTNode*) * MAX_TABLE_SIZE);
ct->hfunc = hfunc;
ct->pfunc = pfunc;
return ct;
}
#else
CTable_t ctable_create(Hashfunc_t hfunc) {
CTable_t ct = NEW(CTable);
memset(ct->head, 0, sizeof(CTNode*) * MAX_TABLE_SIZE);
ct->hfunc = hfunc;
return ct;
}
#endif
void *ctable_lookup(CTable_t ct, const char *key) {
unsigned int hv = (ct->hfunc(key)) % MAX_TABLE_SIZE;
CTNode *p = ct->head[hv];
for (; p; p = p->next)
if (strcmp(p->key, key))
return p->val;
return NULL; /* not found */
}
void ctable_insert(CTable_t ct, const char *key, void *val, int lvl) {
unsigned int hv = (ct->hfunc(key)) % MAX_TABLE_SIZE;
CTNode *np = NEW(CTNode);
np->key = key;
np->val = val;
np->lvl = lvl;
np->next = ct->head[hv];
ct->head[hv] = np;
}
void ctable_clip(CTable_t ct, unsigned int hv, int max_lvl) {
CTNode *p = ct->head[hv], *np;
for (; p && p->lvl > max_lvl; p = np)
{
np = p->next;
free(p);
}
ct->head[hv] = p;
}
CScope_t cscope_create() {
CScope_t p = NEW(CScope);
p->lvl = -1;
p->top = NULL;
#ifdef CIBIC_DEBUG
p->tvar = ctable_create(bkdr_hash, cvar_print);
p->ttype = ctable_create(bkdr_hash, ctype_print);
#else
p->tvar = ctable_create(bkdr_hash);
p->ttype = ctable_create(bkdr_hash);
#endif
cscope_enter(p);
return p;
}
void cscope_push_var(CScope_t cs, CVar *var) {
#ifdef CIBIC_DEBUG
assert(cs->top);
#endif
var->next = cs->top->vhead;
cs->top->vhead = var;
ctable_insert(cs->tvar, var->name, var, cs->lvl);
}
void cscope_push_type(CScope_t cs, CType *type) {
#ifdef CIBIC_DEBUG
assert(cs->top);
#endif
type->next = cs->top->thead;
cs->top->thead = type;
ctable_insert(cs->ttype, type->name, type, cs->lvl);
}
void cscope_enter(CScope_t cs) {
CSNode *np = NEW(CSNode);
np->next = cs->top;
np->vhead = NULL;
np->thead = NULL;
cs->top = np;
cs->lvl++;
}
void cscope_exit(CScope_t cs) {
CSNode *lower = cs->top->next;
CVar *vp;
CType *tp;
for (vp = cs->top->vhead; vp; vp = vp->next)
ctable_clip(cs->tvar, bkdr_hash(vp->name), cs->lvl);
for (tp = cs->top->thead; tp; tp = tp->next)
ctable_clip(cs->ttype, bkdr_hash(tp->name), cs->lvl);
free(cs->top);
cs->top = lower;
cs->lvl--;
}
void ctable_debug_print(CTable_t ct) {
int i;
fprintf(stderr, "*** CTable ***\n");
for (i = 0; i < MAX_TABLE_SIZE; i++)
if (ct->head[i])
{
CTNode *p;
fprintf(stderr, "[%04d]", i);
for (p = ct->head[i]; p; p = p->next)
fprintf(stderr, "->[%s:%d]", ct->pfunc(p), p->lvl);
fprintf(stderr, "\n");
}
fprintf(stderr, "*** CTable ***\n");
}
void cscope_debug_print(CScope_t cs) {
int lvl = cs->lvl;
CSNode *p;
fprintf(stderr, "*** CScope ***\n");
for (p = cs->top; p; p = p->next)
{
CVar *vp;
CType *tp;
fprintf(stderr, "Level %d:\n", lvl--);
fprintf(stderr, "Vars: ");
for (vp = p->vhead; vp; vp = vp->next)
fprintf(stderr, "%s ", vp->name);
fprintf(stderr, "\nTypes: ");
for (tp = p->thead; tp; tp = tp->next)
fprintf(stderr, "%s ", tp->name);
fprintf(stderr, "\n\n");
}
fprintf(stderr, "Var Table:\n");
ctable_debug_print(cs->tvar);
fprintf(stderr, "Type Table:\n");
ctable_debug_print(cs->ttype);
fprintf(stderr, "*** CScope ***\n");
}
CVar *cscope_lookup_var(CScope_t cs, const char *name) {
return ctable_lookup(cs->tvar, name);
}
CType *cscope_lookup_type(CScope_t cs, const char *name) {
return ctable_lookup(cs->ttype, name);
}
unsigned int bkdr_hash(const char *str) {
unsigned int seed = 131;
unsigned int hv = 0;
while (*str)
hv = hv * seed + (unsigned)(*str++);
return hv % 5;
}
const char *cvar_print(void *var) {
static char buff[MAX_DEBUG_PRINT_BUFF];
sprintf(buff, "%s", ((CVar *)var)->name);
return buff;
}
const char *ctype_print(void *type) {
static char buff[MAX_DEBUG_PRINT_BUFF];
sprintf(buff, "%s", ((CType *)type)->name);
return buff;
}
CVar_t cvar_create(const char *name, CType *type) {
CVar *cv = NEW(CVar);
cv->name = name;
cv->type = type;
return cv;
}
CType_t ctype_create(const char *name, int type) {
CType *ct = NEW(CType);
ct->name = name;
ct->type = type;
return ct;
}