aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--const.h4
-rw-r--r--semantics.c180
-rw-r--r--semantics.h47
3 files changed, 129 insertions, 102 deletions
diff --git a/const.h b/const.h
index 80ef83a..ef869c8 100644
--- a/const.h
+++ b/const.h
@@ -18,7 +18,9 @@ enum {
STMT_FOR,
STMT_CONT,
STMT_BREAK,
- STMT_RET
+ STMT_RET,
+ NS_ID,
+ NS_TAG
};
#define MAX_CHDN 1024
diff --git a/semantics.c b/semantics.c
index d2970a3..1ab8376 100644
--- a/semantics.c
+++ b/semantics.c
@@ -68,6 +68,25 @@ static void warning_print(CNode *ast, const char *fmt, ...) {
va_end(args);
}
+const char *csymbol_getname(CSymbol_t sym) {
+ return (sym->kind == CVAR) ?
+ sym->rec.var->name : sym->rec.type->name;
+}
+
+CSymbol_t type2sym(CType_t type) {
+ CSymbol_t p = NEW(CSymbol);
+ p->kind = CTYPE;
+ p->rec.type = type;
+ return p;
+}
+
+CSymbol_t var2sym(CVar_t var) {
+ CSymbol_t p = NEW(CSymbol);
+ p->kind = CVAR;
+ p->rec.var = var;
+ return p;
+}
+
#ifdef CIBIC_DEBUG
CTable_t ctable_create(Hashfunc_t hfunc, Printfunc_t pfunc) {
CTable_t ct = NEW(CTable);
@@ -140,41 +159,27 @@ CScope_t cscope_create() {
p->func = NULL;
p->inside_loop = 0;
#ifdef CIBIC_DEBUG
- p->tvar = ctable_create(bkdr_hash, ctable_cvar_print);
- p->ttype = ctable_create(bkdr_hash, ctable_ctype_print);
+ p->ids = ctable_create(bkdr_hash, csymbol_print);
+ p->tags = ctable_create(bkdr_hash, csymbol_print);
#else
- p->tvar = ctable_create(bkdr_hash);
- p->ttype = ctable_create(bkdr_hash);
+ p->ids = ctable_create(bkdr_hash);
+ p->tags = ctable_create(bkdr_hash);
#endif
cscope_enter(p);
return p;
}
-int cscope_push_var(CScope_t cs, CVar_t var) {
-#ifdef CIBIC_DEBUG
- assert(cs->top);
-#endif
- if (ctable_insert(cs->tvar, var->name, var, cs->lvl))
- {
- CSVar *csvar = NEW(CSVar);
- csvar->var = var;
- csvar->next = cs->top->vhead;
- cs->top->vhead = csvar;
- return 1;
- }
- else return 0; /* naming conflict */
-}
-
-int cscope_push_type(CScope_t cs, CType_t type) {
+int cscope_push(CScope_t cs, CSymbol_t sym, int nspace) {
+ CTable_t ct = nspace == NS_ID ? cs->ids: cs->tags;
#ifdef CIBIC_DEBUG
assert(cs->top);
#endif
- if (ctable_insert(cs->ttype, type->name, type, cs->lvl))
+ if (ctable_insert(ct, csymbol_getname(sym), sym, cs->lvl))
{
- CSType *cstype = NEW(CSType);
- cstype->type = type;
- cstype->next = cs->top->thead;
- cs->top->thead = cstype;
+ CSElem *e = NEW(CSElem);
+ e->sym = sym;
+ e->next = cs->top->symlist;
+ cs->top->symlist = e;
return 1;
}
else return 0; /* naming conflict */
@@ -183,22 +188,22 @@ int cscope_push_type(CScope_t cs, CType_t type) {
void cscope_enter(CScope_t cs) {
CSNode *np = NEW(CSNode);
np->next = cs->top;
- np->vhead = NULL;
- np->thead = NULL;
+ np->symlist = NULL;
cs->top = np;
cs->lvl++;
}
void cscope_exit(CScope_t cs) {
CSNode *top_o = cs->top;
- CSVar *vp;
- CSType *tp;
+ CSElem *p;
cs->lvl--;
cs->top = top_o->next;
- for (vp = top_o->vhead; vp; vp = vp->next)
- ctable_clip(cs->tvar, vp->var->name, cs->lvl);
- for (tp = top_o->thead; tp; tp = tp->next)
- ctable_clip(cs->ttype, tp->type->name, cs->lvl);
+ for (p = top_o->symlist; p; p = p->next)
+ {
+ const char *name = csymbol_getname(p->sym);
+ ctable_clip(cs->ids, name, cs->lvl);
+ ctable_clip(cs->tags, name, cs->lvl);
+ }
free(top_o);
}
@@ -220,33 +225,28 @@ void ctable_debug_print(CTable_t ct) {
void cscope_debug_print(CScope_t cs) {
int lvl = cs->lvl;
CSNode *p;
+ CSElem *tp;
fprintf(stderr, "\n****** CScope ******\n");
for (p = cs->top; p; p = p->next)
{
- CSVar *vp;
- CSType *tp;
fprintf(stderr, "Level %d:\n", lvl--);
- fprintf(stderr, "Vars: ");
- for (vp = p->vhead; vp; vp = vp->next)
- fprintf(stderr, "%s ", vp->var->name);
- fprintf(stderr, "\nTypes: ");
- for (tp = p->thead; tp; tp = tp->next)
- fprintf(stderr, "%s ", tp->type->name);
+ for (tp = p->symlist; tp; tp = tp->next)
+ fprintf(stderr, "%s ", csymbol_print(tp->sym));
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, "IDs:\n");
+ ctable_debug_print(cs->ids);
+ fprintf(stderr, "Tags:\n");
+ ctable_debug_print(cs->tags);
fprintf(stderr, "****** CScope ******\n\n");
}
-CVar_t cscope_lookup_var(CScope_t cs, const char *name) {
- return ctable_lookup(cs->tvar, name);
-}
-
-CType_t cscope_lookup_type(CScope_t cs, const char *name) {
- return ctable_lookup(cs->ttype, name);
+CSymbol_t cscope_lookup(CScope_t cs, const char *name, int nspace) {
+ if (nspace == NS_ID)
+ return ctable_lookup(cs->ids, name);
+ else
+ return ctable_lookup(cs->tags, name);
+ return NULL;
}
unsigned int bkdr_hash(const char *str) {
@@ -257,18 +257,23 @@ unsigned int bkdr_hash(const char *str) {
return hv;
}
-const char *ctable_cvar_print(void *var) {
+const char *csymbol_print(void *csym) {
+ CSymbol_t p = (CSymbol_t)csym;
static char buff[MAX_DEBUG_PRINT_BUFF];
- sprintf(buff, "%s@%lx", ((CVar_t )var)->name, (size_t)var);
+ if (p->kind == CVAR)
+ sprintf(buff, "%s@%lx", p->rec.var->name, (size_t)p->rec.var);
+ else
+ sprintf(buff, "%s@%lx", p->rec.type->name, (size_t)p->rec.type);
return buff;
}
-const char *ctable_ctype_print(void *type) {
+const char *ctable_cvar_print(void *var) {
static char buff[MAX_DEBUG_PRINT_BUFF];
- sprintf(buff, "%s@%lx", ((CType_t )type)->name, (size_t)type);
+ sprintf(buff, "%s@%lx", ((CVar_t )var)->name, (size_t)var);
return buff;
}
+
CVar_t cvar_create(const char *name, CType_t type, CNode *ast) {
CVar_t cv = NEW(CVar);
cv->name = name;
@@ -366,19 +371,21 @@ void ctype_print(CType_t ct) {
static CType_t struct_type_merge(CType_t new, CScope_t scope) {
/* Note: we shall try to lookup first instead of pushing !! */
- CType_t old = cscope_lookup_type(scope, new->name);
- if (!old) /* create it if it does not exist */
+ CSymbol_t lu = cscope_lookup(scope, new->name, NS_TAG);
+ CType_t old;
+ if (!lu) /* create it if it does not exist */
{
- cscope_push_type(scope, new);
+ cscope_push(scope, type2sym(new), NS_TAG);
return new;
} /* otherwise we have it */
+ old = lu->rec.type;
if (old->type != new->type) /* not a struct or union */
ERROR((new->ast, "conflicting types of '%s'", new->name));
/* otherwise it is a struct or union */
if (!new->rec.fields) /* use the old definition */
return old;
/* otherwise there's a completion definition */
- if (cscope_push_type(scope, new)) /* try to push the defintion */
+ if (cscope_push(scope, type2sym(new), NS_TAG)) /* try to push the defintion */
return new;
/* conflict appears */
if (old->rec.fields) /* if the old one is complete */
@@ -448,10 +455,10 @@ int is_same_type(CType_t typea, CType_t typeb) {
static CVar_t var_merge(CVar_t new, CScope_t scope) {
CVar_t old;
- if (cscope_push_var(scope, new))
+ if (cscope_push(scope, var2sym(new), NS_ID))
return new;
else
- old = cscope_lookup_var(scope, new->name);
+ old = cscope_lookup(scope, new->name, NS_ID)->rec.var;
if (!is_same_type(old->type, new->type))
ERROR((new->ast, "conflicting types of '%s'", new->name));
else if (scope->lvl > 0)
@@ -713,7 +720,7 @@ CVar_t semantics_decl(CNode *p, CScope_t scope) {
if ((type->type == CSTRUCT || type->type == CUNION) &&
(*type->name) != '\0')
{
- cscope_push_type(scope, type);
+ cscope_push(scope, type2sym(type), NS_TAG);
useful = 1;
}
if (declr->chd->type != NOP)
@@ -1113,12 +1120,15 @@ ExpType semantics_exp(CNode *p, CScope_t scope) {
switch (p->type)
{
case ID:
- if (!(p->ext.var = cscope_lookup_var(scope, p->rec.strval)))
- ERROR((p, "'%s' undeclared", p->rec.strval));
- res.type = p->ext.var->type;
- res.lval = !(res.type->type == CARR || res.type->type == CFUNC);
- p->ext.is_const = 0;
- FUNC_POINTER_CONV(res.type);
+ {
+ CSymbol_t lu = cscope_lookup(scope, p->rec.strval, NS_ID);
+ if (!lu) ERROR((p, "'%s' undeclared", p->rec.strval));
+ p->ext.var = lu->rec.var;
+ res.type = p->ext.var->type;
+ res.lval = !(res.type->type == CARR || res.type->type == CFUNC);
+ p->ext.is_const = 0;
+ FUNC_POINTER_CONV(res.type);
+ }
break;
case INT:
res.type = basic_type_int;
@@ -1423,11 +1433,11 @@ CVar_t semantics_func(CNode *p, CScope_t scope) {
scope->top = ntop->next;
scope->lvl--;
- if (cscope_push_var(scope, res))
+ if (cscope_push(scope, var2sym(res), NS_ID))
old = res;
if (!old)
{
- old = cscope_lookup_var(scope, res->name);
+ old = cscope_lookup(scope, res->name, NS_ID)->rec.var;
funco = old->type;
if (funco->type != CFUNC)
ERROR((res->ast, "conflicting types of '%s'", res->name));
@@ -1445,7 +1455,7 @@ CVar_t semantics_func(CNode *p, CScope_t scope) {
for (var = func->rec.func.params; var; var = var->next)
{
- cscope_push_var(scope, var);
+ cscope_push(scope, var2sym(var), NS_ID);
if (!type_is_complete(var->type))
ERROR((var->ast, "parameter '%s' has incomplete type", var->name));
}
@@ -1479,12 +1489,12 @@ void semantics_check(CNode *p) {
builtin_malloc = make_builtin_func("malloc", vstar);
}
/* add top-level basic types */
- cscope_push_type(scope, basic_type_int);
- cscope_push_type(scope, basic_type_char);
- cscope_push_type(scope, basic_type_void);
- cscope_push_var(scope, builtin_printf);
- cscope_push_var(scope, builtin_scanf);
- cscope_push_var(scope, builtin_malloc);
+ cscope_push(scope, type2sym(basic_type_int), NS_TAG);
+ cscope_push(scope, type2sym(basic_type_char), NS_TAG);
+ cscope_push(scope, type2sym(basic_type_void), NS_TAG);
+ cscope_push(scope, var2sym(builtin_printf), NS_ID);
+ cscope_push(scope, var2sym(builtin_scanf), NS_ID);
+ cscope_push(scope, var2sym(builtin_malloc), NS_ID);
/* check all definitions and declarations */
for (p = p->chd; p; p = p->next)
{
@@ -1502,15 +1512,23 @@ void semantics_check(CNode *p) {
CTNode *p;
int i;
for (i = 0; i < MAX_TABLE_SIZE; i++)
- for (p = scope->tvar->head[i]; p; p = p->next)
+ for (p = scope->ids->head[i]; p; p = p->next)
{
- cvar_print((CVar_t)p->val);
+ CSymbol_t tp = (CSymbol_t)(p->val);
+ if (tp->kind == CVAR)
+ cvar_print(tp->rec.var);
+ else
+ ctype_print(tp->rec.type);
fprintf(stderr, "\n");
}
for (i = 0; i < MAX_TABLE_SIZE; i++)
- for (p = scope->ttype->head[i]; p; p = p->next)
+ for (p = scope->tags->head[i]; p; p = p->next)
{
- ctype_print((CType_t)p->val);
+ CSymbol_t tp = (CSymbol_t)(p->val);
+ if (tp->kind == CVAR)
+ cvar_print(tp->rec.var);
+ else
+ ctype_print(tp->rec.type);
fprintf(stderr, "\n");
}
}
diff --git a/semantics.h b/semantics.h
index 4c3b892..00c8525 100644
--- a/semantics.h
+++ b/semantics.h
@@ -8,6 +8,8 @@ typedef struct CType CType;
typedef CType *CType_t;
typedef struct CVar CVar;
typedef CVar *CVar_t;
+typedef struct CSymbol CSymbol;
+typedef CSymbol *CSymbol_t;
struct CVar {
const char *name;
@@ -87,22 +89,15 @@ int ctable_insert(CTable_t ct, const char *key, void *val, int lvl);
void ctable_clip(CTable_t ct, const char *key, int max_lvl);
void ctable_debug_print(CTable_t ct);
-typedef struct CSVar CSVar;
-struct CSVar {
- CVar_t var;
- CSVar *next;
-};
-
-typedef struct CSType CSType;
-struct CSType {
- CType_t type;
- CSType *next;
+typedef struct CSElem CSElem;
+struct CSElem {
+ CSymbol_t sym;
+ CSElem *next;
};
typedef struct CSNode CSNode;
struct CSNode {
- CSVar *vhead;
- CSType *thead;
+ CSElem *symlist;
CSNode *next;
};
@@ -113,9 +108,9 @@ struct CScope {
CType_t func;
int inside_loop;
CSNode *top;
- CTable_t tvar;
- CTable_t ttype;
- CTable_t ext_link;
+ CTable_t ids; /* ordinary identifiers */
+ CTable_t tags; /* union & struct tags */
+ CTable_t ext_link; /* external linkage */
};
typedef struct ExpType {
@@ -123,18 +118,30 @@ typedef struct ExpType {
int lval;
} ExpType;
+struct CSymbol {
+ enum {
+ CTYPE,
+ CVAR
+ } kind;
+ union {
+ CType_t type;
+ CVar_t var;
+ } rec;
+};
+const char *csymbol_print(void *csym);
+CSymbol_t type2sym(CType_t type);
+CSymbol_t var2sym(CVar_t var);
+const char *csym_getname(CSymbol_t csym);
+
CScope_t cscope_create();
-CVar_t cscope_lookup_var(CScope_t cs, const char *name);
-CType_t cscope_lookup_type(CScope_t cs, const char *name);
-int cscope_push_var(CScope_t cs, CVar_t var);
-int cscope_push_type(CScope_t cs, CType_t type);
+CSymbol_t cscope_lookup(CScope_t cs, const char *name, int nspace);
+int cscope_push(CScope_t cs, CSymbol_t sym, int nspace);
void cscope_enter(CScope_t cs);
void cscope_exit(CScope_t cs);
void cscope_debug_print(CScope_t cs);
unsigned int bkdr_hash(const char *str);
const char *ctable_cvar_print(void *var);
-const char *ctable_ctype_print(void *type);
void semantics_check(CNode *ast);
#endif