aboutsummaryrefslogtreecommitdiff
path: root/src/prc1/pr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/prc1/pr.c')
-rw-r--r--src/prc1/pr.c343
1 files changed, 132 insertions, 211 deletions
diff --git a/src/prc1/pr.c b/src/prc1/pr.c
index 3a4221a..1cedd4d 100644
--- a/src/prc1/pr.c
+++ b/src/prc1/pr.c
@@ -6,82 +6,29 @@
#include "parse.h"
#include "stmt.h"
#include "storage.h"
+#include "sym.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-static int prey(const struct lex *l, struct prv *p);
-static int pren(const struct lex *l, struct prv *p);
-static int pryy(const struct lex *l, struct prv *p);
-static int pryn(const struct lex *l, struct prv *p);
-static int prny(const struct lex *l, struct prv *p);
-static int prnn(const struct lex *l, struct prv *p);
+static int etc(const struct lex *, struct prv *);
+static int using(const struct lex *, struct prv *);
+static int s_returning(const struct lex *, struct prv *);
+
+static const struct seq returning =
+ {(struct step[]){{ID, "returning"}, {0}}, .fn = s_returning};
static const struct seq seqs[] =
{
- /* function definition with variadic parameters and return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {ID, "etc",},
- {ID, "returning"},
- {ID},
- {0}
- },
- .fn = prey
- },
-
- /* function definition with variadic parameters and no return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {ID, "etc",},
- {0}
- },
- .fn = pren
- },
-
- /* function definition with parameters and return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {ID, "returning"},
- {ID},
- {0}
- },
- .fn = pryy
- },
-
- /* function definition with parameters, no return variable */
- {
- (struct step[])
- {
- {ID, "using"},
- {ID, NULL, 1},
- {0}
- },
-
- .fn = pryn
- },
-
- /* function definition with no parameters, with return variable */
- {
- (struct step[])
- {
- {ID, "returning"},
- {ID},
- {0}
- },
-
- .fn = prny
- },
+ {(struct step[]){{ID, "using"}, {0}}, .fn = using},
+ returning,
+ {0}
+};
+static const struct seq useqs[] =
+{
+ {(struct step[]){{ID, "etc"}, {0}}, .fn = etc},
+ returning,
{0}
};
@@ -117,7 +64,17 @@ static int param(const struct tk *tk, const struct stentry *e, struct pr *pr)
static int setret(const struct tk *tk, const struct stentry *e, struct pr *pr)
{
- if (!(pr->ret = malloc(sizeof *pr->ret)))
+ const struct tk *prm = findparam(tk->s, pr);
+
+ if (prm)
+ {
+ const struct loc *loc = &prm->loc;
+
+ errloc(tk, "return value \"%s\" already listed as "
+ "parameter at %s:%d:%d", tk->s, loc->f, loc->line, loc->col);
+ return -1;
+ }
+ else if (!(pr->ret = malloc(sizeof *pr->ret)))
{
perror("malloc(3)");
return -1;
@@ -133,196 +90,164 @@ static int finalize(const struct lex *l, struct prv *p)
const struct pr *pr = fn->pr;
struct pos init =
{
- .seq = stmts,
- .stseq = stmts,
- .step = stmts->steps
+ .name = __func__,
+ .seq = stmts
};
- if (p->proto)
+ if (pr->using && !pr->params)
+ {
+ errloc(p->stk, "missing parameters");
+ return -1;
+ }
+ else if (pr->returning && !pr->ret)
+ {
+ errloc(p->stk, "missing return variable");
+ return -1;
+ }
+ else if (p->proto)
{
if (pop(l, p))
return -1;
- fputc('\t', stderr);
+ dbg("\t");
}
else if (push(&init, p))
return -1;
- dbg("\tadding procedure using %zu%s parameters and%s return value\n",
- pr->nparams, pr->variadic ? " variadic" : "", pr->ret ? "" : " no");
+ dbg("\tadd procedure to %s using %zu%s parameters and%s return value\n",
+ fn->tk->s, pr->nparams, pr->variadic ? " variadic" : "",
+ pr->ret ? "" : " no");
p->stk = p->tk;
- return 1;
+ return 0;
}
-static int prret(const struct lex *l, const struct tk *tk, struct prv *p)
+static int check(const struct lex *l, struct prv *p, const struct sym *s,
+ int param, const struct stentry **out)
{
const struct fn *fn = fn_cur(p);
- struct pr *pr = fn->pr;
- const char *s = tk->s;
- const struct storage *lk = fn->lk, *gl = fn->gl;
+ const struct tk *tk = s->tk;
const struct stentry *e, *gle;
- const struct tk *prm;
+ const struct storage *lk = fn->lk, *gl = fn->gl;
- if (!lk || !(e = storage_find(s, lk)))
+ if (s->type != SYM_ID)
{
- errloc(tk, "return value \"%s\" not in %s", s, tk->s);
+ errloc(tk, "expected identifier");
return -1;
}
- else if (gl && (gle = storage_find(s, gl)))
+ else if (!lk || !(e = storage_find(tk->s, lk)))
{
- const struct loc *loc = &gle->tk->loc;
-
- errloc(tk, "return value \"%s\" also in %s at %s:%d:%d", s, gl->name,
- loc->f, loc->line, loc->col);
- return -1;
+ if (param && p->proto)
+ {
+ /* ambiguous syntax: param might be confused
+ * with next custom type. */
+ p->stk = s->tk;
+ return pop(l, p);
+ }
+ else
+ {
+ errloc(tk, "\"%s\" not in linkage section", tk->s);
+ return -1;
+ }
}
- else if ((prm = findparam(s, pr)))
+ else if (gl && (gle = storage_find(tk->s, gl)))
{
- const struct loc *loc = &prm->loc;
+ const struct loc *loc = &gle->tk->loc;
- errloc(tk, "return value \"%s\" already listed as "
- "parameter at %s:%d:%d", tk->s, loc->f, loc->line, loc->col);
+ errloc(tk, "\"%s\" also in %s at %d:%d", s, gl->name,
+ loc->line, loc->col);
return -1;
}
- else if (setret(tk, e, pr))
- return -1;
- return finalize(l, p);
+ *out = e;
+ return 0;
}
-static const struct tk *prparams(const struct lex *l, struct prv *p, int *ret)
+static int usym(const struct lex *l, struct prv *p, const struct sym *s)
{
- const struct tk *tk = p->stk + 1;
+ const struct tk *tk = s->tk;
const struct fn *fn = fn_cur(p);
- struct pr *pr = fn->pr;
-
- if (ret)
- *ret = 0;
+ const struct stentry *e = NULL;
- for (;;)
- {
- const struct storage *lk = fn->lk, *gl = fn->gl;
- const struct stentry *e, *gle;
- const struct tk *prm;
- const char *s;
-
- if (lex_eof(l, tk))
- return tk;
- else if (!strcmp((s = tk->s), "returning") && ret)
- {
- *ret = 1;
- return ++tk;
- }
- else if (!strcmp(s, "etc"))
- {
- if (pr->variadic)
- {
- errloc(tk, "keyword \"etc\" may only appear once as a "
- "parameter");
- return NULL;
- }
-
- pr->variadic = tk++ - p->stk;
- }
- else if (kw(s))
- return tk;
- else if (pr->variadic)
- {
- errloc(tk, "keyword \"etc\" must appear as the last parameter");
- return NULL;
- }
- else if ((prm = findparam(s, pr)))
- {
- const struct loc *loc = &prm->loc;
-
- errloc(tk, "parameter \"%s\" already listed at %d:%d", s,
- loc->line, loc->col);
- return NULL;
- }
- else if (!lk || !(e = storage_find(s, lk)))
- {
- if (p->proto)
- {
- /* ambiguous syntax: param might be confused
- * with next custom type. */
- p->tk = p->stk + pr->nparams + 1;
- return tk;
- }
- else
- {
- errloc(tk, "parameter \"%s\" not in %s", s, tk->s);
- return NULL;
- }
- }
- else if (gl && (gle = storage_find(s, gl)))
- {
- const struct loc *loc = &gle->tk->loc;
-
- errloc(tk, "parameter \"%s\" also in %s at %d:%d", s, gl->name,
- loc->line, loc->col);
- return NULL;
- }
- else if (param(tk, e, pr))
- return NULL;
- else
- tk++;
- }
+ if (check(l, p, s, 1, &e))
+ return -1;
+ else if (e)
+ return param(tk, e, fn->pr);
- return tk;
+ return 0;
}
-static int prey(const struct lex *l, struct prv *p)
+static int etc(const struct lex *l, struct prv *p)
{
- int ret;
- const struct tk *tk = prparams(l, p, &ret);
+ const struct fn *fn = fn_cur(p);
+ struct pr *pr = fn->pr;
- if (!tk)
+ if (pr->variadic)
+ {
+ errloc(p->stk, "procedure for \"%s\" already set as variadic",
+ fn->tk->s);
return -1;
- else if (ret)
- return prret(l, tk, p);
+ }
- return finalize(l, p);
+ pr->variadic = 1;
+ reset(p);
+ return 0;
}
-static int pren(const struct lex *l, struct prv *p)
+static int rsym(const struct lex *l, struct prv *p, const struct sym *s)
{
- const struct tk *tk = prparams(l, p, NULL);
+ const struct tk *tk = s->tk;
+ const struct fn *fn = fn_cur(p);
+ const struct stentry *e = NULL;
- if (!tk)
+ if (check(l, p, s, 0, &e))
return -1;
+ else if (e)
+ {
+ if (setret(tk, e, fn->pr))
+ return -1;
- return finalize(l, p);
+ return pop(l, p);
+ }
+
+ return 0;
}
-static int pryy(const struct lex *l, struct prv *p)
+static int s_returning(const struct lex *l, struct prv *p)
{
- int ret;
- const struct tk *tk = prparams(l, p, &ret);
+ const struct fn *fn = fn_cur(p);
+ struct pr *pr = fn->pr;
- if (!tk)
+ if (pr->returning)
+ {
+ errloc(p->stk, "\"returning\" for \"%s\" already set", fn->tk->s);
return -1;
- else if (ret)
- return prret(l, tk, p);
+ }
- return finalize(l, p);
+ pr->returning = 1;
+ return sym(p, rsym);
}
-static int pryn(const struct lex *l, struct prv *p)
+static int using(const struct lex *l, struct prv *p)
{
- if (!prparams(l, p, NULL))
- return -1;
+ const struct fn *fn = fn_cur(p);
+ struct pr *pr = fn->pr;
+ struct pos init =
+ {
+ .name = __func__,
+ .seq = useqs
+ };
- return finalize(l, p);
-}
+ if (pr->using)
+ {
+ errloc(p->stk, "\"using\" for \"%s\" already set", fn->tk->s);
+ return -1;
+ }
-static int prny(const struct lex *l, struct prv *p)
-{
- return prret(l, p->stk + 1, p);
-}
+ if (push(&init, p))
+ return -1;
-static int prnn(const struct lex *l, struct prv *p)
-{
- return finalize(l, p);
+ pr->using = 1;
+ return sym(p, usym);
}
void pr_free(struct pr *pr)
@@ -338,13 +263,13 @@ void pr_free(struct pr *pr)
int pr(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->tk - 1, *next = p->tk;
+ const struct tk *tk = p->stk;
struct fn *fn = fn_cur(p);
struct pos init =
{
+ .name = __func__,
.seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .end = finalize
};
if (fn->pr)
@@ -363,13 +288,9 @@ int pr(const struct lex *l, struct prv *p)
*fn->pr = (struct pr){.tk = tk};
- /* on no parameters or return values, go directly to next sequences list. */
- if (lex_eof(l, next)
- || (strcmp(next->s, "using") && strcmp(next->s, "returning")))
- return prnn(l, p);
- else if (push(&init, p))
+ if (push(&init, p))
return -1;
p->stk = p->tk;
- return 1;
+ return 0;
}