diff options
Diffstat (limited to 'src/prc1/print.c')
| -rw-r--r-- | src/prc1/print.c | 178 |
1 files changed, 114 insertions, 64 deletions
diff --git a/src/prc1/print.c b/src/prc1/print.c index abdb149..604c2a3 100644 --- a/src/prc1/print.c +++ b/src/prc1/print.c @@ -5,99 +5,149 @@ #include "parse.h" #include "prv.h" #include "stmt.h" -#include "storage.h" +#include "sym.h" #include "type.h" #include <stdlib.h> -#include <string.h> -static int entry(const struct lex *l, const struct tk *tk, struct print *pr, - struct prv *p) +static int etc(const struct lex *, struct prv *); + +static const struct seq seqs[] = +{ + {(struct step[]){{ID, "etc"}, {0}}, .fn = etc}, + {0} +}; + +static int invalid(const struct sym *s, const struct type *t) +{ + char *tn = type_name(t); + + if (tn) + errloc(s->tk, "cannot print type \"%s\"", tn); + + free(tn); + return -1; +} + +static const struct sym *inner(const struct sym *s) +{ + for (; s; s = s->child) + if (!s->child) + break; + + return s; +} + +static int setptr(struct prv *p, const struct sym *s, struct prisym *ps, + const struct type *t) { - size_t n = pr->nentries + 1; - struct prientry *entries; - const struct stentry *stentry = NULL; const struct fn *fn = fn_cur(p); - const struct lit *lit = NULL; + const struct stentry *e = fn_var(fn, s->tk); - if (tk->type == ID) + if (!e) { - const struct type *t = NULL; + errloc(s->tk, "undefined reference to \"%s\"", s->tk->s); + return -1; + } + + ps->type = PRS_PTR; + ps->u.e = e; + return 0; +} + +static int settype(struct prv *p, const struct sym *s, struct prisym *ps) +{ + const struct type *t = sym_type(p, s); + const struct tk *tk = s->tk; - if ((t = type_find(fn, tk->s))) + if (!t) + { + errloc(tk, "undefined reference to \"%s\"", tk->s); + return -1; + } + else if (inner(s)->type == SYM_LIT) + { + const struct lit *l = lit_push(tk, p); + + if (!l) + return -1; + else if (t == p->ast->littype) { - if (t->type != C) - { - errloc(tk, "type \"%s\" not a constant", tk->s); - return -1; - } - else if (!(lit = lit_push(t->tk, p))) - return -1; + ps->type = PRS_LIT; + ps->u.lit = l; } - else if (!(stentry = fn_var(fn, tk))) + else { - errloc(tk, "undefined reference to \"%s\"", tk->s); - return -1; + ps->type = PRS_NAM; + ps->u.name = l->name; } } - else if (tk->type == LIT && !(lit = lit_push(tk, p))) - return -1; + else + switch (t->type) + { + case U: + case S: + case T: + case ARY: + return invalid(s, t); + case C: + case BUILTIN: + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + case P: + ps->type = PRS_NAM; + ps->u.name = s->tk->s; + break; + case PTR: + return setptr(p, s, ps, t); + } - if (!(entries = realloc(pr->entries, n * sizeof *entries))) + return 0; +} + +static int onsym(const struct lex *l, struct prv *p, const struct sym *s) +{ + struct stmt *stmt = stmt_cur(p); + struct print *pr = &stmt->u.print; + size_t n = pr->nsyms + 1; + struct prisym *syms, *nsym; + + if (!(syms = realloc(pr->syms, n * sizeof *syms))) { perror("realloc(3)"); return -1; } - pr->entries = entries; - pr->entries[pr->nentries++] = (struct prientry) - { - .tk = tk, - .lit = lit, - .entry = stentry - }; + pr->syms = syms; + nsym = &syms[pr->nsyms++]; + *nsym = (struct prisym){.s = s}; + return settype(p, s, nsym); +} + +static int etc(const struct lex *l, struct prv *p) +{ + struct stmt *stmt = stmt_cur(p); + struct print *pr = &stmt->u.print; + pr->skipln = 1; + reset(p); return 0; } void print_free(struct print *pr) { - free(pr->entries); + free(pr->syms); } -int print(const struct lex *l, struct prv *p, - int (*fn)(const struct lex *, const struct prv *, const struct print *)) +int print(const struct lex *l, struct prv *p) { - const struct tk *tk = p->stk + 1; - struct print pr = {0}; - struct pos *pos = &p->pos[p->i]; - int eof; - - if (lex_eof(l, tk)) + struct pos init = { - errloc(tk - 1, "incomplete %s statement", p->stk->s); - return -1; - } - - for (;;) - if (entry(l, tk, &pr, p)) - goto failure; - else if ((eof = lex_eof(l, ++tk)) || kw(tk->s)) - break; - - if (eof || strcmp(tk->s, "etc")) - pr.println = 1; - else if (!eof) - tk++; - - if (fn(l, p, &pr)) - goto failure; + .name = __func__, + .seq = seqs + }; - pos->seq = pos->stseq = stmts; - pos->step = stmts->steps; - p->stk = tk; - return 1; + if (push(&init, p)) + return -1; -failure: - print_free(&pr); - return -1; + return sym(p, onsym); } |
