diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-09-05 17:14:53 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2026-09-26 03:41:55 +0200 |
| commit | 3c0819236e4f07c8f57aaf1ca46d0d68aa761558 (patch) | |
| tree | bd8b57cf5420cabc4ec29815052df545b55026f9 /type.c | |
| parent | a3f56c76444fee090e62a59f257ed5f60b4e552b (diff) | |
| download | prc-3c0819236e4f07c8f57aaf1ca46d0d68aa761558.tar.gz | |
Move source to src/prc1
Diffstat (limited to 'type.c')
| -rw-r--r-- | type.c | 459 |
1 files changed, 0 insertions, 459 deletions
@@ -1,459 +0,0 @@ -#include "type.h" -#include "errloc.h" -#include "fn.h" -#include "lex.h" -#include "parse.h" -#include "prv.h" -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static int aetc(const struct lex *l, struct prv *p); -static int aid(const struct lex *l, struct prv *p); -static int anum(const struct lex *l, struct prv *p); -static int p(const struct lex *l, struct prv *p); -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"}, {NUM}, {0}}, .fn = anum}, - {(struct step[]){{ID, "array"}, {ID, "of"}, {ID}, {0}}, .fn = aid}, - {(struct step[]){{ID, "pointer"}, {ID, "to"}, {0}}, .fn = p}, - {(struct step[]){{ID, "void"}, {0}}, .fn = t}, - {(struct step[]){{ID, "byte"}, {0}}, .fn = t}, - {(struct step[]){{ID, "halfword"}, {0}}, .fn = t}, - {(struct step[]){{ID, "word"}, {0}}, .fn = t}, - {(struct step[]){{ID, "long"}, {0}}, .fn = t}, - {(struct step[]){{ID, "ubyte"}, {0}}, .fn = t}, - {(struct step[]){{ID, "uhalfword"}, {0}}, .fn = t}, - {(struct step[]){{ID, "uword"}, {0}}, .fn = t}, - {(struct step[]){{ID, "ulong"}, {0}}, .fn = t}, - {(struct step[]){{ID}, {0}}, .fn = t}, - {0} -}; - -void type_free(struct type *t) -{ - switch (t->type) - { - case U: - { - struct u *u = &t->u.u; - - storage_free(u->storage); - } - break; - - case S: - { - struct s *s = &t->u.s; - - storage_free(s->storage); - } - break; - - case C: - break; - - case P: - { - struct p *p = &t->u.p; - - fn_free(p->fn); - free(p->fn); - } - break; - - case T: - case ARY: - case PTR: - case BUILTIN: - break; - } -} - -void type_lfree(struct type *t) -{ - if (t->child) - type_lfree(t->child); - - free(t); -} - -static int append(const char *s, char **out) -{ - size_t n = *out ? strlen(*out) : 0; - char *ns = realloc(*out, strlen(s) + n + 1); - - if (!ns) - { - perror("realloc(3)"); - return -1; - } - - strcpy(ns + n, s); - *out = ns; - return 0; -} - -char *type_name(const struct type *t) -{ - char *ret = NULL; - - while (t) - { - int n = -1; - - switch (t->type) - { - case BUILTIN: - n = append(t->u.b.name, &ret); - break; - - case ARY: - { - const struct ary *ary = &t->u.ary; - char s[sizeof "18446744073709551615 "]; - - if (ary->etc) - snprintf(s, sizeof s, "etc "); - else - snprintf(s, sizeof s, "%llu ", t->u.ary.n); - - n = append("array of ", &ret) || append(s, &ret); - break; - } - - case PTR: - n = append("pointer to ", &ret); - break; - - case U: - case S: - case C: - case P: - case T: - n = append(t->tk->s, &ret); - break; - } - - if (n) - { - free(ret); - return NULL; - } - - t = t->child; - } - - return ret; -} - -const struct type *type_ufind(const struct fn *fn, const char *s) -{ - static const struct type builtins[] = - { - {.type = BUILTIN, .u.b.name = "void"}, - {.type = BUILTIN, .u.b.name = "byte", .sz = 1, .sign = 1, .align = 1}, - {.type = BUILTIN, .u.b.name = "halfword", .sz = 2, .sign = 1, .align = 2}, - {.type = BUILTIN, .u.b.name = "word", .sz = 4, .sign = 1, .align = 4}, - {.type = BUILTIN, .u.b.name = "long", .sz = 8, .sign = 1, .align = 8}, - {.type = BUILTIN, .u.b.name = "ubyte", .sz = 1, .align = 1}, - {.type = BUILTIN, .u.b.name = "uhalfword", .sz = 2, .align = 2}, - {.type = BUILTIN, .u.b.name = "uword", .sz = 4, .align = 4}, - {.type = BUILTIN, .u.b.name = "ulong", .sz = 8, .align = 8} - }; - - const struct td *td = fn->td; - - if (fn->parent) - { - const struct type *t = type_find(fn->parent, s); - - if (t) - return t; - } - - for (size_t i = 0; i < sizeof builtins / sizeof *builtins; i++) - { - const struct type *t = &builtins[i]; - - if (!strcmp(t->u.b.name, s)) - return t; - } - - if (td) - for (size_t i = 0; i < td->ntypes; i++) - { - const struct type *t = &td->types[i]; - - if (!strcmp(t->tk->s, s)) - return t; - } - - for (size_t i = 0; i < fn->nimps; i++) - { - const struct type *t = type_ufind(fn->imps[i].ast.fns, s); - - if (t) - return t; - } - - return NULL; -} - -const struct type *type_find(const struct fn *fn, const char *s) -{ - const struct type *t = type_ufind(fn, s); - - if (t && t->type == T) - return t->u.t.alias; - - return t; -} - -static int queue(struct prv *p, struct type *t) -{ - struct type *tt; - struct pos *pos = &p->pos[p->i]; - - if (!(tt = p->t)) - p->t = t; - else - { - while (tt->child) - tt = tt->child; - - tt->child = t; - } - - pos->seq = pos->stseq; - pos->step = pos->seq->steps; - p->stk = p->tk; - return 1; -} - -static int aetc(const struct lex *l, struct prv *p) -{ - struct type *t; - const struct type *tt = p->t; - - while (tt) - { - if (tt->type == ARY && tt->u.ary.etc) - { - errloc(p->stk, "multi-dimensional arrays " - "with unknown size are not allowed"); - return -1; - } - - tt = tt->next; - } - - if (!(t = malloc(sizeof *t))) - { - perror("malloc"); - return -1; - } - - *t = (struct type){.type = ARY, .u.ary.etc = 1}; - return queue(p, t); -} - -static int aid(const struct lex *l, struct prv *p) -{ - const struct tk *qty = p->stk + 2; - const struct type *ct = type_find(fn_cur(p), qty->s); - struct type *t; - unsigned long long v; - - if (!ct) - { - errloc(qty, "undefined reference to type \"%s\"", qty->s); - return -1; - } - else if (ct->type != C) - { - errloc(qty, "type \"%s\" not a constant", qty->s); - return -1; - } - else if (ct->sign) - { - errloc(qty, "type \"%s\" defines a negative constant (%lld)", - qty->s, ct->u.c.v); - return -1; - } - else if (!(v = ct->u.c.uv)) - { - errloc(qty, "constant \"%s\" equals zero and cannot be used " - "for array sizes", qty->s); - return -1; - } - else if (!(t = malloc(sizeof *t))) - { - perror("malloc"); - return -1; - } - - *t = (struct type){.type = ARY, .u.ary.n = v}; - return queue(p, t); -} - -static int anum(const struct lex *l, struct prv *p) -{ - const struct tk *qty = p->stk + 2; - unsigned long long n = strtoull(qty->s, NULL, 0); - struct type *t; - - if (*qty->s == '-' || errno) - { - errloc(qty, "invalid negative size for array"); - return -1; - } - else if (!n) - { - errloc(qty, "array size cannot be zero"); - return -1; - } - else if (!(t = malloc(sizeof *t))) - { - perror("malloc"); - return -1; - } - - *t = (struct type){.type = ARY, .u.ary.n = n}; - return queue(p, t); -} - -static int p(const struct lex *l, struct prv *p) -{ - struct type *t = malloc(sizeof *t), *tt; - - if (!t) - { - perror("malloc"); - return -1; - } - - *t = (struct type) - { - .type = PTR, - .sz = sizeof (void *), - .align = sizeof (void *) - }; - - if ((tt = p->t) && tt->type == ARY) - { - tt->sz = tt->u.ary.n * sizeof (void *); - tt->align = sizeof (void *); - } - - return queue(p, t); -} - -static int aryeq(const struct type *a, const struct type *b) -{ - const struct ary *aa = &a->u.ary, *ab = &b->u.ary; - - return !memcmp(aa, ab, sizeof *aa); -} - -static int eq(const struct type *a, const struct type *b) -{ - for (; a && b; a = a->child, b = b->child) - if (a->type != b->type) - return 0; - else if (a->type == ARY && !aryeq(a, b)) - return 0; - - return !a && !b; -} - -static const struct type *insert(struct prv *p) -{ - struct ast *ast = p->ast; - struct type *a = p->t, *tt = ast->types; - - for (const struct type *b = ast->types; b; b = b->next) - if (eq(a, b)) - { - type_lfree(a); - return b; - } - - if (!ast->types) - ast->types = a; - else - { - while (tt->next) - tt = tt->next; - - tt->next = a; - } - - return a; -} - -static int t(const struct lex *l, struct prv *p) -{ - const struct fn *fn = fn_cur(p); - const struct tk *tk = p->stk; - const struct type *t = type_find(fn, tk->s); - struct type *tt = p->t; - - if (!t) - { - errloc(tk, "undefined reference to type \"%s\"", tk->s); - return -1; - } - else if (tt) - { - struct type *nt = malloc(sizeof *nt); - - if (!nt) - { - perror("malloc(3)"); - return -1; - } - - *nt = *t; - - while (tt->child) - tt = tt->child; - - tt->child = nt; - tt = p->t; - - /* array size still undecided */ - if (tt->type == ARY && !tt->sz) - { - tt->sz = tt->u.ary.n * nt->sz; - tt->align = t->align; - } - - if (!(t = insert(p))) - return -1; - - p->t = NULL; - } - - return p->type(l, p, t); -} - -int type(const struct lex *l, struct prv *p, - int (*fn)(const struct lex *, struct prv *, const struct type *)) -{ - struct pos init = - { - .seq = seqs, - .stseq = seqs, - .step = seqs->steps - }; - - p->stk = p->tk; - p->type = fn; - return push(&init, p) ? -1 : 1; -} |
