#include "storage.h" #include "errloc.h" #include "fn.h" #include "lex.h" #include "prv.h" #include "type.h" #include #include #include static int vab(const struct lex *l, struct prv *p); static int vac(const struct lex *l, struct prv *p); static int vb(const struct lex *l, struct prv *p); static int vc(const struct lex *l, struct prv *p); #define VAB(x) \ {(const struct step[]){{ID}, {ID, "array"}, {ID, x}, {NUM}, {0}}, .fn = vab} #define VB(x) {(const struct step[]){{ID}, {ID, x}, {0}}, .fn = vb} static const struct seq seqs[] = { /* array with built-in type */ VAB("void"), VAB("byte"), VAB("halfword"), VAB("word"), VAB("long"), VAB("ubyte"), VAB("uhalfword"), VAB("uword"), VAB("ulong"), /* array with custom type */ {(const struct step[]){{ID}, {ID, "array"}, {ID}, {0}}, .fn = vac}, /* var with built-in type */ VB("void"), VB("byte"), VB("halfword"), VB("word"), VB("long"), VB("ubyte"), VB("uhalfword"), VB("uword"), VB("ulong"), /* var with custom type */ {(const struct step[]){{ID}, {ID}, {0}}, .fn = vc}, {0} }; static int stpush(const struct lex *l, struct prv *p, const struct tk *tk, const struct tk *type) { const struct ast *ast = p->ast; struct pos *pos = &p->pos[p->i]; struct stentry *entries; struct storage *st = p->st; size_t n = st->nentries + 1; const struct type *t = type_find(&ast->fns[ast->nfns - 1], type->s); const struct loc *loc = &tk->loc; if (!t) { errloc(type, "undefined reference to type \"%s\"", type->s); return -1; } else if (!t->sz) { errloc(type, "type \"%s\" has null size", type->s); return -1; } else if (!(entries = realloc(st->entries, n * sizeof *entries))) { perror("realloc(3)"); return -1; } /* todo: type*/ entries[st->nentries++] = (struct stentry){.t = t, .tk = tk}; st->entries = entries; p->stk = p->tk; pos->seq = seqs; pos->step = seqs->steps; fprintf(stderr, "\tadding %s (%d:%d) to %s, type %s\n", tk->s, loc->line, loc->col, st->name, type->s); return 1; } static int vb(const struct lex *l, struct prv *p) { const struct tk *name = p->stk, *type = p->tk - 1; const struct fn *fn = fn_cur(p); const struct storage *st = p->st; const struct stentry *e; if (st->check && (e = fn_var(fn, name))) { const struct loc *loc = &e->tk->loc; errloc(name, "variable \"%s\" already defined at %s:%d:%d", name->s, loc->f, loc->line, loc->col); return -1; } /* find var in currently known symbols */ for (size_t i = 0; i < st->nentries; i++) { const struct stentry *e = &st->entries[i]; const struct tk *tk = e->tk; if (!strcmp(tk->s, name->s)) { const struct loc *loc = &tk->loc; errloc(name, "variable \"%s\" already defined at %s:%d:%d", name->s, loc->f, loc->line, loc->col); return -1; } } return stpush(l, p, name, type); } static int vc(const struct lex *l, struct prv *p) { fprintf(stderr, "%s: TODO\n", __func__); return -1; } static int vab(const struct lex *l, struct prv *p) { fprintf(stderr, "%s: TODO\n", __func__); return -1; } static int vac(const struct lex *l, struct prv *p) { fprintf(stderr, "%s: TODO\n", __func__); return -1; } void storage_free(struct storage *s) { if (s) free(s->entries); free(s); } const struct stentry *storage_find(const char *name, const struct storage *s) { for (size_t i = 0; i < s->nentries; i++) { const struct stentry *e = &s->entries[i]; if (!strcmp(name, e->tk->s)) return e; } return NULL; } int storage(const struct lex *l, struct prv *p, const char *name, int check, struct storage **out) { struct storage *st = NULL; const struct tk *tk = p->tk - 1; struct pos init = { .seq = seqs, .stseq = seqs, .step = seqs->steps }; if (*out) { const struct loc *loc = &(*out)->tk->loc; errloc(tk, "%s already defined at %s:%d:%d", name, loc->f, loc->line, loc->col); goto failure; } else if (!(st = malloc(sizeof *st))) { perror("malloc(3)"); goto failure; } else if (push(&init, p)) goto failure; *st = (struct storage){.name = name, .tk = tk, .check = check}; *out = p->st = st; p->stk = p->tk; return 1; failure: free(st); return -1; }