aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--semantics.c163
-rw-r--r--semantics.h7
2 files changed, 138 insertions, 32 deletions
diff --git a/semantics.c b/semantics.c
index b66f93b..2871e9c 100644
--- a/semantics.c
+++ b/semantics.c
@@ -25,6 +25,18 @@ CTable_t ctable_create(Hashfunc_t hfunc) {
return ct;
}
#endif
+void ctable_destory(CTable_t ct) {
+ int i;
+ for (i = 0; i < MAX_TABLE_SIZE; i++)
+ {
+ CTNode *p, *np;
+ for (p = ct->head[i]; p; p = np)
+ {
+ np = p->next;
+ free(p);
+ }
+ }
+}
extern void print_error(char *, char *, int, int, int);
extern char *load_line(int);
@@ -73,6 +85,8 @@ CScope_t cscope_create() {
CScope_t p = NEW(CScope);
p->lvl = -1;
p->top = NULL;
+ 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);
@@ -476,12 +490,17 @@ CVar_t semantics_params(CNode *p, CScope_t scope) {
p = p->chd;
if (p->type == NOP) return NULL; /* void arguments */
CVar_t params = semantics_p_decl(p, scope), tail = params;
- cscope_push_var(scope, params);
+#ifdef CIBIC_DEBUG
+ CTable_t tparams = ctable_create(bkdr_hash, ctable_cvar_print);
+#else
+ CTable_t tparams = ctable_create(bkdr_hash);
+#endif
+ ctable_insert(tparams, params->name, params, 0);
for (p = p->next; p; p = p->next)
{
CVar_t var = semantics_p_decl(p, scope);
if (scope) /* params inside a function definition */
- if (!cscope_push_var(scope, var))
+ if (!ctable_insert(tparams, var->name, var, 0))
{
sprintf(err_buff, "redefinition of parameter '%s'", var->name);
ERROR(var->ast);
@@ -489,6 +508,7 @@ CVar_t semantics_params(CNode *p, CScope_t scope) {
tail->next = var;
tail = var;
}
+ ctable_destory(tparams);
return params;
}
@@ -644,7 +664,7 @@ CVar_t semantics_decl(CNode *p, CScope_t scope) {
}
if (!useful)
{
- /* TODO: useless typename warning */
+ /* useless typename warning */
sprintf(err_buff, "useless declaration");
WARNING(type->ast);
}
@@ -1165,13 +1185,94 @@ ExpType semantics_exp(CNode *p, CScope_t scope) {
return res;
}
+CVar_t semantics_stmt(CNode *p, CScope_t scope);
+
+CVar_t semantics_if(CNode *p, CScope_t scope) {
+ ExpType exp = semantics_exp(p->chd, scope);
+ CNode *body1 = p->chd->next,
+ *body2 = body1->next;
+ CVar_t res;
+ if (!IS_SCALAR(exp.type->type))
+ {
+ sprintf(err_buff, "a scalar is required in 'if' condition");
+ ERROR(p->chd);
+ }
+ cscope_enter(scope);
+ res = semantics_stmt(body1, scope);
+ cscope_exit(scope);
+ if (body2->type != NOP)
+ {
+ cscope_enter(scope);
+ res->next = semantics_stmt(p->chd->next->next, scope);
+ cscope_exit(scope);
+ }
+ return res;
+}
+
+CVar_t semantics_for(CNode *p, CScope_t scope) {
+ ExpType exp = semantics_exp(p->chd->next, scope);
+ semantics_exp(p->chd, scope);
+ semantics_exp(p->chd->next->next, scope);
+ CVar_t res;
+ if (!IS_SCALAR(exp.type->type))
+ {
+ sprintf(err_buff, "a scalar is required in 'for' condition");
+ ERROR(p->chd->next);
+ }
+ cscope_enter(scope);
+ scope->inside_loop++;
+ res = semantics_stmt(p->chd->next->next->next, scope);
+ scope->inside_loop--;
+ cscope_exit(scope);
+ return res;
+}
+
+CVar_t semantics_while(CNode *p, CScope_t scope) {
+ ExpType exp = semantics_exp(p->chd, scope);
+ CVar_t res;
+ if (!IS_SCALAR(exp.type->type))
+ {
+ sprintf(err_buff, "a scalar is required in 'while' condition");
+ ERROR(p->chd);
+ }
+ cscope_enter(scope);
+ scope->inside_loop++;
+ res = semantics_stmt(p->chd->next, scope);
+ scope->inside_loop--;
+ cscope_exit(scope);
+ return res;
+}
+
+CVar_t semantics_check_loop(CNode *p, CScope_t scope, const char *stmt_name) {
+ if (!scope->inside_loop)
+ {
+ sprintf(err_buff, "%s statement not within a loop", stmt_name);
+ ERROR(p->chd);
+ }
+ return NULL;
+}
+CVar_t semantics_return(CNode *p, CScope_t scope) {
+ assert(scope->func);
+ CType_t rt = scope->func->rec.func.ret;
+ if (p->chd->type != NOP)
+ {
+ if (rt->type == CVOID)
+ {
+ sprintf(err_buff, "'return' with a value, in function returning void");
+ WARNING(p->chd);
+ }
+ semantics_exp(p->chd, scope);
+ exp_check_aseq_(rt, p->chd->ext.type, p->chd);
+ }
+ return NULL;
+}
+
CVar_t semantics_comp(CNode *, CScope_t);
CVar_t semantics_stmt(CNode *p, CScope_t scope) {
CHECK_TYPE(p, STMT);
switch (p->rec.subtype)
{
case STMT_EXP:
- /* TODO: expression handle */
semantics_exp(p->chd, scope);
break;
case STMT_COMP:
@@ -1183,29 +1284,17 @@ CVar_t semantics_stmt(CNode *p, CScope_t scope) {
return res;
}
case STMT_IF:
- /* TODO: `if' statement */
- ;
- break;
+ return semantics_if(p, scope);
case STMT_FOR:
- /* TODO: `for' statement */
- ;
- break;
+ return semantics_for(p, scope);
case STMT_WHILE:
- /* TODO: `while' statement */
- ;
- break;
+ return semantics_while(p, scope);
case STMT_CONT:
- /* TODO: `continue' statement */
- ;
- break;
+ return semantics_check_loop(p, scope, "continue");
case STMT_BREAK:
- /* TODO: `break' statement */
- ;
- break;
+ return semantics_check_loop(p, scope, "break");
case STMT_RET:
- /* TODO: `return' statement */
- ;
- break;
+ return semantics_return(p, scope);
default: assert(0);
}
return NULL;
@@ -1244,20 +1333,34 @@ CVar_t semantics_comp(CNode *p, CScope_t scope) {
CVar_t semantics_func(CNode *p, CScope_t scope) {
CHECK_TYPE(p, FUNC_DEF);
- CNode *chd = p->chd->next;
- CType_t func = ctype_create(chd->rec.strval, CFUNC, p), funco;
- CVar_t res = cvar_create(func->name, func, p), old;
+ CVar_t head = semantics_p_declr(p->chd->next, semantics_type_spec(p->chd, scope));
+ CType_t func = ctype_create(head->name, CFUNC, p), funco;
+ CVar_t res = cvar_create(head->name, func, p), old = NULL;
+ CNode *chd = p->chd->next->next;
+
+ func->rec.func.ret = head->type;
+ /* check return type */
+ if (!type_is_complete(head->type))
+ {
+ sprintf(err_buff, "return type is an incomplete type");
+ ERROR(p->chd);
+ }
- chd = chd->next;
- func->rec.func.ret = semantics_type_spec(p->chd, scope); /* check return type */
+ scope->func = func;
cscope_enter(scope); /* enter into function local scope */
func->rec.func.params = semantics_params(chd, scope); /* check params */
+ if (cscope_push_var(scope, res))
+ old = res;
+ {
+ CVar_t p;
+ for (p = func->rec.func.params; p; p = p->next)
+ cscope_push_var(scope, p);
+ }
func->rec.func.local = semantics_comp(chd->next, scope); /* check comp */
func->rec.func.body = chd->next;
cscope_exit(scope); /* exit from local scope */
- if (cscope_push_var(scope, res))
- old = res;
- else
+
+ if (!old)
{
old = cscope_lookup_var(scope, res->name);
funco = old->type;
diff --git a/semantics.h b/semantics.h
index 9136ebb..aed73de 100644
--- a/semantics.h
+++ b/semantics.h
@@ -80,6 +80,7 @@ CTable_t ctable_create(Hashfunc_t hfunc, Printfunc_t pfunc);
#else
CTable_t ctable_create(Hashfunc_t hfunc);
#endif
+void ctable_destroy(CTable_t ct);
void *ctable_lookup(CTable_t ct, const char *key);
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);
@@ -104,9 +105,11 @@ typedef struct CSNode {
typedef struct CScope *CScope_t;
typedef struct CScope {
int lvl;
+ CType_t func;
+ int inside_loop;
struct CSNode *top;
- struct CTable *tvar;
- struct CTable *ttype;
+ CTable_t tvar;
+ CTable_t ttype;
} CScope;
typedef struct ExpType {