From c3b2694834d1e492cf7a06e1881940030aeda713 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 18 Jan 2026 00:33:43 +0100 Subject: [PATCH] Generics with <>. Deprecation of {} generics. --- lib/std/atomic.c3 | 2 +- lib/std/collections/bitset.c3 | 4 +- lib/std/collections/elastic_array.c3 | 2 +- lib/std/collections/enummap.c3 | 2 +- lib/std/collections/enumset.c3 | 2 +- lib/std/collections/hashmap.c3 | 2 +- lib/std/collections/hashset.c3 | 2 +- lib/std/collections/interfacelist.c3 | 2 +- lib/std/collections/linked_blockingqueue.c3 | 2 +- lib/std/collections/linked_hashmap.c3 | 2 +- lib/std/collections/linked_hashset.c3 | 2 +- lib/std/collections/linkedlist.c3 | 2 +- lib/std/collections/list.c3 | 2 +- lib/std/collections/maybe.c3 | 2 +- lib/std/collections/priorityqueue.c3 | 13 +- lib/std/collections/range.c3 | 2 +- lib/std/collections/ringbuffer.c3 | 2 +- lib/std/collections/tuple.c3 | 11 +- lib/std/core/mem.c3 | 4 +- lib/std/core/refcount.c3 | 2 +- lib/std/core/slice2d.c3 | 4 +- lib/std/experimental/FrameScheduler.c3 | 2 +- lib/std/hash/hmac.c3 | 2 +- lib/std/hash/ripemd.c3 | 2 +- lib/std/hash/siphash.c3 | 2 +- lib/std/math/complex.c3 | 2 +- lib/std/math/matrix.c3 | 2 +- lib/std/math/quaternion.c3 | 2 +- lib/std/sort/countingsort.c3 | 2 +- lib/std/sort/insertionsort.c3 | 2 +- lib/std/sort/quicksort.c3 | 2 +- lib/std/threads/buffered_channel.c3 | 2 +- lib/std/threads/pool.c3 | 2 +- lib/std/threads/unbuffered_channel.c3 | 2 +- releasenotes.md | 3 +- resources/examples/map.c3 | 2 +- src/compiler/enums.h | 1 - src/compiler/parse_expr.c | 2 +- src/compiler/parse_global.c | 137 +++++++++--------- src/compiler/parser_internal.h | 4 +- src/compiler/sema_decls.c | 3 - src/compiler/symtab.c | 1 - test/test_suite/any/casting_voidptr_to_any.c3 | 2 +- test/test_suite/any/generic_interface.c3 | 2 +- test/test_suite/arrays/slice_constant_mod.c3t | 2 +- .../concat_untyped_with_struct_array.c3t | 2 +- .../defined_generic_type.c3t | 2 +- test/test_suite/define/test_at.c3 | 2 +- test/test_suite/define/test_at_alias.c3 | 2 +- test/test_suite/enumerations/enum_copy.c3t | 2 +- test/test_suite/expressions/take_address.c3t | 2 +- test/test_suite/functions/test_regression.c3t | 4 +- .../functions/test_regression_mingw.c3t | 4 +- .../generic/different_generic_def.c3 | 4 +- test/test_suite/generic/generic_builtin.c3t | 2 +- .../generic/generic_contract_aggregation.c3 | 2 +- test/test_suite/generic/generic_copy.c3t | 2 +- test/test_suite/generic/generic_cyclic.c3 | 2 +- .../generic/generic_default_wrong_init.c3 | 2 +- test/test_suite/generic/generic_distinct.c3t | 2 +- test/test_suite/generic/generic_fault.c3t | 2 +- test/test_suite/generic/generic_fault2.c3t | 2 +- test/test_suite/generic/generic_idents.c3t | 2 +- .../generic/generic_infer_mismatch.c3 | 4 +- test/test_suite/generic/generic_infer_ok.c3 | 4 +- test/test_suite/generic/generic_inference.c3t | 2 +- test/test_suite/generic/generic_interface.c3t | 2 +- .../generic/generic_lambda_complex.c3t | 2 +- test/test_suite/generic/generic_local.c3 | 2 +- .../generic/generic_merge_constraints.c3 | 4 +- .../generic/generic_new_decl_with_type.c3t | 2 +- test/test_suite/generic/generic_no_arg.c3 | 3 +- test/test_suite/generic/generic_no_params.c3 | 2 +- test/test_suite/generic/generic_num.c3t | 2 +- test/test_suite/generic/generic_over_fn.c3t | 2 +- .../generic/generic_resolution_1402.c3t | 4 +- test/test_suite/generic/generic_self_ref.c3 | 2 +- test/test_suite/generic/generic_testcases.c3t | 8 +- test/test_suite/generic/generic_void.c3t | 2 +- .../generic/generic_with_comment.c3t | 2 +- test/test_suite/generic/generic_with_enum.c3t | 2 +- .../generic/generic_without_param.c3 | 2 +- .../generic/implicit_import_of_generic.c3 | 2 +- .../generic/incorrect_argument_type.c3 | 2 +- test/test_suite/generic/nested_typedef.c3t | 2 +- .../generic/overlapping_generic.c3t | 4 +- test/test_suite/generic/recursive_generic.c3 | 4 +- test/test_suite/generic/recursive_generic2.c3 | 2 +- test/test_suite/globals/links_global.c3 | 2 +- .../initializer_lists/init_any_interface.c3 | 2 +- .../methods/extension_method_check.c3 | 2 +- .../module/module_generic_mixing.c3 | 2 +- .../switch/switch_in_defer_macro.c3t | 4 +- 93 files changed, 179 insertions(+), 197 deletions(-) diff --git a/lib/std/atomic.c3 b/lib/std/atomic.c3 index d8533248a..947359829 100644 --- a/lib/std/atomic.c3 +++ b/lib/std/atomic.c3 @@ -1,7 +1,7 @@ // Copyright (c) 2023-2025 Eduardo José Gómez Hernández. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::atomic::types{Type}; +module std::atomic::types ; struct Atomic { diff --git a/lib/std/collections/bitset.c3 b/lib/std/collections/bitset.c3 index 9e4ea88ca..26b1f5854 100644 --- a/lib/std/collections/bitset.c3 +++ b/lib/std/collections/bitset.c3 @@ -4,7 +4,7 @@ <* @require SIZE > 0 : "The size of the bitset in bits must be at least 1" *> -module std::collections::bitset {SIZE}; +module std::collections::bitset ; const BITS = uint.sizeof * 8; const SZ = (SIZE + BITS - 1) / BITS; @@ -172,7 +172,7 @@ fn void BitSet.set_bool(&self, usz i, bool value) @operator([]=) @inline <* @require Type.kindof == UNSIGNED_INT *> -module std::collections::growablebitset{Type}; +module std::collections::growablebitset ; import std::collections::list; const BITS = Type.sizeof * 8; diff --git a/lib/std/collections/elastic_array.c3 b/lib/std/collections/elastic_array.c3 index 0a0fef789..c5e54c7a2 100644 --- a/lib/std/collections/elastic_array.c3 +++ b/lib/std/collections/elastic_array.c3 @@ -4,7 +4,7 @@ <* @require MAX_SIZE >= 1 : `The size must be at least 1 element big.` *> -module std::collections::elastic_array {Type, MAX_SIZE}; +module std::collections::elastic_array ; import std::io, std::math, std::collections::list_common; alias ElementPredicate = fn bool(Type *type); diff --git a/lib/std/collections/enummap.c3 b/lib/std/collections/enummap.c3 index f492a595c..3577b34a3 100644 --- a/lib/std/collections/enummap.c3 +++ b/lib/std/collections/enummap.c3 @@ -1,7 +1,7 @@ <* @require Enum.kindof == TypeKind.ENUM : "Only enums may be used with an enummap" *> -module std::collections::enummap{Enum, ValueType}; +module std::collections::enummap ; import std::io; struct EnumMap (Printable) diff --git a/lib/std/collections/enumset.c3 b/lib/std/collections/enumset.c3 index 1663ae6d1..6d750f852 100644 --- a/lib/std/collections/enumset.c3 +++ b/lib/std/collections/enumset.c3 @@ -5,7 +5,7 @@ <* @require Enum.kindof == TypeKind.ENUM : "Only enums may be used with an enumset" *> -module std::collections::enumset{Enum}; +module std::collections::enumset ; import std::io; const ENUM_COUNT @private = Enum.values.len; diff --git a/lib/std/collections/hashmap.c3 b/lib/std/collections/hashmap.c3 index 59b562b51..d8c1f1d1a 100644 --- a/lib/std/collections/hashmap.c3 +++ b/lib/std/collections/hashmap.c3 @@ -4,7 +4,7 @@ <* @require $defined((Key){}.hash()) : `No .hash function found on the key` *> -module std::collections::map{Key, Value}; +module std::collections::map ; import std::math; import std::io @norecurse; diff --git a/lib/std/collections/hashset.c3 b/lib/std/collections/hashset.c3 index 4722c1100..5b76343ed 100644 --- a/lib/std/collections/hashset.c3 +++ b/lib/std/collections/hashset.c3 @@ -1,7 +1,7 @@ <* @require $defined((Value){}.hash()) : `No .hash function found on the value` *> -module std::collections::set {Value}; +module std::collections::set ; import std::math; import std::io @norecurse; diff --git a/lib/std/collections/interfacelist.c3 b/lib/std/collections/interfacelist.c3 index ffd51bd73..3e7ea44a6 100644 --- a/lib/std/collections/interfacelist.c3 +++ b/lib/std/collections/interfacelist.c3 @@ -4,7 +4,7 @@ <* @require Type.kindof == INTERFACE || Type.kindof == ANY : "The kind of an interfacelist must be an interface or `any`" *> -module std::collections::interfacelist {Type}; +module std::collections::interfacelist ; import std::io,std::math; alias InterfacePredicate = fn bool(Type value); diff --git a/lib/std/collections/linked_blockingqueue.c3 b/lib/std/collections/linked_blockingqueue.c3 index 082238fa8..9169582a6 100644 --- a/lib/std/collections/linked_blockingqueue.c3 +++ b/lib/std/collections/linked_blockingqueue.c3 @@ -1,4 +1,4 @@ -module std::collections::blockingqueue { Value }; +module std::collections::blockingqueue ; import std::thread, std::time; diff --git a/lib/std/collections/linked_hashmap.c3 b/lib/std/collections/linked_hashmap.c3 index 19ee86f80..6f91c6f30 100644 --- a/lib/std/collections/linked_hashmap.c3 +++ b/lib/std/collections/linked_hashmap.c3 @@ -4,7 +4,7 @@ <* @require $defined((Key){}.hash()) : `No .hash function found on the key` *> -module std::collections::map{Key, Value}; +module std::collections::map ; import std::math; import std::io @norecurse; diff --git a/lib/std/collections/linked_hashset.c3 b/lib/std/collections/linked_hashset.c3 index a79ef8768..4632124a5 100644 --- a/lib/std/collections/linked_hashset.c3 +++ b/lib/std/collections/linked_hashset.c3 @@ -1,7 +1,7 @@ <* @require $defined((Value){}.hash()) : `No .hash function found on the value` *> -module std::collections::set {Value}; +module std::collections::set ; import std::math; import std::io @norecurse; diff --git a/lib/std/collections/linkedlist.c3 b/lib/std/collections/linkedlist.c3 index 54568bba3..91dd2b101 100644 --- a/lib/std/collections/linkedlist.c3 +++ b/lib/std/collections/linkedlist.c3 @@ -1,7 +1,7 @@ // Copyright (c) 2021-2024 Christoffer Lerno. All rights reserved. // Use of self source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::collections::linkedlist{Type}; +module std::collections::linkedlist ; import std::io; const ELEMENT_IS_EQUATABLE = types::is_equatable_type(Type); diff --git a/lib/std/collections/list.c3 b/lib/std/collections/list.c3 index 47b4061a2..0742f0e3e 100644 --- a/lib/std/collections/list.c3 +++ b/lib/std/collections/list.c3 @@ -1,7 +1,7 @@ // Copyright (c) 2021-2024 Christoffer Lerno. All rights reserved. // Use of self source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. -module std::collections::list{Type}; +module std::collections::list ; import std::io, std::math, std::collections::list_common; alias ElementPredicate = fn bool(Type *type); diff --git a/lib/std/collections/maybe.c3 b/lib/std/collections/maybe.c3 index 94e8ea387..0879f5362 100644 --- a/lib/std/collections/maybe.c3 +++ b/lib/std/collections/maybe.c3 @@ -1,4 +1,4 @@ -module std::collections::maybe{Type}; +module std::collections::maybe ; import std::io; struct Maybe (Printable) diff --git a/lib/std/collections/priorityqueue.c3 b/lib/std/collections/priorityqueue.c3 index 253a050cc..57dd9bf9c 100644 --- a/lib/std/collections/priorityqueue.c3 +++ b/lib/std/collections/priorityqueue.c3 @@ -20,16 +20,13 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -module std::collections::priorityqueue{Type}; -import std::collections::priorityqueue::private; - -typedef PriorityQueue = inline PrivatePriorityQueue{Type, false}; -typedef PriorityQueueMax = inline PrivatePriorityQueue{Type, true}; - -module std::collections::priorityqueue::private{Type, MAX}; +module std::collections::priorityqueue; import std::collections::list, std::io; -struct PrivatePriorityQueue (Printable) +typedef PriorityQueue = inline PrivatePriorityQueue{Type, false}; +typedef PriorityQueueMax = inline PrivatePriorityQueue{Type, true}; + +struct PrivatePriorityQueue (Printable) { List{Type} heap; } diff --git a/lib/std/collections/range.c3 b/lib/std/collections/range.c3 index a5f48f115..11ef3e2fa 100644 --- a/lib/std/collections/range.c3 +++ b/lib/std/collections/range.c3 @@ -1,7 +1,7 @@ <* @require Type.is_ordered : "The type must be ordered" *> -module std::collections::range{Type}; +module std::collections::range ; import std::io; struct Range (Printable) diff --git a/lib/std/collections/ringbuffer.c3 b/lib/std/collections/ringbuffer.c3 index 51c9bb5b0..3f91115c9 100644 --- a/lib/std/collections/ringbuffer.c3 +++ b/lib/std/collections/ringbuffer.c3 @@ -1,7 +1,7 @@ <* @require Type.kindof == ARRAY : "Required an array type" *> -module std::collections::ringbuffer{Type}; +module std::collections::ringbuffer ; import std::io; alias Element = $typeof((Type){}[0]); diff --git a/lib/std/collections/tuple.c3 b/lib/std/collections/tuple.c3 index d719bcbab..061a90cfa 100644 --- a/lib/std/collections/tuple.c3 +++ b/lib/std/collections/tuple.c3 @@ -1,4 +1,4 @@ -module std::collections::pair{Type1, Type2}; +module std::collections::pair ; import std::io; struct Pair (Printable) @@ -29,9 +29,7 @@ fn bool Pair.equal(self, Pair other) @operator(==) @if (types::has_equals(Type1) return self.first == other.first && self.second == other.second; } - - -module std::collections::triple{Type1, Type2, Type3}; +module std::collections::triple ; import std::io; struct Triple (Printable) @@ -65,11 +63,10 @@ fn bool Triple.equal(self, Triple other) @operator(==) @if (types::has_equals(Ty return self.first == other.first && self.second == other.second && self.third == other.third; } - -module std::collections::tuple{Type1, Type2}; +module std::collections::tuple ; struct Tuple @deprecated("Use 'Pair' instead") { Type1 first; Type2 second; -} +} \ No newline at end of file diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 787eab18b..a401f19b6 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -1060,7 +1060,7 @@ fn void* __memcpy(void* dst, void* src, usz n) @weak @export("memcpy") } -module std::core::mem::volatile { Type }; +module std::core::mem::volatile ; typedef Volatile @structlike = Type; @@ -1077,7 +1077,7 @@ macro Type Volatile.set(&self, Type val) <* @require mem::@constant_is_power_of_2(ALIGNMENT) : "The alignment must be a power of 2" *> -module std::core::mem::alignment { Type, ALIGNMENT }; +module std::core::mem::alignment ; import std::core::mem @public; <* diff --git a/lib/std/core/refcount.c3 b/lib/std/core/refcount.c3 index 5889283c8..ed25c4fd4 100644 --- a/lib/std/core/refcount.c3 +++ b/lib/std/core/refcount.c3 @@ -8,7 +8,7 @@ @require !$defined(Type.dealloc) ||| $defined(Type.dealloc(&&(Type){})) : "'dealloc' must only take a pointer to the underlying type" @require !$defined(Type.dealloc) ||| $typeof((Type){}.dealloc()) == void : "'dealloc' must return 'void'" *> -module std::core::mem::ref { Type }; +module std::core::mem::ref ; import std::thread, std::atomic; const OVERALIGNED @private = Type.alignof > mem::DEFAULT_MEM_ALIGNMENT; diff --git a/lib/std/core/slice2d.c3 b/lib/std/core/slice2d.c3 index df368cba7..757e63997 100644 --- a/lib/std/core/slice2d.c3 +++ b/lib/std/core/slice2d.c3 @@ -1,10 +1,10 @@ -module std::core::array::slice {Type}; +module std::core::array; <* A slice2d allows slicing an array like int[10][10] into an arbitrary "int[][]"-like counterpart Typically you'd use array::slice2d(...) to create one. *> -struct Slice2d +struct Slice2d { Type* ptr; usz inner_len; diff --git a/lib/std/experimental/FrameScheduler.c3 b/lib/std/experimental/FrameScheduler.c3 index 7d0ae856f..e0b9dc00c 100644 --- a/lib/std/experimental/FrameScheduler.c3 +++ b/lib/std/experimental/FrameScheduler.c3 @@ -1,4 +1,4 @@ -module std::experimental::scheduler{Event}; +module std::experimental::scheduler ; import std::collections, std::thread, std::time; struct DelayedSchedulerEvent @local diff --git a/lib/std/hash/hmac.c3 b/lib/std/hash/hmac.c3 index 657868eae..3875da716 100644 --- a/lib/std/hash/hmac.c3 +++ b/lib/std/hash/hmac.c3 @@ -1,4 +1,4 @@ -module std::hash::hmac{HashAlg, HASH_BYTES, BLOCK_BYTES}; +module std::hash::hmac ; import std::crypto; struct Hmac diff --git a/lib/std/hash/ripemd.c3 b/lib/std/hash/ripemd.c3 index 376ec1cc6..b62d2ef5e 100644 --- a/lib/std/hash/ripemd.c3 +++ b/lib/std/hash/ripemd.c3 @@ -4,7 +4,7 @@ <* @require @in(DIGEST_BITS, ...PERMISSIBLE_SIZES_BITS) : "Invalid DIGEST_BITS; must be one of {128, 160, 256, 320}." *> -module std::hash::ripemd { DIGEST_BITS }; +module std::hash::ripemd ; <* Unchanging block size. *> diff --git a/lib/std/hash/siphash.c3 b/lib/std/hash/siphash.c3 index f65f7556d..2c358f328 100644 --- a/lib/std/hash/siphash.c3 +++ b/lib/std/hash/siphash.c3 @@ -48,7 +48,7 @@ alias hash = siphash::hash { uint128, 4, 8 }; @require OutType.typeid == uint128.typeid || OutType.typeid == ulong.typeid : "Module OutType must be either uint128 or ulong." *> -module std::hash::siphash { OutType, BLOCK_ROUNDS, FINALIZE_ROUNDS }; +module std::hash::siphash ; struct SipHash diff --git a/lib/std/math/complex.c3 b/lib/std/math/complex.c3 index c3310f28b..f03aaea99 100644 --- a/lib/std/math/complex.c3 +++ b/lib/std/math/complex.c3 @@ -16,7 +16,7 @@ alias I_F @builtin = complex::IMAGINARY { float }; @require Real.kindof == FLOAT : "A complex number must use a floating type" *> -module std::math::complex {Real}; +module std::math::complex ; import std::io; union ComplexNumber (Printable) diff --git a/lib/std/math/matrix.c3 b/lib/std/math/matrix.c3 index e6089ee92..8d20b55b5 100644 --- a/lib/std/math/matrix.c3 +++ b/lib/std/math/matrix.c3 @@ -28,7 +28,7 @@ alias MATRIX4F_IDENTITY @builtin = matrix::IDENTITY4 {float}; @require Real.kindof == FLOAT : "A matrix must use a floating type" *> -module std::math::matrix {Real}; +module std::math::matrix ; import std::math::vector; struct Matrix2x2 diff --git a/lib/std/math/quaternion.c3 b/lib/std/math/quaternion.c3 index 2728d9ae1..a7f4168a5 100644 --- a/lib/std/math/quaternion.c3 +++ b/lib/std/math/quaternion.c3 @@ -13,7 +13,7 @@ alias QUATERNIONF_IDENTITY @builtin = quaternion::IDENTITY {float}; @require Real.kindof == FLOAT : "A quaternion must use a floating type" *> -module std::math::quaternion {Real}; +module std::math::quaternion ; import std::math::vector; union QuaternionNumber { diff --git a/lib/std/sort/countingsort.c3 b/lib/std/sort/countingsort.c3 index 08804144d..c1870cd42 100644 --- a/lib/std/sort/countingsort.c3 +++ b/lib/std/sort/countingsort.c3 @@ -39,7 +39,7 @@ macro void quicksort_indexed(list, start, end, cmp = EMPTY_MACRO_SLOT, context = $endif } -module std::sort::cs{Type, KeyFn}; +module std::sort::cs ; alias Counts @private = usz[256]; alias Ranges @private = usz[257]; diff --git a/lib/std/sort/insertionsort.c3 b/lib/std/sort/insertionsort.c3 index 9c5f71721..3cb762975 100644 --- a/lib/std/sort/insertionsort.c3 +++ b/lib/std/sort/insertionsort.c3 @@ -17,7 +17,7 @@ macro void insertionsort(list, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLO $endif } -module std::sort::is{Type, CmpFn, Context}; +module std::sort::is ; alias ElementType = $typeof(((Type){})[0]); const bool IS_SLICE = Type.kindof == SLICE; diff --git a/lib/std/sort/quicksort.c3 b/lib/std/sort/quicksort.c3 index fc2d7c638..a3d0345df 100644 --- a/lib/std/sort/quicksort.c3 +++ b/lib/std/sort/quicksort.c3 @@ -37,7 +37,7 @@ macro quickselect(list, isz k, cmp = EMPTY_MACRO_SLOT, context = EMPTY_MACRO_SLO $endif } -module std::sort::qs{Type, CmpFn, Context}; +module std::sort::qs ; alias ElementType = $typeof(((Type){})[0]); const bool IS_SLICE = Type.kindof == SLICE; diff --git a/lib/std/threads/buffered_channel.c3 b/lib/std/threads/buffered_channel.c3 index 214edb47a..7419b766d 100644 --- a/lib/std/threads/buffered_channel.c3 +++ b/lib/std/threads/buffered_channel.c3 @@ -1,4 +1,4 @@ -module std::thread::channel{Type}; +module std::thread::channel ; typedef BufferedChannel = void*; diff --git a/lib/std/threads/pool.c3 b/lib/std/threads/pool.c3 index 5070824ba..817472ddb 100644 --- a/lib/std/threads/pool.c3 +++ b/lib/std/threads/pool.c3 @@ -1,4 +1,4 @@ -module std::thread::pool{SIZE}; +module std::thread::pool ; import std::thread; struct ThreadPool diff --git a/lib/std/threads/unbuffered_channel.c3 b/lib/std/threads/unbuffered_channel.c3 index 1bb429d86..f1ac08343 100644 --- a/lib/std/threads/unbuffered_channel.c3 +++ b/lib/std/threads/unbuffered_channel.c3 @@ -1,4 +1,4 @@ -module std::thread::channel {Type}; +module std::thread::channel ; typedef UnbufferedChannel = void*; diff --git a/releasenotes.md b/releasenotes.md index 3b165c2c2..11d26ed91 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -11,12 +11,13 @@ - Testing for the presence of methods at the top level is prohibited previous to method registration. - `$$MASK_TO_INT` and `$$INT_TO_MASK` to create bool masks from integers and back. - Better error messages when slicing a pointer to a slice or vector. #2681 -- Generics using `@generic` rather than module based. +- Generics using ad-hoc `<...>` rather than module based. - Reduced memory usage for backtraces on Linux. - On win32 utf-8 console output is now enabled by default in compiled programs - Add `$$VERSION` and `$$PRERELEASE` compile time constants. - Require () around assignment in conditionals. #2716 - $$unaligned_load and $$unaligned_store now also takes a "is_volatile" parameter. +- Module-based generics using {} is deprecated. ### Fixes - Regression with npot vector in struct triggering an assert #2219. diff --git a/resources/examples/map.c3 b/resources/examples/map.c3 index 2d4fa852a..531829b16 100644 --- a/resources/examples/map.c3 +++ b/resources/examples/map.c3 @@ -2,7 +2,7 @@ module std::container::faults; faultdef KEY_NOT_FOUND; -module std::container::map{Key, Type}; +module std::container::map ; import std::core::builtin; import std::io; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index d41f4bff8..4614cacaa 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -279,7 +279,6 @@ typedef enum ATTRIBUTE_EXTERN, ATTRIBUTE_FINALIZER, ATTRIBUTE_FORMAT, - ATTRIBUTE_GENERIC, ATTRIBUTE_IF, ATTRIBUTE_INLINE, ATTRIBUTE_INIT, diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 1d9a23ea5..41530a5ed 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -414,7 +414,7 @@ static Expr *parse_lambda(ParseContext *c, Expr *left, SourceSpan lhs_span UNUSE sig->params = decls; sig->rtype = return_type ? type_infoid(return_type) : 0; sig->variadic = variadic; - if (!parse_attributes(c, &func->attributes, NULL, NULL, NULL, NULL)) return poisoned_expr; + if (!parse_attributes(c, &func->attributes, NULL, NULL, NULL)) return poisoned_expr; RANGE_EXTEND_PREV(func); if (tok_is(c, TOKEN_IMPLIES)) { diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 2eb502458..521b106d8 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -312,11 +312,13 @@ bool parse_module(ParseContext *c, AstId contracts) Visibility visibility = VISIBLE_PUBLIC; Attr** attrs = NULL; bool is_cond = false; - Decl *generic_decl = NULL; - if (!parse_attributes(c, &attrs, &visibility, NULL, &is_cond, &generic_decl)) return false; + + ASSIGN_DECL_OR_RET(Decl *generic_decl, parse_generic_decl(c), false); + + if (!parse_attributes(c, &attrs, &visibility, NULL, &is_cond)) return false; if (generic_decl_old) { - //SEMA_DEPRECATED(generic_decl, "Module-based generics is deprecated, use `@generic` instead."); + SEMA_DEPRECATED(generic_decl_old, "Module-based generics is deprecated, use `<...>` instead."); if (generic_decl) { SEMA_NOTE(generic_decl_old, "Old generics combined with new will ignore the former."); @@ -929,7 +931,7 @@ Decl *parse_local_decl_after_type(ParseContext *c, TypeInfo *type) advance(c); bool is_cond; - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, NULL)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; decl->is_cond = is_cond; if (tok_is(c, TOKEN_EQ)) { @@ -1010,7 +1012,7 @@ Decl *parse_const_declaration(ParseContext *c, bool is_global, bool is_extern) else { bool is_cond; - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, NULL)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; decl->is_cond = is_cond; } @@ -1041,7 +1043,7 @@ Decl *parse_var_decl(ParseContext *c) case TOKEN_IDENT: decl = decl_new_var_current(c, NULL, VARDECL_LOCAL); advance(c); - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, NULL)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; decl->is_cond = is_cond; if (!tok_is(c, TOKEN_EQ)) { @@ -1056,7 +1058,7 @@ Decl *parse_var_decl(ParseContext *c) decl = decl_new_var_current(c, NULL, c->tok == TOKEN_CT_IDENT ? VARDECL_LOCAL_CT : VARDECL_LOCAL_CT_TYPE); advance(c); span = c->span; - if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond, NULL)) return poisoned_decl; + if (!parse_attributes(c, &decl->attributes, NULL, NULL, &is_cond)) return poisoned_decl; if (is_cond || decl->attributes) { print_error_at(span, "Attributes are not allowed on compile time variables."); @@ -1216,22 +1218,6 @@ bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos) advance(c); Expr **list = NULL; - // Special handling of generic attributes - if (!attr->is_custom && attr->attr_kind == ATTRIBUTE_GENERIC) - { - CONSUME_OR_RET(TOKEN_LPAREN, false); - while (1) - { - ASSIGN_EXPR_OR_RET(Expr *expr, parse_expr(c), false); - vec_add(list, expr); - if (try_consume(c, TOKEN_RPAREN)) break; - CONSUME_OR_RET(TOKEN_COMMA, false); - } - attr->exprs = list; - *attribute_ref = attr; - return true; - } - // Consume the optional (expr | attr_param, ...) if (try_consume(c, TOKEN_LPAREN)) { @@ -1322,9 +1308,9 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl) decl->is_export = c->unit->export_by_default; bool is_builtin = false; bool is_cond; - Decl *generics = NULL; bool can_be_generic = decl_may_be_generic(decl); - if (!parse_attributes(c, &decl->attributes, &visibility, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond, &generics)) return false; + ASSIGN_DECL_OR_RET(Decl *generics, parse_generic_decl(c), false); + if (!parse_attributes(c, &decl->attributes, &visibility, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond)) return false; if (generics) { if (!can_be_generic) @@ -1349,8 +1335,7 @@ static bool parse_attributes_for_global(ParseContext *c, Decl *decl) return true; } -static inline bool parse_attribute_list(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, Decl ** - generic_ref, bool use_comma) +static inline bool parse_attribute_list(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, bool use_comma) { Visibility visibility = -1; // NOLINT if (cond_ref) *cond_ref = false; @@ -1368,39 +1353,6 @@ static inline bool parse_attribute_list(ParseContext *c, Attr ***attributes_ref, bool parsed_builtin = false; switch (attr->attr_kind) { - case ATTRIBUTE_GENERIC: - { - if (!generic_ref) RETURN_PRINT_ERROR_AT(false, attr, "'%s' cannot be used here.", attr->name); - if (*generic_ref) RETURN_PRINT_ERROR_AT(false, attr, "Only a single '%s' attribute may be added.", attr->name); - if (vec_size(attr->exprs) < 1) RETURN_PRINT_ERROR_AT(false, attr, "'%s' must have at least one parameter.", attr->name); - *generic_ref = decl_new(DECL_GENERIC, "", attr->span); - const char **names = NULL; - FOREACH(Expr *, expr, attr->exprs) - { - switch (expr->expr_kind) - { - case EXPR_TYPEINFO: - { - TypeInfo *type_info = expr->type_expr; - if (type_info->kind != TYPE_INFO_IDENTIFIER || type_info->subtype != TYPE_COMPRESSED_NONE) break; - if (type_info->unresolved.path) break; - vec_add(names, type_info->unresolved.name); - continue; - } - case EXPR_UNRESOLVED_IDENTIFIER: - { - if (!expr->unresolved_ident_expr.is_const || expr->unresolved_ident_expr.path) break; - vec_add(names, expr->unresolved_ident_expr.ident); - continue; - } - default: - break; - } - RETURN_PRINT_ERROR_AT(false, expr, "Generic parameters must be type or constant identifiers."); - } - (*generic_ref)->generic_decl.parameters = names; - break; - } case ATTRIBUTE_PUBLIC: parsed_visibility = VISIBLE_PUBLIC; break; @@ -1441,12 +1393,54 @@ static inline bool parse_attribute_list(ParseContext *c, Attr ***attributes_ref, if (other_attr->name == name) RETURN_PRINT_ERROR_AT(false, attr, "Repeat of attribute '%s' here.", name); } ADD: - if (attr->attr_kind != ATTRIBUTE_GENERIC) vec_add(*attributes_ref, attr); + vec_add(*attributes_ref, attr); if (use_comma && !try_consume(c, TOKEN_COMMA)) break; } return true; } +Decl *parse_generic_decl(ParseContext *c) +{ + SourceSpan start = c->span; + if (!try_consume(c, TOKEN_LESS)) return NULL; + if (try_consume(c, TOKEN_GREATER)) RETURN_PRINT_ERROR_HERE("The generic parameter list cannot be empty, it needs at least one element."); + + const char **tokens = NULL; + + // No params + while (1) + { + switch (c->tok) + { + case TOKEN_TYPE_IDENT: + case TOKEN_CONST_IDENT: + break; + case TOKEN_COMMA: + PRINT_ERROR_HERE("Unexpected ','"); + return poisoned_decl; + case TOKEN_IDENT: + PRINT_ERROR_HERE("The generic parameter must be a type or a constant."); + return poisoned_decl; + case TOKEN_CT_IDENT: + case TOKEN_CT_TYPE_IDENT: + PRINT_ERROR_HERE("The generic parameter cannot be a $-prefixed name."); + return poisoned_decl; + default: + PRINT_ERROR_HERE("Only generic parameters are allowed here."); + return poisoned_decl; + } + vec_add(tokens, symstr(c)); + advance(c); + if (!try_consume(c, TOKEN_COMMA)) + { + if (!consume(c, TOKEN_GREATER, "Expected '>'.")) return false; + Decl *decl = decl_new(DECL_GENERIC, "", extend_span_with_token(start, c->prev_span)); + decl->generic_decl.parameters = tokens; + return decl; + } + } +} + /** * attribute_list ::= attribute* * @@ -1454,10 +1448,9 @@ ADD: * * @return true if parsing succeeded, false if recovery is needed */ -bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, Decl ** - generic_ref) +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref) { - return parse_attribute_list(c, attributes_ref, visibility_ref, builtin_ref, cond_ref, generic_ref, false); + return parse_attribute_list(c, attributes_ref, visibility_ref, builtin_ref, cond_ref, false); } /** @@ -1575,7 +1568,7 @@ static inline bool parse_enum_param_decl(ParseContext *c, Decl*** parameters) if (token_is_some_ident(c->tok)) RETURN_PRINT_ERROR_HERE("Expected a name starting with a lower-case letter."); RETURN_PRINT_ERROR_HERE("Expected a member name here."); } - if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL, NULL)) return false; + if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL)) return false; vec_add(*parameters, param); RANGE_EXTEND_PREV(param); return true; @@ -1822,7 +1815,7 @@ CHECK_ELLIPSIS: Decl *param = decl_new_var(name, span, type, param_kind); param->var.type_info = type ? type_infoid(type) : 0; param->var.self_addr = ref; - if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL, NULL)) return false; + if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL)) return false; if (!no_name) { if (try_consume(c, TOKEN_EQ)) @@ -1962,7 +1955,7 @@ static bool parse_struct_body(ParseContext *c, Decl *parent) else { bool is_cond; - if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond, NULL)) return false; + if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond)) return false; member->is_cond = true; if (!parse_struct_body(c, member)) return decl_poison(parent); } @@ -2005,7 +1998,7 @@ static bool parse_struct_body(ParseContext *c, Decl *parent) } advance(c); bool is_cond; - if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond, NULL)) return false; + if (!parse_attributes(c, &member->attributes, NULL, NULL, &is_cond)) return false; member->is_cond = true; if (!try_consume(c, TOKEN_COMMA)) break; if (was_inline) @@ -2155,7 +2148,7 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) is_consecutive = true; } bool is_cond = false; - if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond, NULL)) return false; + if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond)) return false; member_decl->is_cond = is_cond; CONSUME_OR_RET(TOKEN_EOS, false); unsigned index = vec_size(decl->strukt.members); @@ -2176,7 +2169,7 @@ static inline bool parse_bitstruct_body(ParseContext *c, Decl *decl) member_decl->var.end = NULL; } bool is_cond = false; - if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond, NULL)) return false; + if (!parse_attributes(c, &member_decl->attributes, NULL, NULL, &is_cond)) return false; member_decl->is_cond = is_cond; CONSUME_EOS_OR_RET(false); if (is_consecutive) @@ -2362,7 +2355,7 @@ static inline Decl *parse_alias_type(ParseContext *c, AstId contracts) { return poisoned_decl; } - if (!parse_attributes(c, &decl_type->attributes, NULL, NULL, NULL, NULL)) return poisoned_decl; + if (!parse_attributes(c, &decl_type->attributes, NULL, NULL, NULL)) return poisoned_decl; RANGE_EXTEND_PREV(decl_type); RANGE_EXTEND_PREV(decl); CONSUME_EOS_OR_RET(poisoned_decl); @@ -2545,7 +2538,7 @@ static inline Decl *parse_attrdef(ParseContext *c) bool is_cond; bool is_builtin = false; - if (!parse_attribute_list(c, &attributes, NULL, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond, NULL,true)) return poisoned_decl; + if (!parse_attribute_list(c, &attributes, NULL, decl_needs_prefix(decl) ? &is_builtin : NULL, &is_cond, true)) return poisoned_decl; decl->attr_decl.attrs = attributes; CONSUME_EOS_OR_RET(poisoned_decl); return decl; diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index d765a6e3c..a890490d3 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -46,8 +46,8 @@ Ast *parse_short_body(ParseContext *c, TypeInfoId return_type, bool is_regular_f bool parse_attribute(ParseContext *c, Attr **attribute_ref, bool expect_eos); -bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref, Decl ** - generic_ref); +bool parse_attributes(ParseContext *c, Attr ***attributes_ref, Visibility *visibility_ref, bool *builtin_ref, bool *cond_ref); +Decl *parse_generic_decl(ParseContext *c); bool parse_switch_body(ParseContext *c, Ast ***cases, TokenType case_type, TokenType default_type); Expr *parse_ct_expression_list(ParseContext *c, bool allow_decl); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 5a77335df..3503e44c0 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -3097,7 +3097,6 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ [ATTRIBUTE_EXTERN] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES, [ATTRIBUTE_FINALIZER] = ATTR_FUNC, [ATTRIBUTE_FORMAT] = ATTR_FUNC | ATTR_MACRO | ATTR_FNTYPE, - [ATTRIBUTE_GENERIC] = ATTR_FUNC | ATTR_MACRO | ATTR_GLOBAL | ATTR_CONST | ATTR_UNION | ATTR_STRUCT | ATTR_INTERFACE | ATTR_ALIAS, [ATTRIBUTE_IF] = (AttributeDomain)~(ATTR_CALL | ATTR_PARAM), [ATTRIBUTE_INIT] = ATTR_FUNC, [ATTRIBUTE_INLINE] = ATTR_FUNC | ATTR_CALL, @@ -3352,8 +3351,6 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_ case ATTRIBUTE_NOALIAS: decl->var.no_alias = true; return true; - case ATTRIBUTE_GENERIC: - UNREACHABLE; case ATTRIBUTE_IF: if (!expr) RETURN_SEMA_ERROR(attr, "'@if' requires a boolean argument."); if (!sema_analyse_expr_rvalue(context, expr)) return false; diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index dd873f9f6..bcc4bd296 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -353,7 +353,6 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_EXTERN] = KW_DEF("@extern"); attribute_list[ATTRIBUTE_FINALIZER] = KW_DEF("@finalizer"); attribute_list[ATTRIBUTE_FORMAT] = KW_DEF("@format"); - attribute_list[ATTRIBUTE_GENERIC] = KW_DEF("@generic"); attribute_list[ATTRIBUTE_IF] = KW_DEF("@if"); attribute_list[ATTRIBUTE_INIT] = KW_DEF("@init"); attribute_list[ATTRIBUTE_INLINE] = KW_DEF("@inline"); diff --git a/test/test_suite/any/casting_voidptr_to_any.c3 b/test/test_suite/any/casting_voidptr_to_any.c3 index f3708379b..883fe156e 100644 --- a/test/test_suite/any/casting_voidptr_to_any.c3 +++ b/test/test_suite/any/casting_voidptr_to_any.c3 @@ -3,7 +3,7 @@ interface IOp { fn void op(); } -module mylib{Type}; +module mylib ; import std::io; import mylib::ifaces; struct Op (IOp) diff --git a/test/test_suite/any/generic_interface.c3 b/test/test_suite/any/generic_interface.c3 index e1422685f..d1559863e 100644 --- a/test/test_suite/any/generic_interface.c3 +++ b/test/test_suite/any/generic_interface.c3 @@ -1,4 +1,4 @@ -module foo{Type}; +module foo ; interface Baz {} diff --git a/test/test_suite/arrays/slice_constant_mod.c3t b/test/test_suite/arrays/slice_constant_mod.c3t index fc26a0c2a..1c5b07e43 100644 --- a/test/test_suite/arrays/slice_constant_mod.c3t +++ b/test/test_suite/arrays/slice_constant_mod.c3t @@ -1,4 +1,4 @@ -module my_module { GENNY }; +module my_module ; import std::io; const uint[5] H = { 1, 2, 3, 4, 5 }; diff --git a/test/test_suite/compile_time/concat_untyped_with_struct_array.c3t b/test/test_suite/compile_time/concat_untyped_with_struct_array.c3t index 2a404e633..9e13e1230 100644 --- a/test/test_suite/compile_time/concat_untyped_with_struct_array.c3t +++ b/test/test_suite/compile_time/concat_untyped_with_struct_array.c3t @@ -20,7 +20,7 @@ fn int main() <* This contains macros for working with arrays at compile time *> -module assert_repro::macros { ValueT }; +module assert_repro::macros ; alias SliceT = ValueT[]; macro SliceT slice(SliceT $from, usz $start, usz $end = usz.max) diff --git a/test/test_suite/compile_time_introspection/defined_generic_type.c3t b/test/test_suite/compile_time_introspection/defined_generic_type.c3t index c9cbc4011..32c92b47c 100644 --- a/test/test_suite/compile_time_introspection/defined_generic_type.c3t +++ b/test/test_suite/compile_time_introspection/defined_generic_type.c3t @@ -14,7 +14,7 @@ fn int main() return 0; } -module foo {Type}; +module foo ; struct Foo { diff --git a/test/test_suite/define/test_at.c3 b/test/test_suite/define/test_at.c3 index e1ae72061..c606fa3ea 100644 --- a/test/test_suite/define/test_at.c3 +++ b/test/test_suite/define/test_at.c3 @@ -1,4 +1,4 @@ -module foo{Type}; +module foo ; import std::io; macro @hello(Type thing) { diff --git a/test/test_suite/define/test_at_alias.c3 b/test/test_suite/define/test_at_alias.c3 index ec3c5c898..4f9addfb2 100644 --- a/test/test_suite/define/test_at_alias.c3 +++ b/test/test_suite/define/test_at_alias.c3 @@ -1,4 +1,4 @@ -module foo{Type}; +module foo ; import std::io; macro @hello(Type thing) { diff --git a/test/test_suite/enumerations/enum_copy.c3t b/test/test_suite/enumerations/enum_copy.c3t index 9dbef9d62..3c7935144 100644 --- a/test/test_suite/enumerations/enum_copy.c3t +++ b/test/test_suite/enumerations/enum_copy.c3t @@ -1,4 +1,4 @@ -module generic_module_enum{N}; +module generic_module_enum ; enum Foo : char (String s) { diff --git a/test/test_suite/expressions/take_address.c3t b/test/test_suite/expressions/take_address.c3t index f6a94baec..3cbf2adcb 100644 --- a/test/test_suite/expressions/take_address.c3t +++ b/test/test_suite/expressions/take_address.c3t @@ -10,7 +10,7 @@ fn void main() blurb::test(&hello_int); } -module foo{Type}; +module foo ; fn void hello() {} diff --git a/test/test_suite/functions/test_regression.c3t b/test/test_suite/functions/test_regression.c3t index e01aff0ef..79cdaf36d 100644 --- a/test/test_suite/functions/test_regression.c3t +++ b/test/test_suite/functions/test_regression.c3t @@ -181,14 +181,14 @@ fn void hello() printf("Mult %f\n", doubleMult(11.1)); } -module foo{Type}; +module foo ; fn Type check(Type i) { return i * i; } -module test2{Type}; +module test2 ; struct Blob { diff --git a/test/test_suite/functions/test_regression_mingw.c3t b/test/test_suite/functions/test_regression_mingw.c3t index 4a9ee96a3..2d214a348 100644 --- a/test/test_suite/functions/test_regression_mingw.c3t +++ b/test/test_suite/functions/test_regression_mingw.c3t @@ -183,14 +183,14 @@ fn void hello() printf("Mult %f\n", doubleMult(11.1)); } -module foo{Type}; +module foo ; fn Type check(Type i) { return i * i; } -module test2{Type}; +module test2 ; struct Blob { diff --git a/test/test_suite/generic/different_generic_def.c3 b/test/test_suite/generic/different_generic_def.c3 index 00dbcef0f..08d51535f 100644 --- a/test/test_suite/generic/different_generic_def.c3 +++ b/test/test_suite/generic/different_generic_def.c3 @@ -6,14 +6,14 @@ fn int main() return 0; } -module test2{Type}; +module test2 ; struct Foo { Type f; } -module test2{Type, FOO}; +module test2 ; struct Foo1 { diff --git a/test/test_suite/generic/generic_builtin.c3t b/test/test_suite/generic/generic_builtin.c3t index 0e249bf49..4813f3ad5 100644 --- a/test/test_suite/generic/generic_builtin.c3t +++ b/test/test_suite/generic/generic_builtin.c3t @@ -1,4 +1,4 @@ -module add{Type}; +module add ; fn Type add(Type a, Type b) @builtin => a + b; diff --git a/test/test_suite/generic/generic_contract_aggregation.c3 b/test/test_suite/generic/generic_contract_aggregation.c3 index efe1f58b4..e37080d7c 100644 --- a/test/test_suite/generic/generic_contract_aggregation.c3 +++ b/test/test_suite/generic/generic_contract_aggregation.c3 @@ -1,7 +1,7 @@ import std::io; <* @require Type.kindof == SIGNED_INT *> -struct Foo @generic(Type) +struct Foo { Type a; } diff --git a/test/test_suite/generic/generic_copy.c3t b/test/test_suite/generic/generic_copy.c3t index 4d6523602..7fdf3e8de 100644 --- a/test/test_suite/generic/generic_copy.c3t +++ b/test/test_suite/generic/generic_copy.c3t @@ -1,4 +1,4 @@ -module foo{Type}; +module foo ; fn void abc() { diff --git a/test/test_suite/generic/generic_cyclic.c3 b/test/test_suite/generic/generic_cyclic.c3 index 033300adc..e98979854 100644 --- a/test/test_suite/generic/generic_cyclic.c3 +++ b/test/test_suite/generic/generic_cyclic.c3 @@ -9,7 +9,7 @@ struct Test BazTest t; } -module bar{Test}; +module bar ; struct Baz { diff --git a/test/test_suite/generic/generic_default_wrong_init.c3 b/test/test_suite/generic/generic_default_wrong_init.c3 index c15dce51f..374d8ddd0 100644 --- a/test/test_suite/generic/generic_default_wrong_init.c3 +++ b/test/test_suite/generic/generic_default_wrong_init.c3 @@ -1,4 +1,4 @@ -fn Type test_val(Type val = Type{}) @generic(Type) => val; // #error: 'Type' is not a generic type. Did you want an initializer but forgot () around the type? That is, you typed 'Type { ... }' but intended '(Type) { ... }' +fn Type test_val(Type val = Type{}) => val; // #error: 'Type' is not a generic type. Did you want an initializer but forgot () around the type? That is, you typed 'Type { ... }' but intended '(Type) { ... }' fn int main() { diff --git a/test/test_suite/generic/generic_distinct.c3t b/test/test_suite/generic/generic_distinct.c3t index ce4e821d7..36de6d9b1 100644 --- a/test/test_suite/generic/generic_distinct.c3t +++ b/test/test_suite/generic/generic_distinct.c3t @@ -8,7 +8,7 @@ fn void main() Foo $f = 1; test1::foo{$f}(); } -module test1 {FOO}; +module test1 ; fn void foo() {} diff --git a/test/test_suite/generic/generic_fault.c3t b/test/test_suite/generic/generic_fault.c3t index ce7bce1d5..879999e53 100644 --- a/test/test_suite/generic/generic_fault.c3t +++ b/test/test_suite/generic/generic_fault.c3t @@ -1,4 +1,4 @@ -module abc {Type}; +module abc ; attrdef @Hello = @inline; faultdef ABC; diff --git a/test/test_suite/generic/generic_fault2.c3t b/test/test_suite/generic/generic_fault2.c3t index 71fd096ea..8b0f070bd 100644 --- a/test/test_suite/generic/generic_fault2.c3t +++ b/test/test_suite/generic/generic_fault2.c3t @@ -1,4 +1,4 @@ -module g{T}; +module g ; faultdef F0, F1; diff --git a/test/test_suite/generic/generic_idents.c3t b/test/test_suite/generic/generic_idents.c3t index d4f8bb775..cca8b2018 100644 --- a/test/test_suite/generic/generic_idents.c3t +++ b/test/test_suite/generic/generic_idents.c3t @@ -1,5 +1,5 @@ // #target: macos-aarch64 -module gen{Type}; +module gen ; fn Type mult(Type x) { diff --git a/test/test_suite/generic/generic_infer_mismatch.c3 b/test/test_suite/generic/generic_infer_mismatch.c3 index 583427953..9491a9456 100644 --- a/test/test_suite/generic/generic_infer_mismatch.c3 +++ b/test/test_suite/generic/generic_infer_mismatch.c3 @@ -1,9 +1,9 @@ import std; -struct Result @generic(WithType2) +struct Result { fault error; } -macro err(fault error) @generic(OfType, SOME_CONST) @builtin => (Result{OfType}){ .error = error }; +macro err(fault error) @builtin => (Result{OfType}){ .error = error }; faultdef TESTIN; diff --git a/test/test_suite/generic/generic_infer_ok.c3 b/test/test_suite/generic/generic_infer_ok.c3 index 655bf393b..bc8b285f4 100644 --- a/test/test_suite/generic/generic_infer_ok.c3 +++ b/test/test_suite/generic/generic_infer_ok.c3 @@ -1,9 +1,9 @@ import std; -struct Result @generic(WithType2) +struct Result { fault error; } -macro err(fault error) @generic(OfType) @builtin => (Result{OfType}){ .error = error }; +macro err(fault error) @builtin => (Result{OfType}){ .error = error }; faultdef TESTIN; diff --git a/test/test_suite/generic/generic_inference.c3t b/test/test_suite/generic/generic_inference.c3t index 0c854e066..3080c3798 100644 --- a/test/test_suite/generic/generic_inference.c3t +++ b/test/test_suite/generic/generic_inference.c3t @@ -14,7 +14,7 @@ fn void main() hello(test2::get_foo{int}()); } -module test2 {Type}; +module test2 ; fn Foo get_foo() => {}; diff --git a/test/test_suite/generic/generic_interface.c3t b/test/test_suite/generic/generic_interface.c3t index 56df954f5..ccff6bf29 100644 --- a/test/test_suite/generic/generic_interface.c3t +++ b/test/test_suite/generic/generic_interface.c3t @@ -1,7 +1,7 @@ // #target: macos-aarch64 module base; -module test{MyType}; +module test ; import base; interface Zzz { diff --git a/test/test_suite/generic/generic_lambda_complex.c3t b/test/test_suite/generic/generic_lambda_complex.c3t index 702ad086d..73f8d69e9 100644 --- a/test/test_suite/generic/generic_lambda_complex.c3t +++ b/test/test_suite/generic/generic_lambda_complex.c3t @@ -5,7 +5,7 @@ module abc_faults; faultdef UNTERMINATED_TAG, EMPTY_TAG, MISSING_TAG, UNSUPPORTED_TAG; <* @require Type.kindof == STRUCT *> -module abc{Type}; +module abc ; import std::io, abc_faults, std::collections::list; alias TextTagList = List{TextTag}; diff --git a/test/test_suite/generic/generic_local.c3 b/test/test_suite/generic/generic_local.c3 index 1e8cdcbc9..8f555457b 100644 --- a/test/test_suite/generic/generic_local.c3 +++ b/test/test_suite/generic/generic_local.c3 @@ -15,7 +15,7 @@ import foo::private; // Bug #856 typedef Foo = inline PrivateFoo{int}; // #error: could not be found -module foo::private{Type} @local; +module foo::private @local; struct PrivateFoo { diff --git a/test/test_suite/generic/generic_merge_constraints.c3 b/test/test_suite/generic/generic_merge_constraints.c3 index 4039d1bcd..62f64d08e 100644 --- a/test/test_suite/generic/generic_merge_constraints.c3 +++ b/test/test_suite/generic/generic_merge_constraints.c3 @@ -1,9 +1,9 @@ <* @require THE_CONST < 5 *> -module the_generic @generic(THE_CONST, Type); +module the_generic ; struct Abc { int a; } -module the_generic @generic(THE_CONST, Type); +module the_generic ; struct TheStruct { diff --git a/test/test_suite/generic/generic_new_decl_with_type.c3t b/test/test_suite/generic/generic_new_decl_with_type.c3t index 1b9f884b7..759bcfaf2 100644 --- a/test/test_suite/generic/generic_new_decl_with_type.c3t +++ b/test/test_suite/generic/generic_new_decl_with_type.c3t @@ -1,4 +1,4 @@ -module custom_type @generic(Type, VALUE); +module custom_type ; struct Example { diff --git a/test/test_suite/generic/generic_no_arg.c3 b/test/test_suite/generic/generic_no_arg.c3 index 591f47e6c..0c9174136 100644 --- a/test/test_suite/generic/generic_no_arg.c3 +++ b/test/test_suite/generic/generic_no_arg.c3 @@ -21,10 +21,9 @@ fn void c() fn int main() { - return 0; } -module bar{Type}; +module bar ; fn void test() {} \ No newline at end of file diff --git a/test/test_suite/generic/generic_no_params.c3 b/test/test_suite/generic/generic_no_params.c3 index 243a64c80..7f0aa33a3 100644 --- a/test/test_suite/generic/generic_no_params.c3 +++ b/test/test_suite/generic/generic_no_params.c3 @@ -1,4 +1,4 @@ -module values {Type}; +module values ; struct Values { diff --git a/test/test_suite/generic/generic_num.c3t b/test/test_suite/generic/generic_num.c3t index 7b89fb531..9349fc177 100644 --- a/test/test_suite/generic/generic_num.c3t +++ b/test/test_suite/generic/generic_num.c3t @@ -1,5 +1,5 @@ // #target: macos-x64 -module hello{Type, FOO}; +module hello ; fn Type x(Type t) { diff --git a/test/test_suite/generic/generic_over_fn.c3t b/test/test_suite/generic/generic_over_fn.c3t index c71ad2fb6..5a9563e3e 100644 --- a/test/test_suite/generic/generic_over_fn.c3t +++ b/test/test_suite/generic/generic_over_fn.c3t @@ -1,5 +1,5 @@ // #target: macos-x64 -module test_generic{Type, Func}; +module test_generic; fn void sort(Type list, isz, isz, Func cmp) {} diff --git a/test/test_suite/generic/generic_resolution_1402.c3t b/test/test_suite/generic/generic_resolution_1402.c3t index 4f1fa8bc3..6fdedb2aa 100644 --- a/test/test_suite/generic/generic_resolution_1402.c3t +++ b/test/test_suite/generic/generic_resolution_1402.c3t @@ -1,5 +1,5 @@ // #target: macos-x64 -module playground::bug{Ty}; +module playground::bug ; import std::io; struct Foo @@ -12,7 +12,7 @@ fn void Foo.print_it(&self) io::printf("Method %s\n", self.x); } -module playground::bug{Ty}; +module playground::bug ; import std::io; macro void print_it(...) diff --git a/test/test_suite/generic/generic_self_ref.c3 b/test/test_suite/generic/generic_self_ref.c3 index 46dabc097..2ba9198dc 100644 --- a/test/test_suite/generic/generic_self_ref.c3 +++ b/test/test_suite/generic/generic_self_ref.c3 @@ -1,4 +1,4 @@ -module gui::widget {Type}; +module gui::widget ; import gui::widget_types; import std::collections::list; import std::io; diff --git a/test/test_suite/generic/generic_testcases.c3t b/test/test_suite/generic/generic_testcases.c3t index 825236f1a..7ed9bfffd 100644 --- a/test/test_suite/generic/generic_testcases.c3t +++ b/test/test_suite/generic/generic_testcases.c3t @@ -1,9 +1,9 @@ // #target: macos-aarch64 -module the_generic @generic(THE_CONST, Type); +module the_generic ; struct Abc { int a; } -module the_generic @generic(THE_CONST, Type); +module the_generic ; struct TheStruct { @@ -37,8 +37,8 @@ module test; import the_generic; <* @require Type.sizeof < 5 *> -fn Type square(Type t) @generic(Type) => t * 3; -fn Type bob(Type2 t) @generic(Type2) => feok * 3; +fn Type square(Type t) => t * 3; +fn Type bob(Type2 t) => feok * 3; fn int main() { diff --git a/test/test_suite/generic/generic_void.c3t b/test/test_suite/generic/generic_void.c3t index d6ea42de8..392fa43da 100644 --- a/test/test_suite/generic/generic_void.c3t +++ b/test/test_suite/generic/generic_void.c3t @@ -1,5 +1,5 @@ // #target: macos-x64 -module test{Type}; +module test ; alias Callback = fn Type(); diff --git a/test/test_suite/generic/generic_with_comment.c3t b/test/test_suite/generic/generic_with_comment.c3t index 01fca993a..60ebc2940 100644 --- a/test/test_suite/generic/generic_with_comment.c3t +++ b/test/test_suite/generic/generic_with_comment.c3t @@ -9,5 +9,5 @@ fn void main() { <* Hello *> -module generic{Param}; +module generic ; struct Generic { int a; } \ No newline at end of file diff --git a/test/test_suite/generic/generic_with_enum.c3t b/test/test_suite/generic/generic_with_enum.c3t index 40b449de1..03e4787d1 100644 --- a/test/test_suite/generic/generic_with_enum.c3t +++ b/test/test_suite/generic/generic_with_enum.c3t @@ -1,5 +1,5 @@ // #target: macos-x64 -module test{FOO}; +module test ; const Z = FOO; diff --git a/test/test_suite/generic/generic_without_param.c3 b/test/test_suite/generic/generic_without_param.c3 index 9f00eeefc..f133710b0 100644 --- a/test/test_suite/generic/generic_without_param.c3 +++ b/test/test_suite/generic/generic_without_param.c3 @@ -5,5 +5,5 @@ fn void main() { abc::test(); // #error: 'test' is a generic function, did you forget the parameters '{ ... }'? } -module abc{Type}; +module abc ; fn void test() {} \ No newline at end of file diff --git a/test/test_suite/generic/implicit_import_of_generic.c3 b/test/test_suite/generic/implicit_import_of_generic.c3 index 18363ec01..c2a2e56f5 100644 --- a/test/test_suite/generic/implicit_import_of_generic.c3 +++ b/test/test_suite/generic/implicit_import_of_generic.c3 @@ -13,6 +13,6 @@ module abc::foo; struct Def { int x; } -module abc::cde{Type}; +module abc::cde ; struct Abc { Type a, b; } \ No newline at end of file diff --git a/test/test_suite/generic/incorrect_argument_type.c3 b/test/test_suite/generic/incorrect_argument_type.c3 index 355b3950d..f9984a644 100644 --- a/test/test_suite/generic/incorrect_argument_type.c3 +++ b/test/test_suite/generic/incorrect_argument_type.c3 @@ -1,4 +1,4 @@ -module foo{Type, SIZE}; +module foo ; struct Foo { diff --git a/test/test_suite/generic/nested_typedef.c3t b/test/test_suite/generic/nested_typedef.c3t index 90f8e1246..dcc7cff81 100644 --- a/test/test_suite/generic/nested_typedef.c3t +++ b/test/test_suite/generic/nested_typedef.c3t @@ -1,5 +1,5 @@ // #target: macos-x64 -module broken{Type}; +module broken ; typedef Bar = Type; alias Bar2 = Type; struct Baz diff --git a/test/test_suite/generic/overlapping_generic.c3t b/test/test_suite/generic/overlapping_generic.c3t index 44498d1e5..60f34e351 100644 --- a/test/test_suite/generic/overlapping_generic.c3t +++ b/test/test_suite/generic/overlapping_generic.c3t @@ -1,9 +1,9 @@ import std; -struct Result @generic(WithType2) +struct Result { fault error; } -macro Result{WithType} err(fault error) @generic(WithType) => { .error = error }; +macro Result{WithType} err(fault error) => { .error = error }; faultdef TESTIN; diff --git a/test/test_suite/generic/recursive_generic.c3 b/test/test_suite/generic/recursive_generic.c3 index 0cdf3475a..09b18b0d6 100644 --- a/test/test_suite/generic/recursive_generic.c3 +++ b/test/test_suite/generic/recursive_generic.c3 @@ -5,10 +5,10 @@ fn int main() => 0; Aa {int} a; -module test1 {Type}; +module test1 ; import test2; alias Cc = Aa {Bb {Type}}; // #error: Generic resolution of this type has become deeply nested struct Aa {Type a;} -module test2 {Type}; +module test2 ; struct Bb {Type b;} \ No newline at end of file diff --git a/test/test_suite/generic/recursive_generic2.c3 b/test/test_suite/generic/recursive_generic2.c3 index 9fe06073d..b64dfd2dd 100644 --- a/test/test_suite/generic/recursive_generic2.c3 +++ b/test/test_suite/generic/recursive_generic2.c3 @@ -1,4 +1,4 @@ -module foo { Type }; +module foo ; import std::collections::list; diff --git a/test/test_suite/globals/links_global.c3 b/test/test_suite/globals/links_global.c3 index 001ae7f90..9d44ae385 100644 --- a/test/test_suite/globals/links_global.c3 +++ b/test/test_suite/globals/links_global.c3 @@ -8,6 +8,6 @@ fn int main(String[] args) return 0; } -module some_module { F }; +module some_module ; import std; const A_CONST = 12 + 2 * math::log2(F / 25); // #error: This expression cannot be evaluated at compile time \ No newline at end of file diff --git a/test/test_suite/initializer_lists/init_any_interface.c3 b/test/test_suite/initializer_lists/init_any_interface.c3 index 98e7f5261..e800e8b94 100644 --- a/test/test_suite/initializer_lists/init_any_interface.c3 +++ b/test/test_suite/initializer_lists/init_any_interface.c3 @@ -15,7 +15,7 @@ fn int main() { return 0; } -module test::generic{Type}; +module test::generic ; struct Test { diff --git a/test/test_suite/methods/extension_method_check.c3 b/test/test_suite/methods/extension_method_check.c3 index 40a163de8..e184446cd 100644 --- a/test/test_suite/methods/extension_method_check.c3 +++ b/test/test_suite/methods/extension_method_check.c3 @@ -11,7 +11,7 @@ fn int main() <* @require $defined(String.hash) *> -module test::generic{Some_Type}; +module test::generic ; enum Test { diff --git a/test/test_suite/module/module_generic_mixing.c3 b/test/test_suite/module/module_generic_mixing.c3 index 683ccb566..c8c8b1ee9 100644 --- a/test/test_suite/module/module_generic_mixing.c3 +++ b/test/test_suite/module/module_generic_mixing.c3 @@ -4,7 +4,7 @@ fn void main() test{int}(); } -module test{Type}; +module test ; fn void test() { Type a; diff --git a/test/test_suite/switch/switch_in_defer_macro.c3t b/test/test_suite/switch/switch_in_defer_macro.c3t index 6cc6f7a61..0c1fcbed6 100644 --- a/test/test_suite/switch/switch_in_defer_macro.c3t +++ b/test/test_suite/switch/switch_in_defer_macro.c3t @@ -10,7 +10,7 @@ faultdef TRIE_FULL; @require $defined((Token){}.token) @require $defined((Comment){}.start) && $defined((Comment){}.end) *> -module lexer {Token, Comment}; +module lexer ; import std::io; import trie; @@ -456,7 +456,7 @@ fn int main(String[] args) <* @require Index.kindof == TypeKind.UNSIGNED_INT *> -module trie{Value, Index}; +module trie ; import std::collections::list; import trie::bitmap; import lexer::faults;