commit 85c2cf9d24765de0a96d19da6bd02c54e9fae58f
parent bffab73a7f79fda23ab30cebbd302c6b68c8813c
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date: Fri, 19 Apr 2024 15:48:59 -0300
Add sketch of a metaschema module
It doesn't quite work, so in the end I'll probably replace it,
if at all, with something based on S-expressions.
Diffstat:
3 files changed, 120 insertions(+), 0 deletions(-)
diff --git a/coding/metaschema.c b/coding/metaschema.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "metaschema.h"
+#include "schema.h"
+
+assoc*
+metacompile(metaschema *m, size_t len)
+{
+ assoc *a = new_assoc();
+
+ /* 1st: Create all schemas */
+ for (size_t i = 0; i < len; i++) {
+ schema *s = new_schema();
+ assoc_set(a, intern(m[i].name), s);
+ }
+
+ /* 2nd: Add all constructors */
+ for (size_t i = 0; i < len; i++) {
+ schema *s = assoc_get(a, intern(m[i].name));
+ for (size_t j = 0; j < SIZE(m[i].constructors); j++) {
+ printf("Adding constructor %s\n", m[i].constructors[j].head);
+ add_constructor(s, intern(m[i].constructors[j].head));
+ }
+ }
+
+ return a;
+}
diff --git a/coding/metaschema.h b/coding/metaschema.h
@@ -0,0 +1,28 @@
+#include <stdlib.h>
+
+#include "assoc.h"
+#include "schema.h"
+
+#define metalen(M) (sizeof(M)/sizeof(metaschema))
+#define SIZE(X) (sizeof(X)/sizeof(X[0]))
+
+typedef struct metaschema metaschema;
+typedef struct metaconstructor metaconstructor;
+typedef struct metakey metakey;
+
+struct metaschema {
+ char *name;
+ struct metaconstructor *constructors;
+};
+
+struct metaconstructor {
+ char *head;
+ struct metakey *keys;
+};
+
+struct metakey {
+ char *key;
+ char *subschema;
+};
+
+assoc* metacompile(metaschema*, size_t);
diff --git a/coding/metaschema.test.c b/coding/metaschema.test.c
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <assert.h>
+
+#include "metaschema.h"
+
+void
+test_empty_metaschema(void)
+{
+ metaschema m[] = {};
+ assoc *a = metacompile(m, metalen(m));
+ assert(a);
+ assert(get_amount_of_keys(a) == 0);
+}
+
+void
+test_empty_schemas(void)
+{
+ metaschema m[] = {
+ { .name = "test",
+ .constructors = (metaconstructor[]){}
+ },
+ { .name = "test2",
+ .constructors = (metaconstructor[]){}
+ },
+ { .name = "test3",
+ .constructors = (metaconstructor[]){}
+ }
+ };
+ assoc *a = metacompile(m, metalen(m));
+ assert(get_amount_of_keys(a) == metalen(m));
+ assert(assoc_get(a, intern("test")));
+ assert(assoc_get(a, intern("test2")));
+ assert(assoc_get(a, intern("test3")));
+}
+
+void
+test_empty_constructors(void)
+{
+ metaschema m[] = {
+ { .name = "test",
+ .constructors = (metaconstructor[]){
+ { .head = "constr0",
+ .keys = (metakey[]){}
+ },
+ { .head = "constr1",
+ .keys = (metakey[]){}
+ }
+ }
+ }
+ };
+ assoc *a = metacompile(m, metalen(m));
+ schema *s = assoc_get(a, intern("test"));
+ assert(is_constructor(s, intern("constr0")));
+ assert(is_constructor(s, intern("constr1")));
+}
+
+int
+main()
+{
+ test_empty_metaschema();
+ test_empty_schemas();
+ test_empty_constructors();
+ return 0;
+}