summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkdx <kikoodx@paranoici.org>2023-12-26 23:55:52 +0100
committerkdx <kikoodx@paranoici.org>2023-12-26 23:55:52 +0100
commit564af1690519d2aaa5bc3e9921974007a49bdb24 (patch)
treef41f112200ba6e107710750ac1525a57f9f7b912
parent548254c577a995d6951c6d8cf3bc6e4d878a6ad5 (diff)
downloado7c-564af1690519d2aaa5bc3e9921974007a49bdb24.tar.gz
first half of type declaration checking
-rw-r--r--inc/type.h3
-rw-r--r--samples/types.o714
-rw-r--r--src/main.c13
-rw-r--r--src/parser/type_.c11
-rw-r--r--src/type.c73
5 files changed, 93 insertions, 21 deletions
diff --git a/inc/type.h b/inc/type.h
index 9d13816..1483de8 100644
--- a/inc/type.h
+++ b/inc/type.h
@@ -72,3 +72,6 @@ void type_add_primaries(VecType *v);
Type type_new_alias(Node *node);
Type type_new_struct(Node *node);
Type type_new_union(Node *node);
+Type *types_exist(VecType *types, SliceU8 name);
+void type_check_early(Type this, VecType *types);
+void types_check_late(VecType *types);
diff --git a/samples/types.o7 b/samples/types.o7
index 067a820..923ef2f 100644
--- a/samples/types.o7
+++ b/samples/types.o7
@@ -2,6 +2,12 @@
alias Truth = bool;
alias Length = f64;
+// only one union field can (and must) have a default value
+union ObjectData {
+ list: *LinkedList, // forward type declaration only works for pointers
+ object: *Object = null
+};
+
// all fields need a default value
struct Object {
type: u16 = 0,
@@ -11,12 +17,6 @@ struct Object {
data: [128]ObjectData = default // does what you think
};
-// only one union field can (and must) have a default value
-union ObjectData {
- list: *LinkedList, // forward type declaration only works for pointers
- object: *Object = null
-};
-
// inheritance
struct Table : Object {
feet: u8 = 4
@@ -29,6 +29,8 @@ struct LinkedList {
alias List = *LinkedList;
+//alias Cringe = *Cringe;
+
fn newLinkedList -> LinkedList {
LinkedList#{ v: null, next: null };
};
diff --git a/src/main.c b/src/main.c
index dd6c1f8..d51d46a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -37,7 +37,6 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
auto types = VecType_new(0);
type_add_primaries(types);
for (auto node = nodes; node; node = node->next) {
- bool is_type = true;
Type type;
switch (node->type) {
case NOD_ALIAS:
@@ -50,17 +49,13 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
type = type_new_union(node);
break;
default:
- is_type = false;
- break;
- }
- if (!is_type)
continue;
- for (size_t i = 0; i < types->size; i++)
- if (SliceU8_cmp(type.name, types->p[i].name) == 0)
- panic("duplicate declaration of type '%.*s'",
- type.name.len, type.name.loc);
+ }
+ type_check_early(type, types);
VecType_push(types, type);
}
+ types_check_late(types);
+
vec_log(types, "%.*s", X->name.len, X->name.loc);
return 0;
diff --git a/src/parser/type_.c b/src/parser/type_.c
index d400266..50e3b6d 100644
--- a/src/parser/type_.c
+++ b/src/parser/type_.c
@@ -15,9 +15,10 @@ type(SliceToken *s)
while (equal(s->loc[ptr_depth], "*"))
ptr_depth++;
node->tok = s->loc[ptr_depth];
+ node->ptr_depth = ptr_depth;
+ *s = SliceToken_sub(*s, ptr_depth + 1, -1);
- if (ptr_depth && equal(s->loc[ptr_depth], "fn")) {
- *s = SliceToken_sub(*s, ptr_depth + 1, -1);
+ if (ptr_depth && equal(node->tok, "fn")) {
skip(s, "(");
node->Lhs = fnargs(s, type);
skip(s, ")");
@@ -27,11 +28,9 @@ type(SliceToken *s)
}
return node;
}
+ else
+ expect(node->tok, TOK_WORD);
- expect(s->loc[ptr_depth], TOK_WORD);
- node->ptr_depth = ptr_depth;
-
- *s = SliceToken_sub(*s, ptr_depth + 1, -1);
return node;
}
diff --git a/src/type.c b/src/type.c
index 42b34f7..c72e8c4 100644
--- a/src/type.c
+++ b/src/type.c
@@ -6,6 +6,7 @@ vec_impl(AggregateElement, AggregateElement);
Type
type_new_alias(Node *node)
{
+ assert(node->Lhs->array_size == nullptr);
return (Type){
.tag = TYPE_ALIAS,
.name = node->tok.s,
@@ -85,3 +86,75 @@ type_new_union(Node *node)
return this;
}
+
+bool
+type_is_aggregate(Type this)
+{
+ switch (this.tag) {
+ case TYPE_STRUCT:
+ case TYPE_UNION:
+ return true;
+ default:
+ return false;
+ }
+}
+
+Type *
+types_exist(VecType *types, SliceU8 name)
+{
+ for (size_t i = 0; i < types->size; i++)
+ if (SliceU8_cmp(name, types->p[i].name) == 0)
+ return &types->p[i];
+ return nullptr;
+}
+
+void
+type_check_early(Type this, VecType *types)
+{
+ if (types_exist(types, this.name))
+ panic("duplicate declaration of type '%.*s'",
+ this.name.len, this.name.loc);
+
+ if (this.tag == TYPE_ALIAS) {
+ if (SliceU8_cmp(this.alias.to,
+ SliceU8_from_ptr((u8*)"fn", 2)) == 0)
+ {} /* checked late */
+ else if (!types_exist(types, this.alias.to))
+ panic("alias to undeclared type '%.*s'",
+ this.alias.to.len, this.alias.to.loc);
+ }
+
+ if (this.tag == TYPE_STRUCT && this.aggregate.parent.len) {
+ auto parent = types_exist(types, this.aggregate.parent);
+ if (parent == nullptr)
+ panic("undeclared struct parent '%.*s'",
+ this.aggregate.parent.len,
+ this.aggregate.parent.loc);
+ if (parent->tag != TYPE_STRUCT)
+ panic("parent '%.*s' is not a struct",
+ parent->name.len, parent->name.loc);
+ }
+
+ if (type_is_aggregate(this)) {
+ for (size_t i = 0; i < this.aggregate.elements->size; i++) {
+ auto e = &this.aggregate.elements->p[i];
+ if (e->type->ptr_depth)
+ continue; /* checked late */
+ if (!types_exist(types, e->type->tok.s))
+ panic("undeclared element type '%.*s'",
+ e->type->tok.s.len, e->type->tok.s.loc);
+ }
+ }
+}
+
+static void
+_type_check_late(Type this, VecType *types)
+{
+}
+
+void
+types_check_late(VecType *types)
+{
+ for (size_t i = 0; i < types->size; i++)
+ _type_check_late(types->p[i], types);
+}