diff options
| author | gingerBill <bill@gingerbill.org> | 2017-11-05 23:38:09 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2017-11-05 23:38:09 +0000 |
| commit | 9df3a94d33a8bcada48d7c6b659de21a0edf6795 (patch) | |
| tree | 3b812ba23c511fc5140034f6d1247225c3d92965 /src/types.cpp | |
| parent | d4f335d06896651cc66a5b5fa1c618d84a3b501e (diff) | |
Fix cyclic type checking bug
Diffstat (limited to 'src/types.cpp')
| -rw-r--r-- | src/types.cpp | 82 |
1 files changed, 41 insertions, 41 deletions
diff --git a/src/types.cpp b/src/types.cpp index 8137c8069..66a56e3db 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1731,7 +1731,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n struct TypePath { - Array<Type *> path; // Entity_TypeName; + Array<Entity *> path; // Entity_TypeName; bool failure; }; @@ -1748,38 +1748,37 @@ void type_path_print_illegal_cycle(TypePath *tp, isize start_index) { GB_ASSERT(tp != nullptr); GB_ASSERT(start_index < tp->path.count); - Type *t = tp->path[start_index]; - GB_ASSERT(t != nullptr); - - GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t)); - Entity *e = t->Named.type_name; - error(e->token, "Illegal declaration cycle of `%.*s`", LIT(t->Named.name)); + Entity *e = tp->path[start_index]; + GB_ASSERT(e != nullptr); + error(e->token, "Illegal declaration cycle of `%.*s`", LIT(e->token.string)); // NOTE(bill): Print cycle, if it's deep enough for (isize j = start_index; j < tp->path.count; j++) { - Type *t = tp->path[j]; - GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t)); - Entity *e = t->Named.type_name; - error(e->token, "\t%.*s refers to", LIT(t->Named.name)); + Entity *e = tp->path[j]; + error(e->token, "\t%.*s refers to", LIT(e->token.string)); } // NOTE(bill): This will only print if the path count > 1 - error(e->token, "\t%.*s", LIT(t->Named.name)); + error(e->token, "\t%.*s", LIT(e->token.string)); tp->failure = true; - t->failure = true; + e->type->failure = true; + base_type(e->type)->failure = true; } -TypePath *type_path_push(TypePath *tp, Type *t) { +bool type_path_push(TypePath *tp, Type *t) { GB_ASSERT(tp != nullptr); + if (t->kind != Type_Named) { + return false; + } + Entity *e = t->Named.type_name; for (isize i = 0; i < tp->path.count; i++) { - if (tp->path[i] == t) { + Entity *p = tp->path[i]; + if (p == e) { type_path_print_illegal_cycle(tp, i); } } - if (!tp->failure && is_type_named(t)) { - array_add(&tp->path, t); - } - return tp; + array_add(&tp->path, e); + return true; } void type_path_pop(TypePath *tp) { @@ -1830,6 +1829,7 @@ i64 type_align_of(gbAllocator allocator, Type *t) { i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { + GB_ASSERT(path != nullptr); if (t->failure) { return FAILURE_ALIGNMENT; } @@ -1853,35 +1853,35 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { case Type_Array: { Type *elem = t->Array.elem; - type_path_push(path, elem); + bool pop = type_path_push(path, elem); if (path->failure) { return FAILURE_ALIGNMENT; } i64 align = type_align_of_internal(allocator, t->Array.elem, path); - type_path_pop(path); + if (pop) type_path_pop(path); return align; } - - case Type_DynamicArray: - // data, count, capacity, allocator - return build_context.word_size; - - case Type_Slice: - return build_context.word_size; - case Type_Vector: { Type *elem = t->Vector.elem; - type_path_push(path, elem); + bool pop = type_path_push(path, elem); if (path->failure) { return FAILURE_ALIGNMENT; } i64 size = type_size_of_internal(allocator, t->Vector.elem, path); - type_path_pop(path); + if (pop) type_path_pop(path); i64 count = gb_max(prev_pow2(t->Vector.count), 1); i64 total = size * count; return gb_clamp(total, 1, build_context.max_align); } break; + case Type_DynamicArray: + // data, count, capacity, allocator + return build_context.word_size; + + case Type_Slice: + return build_context.word_size; + + case Type_Tuple: { i64 max = 1; for_array(i, t->Tuple.variables) { @@ -1911,12 +1911,12 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { i64 max = union_tag_size(t); for_array(i, t->Union.variants) { Type *variant = t->Union.variants[i]; - type_path_push(path, variant); + bool pop = type_path_push(path, variant); if (path->failure) { return FAILURE_ALIGNMENT; } i64 align = type_align_of_internal(allocator, variant, path); - type_path_pop(path); + if (pop) type_path_pop(path); if (max < align) { max = align; } @@ -1932,12 +1932,12 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { i64 max = 1; for_array(i, t->Struct.fields) { Type *field_type = t->Struct.fields[i]->type; - type_path_push(path, field_type); + bool pop = type_path_push(path, field_type); if (path->failure) { return FAILURE_ALIGNMENT; } i64 align = type_align_of_internal(allocator, field_type, path); - type_path_pop(path); + if (pop) type_path_pop(path); if (max < align) { max = align; } @@ -1948,10 +1948,10 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) { // NOTE(bill): Check the fields to check for cyclic definitions for_array(i, t->Struct.fields) { Type *field_type = t->Struct.fields[i]->type; - type_path_push(path, field_type); + bool pop = type_path_push(path, field_type); if (path->failure) return FAILURE_ALIGNMENT; i64 align = type_align_of_internal(allocator, field_type, path); - type_path_pop(path); + if (pop) type_path_pop(path); if (max < align) { max = align; } @@ -2033,12 +2033,12 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { switch (t->kind) { case Type_Named: { - type_path_push(path, t); + bool pop = type_path_push(path, t); if (path->failure) { return FAILURE_ALIGNMENT; } i64 size = type_size_of_internal(allocator, t->Named.base, path); - type_path_pop(path); + if (pop) type_path_pop(path); return size; } break; @@ -2080,12 +2080,12 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) { if (count == 0) { return 0; } - type_path_push(path, t->Vector.elem); + bool pop = type_path_push(path, t->Vector.elem); if (path->failure) { return FAILURE_SIZE; } bit_size = 8*type_size_of_internal(allocator, t->Vector.elem, path); - type_path_pop(path); + if (pop) type_path_pop(path); if (is_type_boolean(t->Vector.elem)) { bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1` // Silly LLVM spec |