mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Generics with <>. Deprecation of {} generics.
This commit is contained in:
@@ -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 <Type>;
|
||||
|
||||
struct Atomic
|
||||
{
|
||||
|
||||
@@ -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 <SIZE>;
|
||||
|
||||
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 <Type>;
|
||||
import std::collections::list;
|
||||
|
||||
const BITS = Type.sizeof * 8;
|
||||
|
||||
@@ -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 <Type, MAX_SIZE>;
|
||||
import std::io, std::math, std::collections::list_common;
|
||||
|
||||
alias ElementPredicate = fn bool(Type *type);
|
||||
|
||||
@@ -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 <Enum, ValueType>;
|
||||
import std::io;
|
||||
|
||||
struct EnumMap (Printable)
|
||||
|
||||
@@ -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 <Enum>;
|
||||
import std::io;
|
||||
|
||||
const ENUM_COUNT @private = Enum.values.len;
|
||||
|
||||
@@ -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 <Key, Value>;
|
||||
import std::math;
|
||||
import std::io @norecurse;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<*
|
||||
@require $defined((Value){}.hash()) : `No .hash function found on the value`
|
||||
*>
|
||||
module std::collections::set {Value};
|
||||
module std::collections::set <Value>;
|
||||
import std::math;
|
||||
import std::io @norecurse;
|
||||
|
||||
|
||||
@@ -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 <Type>;
|
||||
import std::io,std::math;
|
||||
|
||||
alias InterfacePredicate = fn bool(Type value);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::collections::blockingqueue { Value };
|
||||
module std::collections::blockingqueue <Value>;
|
||||
import std::thread, std::time;
|
||||
|
||||
|
||||
|
||||
@@ -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 <Key, Value>;
|
||||
import std::math;
|
||||
import std::io @norecurse;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<*
|
||||
@require $defined((Value){}.hash()) : `No .hash function found on the value`
|
||||
*>
|
||||
module std::collections::set {Value};
|
||||
module std::collections::set <Value>;
|
||||
import std::math;
|
||||
import std::io @norecurse;
|
||||
|
||||
|
||||
@@ -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 <Type>;
|
||||
import std::io;
|
||||
|
||||
const ELEMENT_IS_EQUATABLE = types::is_equatable_type(Type);
|
||||
|
||||
@@ -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 <Type>;
|
||||
import std::io, std::math, std::collections::list_common;
|
||||
|
||||
alias ElementPredicate = fn bool(Type *type);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::collections::maybe{Type};
|
||||
module std::collections::maybe <Type>;
|
||||
import std::io;
|
||||
|
||||
struct Maybe (Printable)
|
||||
|
||||
@@ -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 <Type> = inline PrivatePriorityQueue{Type, false};
|
||||
typedef PriorityQueueMax <Type> = inline PrivatePriorityQueue{Type, true};
|
||||
|
||||
struct PrivatePriorityQueue (Printable) <Type, MAX>
|
||||
{
|
||||
List{Type} heap;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<*
|
||||
@require Type.is_ordered : "The type must be ordered"
|
||||
*>
|
||||
module std::collections::range{Type};
|
||||
module std::collections::range <Type>;
|
||||
import std::io;
|
||||
|
||||
struct Range (Printable)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<*
|
||||
@require Type.kindof == ARRAY : "Required an array type"
|
||||
*>
|
||||
module std::collections::ringbuffer{Type};
|
||||
module std::collections::ringbuffer <Type>;
|
||||
import std::io;
|
||||
|
||||
alias Element = $typeof((Type){}[0]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::collections::pair{Type1, Type2};
|
||||
module std::collections::pair <Type1, Type2>;
|
||||
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 <Type1, Type2, Type3>;
|
||||
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 <Type1, Type2>;
|
||||
|
||||
struct Tuple @deprecated("Use 'Pair' instead")
|
||||
{
|
||||
Type1 first;
|
||||
Type2 second;
|
||||
}
|
||||
}
|
||||
@@ -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 <Type>;
|
||||
|
||||
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 <Type, ALIGNMENT>;
|
||||
import std::core::mem @public;
|
||||
|
||||
<*
|
||||
|
||||
@@ -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 <Type>;
|
||||
import std::thread, std::atomic;
|
||||
|
||||
const OVERALIGNED @private = Type.alignof > mem::DEFAULT_MEM_ALIGNMENT;
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
Type* ptr;
|
||||
usz inner_len;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::experimental::scheduler{Event};
|
||||
module std::experimental::scheduler <Event>;
|
||||
import std::collections, std::thread, std::time;
|
||||
|
||||
struct DelayedSchedulerEvent @local
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::hash::hmac{HashAlg, HASH_BYTES, BLOCK_BYTES};
|
||||
module std::hash::hmac <HashAlg, HASH_BYTES, BLOCK_BYTES>;
|
||||
import std::crypto;
|
||||
|
||||
struct Hmac
|
||||
|
||||
@@ -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 <DIGEST_BITS>;
|
||||
|
||||
|
||||
<* Unchanging block size. *>
|
||||
|
||||
@@ -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 <OutType, BLOCK_ROUNDS, FINALIZE_ROUNDS>;
|
||||
|
||||
|
||||
struct SipHash
|
||||
|
||||
@@ -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 <Real>;
|
||||
import std::io;
|
||||
|
||||
union ComplexNumber (Printable)
|
||||
|
||||
@@ -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 <Real>;
|
||||
import std::math::vector;
|
||||
|
||||
struct Matrix2x2
|
||||
|
||||
@@ -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 <Real>;
|
||||
import std::math::vector;
|
||||
union QuaternionNumber
|
||||
{
|
||||
|
||||
@@ -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 <Type, KeyFn>;
|
||||
|
||||
alias Counts @private = usz[256];
|
||||
alias Ranges @private = usz[257];
|
||||
|
||||
@@ -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 <Type, CmpFn, Context>;
|
||||
|
||||
alias ElementType = $typeof(((Type){})[0]);
|
||||
const bool IS_SLICE = Type.kindof == SLICE;
|
||||
|
||||
@@ -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 <Type, CmpFn, Context>;
|
||||
|
||||
alias ElementType = $typeof(((Type){})[0]);
|
||||
const bool IS_SLICE = Type.kindof == SLICE;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::thread::channel{Type};
|
||||
module std::thread::channel <Type>;
|
||||
|
||||
typedef BufferedChannel = void*;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::thread::pool{SIZE};
|
||||
module std::thread::pool <SIZE>;
|
||||
import std::thread;
|
||||
|
||||
struct ThreadPool
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module std::thread::channel {Type};
|
||||
module std::thread::channel <Type>;
|
||||
|
||||
typedef UnbufferedChannel = void*;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -2,7 +2,7 @@ module std::container::faults;
|
||||
|
||||
faultdef KEY_NOT_FOUND;
|
||||
|
||||
module std::container::map{Key, Type};
|
||||
module std::container::map <Key, Type>;
|
||||
import std::core::builtin;
|
||||
import std::io;
|
||||
|
||||
|
||||
@@ -279,7 +279,6 @@ typedef enum
|
||||
ATTRIBUTE_EXTERN,
|
||||
ATTRIBUTE_FINALIZER,
|
||||
ATTRIBUTE_FORMAT,
|
||||
ATTRIBUTE_GENERIC,
|
||||
ATTRIBUTE_IF,
|
||||
ATTRIBUTE_INLINE,
|
||||
ATTRIBUTE_INIT,
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -3,7 +3,7 @@ interface IOp
|
||||
{
|
||||
fn void op();
|
||||
}
|
||||
module mylib{Type};
|
||||
module mylib <Type>;
|
||||
import std::io;
|
||||
import mylib::ifaces;
|
||||
struct Op (IOp)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module foo{Type};
|
||||
module foo <Type>;
|
||||
|
||||
interface Baz
|
||||
{}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module my_module { GENNY };
|
||||
module my_module <GENNY>;
|
||||
import std::io;
|
||||
|
||||
const uint[5] H = { 1, 2, 3, 4, 5 };
|
||||
|
||||
@@ -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 <ValueT>;
|
||||
alias SliceT = ValueT[];
|
||||
|
||||
macro SliceT slice(SliceT $from, usz $start, usz $end = usz.max)
|
||||
|
||||
@@ -14,7 +14,7 @@ fn int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
module foo {Type};
|
||||
module foo <Type>;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module foo{Type};
|
||||
module foo <Type>;
|
||||
import std::io;
|
||||
|
||||
macro @hello(Type thing) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module foo{Type};
|
||||
module foo <Type>;
|
||||
import std::io;
|
||||
|
||||
macro @hello(Type thing) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module generic_module_enum{N};
|
||||
module generic_module_enum <N>;
|
||||
|
||||
enum Foo : char (String s)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ fn void main()
|
||||
blurb::test(&hello_int);
|
||||
}
|
||||
|
||||
module foo{Type};
|
||||
module foo <Type>;
|
||||
|
||||
fn void hello() {}
|
||||
|
||||
|
||||
@@ -181,14 +181,14 @@ fn void hello()
|
||||
printf("Mult %f\n", doubleMult(11.1));
|
||||
}
|
||||
|
||||
module foo{Type};
|
||||
module foo <Type>;
|
||||
|
||||
fn Type check(Type i)
|
||||
{
|
||||
return i * i;
|
||||
}
|
||||
|
||||
module test2{Type};
|
||||
module test2 <Type>;
|
||||
|
||||
struct Blob
|
||||
{
|
||||
|
||||
@@ -183,14 +183,14 @@ fn void hello()
|
||||
printf("Mult %f\n", doubleMult(11.1));
|
||||
}
|
||||
|
||||
module foo{Type};
|
||||
module foo <Type>;
|
||||
|
||||
fn Type check(Type i)
|
||||
{
|
||||
return i * i;
|
||||
}
|
||||
|
||||
module test2{Type};
|
||||
module test2 <Type>;
|
||||
|
||||
struct Blob
|
||||
{
|
||||
|
||||
@@ -6,14 +6,14 @@ fn int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
module test2{Type};
|
||||
module test2 <Type>;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
Type f;
|
||||
}
|
||||
|
||||
module test2{Type, FOO};
|
||||
module test2 <Type, FOO>;
|
||||
|
||||
struct Foo1
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module add{Type};
|
||||
module add <Type>;
|
||||
fn Type add(Type a, Type b) @builtin =>
|
||||
a + b;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import std::io;
|
||||
|
||||
<* @require Type.kindof == SIGNED_INT *>
|
||||
struct Foo @generic(Type)
|
||||
struct Foo <Type>
|
||||
{
|
||||
Type a;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module foo{Type};
|
||||
module foo <Type>;
|
||||
|
||||
fn void abc()
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ struct Test
|
||||
BazTest t;
|
||||
}
|
||||
|
||||
module bar{Test};
|
||||
module bar <Test>;
|
||||
|
||||
struct Baz
|
||||
{
|
||||
|
||||
@@ -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{}) <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()
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ fn void main()
|
||||
Foo $f = 1;
|
||||
test1::foo{$f}();
|
||||
}
|
||||
module test1 {FOO};
|
||||
module test1 <FOO>;
|
||||
|
||||
fn void foo() {}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module abc {Type};
|
||||
module abc <Type>;
|
||||
|
||||
attrdef @Hello = @inline;
|
||||
faultdef ABC;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module g{T};
|
||||
module g <T>;
|
||||
|
||||
faultdef F0, F1;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-aarch64
|
||||
module gen{Type};
|
||||
module gen <Type>;
|
||||
|
||||
fn Type mult(Type x)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import std;
|
||||
struct Result @generic(WithType2)
|
||||
struct Result <WithType2>
|
||||
{
|
||||
fault error;
|
||||
}
|
||||
macro err(fault error) @generic(OfType, SOME_CONST) @builtin => (Result{OfType}){ .error = error };
|
||||
macro err(fault error) <OfType, SOME_CONST> @builtin => (Result{OfType}){ .error = error };
|
||||
|
||||
faultdef TESTIN;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import std;
|
||||
struct Result @generic(WithType2)
|
||||
struct Result <WithType2>
|
||||
{
|
||||
fault error;
|
||||
}
|
||||
macro err(fault error) @generic(OfType) @builtin => (Result{OfType}){ .error = error };
|
||||
macro err(fault error) <OfType> @builtin => (Result{OfType}){ .error = error };
|
||||
|
||||
faultdef TESTIN;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ fn void main()
|
||||
hello(test2::get_foo{int}());
|
||||
}
|
||||
|
||||
module test2 {Type};
|
||||
module test2 <Type>;
|
||||
|
||||
fn Foo get_foo() => {};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// #target: macos-aarch64
|
||||
module base;
|
||||
|
||||
module test{MyType};
|
||||
module test <MyType>;
|
||||
import base;
|
||||
interface Zzz
|
||||
{
|
||||
|
||||
@@ -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 <Type>;
|
||||
import std::io, abc_faults, std::collections::list;
|
||||
|
||||
alias TextTagList = List{TextTag};
|
||||
|
||||
@@ -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 <Type> @local;
|
||||
|
||||
struct PrivateFoo
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<* @require THE_CONST < 5 *>
|
||||
module the_generic @generic(THE_CONST, Type);
|
||||
module the_generic <THE_CONST, Type>;
|
||||
struct Abc
|
||||
{ int a; }
|
||||
|
||||
module the_generic @generic(THE_CONST, Type);
|
||||
module the_generic <THE_CONST, Type>;
|
||||
|
||||
struct TheStruct
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module custom_type @generic(Type, VALUE);
|
||||
module custom_type <Type, VALUE>;
|
||||
|
||||
struct Example
|
||||
{
|
||||
|
||||
@@ -21,10 +21,9 @@ fn void c()
|
||||
|
||||
fn int main()
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module bar{Type};
|
||||
module bar <Type>;
|
||||
fn void test()
|
||||
{}
|
||||
@@ -1,4 +1,4 @@
|
||||
module values {Type};
|
||||
module values <Type>;
|
||||
|
||||
struct Values
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-x64
|
||||
module hello{Type, FOO};
|
||||
module hello <Type, FOO>;
|
||||
|
||||
fn Type x(Type t)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-x64
|
||||
module test_generic{Type, Func};
|
||||
module test_generic<Type, Func>;
|
||||
|
||||
fn void sort(Type list, isz, isz, Func cmp)
|
||||
{}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-x64
|
||||
module playground::bug{Ty};
|
||||
module playground::bug <Ty>;
|
||||
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 <Ty>;
|
||||
import std::io;
|
||||
|
||||
macro void print_it(...)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module gui::widget {Type};
|
||||
module gui::widget <Type>;
|
||||
import gui::widget_types;
|
||||
import std::collections::list;
|
||||
import std::io;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// #target: macos-aarch64
|
||||
module the_generic @generic(THE_CONST, Type);
|
||||
module the_generic <THE_CONST, Type>;
|
||||
struct Abc
|
||||
{ int a; }
|
||||
|
||||
module the_generic @generic(THE_CONST, Type);
|
||||
module the_generic <THE_CONST, Type>;
|
||||
|
||||
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) <Type> => t * 3;
|
||||
fn Type bob(Type2 t) <Type2> => feok * 3;
|
||||
|
||||
fn int main()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-x64
|
||||
module test{Type};
|
||||
module test <Type>;
|
||||
|
||||
alias Callback = fn Type();
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@ fn void main() {
|
||||
<*
|
||||
Hello
|
||||
*>
|
||||
module generic{Param};
|
||||
module generic <Param>;
|
||||
struct Generic { int a; }
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-x64
|
||||
module test{FOO};
|
||||
module test <FOO>;
|
||||
|
||||
const Z = FOO;
|
||||
|
||||
|
||||
@@ -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 <Type>;
|
||||
fn void test() {}
|
||||
@@ -13,6 +13,6 @@ module abc::foo;
|
||||
|
||||
struct Def { int x; }
|
||||
|
||||
module abc::cde{Type};
|
||||
module abc::cde <Type>;
|
||||
|
||||
struct Abc { Type a, b; }
|
||||
@@ -1,4 +1,4 @@
|
||||
module foo{Type, SIZE};
|
||||
module foo <Type, SIZE>;
|
||||
|
||||
struct Foo
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #target: macos-x64
|
||||
module broken{Type};
|
||||
module broken <Type>;
|
||||
typedef Bar = Type;
|
||||
alias Bar2 = Type;
|
||||
struct Baz
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import std;
|
||||
struct Result @generic(WithType2)
|
||||
struct Result <WithType2>
|
||||
{
|
||||
fault error;
|
||||
}
|
||||
macro Result{WithType} err(fault error) @generic(WithType) => { .error = error };
|
||||
macro Result{WithType} err(fault error) <WithType> => { .error = error };
|
||||
|
||||
faultdef TESTIN;
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ fn int main() => 0;
|
||||
|
||||
Aa {int} a;
|
||||
|
||||
module test1 {Type};
|
||||
module test1 <Type>;
|
||||
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 <Type>;
|
||||
struct Bb {Type b;}
|
||||
@@ -1,4 +1,4 @@
|
||||
module foo { Type };
|
||||
module foo <Type>;
|
||||
|
||||
import std::collections::list;
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ fn int main(String[] args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
module some_module { F };
|
||||
module some_module <F>;
|
||||
import std;
|
||||
const A_CONST = 12 + 2 * math::log2(F / 25); // #error: This expression cannot be evaluated at compile time
|
||||
@@ -15,7 +15,7 @@ fn int main() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
module test::generic{Type};
|
||||
module test::generic <Type>;
|
||||
|
||||
struct Test
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ fn int main()
|
||||
<*
|
||||
@require $defined(String.hash)
|
||||
*>
|
||||
module test::generic{Some_Type};
|
||||
module test::generic <Some_Type>;
|
||||
|
||||
enum Test
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@ fn void main()
|
||||
test{int}();
|
||||
}
|
||||
|
||||
module test{Type};
|
||||
module test <Type>;
|
||||
fn void test()
|
||||
{
|
||||
Type a;
|
||||
|
||||
@@ -10,7 +10,7 @@ faultdef TRIE_FULL;
|
||||
@require $defined((Token){}.token)
|
||||
@require $defined((Comment){}.start) && $defined((Comment){}.end)
|
||||
*>
|
||||
module lexer {Token, Comment};
|
||||
module lexer <Token, Comment>;
|
||||
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 <Value, Index>;
|
||||
import std::collections::list;
|
||||
import trie::bitmap;
|
||||
import lexer::faults;
|
||||
|
||||
Reference in New Issue
Block a user