summaryrefslogtreecommitdiff
path: root/storage.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2026-05-09 02:56:07 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2026-05-17 11:13:23 +0200
commit527c23b73c8dae16f02cca6f450edb7d8225f60f (patch)
tree6b2bfd9e8d814026d6d2c1839d8cfe1bcadc825c /storage.c
downloadslcob-master.tar.gz
Add project skeletonHEADmaster
Diffstat (limited to 'storage.c')
-rw-r--r--storage.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/storage.c b/storage.c
new file mode 100644
index 0000000..4b49fc2
--- /dev/null
+++ b/storage.c
@@ -0,0 +1,201 @@
+#include "storage.h"
+#include "errloc.h"
+#include "fn.h"
+#include "lex.h"
+#include "prv.h"
+#include "type.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int vab(const struct lex *l, struct prv *p);
+static int vac(const struct lex *l, struct prv *p);
+static int vb(const struct lex *l, struct prv *p);
+static int vc(const struct lex *l, struct prv *p);
+
+#define VAB(x) \
+ {(const struct step[]){{ID}, {ID, "array"}, {ID, x}, {NUM}, {0}}, .fn = vab}
+
+#define VB(x) {(const struct step[]){{ID}, {ID, x}, {0}}, .fn = vb}
+
+static const struct seq seqs[] =
+{
+ /* array with built-in type */
+ VAB("void"),
+ VAB("byte"),
+ VAB("halfword"),
+ VAB("word"),
+ VAB("long"),
+ VAB("ubyte"),
+ VAB("uhalfword"),
+ VAB("uword"),
+ VAB("ulong"),
+
+ /* array with custom type */
+ {(const struct step[]){{ID}, {ID, "array"}, {ID}, {0}}, .fn = vac},
+
+ /* var with built-in type */
+ VB("void"),
+ VB("byte"),
+ VB("halfword"),
+ VB("word"),
+ VB("long"),
+ VB("ubyte"),
+ VB("uhalfword"),
+ VB("uword"),
+ VB("ulong"),
+
+ /* var with custom type */
+ {(const struct step[]){{ID}, {ID}, {0}}, .fn = vc},
+ {0}
+};
+
+static int stpush(const struct lex *l, struct prv *p, const struct tk *tk,
+ const struct tk *type)
+{
+ const struct ast *ast = p->ast;
+ struct pos *pos = &p->pos[p->i];
+ struct stentry *entries;
+ struct storage *st = p->st;
+ size_t n = st->nentries + 1;
+ const struct type *t = type_find(&ast->fns[ast->nfns - 1], type->s);
+ const struct loc *loc = &tk->loc;
+
+ if (!t)
+ {
+ errloc(type, "undefined reference to type \"%s\"", type->s);
+ return -1;
+ }
+ else if (!t->sz)
+ {
+ errloc(type, "type \"%s\" has null size", type->s);
+ return -1;
+ }
+ else if (!(entries = realloc(st->entries, n * sizeof *entries)))
+ {
+ perror("realloc(3)");
+ return -1;
+ }
+
+ /* todo: type*/
+ entries[st->nentries++] = (struct stentry){.t = t, .tk = tk};
+ st->entries = entries;
+ p->stk = p->tk;
+ pos->seq = seqs;
+ pos->step = seqs->steps;
+ fprintf(stderr, "\tadding %s (%d:%d) to %s, type %s\n", tk->s,
+ loc->line, loc->col, st->name, type->s);
+ return 1;
+}
+
+static int vb(const struct lex *l, struct prv *p)
+{
+ const struct tk *name = p->stk, *type = p->tk - 1;
+ const struct fn *fn = fn_cur(p);
+ const struct storage *st = p->st;
+ const struct stentry *e;
+
+ if (st->check && (e = fn_var(fn, name)))
+ {
+ const struct loc *loc = &e->tk->loc;
+
+ errloc(name, "variable \"%s\" already defined at %s:%d:%d",
+ name->s, loc->f, loc->line, loc->col);
+ return -1;
+ }
+
+ /* find var in currently known symbols */
+ for (size_t i = 0; i < st->nentries; i++)
+ {
+ const struct stentry *e = &st->entries[i];
+ const struct tk *tk = e->tk;
+
+ if (!strcmp(tk->s, name->s))
+ {
+ const struct loc *loc = &tk->loc;
+
+ errloc(name, "variable \"%s\" already defined at %s:%d:%d",
+ name->s, loc->f, loc->line, loc->col);
+ return -1;
+ }
+ }
+
+ return stpush(l, p, name, type);
+}
+
+static int vc(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+
+static int vab(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+
+static int vac(const struct lex *l, struct prv *p)
+{
+ fprintf(stderr, "%s: TODO\n", __func__);
+ return -1;
+}
+
+void storage_free(struct storage *s)
+{
+ if (s)
+ free(s->entries);
+
+ free(s);
+}
+
+const struct stentry *storage_find(const char *name, const struct storage *s)
+{
+ for (size_t i = 0; i < s->nentries; i++)
+ {
+ const struct stentry *e = &s->entries[i];
+
+ if (!strcmp(name, e->tk->s))
+ return e;
+ }
+
+ return NULL;
+}
+
+int storage(const struct lex *l, struct prv *p, const char *name, int check,
+ struct storage **out)
+{
+ struct storage *st = NULL;
+ const struct tk *tk = p->tk - 1;
+ struct pos init =
+ {
+ .seq = seqs,
+ .stseq = seqs,
+ .step = seqs->steps
+ };
+
+ if (*out)
+ {
+ const struct loc *loc = &(*out)->tk->loc;
+
+ errloc(tk, "%s already defined at %s:%d:%d", name, loc->f, loc->line,
+ loc->col);
+ goto failure;
+ }
+ else if (!(st = malloc(sizeof *st)))
+ {
+ perror("malloc(3)");
+ goto failure;
+ }
+ else if (push(&init, p))
+ goto failure;
+
+ *st = (struct storage){.name = name, .tk = tk, .check = check};
+ *out = p->st = st;
+ p->stk = p->tk;
+ return 1;
+
+failure:
+ free(st);
+ return -1;
+}