#include "print.h" #include "errloc.h" #include "fn.h" #include "lit.h" #include "parse.h" #include "prv.h" #include "stmt.h" #include "sym.h" #include "type.h" #include 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) { const struct fn *fn = fn_cur(p); const struct stentry *e = fn_var(fn, s->tk); if (!e) { 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) { 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) { ps->type = PRS_LIT; ps->u.lit = l; } else { ps->type = PRS_NAM; ps->u.name = l->name; } } 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); } 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->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->syms); } int print(const struct lex *l, struct prv *p) { struct pos init = { .name = __func__, .seq = seqs }; if (push(&init, p)) return -1; return sym(p, onsym); }