aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-04-26 21:08:13 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-04-26 21:08:13 +0300
commit966f97ad7c92f559ae54d0214db90c370e3b48eb (patch)
tree5dfadd4f453cb0076039c70b0574e58dee8ff2a4 /src
parent930e0f29ff5637f38a878d2e61352b151698a0ea (diff)
downloadposthaste-966f97ad7c92f559ae54d0214db90c370e3b48eb.tar.gz
posthaste-966f97ad7c92f559ae54d0214db90c370e3b48eb.zip
add check against proc calls as statements
Diffstat (limited to 'src')
-rw-r--r--src/check.c65
-rw-r--r--src/lower.c9
-rw-r--r--src/parser.y36
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