aboutsummaryrefslogtreecommitdiff
path: root/src/check.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/check.c')
-rw-r--r--src/check.c65
1 files changed, 56 insertions, 9 deletions
diff --git a/src/check.c b/src/check.c
index b4ea2b1..85e5459 100644
--- a/src/check.c
+++ b/src/check.c
@@ -35,6 +35,18 @@ static bool has_type(struct ast *n)
return n->t != 0;
}
+static bool concrete_type(enum type_kind k)
+{
+ switch (k) {
+ case TYPE_VOID:
+ case TYPE_AUTO:
+ return false;
+ default: break;
+ }
+
+ return true;
+}
+
static int analyze(struct state *state, struct scope *scope, struct ast *n);
static int analyze_list(struct state *state, struct scope *scope, struct ast *l)
{
@@ -46,6 +58,25 @@ static int analyze_list(struct state *state, struct scope *scope, struct ast *l)
return 0;
}
+static int analyze_statement_list(struct state *state, struct scope *scope, struct ast *l)
+{
+ foreach_node(n, l) {
+ if (analyze(state, scope, n))
+ return -1;
+
+ if (n->k != AST_PROC_CALL)
+ continue;
+
+ if (n->t != TYPE_VOID) {
+ semantic_error(scope, n,
+ "non-void proc call not allowed as statement");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static struct ast *file_scope_find_analyzed(struct state *state,
struct scope *scope, char *id)
{
@@ -138,7 +169,7 @@ static int analyze_proc_def(struct state *state, struct scope *scope,
if (analyze_list(&proc_state, proc_scope, proc_vars(p)))
return -1;
- if (analyze_list(&proc_state, proc_scope, proc_body(p)))
+ if (analyze_statement_list(&proc_state, proc_scope, proc_body(p)))
return -1;
struct ast *last = ast_last(proc_body(p));
@@ -168,6 +199,12 @@ static int analyze_var_def(struct state *state, struct scope *scope,
if (analyze(state, scope, expr))
return -1;
+ if (!concrete_type(expr->t)) {
+ semantic_error(scope, n, "illegal type in variable definition: %s",
+ type_str(expr->t));
+ return -1;
+ }
+
n->t = expr->t;
return 0;
}
@@ -547,10 +584,22 @@ static int analyze_assign(struct state *state, struct scope *scope,
if (analyze(state, scope, l))
return -1;
+ if (!concrete_type(l->t)) {
+ semantic_error(scope, n, "illegal type for lefthand side: %s",
+ type_str(l->t));
+ return -1;
+ }
+
struct ast *r = assign_r(n);
if (analyze(state, scope, r))
return -1;
+ if (!concrete_type(r->t)) {
+ semantic_error(scope, n, "illegal type for righthand side: %s",
+ type_str(r->t));
+ return -1;
+ }
+
if (l->t != r->t) {
semantic_error(scope, n, "type mismatch: %s vs %s",
type_str(l->t), type_str(r->t));
@@ -667,7 +716,7 @@ static int analyze_until(struct state *state, struct scope *scope,
scope_add_scope(scope, until_scope);
struct ast *body = until_body(n);
- if (analyze_list(state, until_scope, body))
+ if (analyze_statement_list(state, until_scope, body))
return -1;
struct ast *cond = until_cond(n);
@@ -693,7 +742,7 @@ static int analyze_unless(struct state *state, struct scope *scope,
scope_add_scope(scope, otherwise_scope);
struct ast *body = unless_body(n);
- if (analyze_list(state, unless_scope, body))
+ if (analyze_statement_list(state, unless_scope, body))
return -1;
struct ast *cond = unless_cond(n);
@@ -707,7 +756,7 @@ static int analyze_unless(struct state *state, struct scope *scope,
}
struct ast *otherwise = unless_otherwise(n);
- if (otherwise && analyze_list(state, otherwise_scope, otherwise))
+ if (otherwise && analyze_statement_list(state, otherwise_scope, otherwise))
return -1;
n->t = TYPE_VOID;
@@ -824,11 +873,9 @@ int check(struct scope *scope, struct ast *root)
}
/* actually analyze all nodes */
- foreach_node(n, root) {
- struct state state = {0};
- if (analyze(&state, scope, n))
- return -1;
- }
+ struct state state = {0};
+ if (analyze_statement_list(&state, scope, root))
+ return -1;
#ifdef DEBUG
foreach_node(n, root) {