diff options
author | kdx <kikoodx@paranoici.org> | 2023-12-26 23:55:52 +0100 |
---|---|---|
committer | kdx <kikoodx@paranoici.org> | 2023-12-26 23:55:52 +0100 |
commit | 564af1690519d2aaa5bc3e9921974007a49bdb24 (patch) | |
tree | f41f112200ba6e107710750ac1525a57f9f7b912 | |
parent | 548254c577a995d6951c6d8cf3bc6e4d878a6ad5 (diff) | |
download | o7c-564af1690519d2aaa5bc3e9921974007a49bdb24.tar.gz |
first half of type declaration checking
-rw-r--r-- | inc/type.h | 3 | ||||
-rw-r--r-- | samples/types.o7 | 14 | ||||
-rw-r--r-- | src/main.c | 13 | ||||
-rw-r--r-- | src/parser/type_.c | 11 | ||||
-rw-r--r-- | src/type.c | 73 |
5 files changed, 93 insertions, 21 deletions
@@ -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 }; }; @@ -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; } @@ -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); +} |