diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-10-01 01:04:30 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-10-05 00:38:49 +0200 |
| commit | 2b0d4ead061a39da9dbd705c18c9955549c4d405 (patch) | |
| tree | 1412ac39adce3428b96caf67b1e7543f6c1246a5 /src/prc1 | |
| parent | 9140988be4e5bb028b7140aca1a67af1370c72a7 (diff) | |
| download | prc-2b0d4ead061a39da9dbd705c18c9955549c4d405.tar.gz | |
WIP symsym
Diffstat (limited to 'src/prc1')
38 files changed, 1383 insertions, 774 deletions
diff --git a/src/prc1/CMakeLists.txt b/src/prc1/CMakeLists.txt index f5dfa86..8d15806 100644 --- a/src/prc1/CMakeLists.txt +++ b/src/prc1/CMakeLists.txt @@ -17,7 +17,9 @@ add_executable(prc1 lit.c lk.c prc1.c + reset.c set.c + sym.c parse.c pop.c pr.c diff --git a/src/prc1/arg.c b/src/prc1/arg.c index f61bca7..41d22a7 100644 --- a/src/prc1/arg.c +++ b/src/prc1/arg.c @@ -20,7 +20,7 @@ struct arg static int debug(struct args *a, const char *arg) { - dbgen = 1; + dbgen++; return 0; } diff --git a/src/prc1/call.c b/src/prc1/call.c index 21ef4de..ed64070 100644 --- a/src/prc1/call.c +++ b/src/prc1/call.c @@ -7,6 +7,7 @@ #include "parse.h" #include "prv.h" #include "stmt.h" +#include "sym.h" #include "type.h" #include <stddef.h> #include <stdio.h> @@ -149,12 +150,12 @@ static int callpr(const struct lex *l, struct prv *p) else if (pop(l, p)) return -1; - dbg("\t\tadding call to %s using %zu params and %s as return variable\n", + dbg("\t\tadd 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; + return 0; } static int callr(const struct lex *l, struct prv *p) @@ -185,10 +186,10 @@ static int callr(const struct lex *l, struct prv *p) else if (pop(l, p)) return -1; - dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s); + dbg("\t\tadd call to %s with %s as return variable\n", c->tk->s, tk->s); c->ret = e; p->stk = ++tk; - return 1; + return 0; } static int callp(const struct lex *l, struct prv *p) @@ -229,9 +230,9 @@ static int callp(const struct lex *l, struct prv *p) if (pop(l, p)) return -1; - dbg("\t\tadding call to %s with 1 param\n", c->tk->s); + dbg("\t\tadd call to %s with 1 param\n", c->tk->s); p->stk = tk; - return 1; + return 0; } static int callv(const struct lex *l, struct prv *p) @@ -249,9 +250,9 @@ static int callv(const struct lex *l, struct prv *p) else if (pop(l, p)) return -1; - dbg("\t\tadding call to %s with %s as return variable\n", c->tk->s, tk->s); + dbg("\t\tadd call to %s with %s as return variable\n", c->tk->s, tk->s); p->stk = ++tk; - return 1; + return 0; } static const struct pr *find_proto(const struct fn *fn, const char *s) @@ -436,6 +437,12 @@ void call_free(struct call *c) free(c->params); } +static int onsym(const struct lex *l, struct prv *p, const struct sym *s) +{ + fprintf(stderr, "%s: TODO\n", __func__); + return -1; +} + int call(const struct lex *l, struct prv *p) { const struct tk *tk = p->tk; @@ -443,23 +450,21 @@ int call(const struct lex *l, struct prv *p) struct fn *fn = fn_cur(p); size_t n = fn->nstmts +1; struct stmt *stmts; - struct pos init = - { - .seq = seqs, - .stseq = seqs, - .step = seqs->steps - }; /* TODO: function pointers */ - - if (lex_eof(l, tk)) + if (!(pr = find(p->ast, tk->s))) { - errloc(tk - 1, "incomplete call statement"); + errloc(tk, "undefined reference to function \"%s\"", tk->s); return -1; } - else if (!(pr = find(p->ast, tk->s))) + else if (!strcmp((++tk)->s, "using")) { - errloc(tk, "undefined reference to function \"%s\"", tk->s); + fprintf(stderr, "%s: TODO using rule\n", __func__); + return -1; + } + else if (!strcmp(tk->s, "returning")) + { + fprintf(stderr, "%s: TODO returning rule\n", __func__); return -1; } else if (!(stmts = realloc(fn->stmts, n * sizeof *stmts))) @@ -479,9 +484,6 @@ int call(const struct lex *l, struct prv *p) } }; - if (push(&init, p)) - return -1; - p->stk = p->tk; - return 1; + return sym(p, onsym); } diff --git a/src/prc1/dbg.c b/src/prc1/dbg.c index cf2d18c..becb3e5 100644 --- a/src/prc1/dbg.c +++ b/src/prc1/dbg.c @@ -17,3 +17,17 @@ int dbg(const char *fmt, ...) va_end(ap); return n; } + +int ddbg(const char *fmt, ...) +{ + int n; + va_list ap; + + if (dbgen < 2) + return 0; + + va_start(ap, fmt); + n = vfprintf(stderr, fmt, ap); + va_end(ap); + return n; +} diff --git a/src/prc1/dbg.h b/src/prc1/dbg.h index 956187e..aecbd78 100644 --- a/src/prc1/dbg.h +++ b/src/prc1/dbg.h @@ -2,6 +2,7 @@ #define DBG_H int dbg(const char *fmt, ...); +int ddbg(const char *fmt, ...); extern int dbgen; diff --git a/src/prc1/display.c b/src/prc1/display.c index 2fbf331..70fac93 100644 --- a/src/prc1/display.c +++ b/src/prc1/display.c @@ -1,19 +1,21 @@ #include "display.h" #include "cgen.h" #include "dbg.h" +#include "fn.h" #include "parse.h" #include "prv.h" #include "stmt.h" -#include "storage.h" -#include <errno.h> +#include <stddef.h> #include <stdlib.h> -#include <string.h> -static int finalize(const struct lex *l, const struct prv *p, - const struct print *pr) +int display_cgen(const struct print *pr, struct cgen *c) { - const struct ast *ast = p->ast; - struct fn *fn = &ast->fns[ast->nfns - 1]; + return print_cgen(pr, c, "stdout"); +} + +int display(const struct lex *l, struct prv *p) +{ + struct fn *fn = fn_cur(p); size_t n = fn->nstmts + 1; struct stmt *stmts = realloc(fn->stmts, n * sizeof *stmts); @@ -23,121 +25,8 @@ static int finalize(const struct lex *l, const struct prv *p, return -1; } + dbg("\t\tadd display statement\n"); + stmts[fn->nstmts++] = (struct stmt){.type = DISPLAY, .u.print = {0}}; fn->stmts = stmts; - fn->stmts[fn->nstmts++] = (struct stmt) - { - .type = DISPLAY, - .u.display.p = *pr - }; - - dbg("\t\tadding display statement with %zu entries%s\n", pr->nentries, - pr->println ? "" : ", no lf"); - return 0; -} - -static int cg_val(const struct tk *tk) -{ - const char *num = tk->s; - int neg = *num == '-'; - unsigned long long uv; - char *end; - - fputs("call $printf(l $____fmt", stdout); - errno = 0; - uv = strtoull(num, &end, 16); - - if (!neg && !errno && !*end) - printf("lx, ..., l %llu )\n", uv); - else - { - errno = 0; - uv = strtoull(num, &end, 0); - - if (neg || errno || *end) - { - long long v = strtoll(num, NULL, 0); - printf("l, ..., l %lld )\n", v); - } - else - printf("l, ..., l %llu )\n", uv); - } - - return 0; -} - -static int cg_lit(const struct prientry *e) -{ - const struct lit *l = e->lit; - const char *tmp; - - if (!l) - { - fprintf(stderr, "%s: unexpected null literal\n", __func__); - return -1; - } - - printf("%%%s =l loadl $stdout\n", (tmp = cgen_tmp(sizeof (void *)))); - printf("call $fputs(l $%s, w %%%s)\n", l->name, tmp); - return 0; -} - -static int cg_id(const struct prientry *de, const struct fn *fn) -{ - const struct stentry *e = de->entry; - const struct type *t = e->t; - const char *id = e->tk->s; - int global = cgen_global(fn, e); - size_t sz = t->sz; - const char *asz = cgen_sz(sz < 4 ? 4 : sz), *tmp = cgen_tmp(sz); - - if (global) - printf("%%%s =%s load%s $%s\n", tmp, asz, cgen_load(t), id); - else - printf("%%%s =%s load%s %%%s_\n", tmp, asz, cgen_load(t), id); - - fputs("call $printf(l $____fmt", stdout); - - if (t->type == PTR) - fputs("lx, ..., l ", stdout); - else - printf("%s, ..., %s ", cgen_type(t), asz); - - printf("%%%s)\n", tmp); - - return 0; -} - -int display_cgen(const struct display *d, struct cgen *c) -{ - const struct print *p = &d->p; - - for (size_t i = 0; i < p->nentries; i++) - { - const struct prientry *e = &p->entries[i]; - const struct tk *tk = e->tk; - - if (tk->type == LIT && cg_lit(e)) - return -1; - else if (tk->type == NUM && cg_val(tk)) - return -1; - else if (tk->type == ID && e->entry && cg_id(e, c->fn)) - return -1; - else if (tk->type == ID && e->lit && cg_lit(e)) - return -1; - } - - if (p->println) - puts("call $putchar(l 10)"); - - return 0; -} - -void display_free(struct display *d) -{ - print_free(&d->p); -} - -int display(const struct lex *l, struct prv *p) -{ - return print(l, p, finalize); + return print(l, p); } diff --git a/src/prc1/display.h b/src/prc1/display.h index 9b073b1..4367032 100644 --- a/src/prc1/display.h +++ b/src/prc1/display.h @@ -1,17 +1,12 @@ #ifndef DISPLAY_H #define DISPLAY_H +#include "cgen.h" #include "lex.h" #include "print.h" #include "prv.h" -struct display -{ - struct print p; -}; - int display(const struct lex *l, struct prv *p); -int display_cgen(const struct display *d, struct cgen *c); -void display_free(struct display *d); +int display_cgen(const struct print *pr, struct cgen *c); #endif diff --git a/src/prc1/div.c b/src/prc1/div.c index 9061ac6..7236a71 100644 --- a/src/prc1/div.c +++ b/src/prc1/div.c @@ -1,4 +1,5 @@ #include "div.h" +#include "fn.h" #include "gl.h" #include "im.h" #include "lk.h" @@ -6,8 +7,8 @@ #include "td.h" #include "ws.h" -static const struct seq linkage = - {(struct step[]){{ID, "linkage"}, {0}}, .fn = lk}, +static const struct seq + linkage = {(struct step[]){{ID, "linkage"}, {0}}, .fn = lk}, types = {(struct step[]){{ID, "types"}, {0}}, .fn = td}, imports = {(struct step[]){{ID, "imports"}, {0}}, .fn = im}, procedure = {(struct step[]){{ID, "procedure"}, {0}}, .fn = pr}; @@ -42,9 +43,9 @@ int div_fn(const struct lex *l, struct prv *p) { struct pos init = { + .name = __func__, .seq = fnseq, - .stseq = fnseq, - .step = fnseq->steps + .end = fn_end }; if (push(&init, p)) @@ -58,32 +59,38 @@ int div_im(const struct lex *l, struct prv *p) { struct pos init = { + .name = __func__, .seq = imseq, - .stseq = imseq, - .step = imseq->steps }; - if (lex_eof(l, p->stk)) - return 0; - else if (push(&init, p)) + if (push(&init, p)) return -1; p->stk = p->tk; - return 1; + return 0; +} + +static int endp(const struct lex *l, struct prv *p) +{ + if (fn_end(l, p)) + return -1; + + p->proto = NULL; + return 0; } int div_p(const struct lex *l, struct prv *p) { struct pos init = { + .name = __func__, .seq = pseq, - .stseq = pseq, - .step = pseq->steps + .end = endp }; if (push(&init, p)) return -1; p->stk = p->tk; - return 1; + return 0; } diff --git a/src/prc1/end.c b/src/prc1/end.c index 561c981..021142c 100644 --- a/src/prc1/end.c +++ b/src/prc1/end.c @@ -76,6 +76,6 @@ int end(const struct lex *l, struct prv *p) pos->seq = pos->stseq = stmts; pos->step = stmts->steps; p->stk = p->tk; - dbg("\t\tadding end statement, block index %zu\n", bl_i); - return 1; + dbg("\t\tadd end statement, block index %zu\n", bl_i); + return 0; } diff --git a/src/prc1/fn.c b/src/prc1/fn.c index 03aa11e..84f6c4b 100644 --- a/src/prc1/fn.c +++ b/src/prc1/fn.c @@ -9,6 +9,7 @@ #include "pr.h" #include "stmt.h" #include "storage.h" +#include "sym.h" #include "td.h" #include "ws.h" #include <stdlib.h> @@ -20,11 +21,8 @@ static int prvfn(const struct lex *l, struct prv *p); static const struct seq fnseq[] = { - {(struct step[]) - {{ID, "public"}, {ID, "function"}, {ID}, {0}}, .fn = pubfn, - .end = fn_end}, - {(struct step[]) - {{ID, "function"}, {ID}, {0}}, .fn = prvfn, .end = fn_end}, + {(struct step[]){{ID, "public"}, {ID, "function"}, {ID}, {0}}, .fn = pubfn}, + {(struct step[]){{ID, "function"}, {ID}, {0}}, .fn = prvfn}, {0} }; @@ -92,8 +90,8 @@ static int pushfn(const struct tk *tk, const struct lex *lex, struct prv *p, if (div_fn(lex, p)) return -1; - dbg("adding %s function %s\n", l == STATIC ? "private" : "public", tk->s); - return 1; + dbg("add %s function %s\n", l == STATIC ? "private" : "public", tk->s); + return 0; } static int pubfn(const struct lex *l, struct prv *p) @@ -229,6 +227,14 @@ void fn_free(struct fn *fn) t = next; } + for (struct sym *s = fn->syms; s;) + { + struct sym *next = s->next; + + sym_free(s); + s = next; + } + storage_free(fn->lk); storage_free(fn->ws); storage_free(fn->gl); @@ -253,14 +259,11 @@ int fn(const struct lex *l, struct prv *p) { struct pos init = { - .seq = fnseq, - .stseq = fnseq, - .step = fnseq->steps + .name = __func__, + .seq = fnseq }; - if (lex_eof(l, p->stk)) - return 0; - else if (lex_eof(l, p->stk + 1)) + if (lex_eof(l, p->stk + 1)) { errloc(p->stk, "incomplete function statement"); return -1; @@ -269,5 +272,5 @@ int fn(const struct lex *l, struct prv *p) return -1; p->stk = p->tk; - return 1; + return 0; } diff --git a/src/prc1/from.c b/src/prc1/from.c index 838d1de..83f9b71 100644 --- a/src/prc1/from.c +++ b/src/prc1/from.c @@ -297,13 +297,13 @@ int from(const struct lex *l, struct prv *p) || !(fr.var = tmp_create(fn, t))) return -1; - dbg("\t\tadding from statement [%s, %s]", start->s, end->s); + dbg("\t\tadd from statement [%s, %s]", start->s, end->s); if (finalize(p, fn, &fr)) return -1; p->stk = ++end; - return 1; + return 0; } static int checkvar(const struct fn *fn, const struct tk *tk, struct from *fr) @@ -341,14 +341,14 @@ int from_id(const struct lex *l, struct prv *p) || checkvar(fn, var, &fr)) return -1; - dbg("\t\tadding from statement [%s, %s] using %s", start->s, end->s, + dbg("\t\tadd from statement [%s, %s] using %s", start->s, end->s, var->s); if (finalize(p, fn, &fr)) return -1; p->stk = ++var; - return 1; + return 0; } int from_by(const struct lex *l, struct prv *p) diff --git a/src/prc1/im.c b/src/prc1/im.c index e9a208c..68ff9f3 100644 --- a/src/prc1/im.c +++ b/src/prc1/im.c @@ -1,77 +1,143 @@ #include "im.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "prv.h" #include "parse.h" +#include "sym.h" #include <errno.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -static int imlit(const struct lex *, struct prv *); - -static const struct seq seqs[] = -{ - {(struct step[]){{LIT, NULL, 1}, {0}}, .fn = imlit}, - {0} -}; - void im_free(struct im *im) { ast_free(&im->ast); lex_free(&im->l); } +static FILE *tryinc(const char *dir, const char *path, char **fullpath) +{ + FILE *ret = NULL; + size_t n = strlen(dir) + strlen(path) + 2; + char *fp = malloc(n); + + if (!fp) + { + perror("malloc(3)"); + goto end; + } + else if (snprintf(fp, n, "%s/%s", dir, path) < 0) + { + fprintf(stderr, "%s: snprintf(3) failed\n", __func__); + goto end; + } + else if ((ret = fopen(fp, "rb"))) + *fullpath = fp; + +end: + if (!ret) + free(fp); + + return ret; +} + +static char *fpath(const char *cur, const char *path) +{ + const char *sl = strrchr(cur, '/'); + char *ret; + /* '/' + '\0' */ + size_t n = 2; + int curlen; + + if (!sl) + { + cur = "."; + curlen = 1; + } + else + curlen = sl - cur; + + n += curlen + strlen(path); + + if ((ret = malloc(n))) + snprintf(ret, n, "%.*s/%s", curlen, cur, path); + else + perror("malloc(3)"); + + return ret; +} + static int doim(const struct lex *l, const struct tk *tk, struct prv *p) { int ret = -1; FILE *f = NULL; struct im *im; - struct fn *fn = fn_cur(p); + struct fn *fn = fn_cur(p), *fns = NULL; struct ast *ast; - size_t n = fn->nimps + 1; const char *path = tk->s; + size_t n = fn->nimps + 1; + char *fp = NULL, *incfp; + const struct loc *loc = &tk->loc; - if (!strcmp(l->loc.f, path)) - { - errloc(tk, "detected recursive import \"%s\"", path); + /* TODO: no protection against recursive imports */ + if (!(fp = fpath(l->loc.f, path))) goto end; + else if (!(f = fopen(fp, "rb"))) + { + const struct arg_input *incs = &l->args->incs; + + for (size_t i = 0; i < incs->n; i++) + if ((f = tryinc(incs->v[i], path, &incfp))) + { + free(fp); + fp = incfp; + break; + } } - /* TODO: honor -I flags */ - if (!(f = fopen(path, "rb"))) + + if (!f) { - errloc(tk, "failed to open import \"%s\": %s", path, strerror(errno)); + errloc(tk, "failed to open import \"%s\"", path); goto end; } - else if (!(im = realloc(fn->imps, n * sizeof *im))) + else if (!(fns = malloc(sizeof *fns))) { - perror("realloc(3)"); + perror("malloc(3)"); goto end; } - fn->imps = im; - im = &fn->imps[fn->nimps++]; - *im = (struct im){.l.loc.f = path}; - ast = &im->ast; + *fns = (struct fn){.tk = tk}; - if (!(ast->fns = malloc(sizeof *ast->fns))) + if (!(im = realloc(fn->imps, n * sizeof *im))) { - perror("malloc(3)"); + perror("realloc(3)"); goto end; } - *ast->fns = (struct fn){.tk = tk}; + fn->imps = im; + im = &fn->imps[fn->nimps++]; + *im = (struct im){.l = {.loc.f = fp, .args = l->args}}; + ast = &im->ast; + ast->fns = fns; /* hack: treat imports as a function */ ast->nfns = 1; + fp = NULL; + dbg("start import %s (from %s:%d:%d)\n", im->l.loc.f, loc->f, loc->line, + loc->col); if (lex(&im->l, f) || parse_im(&im->l, ast)) goto end; + dbg("end import %s\n", im->l.loc.f); ret = 0; end: + if (ret) + free(fp); + if (f && fclose(f)) { fprintf(stderr, "fclose(3) %s: %s\n", path, strerror(errno)); @@ -81,30 +147,19 @@ end: return ret; } -static int imlit(const struct lex *l, struct prv *p) +static int onsym(const struct lex *l, struct prv *p, const struct sym *s) { - const struct tk *tk = p->stk; - - while (!lex_eof(l, tk) && !kw(tk->s)) - if (doim(l, tk++, p)) - return -1; - - if (pop(l, p)) + if (s->type != SYM_LIT) + { + errloc(s->tk, "expected literal"); return -1; + } - p->stk = p->tk; - return 1; + return doim(l, s->tk, p); } int im(const struct lex *l, struct prv *p) { - struct pos init = - { - .seq = seqs, - .stseq = seqs, - .step = seqs->steps - }; - struct fn *fn = fn_cur(p); if (fn->im) @@ -116,10 +171,7 @@ int im(const struct lex *l, struct prv *p) return -1; } - if (push(&init, p)) - return -1; - fn->im = p->stk; p->stk = p->tk; - return 1; + return sym(p, onsym); } diff --git a/src/prc1/kw.c b/src/prc1/kw.c index c72ac97..45657b7 100644 --- a/src/prc1/kw.c +++ b/src/prc1/kw.c @@ -11,8 +11,10 @@ static const char *kws[] = /* types */ "union", "struct", "constant", "alias", "prototype", /* operators */ - "add", "subtract", "multiply", "divide", "xor", "bitor", "bitand", - "leftshift", "rightshift", "address", "size", "call", "set", + "add", "subtract", "multiply", "divide", "negate", "xor", "bitor", "bitand", + "leftshift", "rightshift", "call", "set", + /* expressions */ + "address", "cast", "contents", "offset", "size", /* procedures */ "using", "returning", /* built-in functions */ diff --git a/src/prc1/lex.c b/src/prc1/lex.c index 736ebdd..ad7a084 100644 --- a/src/prc1/lex.c +++ b/src/prc1/lex.c @@ -223,6 +223,7 @@ void lex_free(struct lex *lex) free_tk(&lex->tokens[i]); free(lex->tokens); + free(lex->loc.f); free_tk(&lex->tk); } @@ -240,7 +241,7 @@ int lex(struct lex *l, FILE *f) int c = fgetc(f); if (c == EOF) - break; + return fintok(l); else if (clex(c, l)) return -1; } diff --git a/src/prc1/lex.h b/src/prc1/lex.h index 4ab3e70..758ad1d 100644 --- a/src/prc1/lex.h +++ b/src/prc1/lex.h @@ -9,7 +9,7 @@ enum tktype {UNDEF, ID, LIT, NUM, ANY}; struct loc { - const char *f; + char *f; int line, col; }; diff --git a/src/prc1/lit.c b/src/prc1/lit.c index 1faf247..065101b 100644 --- a/src/prc1/lit.c +++ b/src/prc1/lit.c @@ -93,7 +93,7 @@ const struct lit *lit_push(const struct tk *tk, struct prv *p) else if (ast->lastlit) ast->lastlit->next = l; - dbg("adding literal \"%s\"\n", name); + dbg("add literal \"%s\"\n", name); ast->lastlit = l; return l; diff --git a/src/prc1/parse.c b/src/prc1/parse.c index 1c3aba2..81bb2ff 100644 --- a/src/prc1/parse.c +++ b/src/prc1/parse.c @@ -4,6 +4,7 @@ #include "fn.h" #include "lex.h" #include "lit.h" +#include "sym.h" #include "prv.h" #include "type.h" #include <stddef.h> @@ -45,6 +46,29 @@ static const char *expected(const struct step *s) return s->id ? s->id : tmap[s->type]; } +static int unexpected(const struct tk *tk) +{ + switch (tk->type) + { + case LIT: + errloc(tk, "unexpected literal \"%s\"", tk->s); + break; + case NUM: + errloc(tk, "unexpected number %s", tk->s); + break; + case ID: + errloc(tk, "unexpected %s %s", kw(tk->s) ? + "keyword" : "identifier", tk->s); + break; + case ANY: + case UNDEF: + errloc(tk, "%s: unreachable", __func__); + break; + } + + return -1; +} + static int iter(const struct lex *l, struct prv *p) { struct pos *pos = p->pos; @@ -52,41 +76,28 @@ static int iter(const struct lex *l, struct prv *p) const struct tk *tk = p->tk; if (!pos) - return p->entry(l, p); + { + if (lex_eof(l, p->stk)) + return 0; + + return p->entry(l, p) ? -1 : 1; + } pos = &p->pos[p->i]; + /* no rules have matched the current token */ if (!(s = pos->step)) { - if (lex_eof(l, tk)) - return 0; - else if (p->n > 1) + if (p->n > 1) return pop(l, p) ? -1 : 1; + else if (lex_eof(l, tk)) + return 0; else - { - switch (tk->type) - { - case LIT: - errloc(tk, "unexpected literal \"%s\"", tk->s); - break; - case NUM: - errloc(tk, "unexpected number %s", tk->s); - break; - case ID: - errloc(tk, "unexpected %s %s", kw(tk->s) ? - "keyword" : "identifier", tk->s); - break; - case ANY: - case UNDEF: - errloc(tk, "%s: unreachable", __func__); - break; - } - - return -1; - } + return unexpected(tk); } else if (lex_eof(l, tk)) { + /* pop all remaining rules */ if (p->stk == p->tk) return pop(l, p) ? -1 : 1; else if (s->type) @@ -101,41 +112,26 @@ static int iter(const struct lex *l, struct prv *p) } } + /* rule has been completely parsed, execute */ if (!s->type) - return pos->seq->fn(l, p); - else if ((s->type == ID || s->type == ANY) && !s->id && kw(tk->s) - && !s->chain) - { - if (tk != p->stk || !p->n) - { - errloc(tk, "unexpected keyword %s", tk->s); - return -1; - } - else if (pop(l, p)) - return -1; - - pos = &p->pos[p->i]; - } - else if ((s->type != tk->type && s->type != ANY) + return pos->seq->fn(l, p) ? -1 : 1; + /* skip if: */ + else if ( + /* rule type does not match */ + s->type != tk->type + /* ID does not match */ || (s->type == ID && s->id && strcmp(s->id, tk->s)) - || (s->type == ID && kw(tk->s) && s->chain)) + /* rule does not expect a keyword */ + || (s->type == ID && !s->id && kw(tk->s))) { + /* move to next rule on no match */ pos->step = (++pos->seq)->steps; p->tk = p->stk; } + /* move to next step */ else { - const struct tk *next = tk + 1; - - if (!s->chain) - pos->step++; - else if (!lex_eof(l, next)) - { - if (s->chain && kw(next->s)) - pos->step++; - } - else - pos->step++; + pos->step++; if (!lex_eof(l, p->tk)) p->tk++; @@ -146,6 +142,7 @@ static int iter(const struct lex *l, struct prv *p) static void free_prv(struct prv *p) { + sym_free(p->s); free(p->tdc); free(p->pos); } diff --git a/src/prc1/parse.h b/src/prc1/parse.h index 5d3d25a..97c7848 100644 --- a/src/prc1/parse.h +++ b/src/prc1/parse.h @@ -49,7 +49,7 @@ struct builtin struct type { - enum {U, S, C, P, T, PTR, ARY, BUILTIN} type; + enum ttype {U, S, C, P, T, PTR, ARY, BUILTIN} type; const struct tk *tk; size_t sz, align; int sign; @@ -68,6 +68,36 @@ struct type } u; }; +struct sym +{ + enum symtype + { + SYM_ID, + SYM_TMP, + SYM_LIT, + SYM_CAST, + SYM_NUM, + SYM_ADDR, + SYM_SZ, + SYM_CNT, + SYM_OFF + } type; + + struct sym *child, *next, *parent; + const struct tk *tk; + + union + { + const struct tmp *tmp; + const struct type *t; + struct + { + int sign; + union c c; + } num; + } u; +}; + struct param { const struct tk *tk; @@ -79,14 +109,13 @@ struct pr const struct tk *tk; struct param *params, *ret; size_t nparams; - int variadic; + int using, returning, variadic; }; struct td { const struct tk *tk; struct type *types; - size_t ntypes; }; struct tmp @@ -103,6 +132,7 @@ struct fn enum linkage {EXTERNAL, STATIC} linkage; struct storage *lk, *ws, *gl; struct stmt *stmts; + struct sym *syms; struct tmp *tmps; struct im *imps; struct pr *pr; diff --git a/src/prc1/pop.c b/src/prc1/pop.c index ba2f3a1..977129e 100644 --- a/src/prc1/pop.c +++ b/src/prc1/pop.c @@ -1,20 +1,28 @@ #include "prv.h" +#include "dbg.h" #include <stdlib.h> int pop(const struct lex *l, struct prv *p) { size_t n; - struct pos *pos = NULL; + struct pos *pos; + int (*end)(const struct lex *, struct prv *); + const char *name; if (!p->n) { fprintf(stderr, "%s: underflow\n", __func__); return -1; } - else if (!(n = p->n - 1)) + + pos = &p->pos[p->i]; + end = pos->end; + name = pos->name; + + if (!(n = p->n - 1)) { free(p->pos); - p->pos = NULL; + p->pos = pos = NULL; } else if (!(pos = realloc(p->pos, n * sizeof *pos))) { @@ -22,16 +30,18 @@ int pop(const struct lex *l, struct prv *p) return -1; } + ddbg("pop rule %s [%zu]", name, p->i); + + if (end) + ddbg(", end=%p", end); + + ddbg("\n"); p->pos = pos; p->n = n; + p->i--; - if (p->n) - { - const struct pos *old = &p->pos[--p->i]; - - if (old->end && old->end(l, p)) - return -1; - } + if (end) + return end(l, p); return 0; } 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; } diff --git a/src/prc1/prc1.c b/src/prc1/prc1.c index 2822cc5..634608b 100644 --- a/src/prc1/prc1.c +++ b/src/prc1/prc1.c @@ -41,7 +41,14 @@ int main(int argc, char *argv[]) fname = args.src; } - l.loc.f = fname; + if (!(l.loc.f = malloc(strlen(fname) + 1))) + { + perror("malloc(3)"); + goto end; + } + else + strcpy(l.loc.f, fname); + l.args = a.args = &args; if (lex(&l, f) || parse(&l, &a) || cgen(&a, &c)) diff --git a/src/prc1/print.c b/src/prc1/print.c index abdb149..e257b8b 100644 --- a/src/prc1/print.c +++ b/src/prc1/print.c @@ -1,14 +1,16 @@ #include "print.h" +#include "dbg.h" #include "errloc.h" #include "fn.h" #include "lit.h" #include "parse.h" #include "prv.h" #include "stmt.h" -#include "storage.h" +#include "sym.h" #include "type.h" #include <stdlib.h> -#include <string.h> + +#if 0 static int entry(const struct lex *l, const struct tk *tk, struct print *pr, struct prv *p) @@ -58,46 +60,160 @@ static int entry(const struct lex *l, const struct tk *tk, struct print *pr, return 0; } +#endif -void print_free(struct print *pr) +static int etc(const struct lex *, struct prv *); + +static const struct seq seqs[] = { - free(pr->entries); -} + {(struct step[]){{ID, "etc"}, {0}}, .fn = etc}, + {0} +}; -int print(const struct lex *l, struct prv *p, - int (*fn)(const struct lex *, const struct prv *, const struct print *)) +static const struct sym *inner(const struct sym *s) { - const struct tk *tk = p->stk + 1; - struct print pr = {0}; - struct pos *pos = &p->pos[p->i]; - int eof; + for (; s; s = s->child) + if (!s->child) + break; - if (lex_eof(l, tk)) + return s; +} + +static int fill(struct prv *p, const struct sym *s, struct prisym *ps) +{ + switch (s->type) { - errloc(tk - 1, "incomplete %s statement", p->stk->s); + case SYM_LIT: + if (!(ps->u.lit = lit_push(s->tk, p))) + return -1; + + ps->type = PRS_LIT; + break; + + case SYM_ID: + case SYM_TMP: + case SYM_NUM: + fprintf(stderr, "%s: TODO\n", __func__); + return -1; + + case SYM_CAST: + case SYM_ADDR: + case SYM_SZ: + case SYM_CNT: + case SYM_OFF: + fprintf(stderr, "%s: unreachable\n", __func__); return -1; } - for (;;) - if (entry(l, tk, &pr, p)) - goto failure; - else if ((eof = lex_eof(l, ++tk)) || kw(tk->s)) - break; + return 0; +} - if (eof || strcmp(tk->s, "etc")) - pr.println = 1; - else if (!eof) - tk++; +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 (fn(l, p, &pr)) - goto failure; + if (!(syms = realloc(pr->syms, n * sizeof *syms))) + { + perror("realloc(3)"); + return -1; + } - pos->seq = pos->stseq = stmts; - pos->step = stmts->steps; - p->stk = tk; - return 1; + pr->syms = syms; + nsym = &syms[pr->nsyms++]; + *nsym = (struct prisym){.s = s}; + return fill(p, inner(s), nsym); +} -failure: - print_free(&pr); +static int cg_str(const struct prisym *s, const char *f) +{ + fprintf(stderr, "%s: TODO\n", __func__); + return -1; +} + +static int cg_ptr(const struct prisym *s, const char *f) +{ + fprintf(stderr, "%s: TODO\n", __func__); return -1; } + +static int cg_num(const struct prisym *s, const char *f) +{ + fprintf(stderr, "%s: TODO\n", __func__); + return -1; +} + +static int cg_lit(const struct prisym *s, const char *f) +{ + const struct lit *l = s->u.lit; + const char *tmp; + + if (!l) + { + fprintf(stderr, "%s: unexpected null literal\n", __func__); + return -1; + } + + /* TODO: ask target for sizeof (void *) */ + tmp = cgen_tmp(sizeof (void *)); + printf("%%%s =l loadl $%s\n", tmp, f); + printf("call $fputs(l $%s, w %%%s)\n", l->name, tmp); + return 0; +} + +int print_cgen(const struct print *pr, struct cgen *c, const char *f) +{ + for (size_t i = 0; i < pr->nsyms; i++) + { + const struct prisym *ps = &pr->syms[i]; + static int (*fn[])(const struct prisym *, const char *) = + { + [PRS_LIT] = cg_lit, + [PRS_STR] = cg_str, + [PRS_PTR] = cg_ptr, + [PRS_NUM] = cg_num + }; + + if (fn[ps->type](ps, f)) + return -1; + } + + if (!pr->skipln) + { + printf("%%v =l loadl $%s\n", f); + puts("call $fputc(l 10 , w %v)"); + } + + return 0; +} + +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); +} diff --git a/src/prc1/print.h b/src/prc1/print.h index 950e0bc..541c597 100644 --- a/src/prc1/print.h +++ b/src/prc1/print.h @@ -3,24 +3,29 @@ #include "cgen.h" #include "lex.h" +#include "prv.h" #include <stddef.h> -struct prientry +struct prisym { - const struct tk *tk; - const struct lit *lit; - const struct stentry *entry; + enum {PRS_LIT, PRS_STR, PRS_PTR, PRS_NUM} type; + const struct sym *s; + + union + { + const struct lit *lit; + } u; }; struct print { - struct prientry *entries; - size_t nentries; - int println; + struct prisym *syms; + size_t nsyms; + int skipln; }; -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); +int print_cgen(const struct print *pr, struct cgen *c, const char *f); void print_free(struct print *p); #endif diff --git a/src/prc1/prv.h b/src/prc1/prv.h index c0c8930..e3658bc 100644 --- a/src/prc1/prv.h +++ b/src/prc1/prv.h @@ -10,11 +10,11 @@ struct step { enum tktype type; const char *id; - int chain; }; struct pos { + const char *name; const struct seq *seq, *stseq; const struct step *step; int (*end)(const struct lex *, struct prv *); @@ -29,23 +29,24 @@ struct prv struct ast *ast; struct type *ag, *t; struct fn *proto; - size_t n, i, block; + size_t n, i, block, cast; + struct sym *s; int (*entry)(const struct lex *, struct prv *); int (*type)(const struct lex *, struct prv *p, const struct type *t); + int (*sym)(const struct lex *, struct prv *, const struct sym *); }; struct seq { const struct step *steps; int (*fn)(const struct lex *l, struct prv *p); - int (*end)(const struct lex *l, struct prv *p); - const char *chain; }; int kw(const char *s); int prev(const struct prv *p); int push(const struct pos *pos, struct prv *p); int pop(const struct lex *l, struct prv *p); +void reset(struct prv *p); char *sdup(const char *s); #endif diff --git a/src/prc1/push.c b/src/prc1/push.c index 1a9056d..2354305 100644 --- a/src/prc1/push.c +++ b/src/prc1/push.c @@ -1,10 +1,11 @@ #include "prv.h" +#include "dbg.h" #include <stdlib.h> int push(const struct pos *pos, struct prv *p) { size_t n = p->n + 1; - struct pos *npos = realloc(p->pos, n * sizeof *npos); + struct pos *npos = realloc(p->pos, n * sizeof *npos), *pp; if (!npos) { @@ -15,13 +16,21 @@ int push(const struct pos *pos, struct prv *p) { struct pos *prev = &npos[p->n - 1]; - prev->end = prev->seq->end; prev->seq = prev->stseq; prev->step = prev->seq->steps; p->i++; } - npos[p->n++] = *pos; + ddbg("push rule %s [%zu]", pos->name, p->n); + + if (pos->end) + ddbg(", end=%p", pos->end); + + ddbg("\n"); + pp = &npos[p->n++]; + *pp = *pos; + pp->stseq = pp->seq; + pp->step = pp->seq->steps; p->pos = npos; return 0; } diff --git a/src/prc1/reset.c b/src/prc1/reset.c new file mode 100644 index 0000000..53145f1 --- /dev/null +++ b/src/prc1/reset.c @@ -0,0 +1,10 @@ +#include "prv.h" + +void reset(struct prv *p) +{ + struct pos *pos = &p->pos[p->i]; + + pos->seq = pos->stseq; + pos->step = pos->seq->steps; + p->stk = p->tk; +} diff --git a/src/prc1/set.c b/src/prc1/set.c index 3b83fc9..43d600b 100644 --- a/src/prc1/set.c +++ b/src/prc1/set.c @@ -8,12 +8,23 @@ #include "prv.h" #include "stmt.h" #include "storage.h" +#include "sym.h" #include "type.h" #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> +static int to(const struct lex *, struct prv *); + +static const struct seq seqs[] = +{ + {(struct step[]){{ID, "to"}, {0}}, .fn = to}, + {0} +}; + +#if 0 + static int mv(const struct lex *l, struct prv *p); static int maddr(const struct lex *l, struct prv *p); static int msz(const struct lex *l, struct prv *p); @@ -132,29 +143,6 @@ static unsigned long long tonum(const char *s) return v; } -static int dst(const struct lex *l, const struct tk *tk, struct set *s, - struct prv *p) -{ - const struct stentry *e = fn_var(fn_cur(p), tk); - size_t n = s->ndsts + 1; - struct setdst *dsts; - - if (!e) - { - errloc(tk, "undefined reference to \"%s\"", tk->s); - return -1; - } - else if (!(dsts = realloc(s->dsts, n * sizeof *dsts))) - { - perror("realloc(3)"); - return -1; - } - - s->dsts = dsts; - s->dsts[s->ndsts++] = (struct setdst){.entry = e}; - return 0; -} - static int checkzero(const struct tk *tk, const struct set *s, unsigned long long v) { @@ -260,7 +248,7 @@ static int mv(const struct lex *l, struct prv *p) } } - dbg("\t\tadding set "); + dbg("\t\tadd set "); for (size_t i = 0; i < s->ndsts; i++) dbg("%s ", s->dsts[i].entry->tk->s); @@ -308,7 +296,7 @@ static int maddr(const struct lex *l, struct prv *p) s->type = SET_ADDR; s->src = e; p->stk = ++tk; - dbg("\t\tadding set "); + dbg("\t\tadd set "); for (size_t i = 0; i < s->ndsts; i++) dbg("%s ", s->dsts[i].entry->tk->s); @@ -369,7 +357,7 @@ static int msz(const struct lex *l, struct prv *p) s->type = SET_VAL; p->stk = ++tk; - dbg("\t\tadding set "); + dbg("\t\tadd set "); for (size_t i = 0; i < s->ndsts; i++) dbg("%s ", s->dsts[i].entry->tk->s); @@ -392,7 +380,7 @@ static int mimb(const struct lex *l, struct prv *p) /* skip "to" */ tk++; - dbg("\t\tadding set "); + dbg("\t\tadd set "); for (size_t i = 0; i < s->ndsts; i++) dbg("%s ", s->dsts[i].entry->tk->s); @@ -428,7 +416,7 @@ static int mimb(const struct lex *l, struct prv *p) p->stk = ++tk; return 1; } - +#endif void set_free(struct set *m) { if (m) @@ -511,43 +499,78 @@ int set_cgen(const struct set *s, struct cgen *c) return 0; } -int set(const struct lex *l, struct prv *p) +static int to(const struct lex *l, struct prv *p) { - const struct tk *next = p->tk; - const char *ns; - struct fn *fn = fn_cur(p); - size_t n = fn->nstmts + 1; - struct stmt *stmts; + fprintf(stderr, "%s: TODO\n", __func__); + return -1; +} + +static int dst(const struct lex *l, struct prv *p, const struct sym *s) +{ + const struct fn *fn = fn = fn_cur(p); + struct stmt *stmt = stmt_cur(p); - if (lex_eof(l, next)) + if (sym_rval(s)) { - errloc(next - 1, "incomplete set statement"); + errloc(p->stk, "expression is not assignable"); return -1; } - else if (kw((ns = next->s))) + + fprintf(stderr, "%s: TODO\n", __func__); + return -1; +#if 0 + const struct stentry *e; + size_t n = s->ndsts + 1; + struct setdst *dsts; + + if (rval()) + + if (!(e = fn_var(fn, ))) { - errloc(next, "incomplete set statement"); + errloc(tk, "undefined reference to \"%s\"", tk->s); return -1; } - else if (!(stmts = realloc(fn->stmts, n * sizeof *stmts))) + else if (!(dsts = realloc(s->dsts, n * sizeof *dsts))) { perror("realloc(3)"); return -1; } - fn->stmts = stmts; - fn->stmts[fn->nstmts++] = (struct stmt){.type = SET}; + s->dsts = dsts; + s->dsts[s->ndsts++] = (struct setdst){.entry = e}; + return 0; +#endif +} + +static int finalize(const struct lex *l, struct prv *p) +{ + fprintf(stderr, "%s: TODO\n", __func__); + return -1; +} +int set(const struct lex *l, struct prv *p) +{ + 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 = finalize }; + if (!(stmts = realloc(fn->stmts, n * sizeof *stmts))) + { + perror("realloc(3)"); + return -1; + } + + fn->stmts = stmts; + fn->stmts[fn->nstmts++] = (struct stmt){.type = SET}; + if (push(&init, p)) return -1; - p->stk = p->tk; - return 1; + return sym(p, dst); } diff --git a/src/prc1/set.h b/src/prc1/set.h index fdd067a..985f28b 100644 --- a/src/prc1/set.h +++ b/src/prc1/set.h @@ -3,7 +3,6 @@ #include "cgen.h" #include "lex.h" -#include "parse.h" #include "prv.h" #include "storage.h" #include <stddef.h> diff --git a/src/prc1/stmt.c b/src/prc1/stmt.c index 8d2fdd4..d44f392 100644 --- a/src/prc1/stmt.c +++ b/src/prc1/stmt.c @@ -14,7 +14,8 @@ void stmt_free(struct stmt *s) switch (s->type) { case DISPLAY: - display_free(&s->u.display); + case WARN: + print_free(&s->u.print); break; case SET: set_free(&s->u.set); @@ -22,9 +23,6 @@ void stmt_free(struct stmt *s) case CALL: call_free(&s->u.call); break; - case WARN: - warn_free(&s->u.warn); - break; case FROM: from_free(&s->u.from); break; @@ -39,13 +37,13 @@ int stmt_cgen(const struct stmt *s, struct cgen *c) switch (s->type) { case DISPLAY: - return display_cgen(&s->u.display, c); + return display_cgen(&s->u.print, c); case SET: return set_cgen(&s->u.set, c); case CALL: return call_cgen(&s->u.call, c); case WARN: - return warn_cgen(&s->u.warn, c); + return warn_cgen(&s->u.print, c); case FROM: return from_cgen(&s->u.from, c); case END: @@ -65,14 +63,8 @@ struct stmt *stmt_cur(const struct prv *p) const struct seq stmts[] = { - {(struct step[]){ - {ID, "display"}, {ANY, NULL, 1}, {ID, "etc"}, {0}}, .fn = display}, - {(struct step[]) - {{ID, "display"}, {ANY, NULL, 1}, {0}}, .fn = display}, - {(struct step[]){ - {ID, "warn"}, {ANY, NULL, 1}, {ID, "etc"}, {0}}, .fn = warn}, - {(struct step[]) - {{ID, "warn"}, {ANY, NULL, 1}, {0}}, .fn = warn}, + {(struct step[]){{ID, "display"}, {0}}, .fn = display}, + {(struct step[]){{ID, "warn"}, {0}}, .fn = warn}, {(struct step[]) {{ID, "from"}, {ANY}, {ID, "to"}, {ANY}, {ID, "using"}, {ID}, {ID, "by"}, {ANY}, {0}}, .fn = from_idby}, @@ -84,9 +76,9 @@ const struct seq stmts[] = .fn = from_id}, {(struct step[]) {{ID, "from"}, {ANY}, {ID, "to"}, {ANY}, {0}}, .fn = from}, + {(struct step[]){{ID, "call"}, {ID}, {0}}, .fn = call}, {(struct step[]){{ID, "exit"}, {0}}, .fn = s_exit}, {(struct step[]){{ID, "set"}, {0}}, .fn = set}, - {(struct step[]){{ID, "call"}, {0}}, .fn = call}, {(struct step[]){{ID, "end"}, {0}}, .fn = end}, {0} }; diff --git a/src/prc1/stmt.h b/src/prc1/stmt.h index 5cc650d..c23239d 100644 --- a/src/prc1/stmt.h +++ b/src/prc1/stmt.h @@ -2,13 +2,12 @@ #define STMTS_H #include "cgen.h" +#include "print.h" #include "prv.h" #include "call.h" -#include "display.h" #include "end.h" #include "from.h" #include "set.h" -#include "warn.h" struct stmt { @@ -26,10 +25,9 @@ struct stmt union { - struct display display; + struct print print; struct set set; struct call call; - struct warn warn; struct from from; struct end end; } u; diff --git a/src/prc1/storage.c b/src/prc1/storage.c index 828ca1b..5ffff92 100644 --- a/src/prc1/storage.c +++ b/src/prc1/storage.c @@ -116,9 +116,7 @@ static int stpush(const struct lex *l, struct prv *p, const struct tk *name, } } - if (pop(l, p)) - goto end; - else if (!(entries = realloc(st->entries, n * sizeof *entries))) + if (!(entries = realloc(st->entries, n * sizeof *entries))) { perror("realloc(3)"); goto end; @@ -139,12 +137,12 @@ static int stpush(const struct lex *l, struct prv *p, const struct tk *name, p->stk = p->tk; if (p->proto) - fputc('\t', stderr); + dbg("\t"); - dbg("\tadding %s (%d:%d) to %s, type %s, offset %zu, size %zu\n", + dbg("\tadd %s (%d:%d) to %s, type %s, offset %zu, size %zu\n", name->s, loc->line, loc->col, st->name, tname, entries[st->nentries - 1].offset, t->sz); - ret = 1; + ret = 0; end: free(tname); return ret; @@ -188,9 +186,8 @@ int storage(const struct lex *l, struct prv *p, const char *name, int check, struct storage *st = NULL; struct pos init = { - .seq = seqs, - .stseq = seqs, - .step = seqs->steps + .name = __func__, + .seq = seqs }; if (*out) @@ -212,7 +209,7 @@ int storage(const struct lex *l, struct prv *p, const char *name, int check, *st = (struct storage){.name = name, .tk = p->stk, .check = check}; *out = p->st = st; p->stk = p->tk; - return 1; + return 0; failure: free(st); diff --git a/src/prc1/sym.c b/src/prc1/sym.c new file mode 100644 index 0000000..90ec760 --- /dev/null +++ b/src/prc1/sym.c @@ -0,0 +1,495 @@ +#include "sym.h" +#include "errloc.h" +#include "fn.h" +#include "lex.h" +#include "parse.h" +#include "prv.h" +#include "storage.h" +#include "type.h" +#include <stdio.h> +#include <stdlib.h> + +static int addr(const struct lex *, struct prv *); +static int cnt(const struct lex *, struct prv *); +static int off(const struct lex *, struct prv *); +static int szof(const struct lex *, struct prv *); +static int idof(const struct lex *, struct prv *); +static int numof(const struct lex *, struct prv *); +static int cast(const struct lex *, struct prv *); +static int to(const struct lex *, struct prv *); +static int lit(const struct lex *, struct prv *); +static int num(const struct lex *, struct prv *); +static int id(const struct lex *, struct prv *); + +static const struct seq seqs[] = +{ + {(struct step[]){{ID, "address"}, {ID, "of"}, {0}}, .fn = addr}, + {(struct step[]){{ID, "contents"}, {ID, "of"}, {0}}, .fn = cnt}, + {(struct step[]){{ID, "offset"}, {ID, "of"}, {0}}, .fn = off}, + {(struct step[]){{ID, "size"}, {ID, "of"}, {0}}, .fn = szof}, + {(struct step[]){{ID, "cast"}, {0}}, .fn = cast}, + {(struct step[]){{ID}, {ID, "of"}, {0}}, .fn = idof}, + {(struct step[]){{NUM}, {ID, "of"}, {0}}, .fn = numof}, + {(struct step[]){{LIT}, {0}}, .fn = lit}, + {(struct step[]){{NUM}, {0}}, .fn = num}, + {(struct step[]){{ID}, {0}}, .fn = id}, + {0} +}; + +static const struct seq cast_seqs[] = +{ + {(struct step[]){{ID, "to"}, {0}}, .fn = to}, + {0} +}; + +static void queue(struct prv *p, struct sym *s) +{ + struct sym *ss = p->s; + + s->tk = p->stk; + + if (!ss) + p->s = s; + else + { + while (ss->child) + ss = ss->child; + + ss->child = s; + s->parent = ss; + } + + reset(p); +} + +static int pushsym(struct prv *p, enum symtype t) +{ + struct sym *s = malloc(sizeof *s); + + if (!s) + { + perror("malloc(3)"); + return -1; + } + + *s = (struct sym){.type = t}; + queue(p, s); + return 0; +} + +static int addr(const struct lex *l, struct prv *p) +{ + return pushsym(p, SYM_ADDR); +} + +static int cnt(const struct lex *l, struct prv *p) +{ + return pushsym(p, SYM_CNT); +} + +static int off(const struct lex *l, struct prv *p) +{ + return pushsym(p, SYM_OFF); +} + +static int szof(const struct lex *l, struct prv *p) +{ + return pushsym(p, SYM_SZ); +} + +static void insert(struct fn *fn, struct sym *s) +{ + struct sym *ss = fn->syms; + + while (ss && ss->next) + ss = ss->next; + + if (!ss) + fn->syms = s; + else + ss->next = s; +} + +static int symbol(const struct sym *s) +{ + switch (s->type) + { + case SYM_ID: + case SYM_TMP: + case SYM_LIT: + case SYM_NUM: + return 1; + + case SYM_CAST: + case SYM_ADDR: + case SYM_SZ: + case SYM_CNT: + case SYM_OFF: + break; + } + + return 0; +} + +static struct sym *getsym(struct sym *s) +{ + for (struct sym *ss = s; ss; ss = ss->child) + if (symbol(ss)) + return ss; + + return NULL; +} + +static int idof(const struct lex *l, struct prv *p) +{ + fprintf(stderr, "%s: TODO\n", __func__); + reset(p); + return -1; +} + +static int numof(const struct lex *l, struct prv *p) +{ + fprintf(stderr, "%s: TODO\n", __func__); + reset(p); + return -1; +} + +static struct sym *inner(struct sym *s) +{ + struct sym *ret = NULL; + + for (; s; s = s->child) + if (s->type == SYM_CAST && !s->u.t) + ret = s; + + return ret; +} + +static int run(const struct lex *l, struct prv *p) +{ + struct fn *fn = fn_cur(p); + struct sym *s = p->s; + + insert(fn, s); + p->s = NULL; + + if (getsym(s)) + return p->sym(l, p, s); + + errloc(p->stk - 1, "expected identifier, literal or number"); + return -1; +} + +static int totype(const struct lex *l, struct prv *p, const struct type *t) +{ + struct sym *s = inner(p->s); + + if (!s || s->u.t) + { + errloc(p->tk - 1, "incomplete cast"); + return -1; + } + + s->u.t = t; + + if (pop(l, p)) + return -1; + + return !inner(p->s) && getsym(p->s) ? run(l, p) : 0; +} + +static int to(const struct lex *l, struct prv *p) +{ + return type(l, p, totype); +} + +static int push_to(struct prv *); + +static int endcast(const struct lex *l, struct prv *p) +{ + struct sym *s = inner(p->s); + + if (!p->cast--) + { + errloc(p->tk - 1, "incomplete cast"); + return -1; + } + else if (s) + { + if (lex_eof(l, p->tk)) + { + errloc(p->tk - 1, "incomplete cast"); + return -1; + } + else if (push_to(p)) + return -1; + } + + return 0; +} + +static int cast(const struct lex *l, struct prv *p) +{ + struct sym *s = malloc(sizeof *s); + + if (!s) + { + perror("malloc(3)"); + return -1; + } + + *s = (struct sym){.type = SYM_CAST}; + p->cast++; + queue(p, s); + return 0; +} + +static int push_to(struct prv *p) +{ + struct pos init = + { + .name = __func__, + .seq = cast_seqs, + .end = endcast + }; + + return push(&init, p); +} + +static int lit(const struct lex *l, struct prv *p) +{ + const struct tk *tk = p->stk; + struct sym *s, *cs = inner(p->s); + + if (!(s = malloc(sizeof *s))) + { + perror("malloc(3)"); + return -1; + } + + *s = (struct sym){.type = SYM_LIT, .tk = tk}; + queue(p, s); + + if (cs) + return push_to(p); + + return run(l, p); +} + +static int num(const struct lex *l, struct prv *p) +{ + fprintf(stderr, "%s: TODO\n", __func__); + reset(p); + return -1; +} + +static int id(const struct lex *l, struct prv *p) +{ + const struct tk *tk = p->stk; + struct sym *s, *cs = inner(p->s); + + if (!(s = malloc(sizeof *s))) + { + perror("malloc(3)"); + return -1; + } + + *s = (struct sym){.type = SYM_ID, .tk = tk}; + queue(p, s); + + if (cs) + return push_to(p); + + p->stk = p->tk; + return run(l, p); +} + +void sym_free(struct sym *s) +{ + struct sym *ss = s; + + while (ss) + { + struct sym *child = ss->child; + + free(ss); + ss = child; + } +} + +int sym_lval(const struct sym *s) +{ + int ret = 1; + + while (s) + { + switch (s->type) + { + case SYM_OFF: + case SYM_SZ: + case SYM_LIT: + case SYM_NUM: + case SYM_TMP: + ret = 0; + break; + + case SYM_ADDR: + if (!s->parent || s->parent->type != SYM_CNT) + ret = 0; + case SYM_ID: + case SYM_CNT: + case SYM_CAST: + break; + } + + s = s->child; + } + + return ret; +} + +static int endsym(const struct lex *l, struct prv *p) +{ + return p->s ? run(l, p) : 0; +} + +static int invalid(const struct tk *tk, const struct type *a, + const struct type *b) +{ + static int t[BUILTIN + 1][BUILTIN + 1] = + { + /* U S C P T PTR ARY BUILTIN */ + /* U */ {1, 0, 0, 0, 0, 0, 0, 0}, + /* S */ {0, 1, 0, 0, 0, 0, 0, 0}, + /* C */ {0, 0, 1, 0, 0, 0, 0, 0}, + /* P */ {0, 0, 0, 1, 0, 1, 0, 0}, + /* T */ {0, 0, 0, 0, 1, 0, 0, 0}, + /* PTR */ {0, 0, 0, 0, 0, 1, 1, 0}, + /* ARY */ {0, 0, 0, 0, 0, 0, 1, 0}, + /* BUILTIN */ {0, 0, 0, 0, 0, 0, 0, 1} + }; + + int valid = t[a->type][b->type]; + + if (!valid) + { + char *s1 = type_name(b), *s2 = type_name(a); + + if (s1 && s2) + errloc(tk, "cannot convert \"%s\" to \"%s\"", s1, s2); + + free(s1); + free(s2); + } + + return !valid; +} + +const struct type *littype(struct prv *p) +{ + const struct fn *fn = fn_cur(p); + const struct type *byte = type_find(fn, "byte"); + struct type *bytedup = NULL, *t = NULL; + + if (!byte) + return NULL; + else if (!(bytedup = malloc(sizeof *bytedup)) + || !(t = malloc(sizeof *t))) + { + perror("malloc(3)"); + goto failure; + } + + *bytedup = *byte; + *t = (struct type) + { + .type = ARY, + .u.ary.etc = 1, + .child = bytedup + }; + + return type_insert(p, t); + +failure: + free(t); + free(bytedup); + return NULL; +} + +const struct type *sym_type(struct prv *p, const struct sym *s) +{ + const struct fn *fn = fn_cur(p); + const struct type *ret = NULL; + + for (; s; s = s->child) + { + const struct tk *tk = s->tk; + + switch (s->type) + { + case SYM_CAST: + if (!ret) + ret = s->u.t; + else if (invalid(tk, ret, s->u.t)) + return NULL; + + break; + + case SYM_ID: + { + const struct stentry *e = fn_var(fn, tk); + + if (!e) + { + errloc(tk, "undefined reference to \"%s\"", tk->s); + return NULL; + } + else if (!ret) + ret = e->t; + else if (invalid(tk, ret, e->t)) + return NULL; + } + break; + + case SYM_LIT: + { + const struct type *lt = littype(p); + + if (!ret) + ret = lt; + else if (invalid(tk, ret, lt)) + return NULL; + } + break; + + case SYM_ADDR: + case SYM_TMP: + case SYM_NUM: + case SYM_SZ: + case SYM_CNT: + case SYM_OFF: + break; + } + } + + return ret; +} + +int sym_rval(const struct sym *s) +{ + return !sym_lval(s); +} + +int sym(struct prv *p, sym_fn fn) +{ + struct pos init = + { + .name = __func__, + .seq = seqs, + .end = endsym + }; + + p->stk = p->tk; + p->sym = fn; + return push(&init, p); +} diff --git a/src/prc1/sym.h b/src/prc1/sym.h new file mode 100644 index 0000000..17a54b3 --- /dev/null +++ b/src/prc1/sym.h @@ -0,0 +1,15 @@ +#ifndef SYM_H +#define SYM_H + +#include "lex.h" +#include "prv.h" + +typedef int (*sym_fn)(const struct lex *, struct prv *, const struct sym *); + +int sym(struct prv *p, sym_fn fn); +int sym_lval(const struct sym *s); +int sym_rval(const struct sym *s); +void sym_free(struct sym *s); +const struct type *sym_type(struct prv *p, const struct sym *s); + +#endif diff --git a/src/prc1/td.c b/src/prc1/td.c index 06572e7..af88af8 100644 --- a/src/prc1/td.c +++ b/src/prc1/td.c @@ -18,7 +18,6 @@ static int cid(const struct lex *, struct prv *); static int cnum(const struct lex *, struct prv *); static int end(const struct lex *, struct prv *); -static int endp(const struct lex *, struct prv *); static int u(const struct lex *, struct prv *); static int s(const struct lex *, struct prv *); static int c(const struct lex *, struct prv *); @@ -34,19 +33,10 @@ static const struct seq seqs[] = {(struct step[]){{ID}, {ID, "union"}, {0}}, .fn = u}, {(struct step[]){{ID}, {ID, "struct"}, {0}}, .fn = s}, {(struct step[]){{ID}, {ID, "constant"}, {0}}, .fn = c}, - {(struct step[]){{ID}, {ID, "prototype"}, {0}}, .fn = p, .end = endp}, + {(struct step[]){{ID}, {ID, "prototype"}, {0}}, .fn = p}, {0} }; -static void reset(struct prv *p) -{ - struct pos *pos = &p->pos[p->i]; - - pos->seq = seqs; - pos->step = seqs->steps; - p->stk = p->tk; -} - static int bump(const struct tk *tk, const struct type *t, struct prv *p) { struct tdconstant *tdc = p->tdc; @@ -90,6 +80,21 @@ static int bump(const struct tk *tk, const struct type *t, struct prv *p) return 0; } +static void insert(struct td *td, struct type *t) +{ + struct type *tt = td->types; + + if (!tt) + td->types = t; + else + for (; tt; tt = tt->next) + if (!tt->next) + { + tt->next = t; + break; + } +} + static int cid(const struct lex *l, struct prv *p) { const struct fn *fn = fn_cur(p); @@ -98,29 +103,26 @@ static int cid(const struct lex *l, struct prv *p) const struct type *t = type_find(fn, id->s); struct tdconstant *tdc = p->tdc; struct td *td = fn->td; - size_t n = td->ntypes + 1; - struct type *types, *nt; + struct type *nt; + const struct loc *loc; if (t) { - const struct loc *loc = &t->tk->loc; - + loc = &t->tk->loc; errloc(id, "type \"%s\" already defined at %s:%d:%d", id->s, loc->f, loc->line, loc->col); return -1; } else if ((e = fn_var(fn, id))) { - const struct loc *loc = &e->tk->loc; - + loc = &e->tk->loc; errloc(id, "\"%s\" already defined as a variable at %s:%d:%d", id->s, loc->f, loc->line, loc->col); return -1; } else if ((e = fn_var(fn, v))) { - const struct loc *loc = &e->tk->loc; - + loc = &e->tk->loc; errloc(id, "value \"%s\" (defined at %s:%d:%d) is not a constant", v->s, loc->f, loc->line, loc->col); return -1; @@ -132,20 +134,17 @@ static int cid(const struct lex *l, struct prv *p) } else if (t->type != C) { - const struct loc *loc = &t->tk->loc; - + loc = &t->tk->loc; errloc(id, "value \"%s\" (defined at %s:%d:%d) is not a constant", v->s, loc->f, loc->line, loc->col); return -1; } - else if (!(types = realloc(td->types, n * sizeof *types))) + else if (!(nt = malloc(sizeof *nt))) { - perror("realloc(3)"); + perror("malloc(3)"); return -1; } - td->types = types; - nt = &td->types[td->ntypes++]; *nt = (struct type) { .type = C, @@ -154,6 +153,7 @@ static int cid(const struct lex *l, struct prv *p) .u.c = t->u.c }; + insert(td, nt); tdc->neg = t->sign; if (bump(id, t, p)) @@ -162,9 +162,11 @@ static int cid(const struct lex *l, struct prv *p) for (size_t i = 0; i < p->block; i++) dbg("\t"); - dbg("\tadding constant %s to %s (%lld)\n", id->s, v->s, t->u.c.v); + loc = &id->loc; + dbg("\tadd constant %s (%d:%d) to %s (%lld)\n", id->s, loc->line, + loc->col, v->s, t->u.c.v); reset(p); - return 1; + return 0; } static int cnum(const struct lex *l, struct prv *p) @@ -174,12 +176,12 @@ static int cnum(const struct lex *l, struct prv *p) const char *name = id->s; const struct stentry *e; struct td *td = fn->td; - size_t n = td->ntypes + 1; - struct type *types, *nt; + struct type *nt; struct tdconstant *tdc = p->tdc; const struct type *t = type_find(fn, name); int sign = *num->s == '-'; unsigned long long uv = 0; + const struct loc *loc; long long v; char *end; @@ -194,28 +196,24 @@ static int cnum(const struct lex *l, struct prv *p) if (t) { - const struct loc *loc = &t->tk->loc; - + loc = &t->tk->loc; errloc(id, "type \"%s\" already defined at %s:%d:%d", name, loc->f, loc->line, loc->col); return -1; } else if ((e = fn_var(fn, id))) { - const struct loc *loc = &e->tk->loc; - + loc = &e->tk->loc; errloc(id, "\"%s\" already defined as a variable at %s:%d:%d", id->s, loc->f, loc->line, loc->col); return -1; } - else if (!(types = realloc(td->types, n * sizeof *types))) + else if (!(nt = malloc(sizeof *nt))) { - perror("realloc(3)"); + perror("malloc(3)"); return -1; } - td->types = types; - nt = &td->types[td->ntypes++]; *nt = (struct type) { .type = C, @@ -228,18 +226,21 @@ static int cnum(const struct lex *l, struct prv *p) else tdc->u.uv = nt->u.c.uv = uv; + insert(td, nt); tdc->neg = sign; for (size_t i = 0; i < p->block; i++) dbg("\t"); - dbg("\tadding constant %s to %s\n", id->s, num->s); + loc = &id->loc; + dbg("\tadd constant %s (%d:%d) to %s\n", id->s, loc->line, loc->col, + num->s); if (bump(id, nt, p)) return -1; reset(p); - return 1; + return 0; } static int c(const struct lex *l, struct prv *p) @@ -249,34 +250,30 @@ static int c(const struct lex *l, struct prv *p) const struct stentry *e; const struct type *t = type_find(fn, id->s); struct td *td = fn->td; - size_t n = td->ntypes + 1; - struct type *types, *nt; + struct type *nt; const struct tdconstant *tdc = p->tdc; + const struct loc *loc; if (t) { - const struct loc *loc = &t->tk->loc; - + loc = &t->tk->loc; errloc(id, "type \"%s\" already defined at %s:%d:%d", id->s, loc->f, loc->line, loc->col); return -1; } else if ((e = fn_var(fn, id))) { - const struct loc *loc = &e->tk->loc; - + loc = &e->tk->loc; errloc(id, "\"%s\" already defined as a variable at %s:%d:%d", id->s, loc->f, loc->line, loc->col); return -1; } - else if (!(types = realloc(td->types, n * sizeof *types))) + else if (!(nt = malloc(sizeof *nt))) { - perror("realloc(3)"); + perror("malloc(3)"); return -1; } - td->types = types; - nt = &td->types[td->ntypes]; *nt = (struct type) { .type = C, @@ -289,31 +286,33 @@ static int c(const struct lex *l, struct prv *p) else nt->u.c.uv = tdc->u.uv; + insert(td, nt); + for (size_t i = 0; i < p->block; i++) dbg("\t"); - dbg("\tadding constant %s to ", id->s); + loc = &id->loc; + dbg("\tadd constant %s (%d:%d) to ", id->s, loc->line, loc->col); if (tdc->neg) dbg("%lld", tdc->u.v); else dbg("%llu", tdc->u.uv); - dbg("\n", stderr); + dbg("\n"); - if (bump(id, &td->types[td->ntypes++], p)) + if (bump(id, nt, p)) return -1; reset(p); - return 1; + return 0; } static int p(const struct lex *l, struct prv *p) { struct fn *fn = fn_cur(p), *pt = NULL; struct td *td = fn->td; - size_t n = td->ntypes + 1; - struct type *types; + struct type *nt = NULL; if (!(pt = malloc(sizeof *pt))) { @@ -323,28 +322,30 @@ static int p(const struct lex *l, struct prv *p) *pt = (struct fn){.tk = p->stk, .parent = fn}; - if (!(types = realloc(td->types, n * sizeof *types))) + if (!(nt = malloc(sizeof *nt))) { - perror("realloc(3)"); + perror("malloc(3)"); goto failure; } - types[td->ntypes++] = (struct type) + *nt = (struct type) { .type = P, .tk = p->stk, + /* TODO: use frontend-specific pointer size */ .sz = sizeof (void *), .align = sizeof (void *), .u.p.fn = pt }; - td->types = types; + insert(td, nt); p->proto = pt; - dbg("\tadding prototype %s\n", p->stk->s); + dbg("\tadd prototype %s\n", p->stk->s); return div_p(l, p); failure: free(pt); + type_free(nt); return -1; } @@ -364,7 +365,7 @@ static int ends(struct type *t) t->align = st->entries->t->align; t->sz = e->offset + e->t->sz; t->sz += t->align - (t->sz % t->align); - dbg("\tadding struct %s, size %zu, align %zu\n", t->tk->s, t->sz, t->align); + dbg("\tadd struct %s, size %zu, align %zu\n", t->tk->s, t->sz, t->align); return 0; } @@ -419,15 +420,6 @@ static int end(const struct lex *l, struct prv *p) p->ag = NULL; p->block--; reset(p); - return 1; -} - -static int endp(const struct lex *l, struct prv *p) -{ - if (fn_end(l, p)) - return -1; - - p->proto = NULL; return 0; } @@ -436,8 +428,7 @@ static int s(const struct lex *l, struct prv *p) const struct tk *id = p->stk; struct fn *fn = fn_cur(p); struct td *td = fn->td; - size_t nt = td->ntypes + 1; - struct type *types, *newt; + struct type *nt; const struct type *t = type_find(fn, id->s); if (t) @@ -448,23 +439,22 @@ static int s(const struct lex *l, struct prv *p) loc->line, loc->col); return -1; } - else if (!(types = realloc(td->types, nt * sizeof *types))) + else if (!(nt = malloc(sizeof *nt))) { perror("realloc(3)"); return -1; } - td->types = types; - newt = &td->types[td->ntypes++]; - *newt = (struct type) + *nt = (struct type) { .type = S, .tk = id }; - p->ag = newt; + p->ag = nt; p->block++; - return storage(l, p, id->s, 0, &newt->u.s.storage); + insert(td, nt); + return storage(l, p, id->s, 0, &nt->u.s.storage); } static int u(const struct lex *l, struct prv *p) @@ -481,8 +471,7 @@ static int tt(const struct lex *l, struct prv *p, const struct type *t) const struct type *tp = type_ufind(fn, id->s); const struct loc *loc = &id->loc; struct td *td = fn->td; - size_t n = td->ntypes + 1; - struct type *types, *nt; + struct type *nt; char *s = type_name(t); if (!s) @@ -495,16 +484,12 @@ static int tt(const struct lex *l, struct prv *p, const struct type *t) loc->line, loc->col); goto end; } - else if (pop(l, p)) - return -1; - else if (!(types = realloc(td->types, n * sizeof *types))) + else if (!(nt = malloc(sizeof *nt))) { perror("realloc(3)"); goto end; } - td->types = types; - nt = &td->types[td->ntypes++]; *nt = (struct type) { .type = T, @@ -512,10 +497,11 @@ static int tt(const struct lex *l, struct prv *p, const struct type *t) .u.t.alias = t }; - dbg("\tadding %s (%d:%d) alias %s\n", id->s, loc->line, loc->col, s); + dbg("\tadd %s (%d:%d) alias %s\n", id->s, loc->line, loc->col, s); + insert(td, nt); reset(p); p->id = NULL; - ret = 1; + ret = 0; end: free(s); return ret; @@ -530,12 +516,11 @@ static int a(const struct lex *l, struct prv *p) void td_free(struct td *td) { if (td) - { - for (size_t i = 0; i < td->ntypes; i++) - type_free(&td->types[i]); - - free(td->types); - } + for (struct type *t = td->types, *next; t; t = next) + { + next = t->next; + type_lfree(t); + } free(td); } @@ -548,9 +533,8 @@ int td(const struct lex *l, struct prv *p) struct tdconstant *tdc = NULL; struct pos init = { - .seq = seqs, - .stseq = seqs, - .step = seqs->steps + .name = __func__, + .seq = seqs }; if (prev) @@ -575,7 +559,7 @@ int td(const struct lex *l, struct prv *p) fn->td = td; p->tdc = tdc; p->stk = p->tk; - return 1; + return 0; failure: free(tdc); diff --git a/src/prc1/type.c b/src/prc1/type.c index c7e43d0..b7f6882 100644 --- a/src/prc1/type.c +++ b/src/prc1/type.c @@ -17,8 +17,7 @@ static int t(const struct lex *l, struct prv *p); static const struct seq seqs[] = { - {(struct step[]) - {{ID, "array"}, {ID, "of"}, {ID, "etc"}, {0}}, .fn = aetc}, + {(struct step[]){{ID, "array"}, {ID, "of"}, {ID, "etc"}, {0}}, .fn = aetc}, {(struct step[]){{ID, "array"}, {ID, "of"}, {NUM}, {0}}, .fn = anum}, {(struct step[]){{ID, "array"}, {ID, "of"}, {ID}, {0}}, .fn = aid}, {(struct step[]){{ID, "pointer"}, {ID, "to"}, {0}}, .fn = p}, @@ -77,8 +76,13 @@ void type_free(struct type *t) void type_lfree(struct type *t) { - if (t->child) - type_lfree(t->child); + if (t) + { + if (t->child) + type_lfree(t->child); + + type_free(t); + } free(t); } @@ -186,13 +190,9 @@ const struct type *type_ufind(const struct fn *fn, const char *s) } if (td) - for (size_t i = 0; i < td->ntypes; i++) - { - const struct type *t = &td->types[i]; - + for (const struct type *t = td->types; t; t = t->next) if (!strcmp(t->tk->s, s)) return t; - } for (size_t i = 0; i < fn->nimps; i++) { @@ -215,10 +215,9 @@ const struct type *type_find(const struct fn *fn, const char *s) return t; } -static int queue(struct prv *p, struct type *t) +static void queue(struct prv *p, struct type *t) { struct type *tt; - struct pos *pos = &p->pos[p->i]; if (!(tt = p->t)) p->t = t; @@ -230,10 +229,8 @@ static int queue(struct prv *p, struct type *t) tt->child = t; } - pos->seq = pos->stseq; - pos->step = pos->seq->steps; p->stk = p->tk; - return 1; + reset(p); } static int aetc(const struct lex *l, struct prv *p) @@ -255,12 +252,13 @@ static int aetc(const struct lex *l, struct prv *p) if (!(t = malloc(sizeof *t))) { - perror("malloc"); + perror("malloc(3)"); return -1; } *t = (struct type){.type = ARY, .u.ary.etc = 1}; - return queue(p, t); + queue(p, t); + return 0; } static int aid(const struct lex *l, struct prv *p) @@ -294,12 +292,13 @@ static int aid(const struct lex *l, struct prv *p) } else if (!(t = malloc(sizeof *t))) { - perror("malloc"); + perror("malloc(3)"); return -1; } *t = (struct type){.type = ARY, .u.ary.n = v}; - return queue(p, t); + queue(p, t); + return 0; } static int anum(const struct lex *l, struct prv *p) @@ -320,12 +319,13 @@ static int anum(const struct lex *l, struct prv *p) } else if (!(t = malloc(sizeof *t))) { - perror("malloc"); + perror("malloc(3)"); return -1; } *t = (struct type){.type = ARY, .u.ary.n = n}; - return queue(p, t); + queue(p, t); + return 0; } static int p(const struct lex *l, struct prv *p) @@ -334,24 +334,27 @@ static int p(const struct lex *l, struct prv *p) if (!t) { - perror("malloc"); + perror("malloc(3)"); return -1; } *t = (struct type) { .type = PTR, + /* TODO: ask target for sizeof (void *) */ .sz = sizeof (void *), .align = sizeof (void *) }; if ((tt = p->t) && tt->type == ARY) { + /* TODO: ask target for sizeof (void *) */ tt->sz = tt->u.ary.n * sizeof (void *); tt->align = sizeof (void *); } - return queue(p, t); + queue(p, t); + return 0; } static int aryeq(const struct type *a, const struct type *b) @@ -372,10 +375,10 @@ static int eq(const struct type *a, const struct type *b) return !a && !b; } -static const struct type *insert(struct prv *p) +const struct type *type_insert(struct prv *p, struct type *a) { struct ast *ast = p->ast; - struct type *a = p->t, *tt = ast->types; + struct type *tt = ast->types; for (const struct type *b = ast->types; b; b = b->next) if (eq(a, b)) @@ -434,26 +437,42 @@ static int t(const struct lex *l, struct prv *p) tt->align = t->align; } - if (!(t = insert(p))) + if (!(t = type_insert(p, p->t))) return -1; - - p->t = NULL; } + else + p->t = (struct type *)t; + if (pop(l, p)) + return -1; + + p->stk = p->tk; + p->t = NULL; return p->type(l, p, t); } +static int endtype(const struct lex *l, struct prv *p) +{ + if (!p->t) + { + errloc(p->stk - 1, "expected type"); + return -1; + } + + return 0; +} + int type(const struct lex *l, struct prv *p, int (*fn)(const struct lex *, struct prv *, const struct type *)) { struct pos init = { + .name = __func__, .seq = seqs, - .stseq = seqs, - .step = seqs->steps + .end = endtype }; p->stk = p->tk; p->type = fn; - return push(&init, p) ? -1 : 1; + return push(&init, p); } diff --git a/src/prc1/type.h b/src/prc1/type.h index 7de6c28..455f243 100644 --- a/src/prc1/type.h +++ b/src/prc1/type.h @@ -7,6 +7,7 @@ const struct type *type_ufind(const struct fn *fn, const char *s); const struct type *type_find(const struct fn *fn, const char *s); +const struct type *type_insert(struct prv *p, struct type *a); char *type_name(const struct type *t); int type(const struct lex *l, struct prv *p, int (*fn)(const struct lex *, struct prv *p, const struct type *t)); diff --git a/src/prc1/warn.c b/src/prc1/warn.c index 93635db..9fb535e 100644 --- a/src/prc1/warn.c +++ b/src/prc1/warn.c @@ -1,6 +1,7 @@ #include "warn.h" #include "cgen.h" #include "dbg.h" +#include "fn.h" #include "parse.h" #include "prv.h" #include "stmt.h" @@ -9,6 +10,8 @@ #include <stdlib.h> #include <string.h> +#if 0 + static int finalize(const struct lex *l, const struct prv *p, const struct print *pr) { @@ -30,7 +33,7 @@ static int finalize(const struct lex *l, const struct prv *p, .u.warn.p = *pr }; - dbg("\t\tadding warn statement with %zu entries%s\n", pr->nentries, + dbg("\t\tadd warn statement with %zu entries%s\n", pr->nentries, pr->println ? "" : ", no lf"); return 0; } @@ -135,13 +138,27 @@ int warn_cgen(const struct warn *w, struct cgen *c) return 0; } +#endif -void warn_free(struct warn *w) +int warn_cgen(const struct print *pr, struct cgen *c) { - print_free(&w->p); + return print_cgen(pr, c, "stderr"); } int warn(const struct lex *l, struct prv *p) { - return print(l, p, finalize); + struct fn *fn = fn_cur(p); + size_t n = fn->nstmts + 1; + struct stmt *stmts = realloc(fn->stmts, n * sizeof *stmts); + + if (!stmts) + { + perror("realloc(3)"); + return -1; + } + + dbg("\t\tadd warn statement\n"); + stmts[fn->nstmts++] = (struct stmt){.type = WARN, .u.print = {0}}; + fn->stmts = stmts; + return print(l, p); } diff --git a/src/prc1/warn.h b/src/prc1/warn.h index 5327592..9a50857 100644 --- a/src/prc1/warn.h +++ b/src/prc1/warn.h @@ -1,17 +1,12 @@ #ifndef WARN_H #define WARN_H +#include "cgen.h" #include "lex.h" #include "print.h" #include "prv.h" -struct warn -{ - struct print p; -}; - int warn(const struct lex *l, struct prv *p); -int warn_cgen(const struct warn *w, struct cgen *c); -void warn_free(struct warn *w); +int warn_cgen(const struct print *pr, struct cgen *c); #endif |
