aboutsummaryrefslogtreecommitdiff
path: root/type.c
diff options
context:
space:
mode:
Diffstat (limited to 'type.c')
-rw-r--r--type.c459
1 files changed, 0 insertions, 459 deletions
diff --git a/type.c b/type.c
deleted file mode 100644
index c7e43d0..0000000
--- a/type.c
+++ /dev/null
@@ -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;
-}