diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-04-26 21:08:13 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-04-26 21:08:13 +0300 |
commit | 966f97ad7c92f559ae54d0214db90c370e3b48eb (patch) | |
tree | 5dfadd4f453cb0076039c70b0574e58dee8ff2a4 /src | |
parent | 930e0f29ff5637f38a878d2e61352b151698a0ea (diff) | |
download | posthaste-966f97ad7c92f559ae54d0214db90c370e3b48eb.tar.gz posthaste-966f97ad7c92f559ae54d0214db90c370e3b48eb.zip |
add check against proc calls as statements
Diffstat (limited to 'src')
-rw-r--r-- | src/check.c | 65 | ||||
-rw-r--r-- | src/lower.c | 9 | ||||
-rw-r--r-- | src/parser.y | 36 |
3 files changed, 61 insertions, 49 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) { diff --git a/src/lower.c b/src/lower.c index 7c5fdbd..1949bd5 100644 --- a/src/lower.c +++ b/src/lower.c @@ -299,11 +299,11 @@ static void lower_proc_call(struct fn *f, struct ast *c) output_insn(f, CALL, null_loc(), null_loc(), null_loc(), loc_as_int(def->l)); + f->sp -= count; + c->l = build_local_loc(f->sp); if (c->t != TYPE_VOID) output_insn(f, RETVAL, c->l, null_loc(), null_loc(), 0); - - f->sp -= count; } static void lower_func_call(struct fn *f, struct ast *c) @@ -322,11 +322,12 @@ static void lower_func_call(struct fn *f, struct ast *c) struct ast *def = file_scope_find(c->scope, func_call_id(c)); output_insn(f, CALL, null_loc(), null_loc(), null_loc(), loc_as_int(def->l)); + + f->sp -= count; + c->l = build_local_loc(f->sp); if (c->t != TYPE_VOID) output_insn(f, RETVAL, c->l, null_loc(), null_loc(), 0); - - f->sp -= count; } static void lower_eq(struct fn *f, struct ast *n) diff --git a/src/parser.y b/src/parser.y index 7aacd39..d053cce 100644 --- a/src/parser.y +++ b/src/parser.y @@ -9,42 +9,6 @@ #include <posthaste/date.h> #include <posthaste/ast.h> -#define FOREACH_TOKEN(M) \ - M(LPAREN) \ - M(RPAREN) \ - M(LSQUARE) \ - M(RSQUARE) \ - M(LCURLY) \ - M(RCURLY) \ - M(APOSTROPHE) \ - M(AMPERSAND) \ - M(COMMA) \ - M(DOT) \ - M(EQ) \ - M(LT) \ - M(PLUS) \ - M(MINUS) \ - M(MULT) \ - M(DIV) \ - M(VAR) \ - M(IS) \ - M(UNLESS) \ - M(OTHERWISE) \ - M(UNTIL) \ - M(DO) \ - M(DONE) \ - M(PROCEDURE) \ - M(FUNCTION) \ - M(RETURN) \ - M(PRINT) \ - M(END) \ - M(STRING) \ - M(DATE_LITERAL) \ - M(INT_LITERAL) \ - M(IDENT) \ - M(FUNC_IDENT) \ - M(PROC_IDENT) - %} %locations |