aboutsummaryrefslogtreecommitdiff
path: root/src/prc1/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/prc1/call.c')
-rw-r--r--src/prc1/call.c486
1 files changed, 123 insertions, 363 deletions
diff --git a/src/prc1/call.c b/src/prc1/call.c
index 21ef4de..f06f25b 100644
--- a/src/prc1/call.c
+++ b/src/prc1/call.c
@@ -5,263 +5,171 @@
#include "lex.h"
#include "lit.h"
#include "parse.h"
+#include "pr.h"
#include "prv.h"
#include "stmt.h"
+#include "sym.h"
#include "type.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-static int callpr(const struct lex *l, struct prv *p);
-static int callp(const struct lex *l, struct prv *p);
-static int callr(const struct lex *l, struct prv *p);
-static int callv(const struct lex *l, struct prv *p);
+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[] =
{
- {(struct step[]){
- {ID},
- {ID, "using"},
- {ANY, NULL, 1},
- {ID, "returning"},
- {ID},
- {0}}, .fn = callpr},
- {(struct step[]){
- {ID},
- {ID, "using"},
- {ANY, NULL, 1},
- {0}}, .fn = callp},
- {(struct step[]){
- {ID},
- {ID, "returning"},
- {ID},
- {0}}, .fn = callr},
- {(struct step[]){
- {ID},
- {0}}, .fn = callv},
+ {(struct step[]){{ID, "using"}, {0}}, .fn = using},
+ returning,
{0}
};
-static int param(const struct lex *l, struct prv *p, const struct tk *tk,
- struct call *c)
+static const struct seq useqs[] =
{
- const struct fn *fn = fn_cur(p);
+ returning,
+ {0}
+};
+
+static int param(const struct lex *l, struct prv *p, const struct sym *s)
+{
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
size_t n = c->nparams + 1;
- struct callparam *params;
- const struct lit *lit = NULL;
- const struct stentry *e = NULL;
- const struct type *t = NULL;
- int sign = 0;
- union callv u = {0};
-
- if (tk->type == LIT)
- {
- if (!(lit = lit_push(tk, p)))
- return -1;
- }
- else if (tk->type == NUM)
- {
- if ((sign = *tk->s == '-'))
- u.v = strtoll(tk->s, NULL, 0);
- else
- u.uv = strtoull(tk->s, NULL, 0);
- }
- else if ((t = type_find(fn, tk->s)))
- {
- if (t->type != C)
- {
- errloc(tk, "type \"%s\" not a constant", tk->s);
- return -1;
- }
- }
- else if (!(e = fn_var(fn, tk)))
- {
- errloc(tk, "undefined reference to parameter \"%s\"", tk->s);
- return -1;
- }
+ struct callparam *params = realloc(c->params, n * sizeof *params);
- if (!(params = realloc(c->params, n * sizeof *params)))
+ if (!params)
{
perror("realloc(3)");
return -1;
}
+ params[c->nparams++] = (struct callparam){.s = s};
c->params = params;
- c->params[c->nparams++] = (struct callparam)
- {
- .entry = e,
- .lit = lit,
- .t = t,
- .u = u
- };
-
return 0;
}
-static int callpr(const struct lex *l, struct prv *p)
+static int using(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->stk + 2;
- struct call *c = &stmt_cur(p)->u.call;
- const struct pr *pr = c->pr;
- const struct stentry *e;
- size_t n = 0;
+ struct pos init =
+ {
+ .name = __func__,
+ .seq = useqs
+ };
- while (!lex_eof(l, tk) && !kw((tk++)->s))
- n++;
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
+ const struct tk *tk = c->pr->tk, *u = c->using;
- if (pr->variadic)
+ if (u)
{
- if (n < pr->nparams)
- {
- errloc(tk, "function \"%s\" expects at least %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
- return -1;
- }
- }
- else if (n != pr->nparams)
- {
- tk -= 2;
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
- return -1;
- }
+ const struct loc *loc = &u->loc;
- if (!pr->ret)
- {
- errloc(tk, "function \"%s\" does not expect any return variable",
- c->tk->s);
+ errloc(p->stk, "\"using\" for \"%s\" already set at %d:%d", tk->s,
+ loc->line, loc->col);
return -1;
}
+ else if (push(&init, p))
+ return -1;
- tk = p->stk + 2;
+ c->using = p->stk;
+ return sym(p, param);
+}
- for (size_t i = 0; i < n; i++)
- if (param(l, p, tk++, c))
- return -1;
+static int setret(const struct lex *l, struct prv *p, const struct sym *s)
+{
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
- if (!(e = fn_var(fn_cur(p), ++tk)))
+ c->ret = s;
+ return pop(l, p);
+}
+
+static int s_returning(const struct lex *l, struct prv *p)
+{
+ struct pos init =
{
- errloc(tk, "undefined reference to return variable \"%s\"",
- tk->s);
+ .name = __func__,
+ .seq = useqs
+ };
+
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
+ const struct tk *tk = c->pr->tk, *r = c->returning;
+
+ if (r)
+ {
+ const struct loc *loc = &r->loc;
+
+ errloc(p->stk, "\"returning\" for \"%s\" already set at %d:%d",
+ tk->s, loc->line, loc->col);
return -1;
}
- else if (pop(l, p))
+
+ if (push(&init, p))
return -1;
- dbg("\t\tadding call to %s using %zu params and %s as return variable\n",
- c->tk->s, n, tk->s);
- c->ret = e;
- c->nparams = n;
- p->stk = ++tk;
- return 1;
+ c->returning = p->stk;
+ return sym(p, setret);
}
-static int callr(const struct lex *l, struct prv *p)
+static int endcall(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->stk + 2;
- const struct fn *fn = fn_cur(p);
- const struct stentry *e;
- struct call *c = &stmt_cur(p)->u.call;
+ const struct stmt *stmt = stmt_cur(p);
+ const struct call *c = &stmt->u.call;
const struct pr *pr = c->pr;
+ const struct tk *tk = c->id->tk;
+ size_t n = c->nparams;
- if (!pr->ret)
+ if (!pr)
{
- errloc(tk, "function \"%s\" does not expect any return variable",
- c->tk->s);
+ errloc(p->stk - 1, "incomplete \"call\" statement");
return -1;
}
- else if (pr->nparams)
+ else if (c->using && !n)
{
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but none were given", c->tk->s, pr->nparams);
+ errloc(c->using, "\"using\" without arguments");
return -1;
}
- else if (!(e = fn_var(fn, tk)))
+ else if (c->returning && !c->ret)
{
- errloc(tk, "undefined reference to return variable \"%s\"", tk->s);
+ errloc(c->using, "\"returning\" without return variable");
return -1;
}
- else if (pop(l, p))
- return -1;
-
- dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s);
- c->ret = e;
- p->stk = ++tk;
- return 1;
-}
-
-static int callp(const struct lex *l, struct prv *p)
-{
- const struct tk *tk = p->stk + 2;
- struct call *c = &stmt_cur(p)->u.call;
- const struct pr *pr = c->pr;
- size_t n = 0;
-
- while (!lex_eof(l, tk) && !kw((tk++)->s))
- n++;
-
- if (lex_eof(l, tk))
- tk--;
-
- if (pr->variadic)
+ else if (pr->variadic)
{
if (n < pr->nparams)
{
- errloc(tk, "function \"%s\" expects at least %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
+ errloc(tk, "\"%s\" expects at least %zu parameters, "
+ "but %zu were given", tk->s, pr->nparams, n);
return -1;
}
}
- else if (pr->nparams != n)
+ else if (n != pr->nparams)
{
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but %zu were given", c->tk->s, pr->nparams, n);
+ errloc(tk, "\"%s\" expects %zu parameters, but %zu were given",
+ tk->s, pr->nparams, n);
return -1;
}
- tk = p->stk + 2;
-
- for (size_t i = 0; i < n; i++)
- if (param(l, p, tk++, c))
- return -1;
-
- if (pop(l, p))
- return -1;
-
- dbg("\t\tadding call to %s with 1 param\n", c->tk->s);
- p->stk = tk;
- return 1;
-}
-
-static int callv(const struct lex *l, struct prv *p)
-{
- const struct tk *tk = p->stk;
- struct call *c = &stmt_cur(p)->u.call;
- const struct pr *pr = c->pr;
-
- if (pr->nparams)
+ if (!pr->ret && c->ret)
{
- errloc(tk, "function \"%s\" expects %zu parameters, "
- "but none were given", c->tk->s, pr->nparams);
+ errloc(tk, "function \"%s\" does not expect any return variable",
+ tk->s);
return -1;
}
- else if (pop(l, p))
- return -1;
- dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s);
- p->stk = ++tk;
- return 1;
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
}
-static const struct pr *find_proto(const struct fn *fn, const char *s)
+void call_free(struct call *c)
{
- const struct type *t = type_find(fn, s);
-
- if (t && t->type == P)
- return t->u.p.fn->pr;
-
- return NULL;
+ if (c)
+ free(c->params);
}
static const struct pr *find(const struct ast *ast, const char *s)
@@ -269,219 +177,71 @@ static const struct pr *find(const struct ast *ast, const char *s)
for (size_t i = 0; i < ast->nfns; i++)
{
const struct fn *fn = &ast->fns[i];
- const struct pr *pr;
- if ((pr = find_proto(fn, s)))
- return pr;
- else if (!strcmp(fn->tk->s, s))
+ if (!strcmp(fn->tk->s, s))
return fn->pr;
}
return NULL;
}
-static int gettmp(char *tmp, size_t n)
-{
- size_t j;
-
- for (j = 0; j < n; j++)
- {
- char c = tmp[j];
-
- if (!c)
- return tmp[j] = 'a';
- else if (c != 'z')
- return ++(tmp[j]);
- }
-
- return EOF;
-}
-
-static int param_lit(const struct lit *lit, struct cgen *c)
-{
- printf("l $%s", lit->name);
- return 0;
-}
-
-static int param_id(const struct stentry *e, struct cgen *c, char *tmp,
- size_t n)
-{
- const char *name = e->tk->s;
- const struct type *t = e->t;
-
- printf("%s ", cgen_sz(t->sz));
-
- if (cgen_global(c->fn, e))
- printf("$%s", name);
- else if (cgen_abity(t))
- {
- if (gettmp(tmp, n) == EOF)
- return -1;
-
- printf("%%%s", tmp);
- }
- else
- printf("%%%s_", name);
-
- return 0;
-}
-
-static int param_c(const struct type *t, struct cgen *cg)
-{
- const union c *c = &t->u.c;
-
- /* TODO: adapt type to expected param size */
- fputs("l ", stdout);
-
- if (t->sign)
- printf("%lld", c->v);
- else
- printf("%llu", c->uv);
-
- return 0;
-}
-
-static int param_num(const struct callparam *cp, struct cgen *c)
-{
- const union callv *u = &cp->u;
-
- /* TODO: adapt type to expected param size */
- fputs("w ", stdout);
-
- if (cp->sign)
- printf("%lld", u->v);
- else
- printf("%llu", u->uv);
-
- return 0;
-}
-
-static int param_load(const struct call *m, struct cgen *c)
+static int onsym(const struct lex *l, struct prv *p, const struct sym *s)
{
- char tmp[sizeof "abcdefghijklmnopqrstuvwxyz"] = {0};
+ const struct fn *fn = fn_cur(p);
+ struct stmt *stmt = stmt_cur(p);
+ struct call *c = &stmt->u.call;
+ const struct tk *tk = s->tk;
+ const struct pr *pr = find(p->ast, tk->s);
+ const struct stentry *e;
- for (size_t i = 0; i < m->nparams; i++)
+ if (pr)
+ c->pr = pr;
+ else if (!(e = fn_var(fn, tk)))
{
- const struct callparam *cp = &m->params[i];
- const struct stentry *e = cp->entry;
-
- if (!e || cgen_global(c->fn, e) || !cgen_abity(e->t))
- continue;
- else if (gettmp(tmp, sizeof tmp - 1) == EOF)
- {
- fprintf(stderr, "%s: exhausted temporaries\n", __func__);
- return -1;
- }
-
- printf("%%%s =%s load%s %%%s_\n", tmp, cgen_sz(e->t->sz),
- cgen_load(e->t), e->tk->s);
- }
-
- return 0;
-}
-
-int call_cgen(const struct call *m, struct cgen *c)
-{
- char tmps[sizeof "abcdefghijklmnopqrstuvwxyz"] = {0};
- const struct stentry *ret = m->ret;
- const char *tmp;
- size_t sz;
-
- if (param_load(m, c))
+ errloc(tk, "undefined reference to \"%s\"", tk->s);
return -1;
- else if (ret)
- {
- tmp = cgen_tmp((sz = ret->t->sz));
- printf("%%%s =%s ", tmp, cgen_sz(sz));
}
-
- printf("call $%s(", m->tk->s);
-
- for (size_t i = 0; i < m->nparams; i++)
+ else if (e->t->type != P)
{
- const struct callparam *cp = &m->params[i];
- int var = m->pr->variadic;
-
- if (cp->lit)
- param_lit(cp->lit, c);
- else if (cp->entry)
- param_id(cp->entry, c, tmps, sizeof tmps - 1);
- else if (cp->t)
- param_c(cp->t, c);
- else
- param_num(cp, c);
-
- if (var && i + 1 == var - 1)
- fputs(", ...", stdout);
-
- if (i + 1 < m->nparams)
- fputs(", ", stdout);
- }
+ char *tn = type_name(e->t);
- puts(")");
+ if (tn)
+ errloc(tk, "cannot call \"%s\" with type \"%s\"", tk->s, tn);
- if (ret)
- {
- printf("store%s %%%s, ", cgen_sz(sz), tmp);
- cgen_printvar(c->fn, ret);
- putchar('\n');
+ free(tn);
+ return -1;
}
+ else
+ c->pr = e->t->u.p.fn->pr;
- return 0;
-}
-
-void call_free(struct call *c)
-{
- if (c)
- free(c->params);
+ c->id = s;
+ return pop(l, p);
}
int call(const struct lex *l, struct prv *p)
{
- const struct tk *tk = p->tk;
- const struct pr *pr;
- struct fn *fn = fn_cur(p);
- size_t n = fn->nstmts +1;
- struct stmt *stmts;
struct pos init =
{
+ .name = __func__,
.seq = seqs,
- .stseq = seqs,
- .step = seqs->steps
+ .end = endcall,
};
- /* TODO: function pointers */
+ struct fn *fn = fn_cur(p);
+ size_t n = fn->nstmts + 1;
+ struct stmt *stmts = realloc(fn->stmts, n * sizeof *stmts);
- if (lex_eof(l, tk))
- {
- errloc(tk - 1, "incomplete call statement");
- return -1;
- }
- else if (!(pr = find(p->ast, tk->s)))
- {
- errloc(tk, "undefined reference to function \"%s\"", tk->s);
- return -1;
- }
- else if (!(stmts = realloc(fn->stmts, n * sizeof *stmts)))
+ if (!stmts)
{
perror("realloc(3)");
return -1;
}
+ stmts[fn->nstmts++] = (struct stmt){.type = CALL, .u.call.tk = p->stk};
fn->stmts = stmts;
- fn->stmts[fn->nstmts++] = (struct stmt)
- {
- .type = CALL,
- .u.call =
- {
- .tk = tk,
- .pr = pr
- }
- };
if (push(&init, p))
return -1;
- p->stk = p->tk;
- return 1;
+ return sym(p, onsym);
}