Add methods to basic types. Remove "intvec" and "floatvec" overloads. Update bits and math to use the new functionality. Introduces [<*>] and [<>] types. Bump version to 0.3.47

This commit is contained in:
Christoffer Lerno
2022-09-17 17:07:24 +02:00
committed by Christoffer Lerno
parent 28f2247602
commit 81a2474f75
32 changed files with 573 additions and 319 deletions

View File

@@ -1,78 +1,173 @@
module std::bits;
/**
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
**/
macro popcount(i) @operator(intvec)
{
return $$popcount(i);
}
/**
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
**/
macro reverse(i)
{
return $$bitreverse(i);
}
macro reverse(i) = $$bitreverse(i);
/**
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
**/
macro bswap(i) @builtin
{
return $$bswap(i);
}
macro bswap(i) @builtin = $$bswap(i);
/**
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
**/
macro ctz(i) @operator(intvec) @builtin
{
return $$ctz(i);
}
/**
* @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector`
**/
macro clz(i) @operator(intvec) @builtin
{
return $$clz(i);
}
macro uint[<*>].popcount(uint[<*>] i) = $$popcount(i);
macro uint[<*>].ctz(uint[<*>] i) = $$ctz(i);
macro uint[<*>].clz(uint[<*>] i) = $$clz(i);
macro uint[<*>] uint[<*>].fshl(uint[<*>] hi, uint[<*>] lo, uint[<*>] shift) => $$fshl(hi, lo, shift);
macro uint[<*>] uint[<*>].fshr(uint[<*>] hi, uint[<*>] lo, uint[<*>] shift) => $$fshr(hi, lo, shift);
macro uint[<*>] uint[<*>].rotl(uint[<*>] i, uint[<*>] shift) => $$fshl(i, i, shift);
macro uint[<*>] uint[<*>].rotr(uint[<*>] i, uint[<*>] shift) => $$fshr(i, i, shift);
/**
* @require types::is_intlike($typeof(hi)) && types::is_intlike($typeof(lo)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector`
* @require types::@has_same(hi, lo, shift) `Hi, low and shift arguments must have the same type`
**/
macro fshl(hi, lo, shift) @builtin
{
return $$fshl(hi, lo, ($typeof(hi))shift);
}
macro int[<*>].popcount(int[<*>] i) = $$popcount(i);
macro int[<*>].ctz(int[<*>] i) = $$ctz(i);
macro int[<*>].clz(int[<*>] i) = $$clz(i);
macro int[<*>] int[<*>].fshl(int[<*>] hi, int[<*>] lo, int[<*>] shift) => $$fshl(hi, lo, shift);
macro int[<*>] int[<*>].fshr(int[<*>] hi, int[<*>] lo, int[<*>] shift) => $$fshr(hi, lo, shift);
macro int[<*>] int[<*>].rotl(int[<*>] i, int[<*>] shift) => $$fshl(i, i, shift);
macro int[<*>] int[<*>].rotr(int[<*>] i, int[<*>] shift) => $$fshr(i, i, shift);
/**
* @require types::is_intlike($typeof(hi)) && types::is_intlike($typeof(lo)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector`
* @require types::@has_same(hi, lo, shift) `Hi, low and shift arguments must have the same type`
**/
macro fshr(hi, lo, shift) @builtin
{
return $$fshr(hi, lo, ($typeof(hi))shift);
}
macro ushort[<*>].popcount(ushort[<*>] i) = $$popcount(i);
macro ushort[<*>].ctz(ushort[<*>] i) = $$ctz(i);
macro ushort[<*>].clz(ushort[<*>] i) = $$clz(i);
macro ushort[<*>] ushort[<*>].fshl(ushort[<*>] hi, ushort[<*>] lo, ushort[<*>] shift) => $$fshl(hi, lo, shift);
macro ushort[<*>] ushort[<*>].fshr(ushort[<*>] hi, ushort[<*>] lo, ushort[<*>] shift) => $$fshr(hi, lo, shift);
macro ushort[<*>] ushort[<*>].rotl(ushort[<*>] i, ushort[<*>] shift) => $$fshl(i, i, shift);
macro ushort[<*>] ushort[<*>].rotr(ushort[<*>] i, ushort[<*>] shift) => $$fshr(i, i, shift);
/**
* @require types::is_intlike($typeof(i)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector`
* @require types::@has_same(i, shift) `The shift value must have the same type as shifted types`
**/
macro rotl(i, shift) @operator(intvec) @builtin
{
return $$fshl(i, i, shift);
}
macro short[<*>].popcount(short[<*>] i) = $$popcount(i);
macro short[<*>].ctz(short[<*>] i) = $$ctz(i);
macro short[<*>].clz(short[<*>] i) = $$clz(i);
macro short[<*>] short[<*>].fshl(short[<*>] hi, short[<*>] lo, short[<*>] shift) => $$fshl(hi, lo, shift);
macro short[<*>] short[<*>].fshr(short[<*>] hi, short[<*>] lo, short[<*>] shift) => $$fshr(hi, lo, shift);
macro short[<*>] short[<*>].rotl(short[<*>] i, short[<*>] shift) => $$fshl(i, i, shift);
macro short[<*>] short[<*>].rotr(short[<*>] i, short[<*>] shift) => $$fshr(i, i, shift);
/**
* @require types::is_intlike($typeof(i)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector`
* @require types::@has_same(i, shift) `The shift value must have the same type as shifted types`
**/
macro rotr(i, shift) @operator(intvec) @builtin
{
return $$fshr(i, i, shift);
}
macro char[<*>].popcount(char[<*>] i) = $$popcount(i);
macro char[<*>].ctz(char[<*>] i) = $$ctz(i);
macro char[<*>].clz(char[<*>] i) = $$clz(i);
macro char[<*>] char[<*>].fshl(char[<*>] hi, char[<*>] lo, char[<*>] shift) => $$fshl(hi, lo, shift);
macro char[<*>] char[<*>].fshr(char[<*>] hi, char[<*>] lo, char[<*>] shift) => $$fshr(hi, lo, shift);
macro char[<*>] char[<*>].rotl(char[<*>] i, char[<*>] shift) => $$fshl(i, i, shift);
macro char[<*>] char[<*>].rotr(char[<*>] i, char[<*>] shift) => $$fshr(i, i, shift);
macro ichar[<*>].popcount(ichar[<*>] i) = $$popcount(i);
macro ichar[<*>].ctz(ichar[<*>] i) = $$ctz(i);
macro ichar[<*>].clz(ichar[<*>] i) = $$clz(i);
macro ichar[<*>] ichar[<*>].fshl(ichar[<*>] hi, ichar[<*>] lo, ichar[<*>] shift) => $$fshl(hi, lo, shift);
macro ichar[<*>] ichar[<*>].fshr(ichar[<*>] hi, ichar[<*>] lo, ichar[<*>] shift) => $$fshr(hi, lo, shift);
macro ichar[<*>] ichar[<*>].rotl(ichar[<*>] i, ichar[<*>] shift) => $$fshl(i, i, shift);
macro ichar[<*>] ichar[<*>].rotr(ichar[<*>] i, ichar[<*>] shift) => $$fshr(i, i, shift);
macro ulong[<*>].popcount(ulong[<*>] i) = $$popcount(i);
macro ulong[<*>].ctz(ulong[<*>] i) = $$ctz(i);
macro ulong[<*>].clz(ulong[<*>] i) = $$clz(i);
macro ulong[<*>] ulong[<*>].fshl(ulong[<*>] hi, ulong[<*>] lo, ulong[<*>] shift) => $$fshl(hi, lo, shift);
macro ulong[<*>] ulong[<*>].fshr(ulong[<*>] hi, ulong[<*>] lo, ulong[<*>] shift) => $$fshr(hi, lo, shift);
macro ulong[<*>] ulong[<*>].rotl(ulong[<*>] i, ulong[<*>] shift) => $$fshl(i, i, shift);
macro ulong[<*>] ulong[<*>].rotr(ulong[<*>] i, ulong[<*>] shift) => $$fshr(i, i, shift);
macro long[<*>].popcount(long[<*>] i) = $$popcount(i);
macro long[<*>].ctz(long[<*>] i) = $$ctz(i);
macro long[<*>].clz(long[<*>] i) = $$clz(i);
macro long[<*>] long[<*>].fshl(long[<*>] hi, long[<*>] lo, long[<*>] shift) => $$fshl(hi, lo, shift);
macro long[<*>] long[<*>].fshr(long[<*>] hi, long[<*>] lo, long[<*>] shift) => $$fshr(hi, lo, shift);
macro long[<*>] long[<*>].rotl(long[<*>] i, long[<*>] shift) => $$fshl(i, i, shift);
macro long[<*>] long[<*>].rotr(long[<*>] i, long[<*>] shift) => $$fshr(i, i, shift);
macro uint128[<*>].popcount(uint128[<*>] i) = $$popcount(i);
macro uint128[<*>].ctz(uint128[<*>] i) = $$ctz(i);
macro uint128[<*>].clz(uint128[<*>] i) = $$clz(i);
macro uint128[<*>] uint128[<*>].fshl(uint128[<*>] hi, uint128[<*>] lo, uint128[<*>] shift) => $$fshl(hi, lo, shift);
macro uint128[<*>] uint128[<*>].fshr(uint128[<*>] hi, uint128[<*>] lo, uint128[<*>] shift) => $$fshr(hi, lo, shift);
macro uint128[<*>] uint128[<*>].rotl(uint128[<*>] i, uint128[<*>] shift) => $$fshl(i, i, shift);
macro uint128[<*>] uint128[<*>].rotr(uint128[<*>] i, uint128[<*>] shift) => $$fshr(i, i, shift);
macro int128[<*>].popcount(int128[<*>] i) = $$popcount(i);
macro int128[<*>].ctz(int128[<*>] i) = $$ctz(i);
macro int128[<*>].clz(int128[<*>] i) = $$clz(i);
macro int128[<*>] int128[<*>].fshl(int128[<*>] hi, int128[<*>] lo, int128[<*>] shift) => $$fshl(hi, lo, shift);
macro int128[<*>] int128[<*>].fshr(int128[<*>] hi, int128[<*>] lo, int128[<*>] shift) => $$fshr(hi, lo, shift);
macro int128[<*>] int128[<*>].rotl(int128[<*>] i, int128[<*>] shift) => $$fshl(i, i, shift);
macro int128[<*>] int128[<*>].rotr(int128[<*>] i, int128[<*>] shift) => $$fshr(i, i, shift);
macro uint.popcount(uint i) = $$popcount(i);
macro uint.ctz(uint i) = $$ctz(i);
macro uint.clz(uint i) = $$clz(i);
macro uint uint.fshl(uint hi, uint lo, uint shift) => $$fshl(hi, lo, shift);
macro uint uint.fshr(uint hi, uint lo, uint shift) => $$fshr(hi, lo, shift);
macro uint uint.rotl(uint i, uint shift) => $$fshl(i, i, shift);
macro uint uint.rotr(uint i, uint shift) => $$fshr(i, i, shift);
macro int.popcount(int i) = $$popcount(i);
macro int.ctz(int i) = $$ctz(i);
macro int.clz(int i) = $$clz(i);
macro int int.fshl(int hi, int lo, int shift) => $$fshl(hi, lo, shift);
macro int int.fshr(int hi, int lo, int shift) => $$fshr(hi, lo, shift);
macro int int.rotl(int i, int shift) => $$fshl(i, i, shift);
macro int int.rotr(int i, int shift) => $$fshr(i, i, shift);
macro ushort.popcount(ushort i) = $$popcount(i);
macro ushort.ctz(ushort i) = $$ctz(i);
macro ushort.clz(ushort i) = $$clz(i);
macro ushort ushort.fshl(ushort hi, ushort lo, ushort shift) => $$fshl(hi, lo, shift);
macro ushort ushort.fshr(ushort hi, ushort lo, ushort shift) => $$fshr(hi, lo, shift);
macro ushort ushort.rotl(ushort i, ushort shift) => $$fshl(i, i, shift);
macro ushort ushort.rotr(ushort i, ushort shift) => $$fshr(i, i, shift);
macro short.popcount(short i) = $$popcount(i);
macro short.ctz(short i) = $$ctz(i);
macro short.clz(short i) = $$clz(i);
macro short short.fshl(short hi, short lo, short shift) => $$fshl(hi, lo, shift);
macro short short.fshr(short hi, short lo, short shift) => $$fshr(hi, lo, shift);
macro short short.rotl(short i, short shift) => $$fshl(i, i, shift);
macro short short.rotr(short i, short shift) => $$fshr(i, i, shift);
macro char.popcount(char i) = $$popcount(i);
macro char.ctz(char i) = $$ctz(i);
macro char.clz(char i) = $$clz(i);
macro char char.fshl(char hi, char lo, char shift) => $$fshl(hi, lo, shift);
macro char char.fshr(char hi, char lo, char shift) => $$fshr(hi, lo, shift);
macro char char.rotl(char i, char shift) => $$fshl(i, i, shift);
macro char char.rotr(char i, char shift) => $$fshr(i, i, shift);
macro ichar.popcount(ichar i) = $$popcount(i);
macro ichar.ctz(ichar i) = $$ctz(i);
macro ichar.clz(ichar i) = $$clz(i);
macro ichar ichar.fshl(ichar hi, ichar lo, ichar shift) => $$fshl(hi, lo, shift);
macro ichar ichar.fshr(ichar hi, ichar lo, ichar shift) => $$fshr(hi, lo, shift);
macro ichar ichar.rotl(ichar i, ichar shift) => $$fshl(i, i, shift);
macro ichar ichar.rotr(ichar i, ichar shift) => $$fshr(i, i, shift);
macro ulong.popcount(ulong i) = $$popcount(i);
macro ulong.ctz(ulong i) = $$ctz(i);
macro ulong.clz(ulong i) = $$clz(i);
macro ulong ulong.fshl(ulong hi, ulong lo, ulong shift) => $$fshl(hi, lo, shift);
macro ulong ulong.fshr(ulong hi, ulong lo, ulong shift) => $$fshr(hi, lo, shift);
macro ulong ulong.rotl(ulong i, ulong shift) => $$fshl(i, i, shift);
macro ulong ulong.rotr(ulong i, ulong shift) => $$fshr(i, i, shift);
macro long.popcount(long i) = $$popcount(i);
macro long.ctz(long i) = $$ctz(i);
macro long.clz(long i) = $$clz(i);
macro long long.fshl(long hi, long lo, long shift) => $$fshl(hi, lo, shift);
macro long long.fshr(long hi, long lo, long shift) => $$fshr(hi, lo, shift);
macro long long.rotl(long i, long shift) => $$fshl(i, i, shift);
macro long long.rotr(long i, long shift) => $$fshr(i, i, shift);
macro uint128.popcount(uint128 i) = $$popcount(i);
macro uint128.ctz(uint128 i) = $$ctz(i);
macro uint128.clz(uint128 i) = $$clz(i);
macro uint128 uint128.fshl(uint128 hi, uint128 lo, uint128 shift) => $$fshl(hi, lo, shift);
macro uint128 uint128.fshr(uint128 hi, uint128 lo, uint128 shift) => $$fshr(hi, lo, shift);
macro uint128 uint128.rotl(uint128 i, uint128 shift) => $$fshl(i, i, shift);
macro uint128 uint128.rotr(uint128 i, uint128 shift) => $$fshr(i, i, shift);
macro int128.popcount(int128 i) = $$popcount(i);
macro int128.ctz(int128 i) = $$ctz(i);
macro int128.clz(int128 i) = $$clz(i);
macro int128 int128.fshl(int128 hi, int128 lo, int128 shift) => $$fshl(hi, lo, shift);
macro int128 int128.fshr(int128 hi, int128 lo, int128 shift) => $$fshr(hi, lo, shift);
macro int128 int128.rotl(int128 i, int128 shift) => $$fshl(i, i, shift);
macro int128 int128.rotr(int128 i, int128 shift) => $$fshr(i, i, shift);

View File

@@ -81,10 +81,6 @@ macro min(x, y) @builtin
return x < y ? x : y;
}
macro abs(x) @builtin
{
return $$abs(x);
}
fn double log10(double x) @inline
{
@@ -96,63 +92,43 @@ fn double log2(double x) @inline
return $$log2(x);
}
/**
* @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector`
**/
macro log(f)
{
return $$log(f);
}
macro abs(x) @builtin = $$abs(x);
/**
* @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector`
**/
macro cos(f)
{
return $$cos(f);
}
macro log(f) = $$log(f);
/**
* @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector`
**/
macro sin(f)
{
return $$sin(f);
}
macro cos(f) = $$cos(f);
/**
* @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector`
**/
macro exp(f)
{
return $$exp(f);
}
/**
* @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector`
* @require types::@has_same(f, exp) `Parameters must have the same type`
**/
macro pow(f, exp) @operator(floatvec)
{
return $$pow(f, exp);
}
macro sin(f) = $$sin(f);
/**
* @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector`
**/
macro trunc(x) @operator(floatvec)
{
return $$trunc(x);
}
macro exp(f) = $$exp(f);
/**
* @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector`
**/
macro ceil(x) @operator(floatvec)
{
return $$ceil(x);
}
macro float float.ceil(float x) = $$ceil(x);
macro float float.trunc(float x) = $$trunc(x);
macro float float.pow(float f, float exp) = $$pow(f, exp);
macro float[<*>] float[<*>].ceil(float[<*>] x) = $$ceil(x);
macro float[<*>] float[<*>].trunc(float[<*>] x) = $$trunc(x);
macro float[<*>] float[<*>].pow(float[<*>] f, float[<*>] exp) = $$pow(f, exp);
macro double double.ceil(double x) = $$ceil(x);
macro double double.trunc(double x) = $$trunc(x);
macro double double.pow(double f, double exp) = $$pow(f, exp);
macro double[<*>] double[<*>].ceil(double[<*>] x) = $$ceil(x);
macro double[<*>] double[<*>].trunc(double[<*>] x) = $$trunc(x);
macro double[<*>] double[<*>].pow(double[<*>] f, double[<*>] exp) = $$pow(f, exp);
/**
* @checked x & 1

View File

@@ -618,6 +618,7 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
{
case TYPE_POISONED:
case TYPE_VOID:
case TYPE_INFERRED_VECTOR:
UNREACHABLE
case ALL_INTS:
expr_rewrite_const_int(expr, type, 0, true);
@@ -653,6 +654,7 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type)
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_UNTYPED_LIST:
case TYPE_SCALED_VECTOR:
case TYPE_VECTOR:
{
ConstInitializer *init = CALLOCS(ConstInitializer);

View File

@@ -234,6 +234,7 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
}
goto TYPECHECK;
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
return false;
case TYPE_ARRAY:
// Empty arrays? Not homogenous.

View File

@@ -534,8 +534,6 @@ typedef struct
};
struct
{
bool attr_intvec : 1;
bool attr_floatvec : 1;
DeclId body_param;
CompilationUnit *unit;
};
@@ -1424,8 +1422,6 @@ typedef struct Module_
Ast **files; // Asts
Decl** method_extensions;
Decl** intvec_extensions;
Decl** floatvec_extensions;
HTable symbols;
struct CompilationUnit_ **units;
Module *parent_module;
@@ -1791,8 +1787,6 @@ extern const char *kw_out;
extern const char *kw_inout;
extern const char *kw_deprecated;
extern const char *kw_distinct;
extern const char *kw_intvec;
extern const char *kw_floatvec;
extern const char *kw_inline;
extern const char *kw_inf;
extern const char *kw_kind;
@@ -2149,6 +2143,7 @@ Decl *sema_resolve_symbol_in_current_dynamic_scope(SemaContext *context, const c
Decl *sema_decl_stack_resolve_symbol(const char *symbol);
Decl *sema_find_decl_in_modules(Module **module_list, Path *path, const char *interned_name);
Decl *unit_resolve_parameterized_symbol(CompilationUnit *unit, NameResolve *name_resolve);
Decl *sema_resolve_type_method(CompilationUnit *unit, Type *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref);
Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref);
Decl *sema_find_extension_method_in_module(Module *module, Type *type, const char *method_name);
@@ -2234,7 +2229,9 @@ Type *type_get_ptr(Type *ptr_type);
Type *type_get_ptr_recurse(Type *ptr_type);
Type *type_get_subarray(Type *arr_type);
Type *type_get_inferred_array(Type *arr_type);
Type *type_get_inferred_vector(Type *arr_type);
Type *type_get_flexible_array(Type *arr_type);
Type *type_get_scaled_vector(Type *arr_type);
Type *type_get_failable(Type *failable_type);
Type *type_get_vector(Type *vector_type, unsigned len);
Type *type_get_vector_bool(Type *original_type);
@@ -2254,6 +2251,7 @@ bool type_flat_is_floatlike(Type *type);
bool type_flat_is_intlike(Type *type);
bool type_flat_is_numlike(Type *type);
bool type_may_have_sub_elements(Type *type);
bool type_may_have_method(Type *type);
const char *type_to_error_string(Type *type);
const char *type_quoted_error_string(Type *type);
INLINE bool type_may_negate(Type *type);
@@ -2347,6 +2345,13 @@ INLINE Type *type_add_optional(Type *type, bool make_optional)
return type_get_failable(type);
}
INLINE bool type_len_is_inferred(Type *type)
{
if (!type) return true;
DECL_TYPE_KIND_REAL(kind, type);
return kind == TYPE_INFERRED_VECTOR || kind == TYPE_INFERRED_ARRAY;
}
INLINE bool type_is_optional(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type);

View File

@@ -596,6 +596,8 @@ TypeInfo *copy_type_info(CopyStruct *c, TypeInfo *source)
return copy;
case TYPE_INFO_INFERRED_ARRAY:
case TYPE_INFO_SUBARRAY:
case TYPE_INFO_INFERRED_VECTOR:
case TYPE_INFO_SCALED_VECTOR:
assert(source->resolve_status == RESOLVE_NOT_DONE);
copy->array.base = copy_type_info(c, source->array.base);
return copy;

View File

@@ -364,6 +364,8 @@ typedef enum
TYPE_INFO_ARRAY,
TYPE_INFO_VECTOR,
TYPE_INFO_INFERRED_ARRAY,
TYPE_INFO_INFERRED_VECTOR,
TYPE_INFO_SCALED_VECTOR,
TYPE_INFO_SUBARRAY,
TYPE_INFO_POINTER,
} TypeInfoKind;
@@ -644,11 +646,13 @@ typedef enum
TYPE_FAILABLE,
TYPE_FAILABLE_ANY,
TYPE_TYPEINFO,
TYPE_INFERRED_VECTOR,
TYPE_SCALED_VECTOR,
TYPE_VECTOR,
TYPE_LAST = TYPE_ANY
} TypeKind;
#define CT_TYPES TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: case TYPE_UNTYPED_LIST: case TYPE_POISONED
#define CT_TYPES TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: case TYPE_INFERRED_VECTOR: case TYPE_UNTYPED_LIST: case TYPE_POISONED
#define ALL_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128: \
case TYPE_U8: case TYPE_U16: case TYPE_U32: case TYPE_U64: case TYPE_U128
#define ALL_SIGNED_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128

View File

@@ -97,6 +97,7 @@ static void header_print_type(FILE *file, Type *type)
case TYPE_FAULTTYPE:
OUTPUT("enum %s__", type->decl->extname);
return;
case TYPE_SCALED_VECTOR:
case TYPE_FLEXIBLE_ARRAY:
TODO
case TYPE_FUNC:

View File

@@ -436,6 +436,9 @@ static void x64_classify(Type *type, ByteSize offset_base, X64Class *lo_class, X
case TYPE_VECTOR:
x64_classify_vector(type, offset_base, current, lo_class, hi_class, named);
break;
case TYPE_SCALED_VECTOR:
*current = CLASS_MEMORY;
break;
}
}
@@ -593,6 +596,8 @@ AbiType x64_get_int_type_at_offset(Type *type, unsigned offset, Type *source_typ
case TYPE_UNION:
case TYPE_VECTOR:
break;
case TYPE_SCALED_VECTOR:
return (AbiType) { .type = type };
}
ByteSize size = type_size(source_type);
assert(size != source_offset);

View File

@@ -125,6 +125,8 @@ static bool x86_should_return_type_in_reg(Type *type)
case TYPE_FAILABLE_ANY:
case TYPE_FLEXIBLE_ARRAY:
UNREACHABLE
case TYPE_SCALED_VECTOR:
return false;
case ALL_INTS:
case ALL_FLOATS:
case TYPE_BOOL:
@@ -604,6 +606,8 @@ static ABIArgInfo *x86_classify_argument(CallABI call, Regs *regs, Type *type)
case TYPE_ANY:
case TYPE_ARRAY:
return x86_classify_aggregate(call, regs, type);
case TYPE_SCALED_VECTOR:
TODO
}
UNREACHABLE
}

View File

@@ -593,6 +593,8 @@ static inline LLVMMetadataRef llvm_get_debug_type_internal(GenContext *c, Type *
return type->backend_debug_type = llvm_debug_errunion_type(c, type);
case TYPE_ANY:
return type->backend_debug_type = llvm_debug_any_type(c, type);
case TYPE_SCALED_VECTOR:
TODO
}
UNREACHABLE
}

View File

@@ -3985,6 +3985,7 @@ static void llvm_expand_type_to_args(GenContext *context, Type *param_type, LLVM
case CT_TYPES:
case TYPE_FAILABLE_ANY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
UNREACHABLE
break;
case TYPE_BOOL:

View File

@@ -383,6 +383,8 @@ LLVMTypeRef llvm_get_type(GenContext *c, Type *any_type)
LLVMStructSetBody(virtual_type, types, 2, false);
return any_type->backend_type = virtual_type;
}
case TYPE_SCALED_VECTOR:
TODO
case TYPE_VECTOR:
return any_type->backend_type = LLVMVectorType(llvm_get_type(c, any_type->array.base), any_type->array.len);
}
@@ -708,6 +710,7 @@ LLVMValueRef llvm_get_typeid(GenContext *c, Type *type)
case TYPE_TYPEDEF:
return llvm_get_typeid(c, type->canonical);
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_UNTYPED_LIST:
case TYPE_FAILABLE_ANY:
case TYPE_TYPEINFO:
@@ -737,6 +740,8 @@ LLVMValueRef llvm_get_typeid(GenContext *c, Type *type)
return llvm_get_introspection_for_builtin_type(c, type, INTROSPECT_TYPE_TYPEID, 0);
case TYPE_POISONED:
UNREACHABLE
case TYPE_SCALED_VECTOR:
TODO
}
UNREACHABLE
}

View File

@@ -630,8 +630,20 @@ static inline TypeInfo *parse_vector_type_index(ParseContext *c, TypeInfo *type)
advance_and_verify(c, TOKEN_LVEC);
TypeInfo *vector = type_info_new(TYPE_INFO_VECTOR, type->span);
vector->array.base = type;
if (try_consume(c, TOKEN_RVEC))
{
vector->kind = TYPE_INFO_SCALED_VECTOR;
}
else if (try_consume(c, TOKEN_STAR))
{
CONSUME_OR_RET(TOKEN_RVEC, poisoned_type_info);
vector->kind = TYPE_INFO_INFERRED_VECTOR;
}
else
{
ASSIGN_EXPR_OR_RET(vector->array.len, parse_expr(c), poisoned_type_info);
CONSUME_OR_RET(TOKEN_RVEC, poisoned_type_info);
}
RANGE_EXTEND_PREV(vector);
return vector;
}

View File

@@ -1365,7 +1365,8 @@ Ast* parse_short_stmt(ParseContext *c, TypeInfoId return_type)
Ast *ast = ast_new_curr(c, AST_COMPOUND_STMT);
AstId *next = &ast->compound_stmt.first_stmt;
if (!return_type || type_infoptr(return_type)->type->type_kind != TYPE_VOID)
TypeInfo *rtype = return_type ? type_infoptr(return_type) : NULL;
if (!rtype || (rtype->resolve_status != RESOLVE_DONE || rtype->type->type_kind != TYPE_VOID))
{
Ast *ret = ast_new_curr(c, AST_RETURN_STMT);
ast_append(&next, ret);

View File

@@ -397,6 +397,8 @@ CastKind cast_to_bool_kind(Type *type)
case TYPE_ANY:
case TYPE_FAILABLE_ANY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
case TYPE_INFERRED_VECTOR:
return CAST_ERROR;
}
UNREACHABLE
@@ -432,6 +434,11 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
if (from_type->type_kind == TYPE_ARRAY && type_flatten_distinct(from_type->array.base) == type_flatten_distinct(to_type->array.base)) return true;
return false;
}
if (to_type->type_kind == TYPE_INFERRED_VECTOR)
{
if (from_type->type_kind == TYPE_VECTOR && type_flatten_distinct(from_type->array.base) == type_flatten_distinct(to_type->array.base)) return true;
return false;
}
TypeKind to_kind = to_type->type_kind;
switch (from_type->type_kind)
@@ -447,6 +454,9 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
case TYPE_VOID:
case TYPE_TYPEINFO:
case TYPE_FUNC:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_SCALED_VECTOR:
return false;
case TYPE_TYPEID:
// May convert to anything pointer sized or larger, no enums
@@ -490,8 +500,6 @@ bool cast_may_explicit(Type *from_type, Type *to_type, bool ignore_failability,
case TYPE_FAULTTYPE:
// Allow MyError.A -> error, to an integer or to bool
return to_type->type_kind == TYPE_ANYERR || type_is_integer(to_type) || to_type == type_bool;
case TYPE_FLEXIBLE_ARRAY:
return false;
case TYPE_ARRAY:
if (to_kind == TYPE_VECTOR)
{
@@ -631,6 +639,11 @@ bool cast_may_implicit(Type *from_type, Type *to_type, bool is_simple_expr, bool
if (from->type_kind == TYPE_ARRAY && type_flatten_distinct(from->array.base) == type_flatten_distinct(to_type->array.base)) return true;
return false;
}
if (to_type->type_kind == TYPE_INFERRED_VECTOR)
{
if (from->type_kind == TYPE_VECTOR && type_flatten_distinct(from->array.base) == type_flatten_distinct(to_type->array.base)) return true;
return false;
}
// 5. Handle sub arrays
if (to->type_kind == TYPE_SUBARRAY)
@@ -1330,6 +1343,7 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type)
if (type_is_integer(to)) return insert_cast(expr, CAST_ERINT, to_type);
break;
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
return false;
case TYPE_ARRAY:
if (to->type_kind == TYPE_VECTOR) return arr_to_vec(expr, to_type);
@@ -1401,7 +1415,7 @@ bool cast(Expr *expr, Type *to_type)
from_is_failable = true;
}
from_type = type_flatten_distinct(from_type);
if (to_type->type_kind == TYPE_INFERRED_ARRAY)
if (type_len_is_inferred(to_type))
{
to_type = from_type;
to = type_flatten(from_type);

View File

@@ -154,6 +154,11 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl **
SEMA_ERROR(member, "Flexible array members not allowed in unions.");
return false;
}
if (member->type->type_kind == TYPE_SCALED_VECTOR)
{
SEMA_ERROR(member, "Scaled vector members not allowed in unions / structs.");
return false;
}
AlignSize member_alignment = type_abi_alignment(member->type);
ByteSize member_size = type_size(member->type);
assert(member_size <= MAX_TYPE_SIZE);
@@ -258,6 +263,11 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl *
}
decl->has_variable_array = true;
}
if (member_type->type_kind == TYPE_SCALED_VECTOR)
{
SEMA_ERROR(member, "Scaled vectors may not be used in structs and unions.");
return false;
}
if (member_type->type_kind == TYPE_INFERRED_ARRAY)
{
if (i != member_count - 1)
@@ -587,7 +597,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
Decl **params = sig->params;
unsigned param_count = vec_size(params);
unsigned vararg_index = sig->vararg_index;
bool is_fn = !sig->is_macro;
bool is_macro = sig->is_macro;
bool is_macro_at_name = sig->is_at_macro;
// Check return type
@@ -596,13 +606,13 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
if (sig->rtype)
{
TypeInfo *rtype_info = type_infoptr(sig->rtype);
if (!sema_resolve_type_info(context, type_infoptr(sig->rtype))) return false;
if (!sema_resolve_type_info_maybe_inferred(context, type_infoptr(sig->rtype), is_macro)) return false;
rtype = rtype_info->type;
if (sig->attrs.nodiscard)
{
if (rtype == type_void)
{
SEMA_ERROR(rtype_info, "@nodiscard cannot be used on %s returning 'void'.", is_fn ? "functions" : "macros");
SEMA_ERROR(rtype_info, "@nodiscard cannot be used on %s returning 'void'.", is_macro ? "macros" : "functions");
return false;
}
}
@@ -610,7 +620,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
{
if (!type_is_optional(rtype))
{
SEMA_ERROR(rtype_info, "@maydiscard can only be used on %s returning optional values.", is_fn ? "functions" : "macros");
SEMA_ERROR(rtype_info, "@maydiscard can only be used on %s returning optional values.", is_macro ? "macros" : "functions");
return false;
}
}
@@ -640,7 +650,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
}
if (vararg_index < i)
{
if (is_fn && variadic_type == VARIADIC_RAW)
if (!is_macro && variadic_type == VARIADIC_RAW)
{
SEMA_ERROR(param, "C-style varargs cannot be followed by regular parameters.");
return decl_poison(param);
@@ -664,7 +674,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
{
case VARDECL_PARAM_EXPR:
case VARDECL_PARAM_REF:
if (is_fn)
if (!is_macro)
{
SEMA_ERROR(param, "Only regular parameters are allowed for functions.");
return decl_poison(param);
@@ -676,7 +686,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
}
FALLTHROUGH;
case VARDECL_PARAM_CT:
if (is_fn)
if (!is_macro)
{
SEMA_ERROR(param, "Only regular parameters are allowed for functions.");
return decl_poison(param);
@@ -685,10 +695,10 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
case VARDECL_PARAM:
if (param->var.type_info)
{
if (!sema_resolve_type_info(context, param->var.type_info)) return decl_poison(param);
if (!sema_resolve_type_info_maybe_inferred(context, param->var.type_info, is_macro)) return decl_poison(param);
param->type = param->var.type_info->type;
}
else if (is_fn)
else if (!is_macro)
{
SEMA_ERROR(param, "Only typed parameters are allowed for functions.");
return false;
@@ -696,7 +706,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
if (!sema_analyse_attributes_for_var(context, param)) return false;
break;
case VARDECL_PARAM_CT_TYPE:
if (is_fn)
if (!is_macro)
{
SEMA_ERROR(param, "Only regular parameters are allowed for functions.");
return decl_poison(param);
@@ -736,7 +746,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig)
{
if (vararg_index != i)
{
SEMA_ERROR(param, "A %s may not have more than one vararg.", is_fn ? "function" : "macro");
SEMA_ERROR(param, "A %s may not have more than one vararg.", is_macro ? "macro" : "function");
return decl_poison(param);
}
}
@@ -866,6 +876,7 @@ static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl)
case TYPE_ARRAY:
case TYPE_SUBARRAY:
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
break;
}
// Do we need anything else?
@@ -1172,68 +1183,6 @@ Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload oper
return NULL;
}
INLINE Decl *sema_find_vec_operator_in_module(Module *module, const char *kw, bool is_int, bool allow_private, Decl *prev, Decl **private, SourceSpan span)
{
Decl **funcs = is_int ? module->intvec_extensions : module->floatvec_extensions;
Decl *found = NULL;
FOREACH_BEGIN(Decl *func, funcs)
if (func->name == kw)
{
if (func->visibility != VISIBLE_PUBLIC && !allow_private)
{
if (!prev) *private = func;
continue;
}
found = func;
// Assume only one per module.
break;
}
FOREACH_END();
if (!found) return prev;
*private = NULL;
if (prev)
{
sema_error_at(span, "Ambiguous name '%s', try to import fewer modules.", kw);
return poisoned_decl;
}
return found;
}
INLINE Decl *sema_find_vec_operator_in_module_recursively(Module *module, const char *kw, bool is_int, bool allow_private, Decl *prev, Decl **private_ref, SourceSpan span)
{
Decl *decl = sema_find_vec_operator_in_module(module, kw, is_int, allow_private, prev, private_ref, span);
if (decl) return decl;
FOREACH_BEGIN(Module *sub_module, module->sub_modules)
decl = sema_find_vec_operator_in_module(sub_module, kw, is_int, false, decl, private_ref, span);
if (!decl) continue;
if (!decl_ok(decl)) return decl;
FOREACH_END();
return decl;
}
Decl *sema_find_vec_operator(SemaContext *context, const char *kw, Type *base_type, SourceSpan span)
{
bool is_int = type_is_integer(base_type);
Decl *private = NULL;
Decl *decl = sema_find_vec_operator_in_module(context->compilation_unit->module, kw, is_int, true, NULL, &private, span);
if (decl) return decl;
Decl **imports = context->unit->imports;
FOREACH_BEGIN(Decl *import, context->unit->imports)
Module *imported_module = import->import.module;
bool is_private = import->import.private;
decl = sema_find_vec_operator_in_module_recursively(imported_module, kw, is_int, is_private, decl, &private, span);
if (!decl) continue;
if (!decl_ok(decl)) return decl;
FOREACH_END();
if (!decl && private)
{
sema_error_at(span, "The vector operator '%s' could not be found except the private implementation in '%s'.", private->unit->module->name->module);
return poisoned_decl;
}
return decl;
}
static inline bool sema_analyse_operator_element_at(Decl *method)
{
@@ -1289,10 +1238,33 @@ static bool sema_check_operator_method_validity(Decl *method)
UNREACHABLE
}
static inline bool unit_add_base_extension_method(CompilationUnit *unit, Type *parent_type, Decl *method_like)
{
if (!method_like->has_extname)
{
scratch_buffer_clear();
if (method_like->visibility <= VISIBLE_MODULE)
{
scratch_buffer_append(parent_type->name);
scratch_buffer_append_char('$');
scratch_buffer_append(method_like->name);
}
else
{
scratch_buffer_append(parent_type->name);
scratch_buffer_append("_");
scratch_buffer_append(method_like->name);
}
method_like->extname = scratch_buffer_copy();
}
DEBUG_LOG("Method-like '%s.%s' analysed.", parent_type->name, method_like->name);
vec_add(unit->module->method_extensions, method_like);
return true;
}
static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type, Decl *method_like)
{
assert(parent_type->canonical == parent_type);
Decl *parent = parent_type->decl;
const char *name = method_like->name;
Decl *method = sema_find_extension_method_in_module(unit->module, parent_type, name);
if (method)
@@ -1301,6 +1273,8 @@ static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type
SEMA_NOTE(method, "The previous definition was here.");
return false;
}
if (!type_is_user_defined(parent_type)) return unit_add_base_extension_method(unit, parent_type, method_like);
Decl *parent = parent_type->decl;
Decl *ambiguous = NULL;
Decl *private = NULL;
method = sema_resolve_method(unit, parent, name, &ambiguous, &private);
@@ -1347,7 +1321,7 @@ static inline bool sema_analyse_method(SemaContext *context, Decl *decl)
TypeInfo *parent_type = type_infoptr(decl->func_decl.type_parent);
if (!sema_resolve_type_info(context, parent_type)) return false;
Type *type = parent_type->type->canonical;
if (!type_may_have_sub_elements(type))
if (!type_may_have_sub_elements(type) && !type_underlying_is_numeric(type) && !type_is_arraylike(type))
{
SEMA_ERROR(decl,
"Methods can not be associated with '%s'",
@@ -1538,34 +1512,6 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
}
decl->operator = OVERLOAD_LEN;
}
else if (kw == kw_floatvec)
{
if (decl->decl_kind != DECL_MACRO)
{
SEMA_ERROR(expr, "@operator(floatvec) can only be used with macros.");
return false;
}
if (decl->func_decl.type_parent)
{
SEMA_ERROR(expr, "@operator(floatvec) cannot be used with methods.");
return false;
}
decl->func_decl.attr_floatvec = true;
}
else if (kw == kw_intvec)
{
if (decl->decl_kind != DECL_MACRO)
{
SEMA_ERROR(expr, "@operator(intvec) can only be used with macros.");
return false;
}
if (decl->func_decl.type_parent)
{
SEMA_ERROR(expr, "@operator(intvec) cannot be used with methods.");
return false;
}
decl->func_decl.attr_intvec = true;
}
else
{
goto FAILED_OP_TYPE;
@@ -2094,7 +2040,6 @@ static inline bool sema_is_valid_method_param(SemaContext *context, Decl *param,
if (param_type == parent_type) return true;
// 2. A pointer is ok!
if (param_type->type_kind == TYPE_POINTER && param_type->pointer == parent_type) return true;
ERROR:
SEMA_ERROR(param, "The first parameter must be of type %s or %s.", type_quoted_error_string(parent_type),
type_quoted_error_string(type_get_ptr(parent_type)));
@@ -2104,9 +2049,9 @@ ERROR:
static bool sema_analyse_macro_method(SemaContext *context, Decl *decl)
{
TypeInfo *parent_type_info = type_infoptr(decl->func_decl.type_parent);
if (!sema_resolve_type_info(context, parent_type_info)) return false;
if (!sema_resolve_type_info_maybe_inferred(context, parent_type_info, true)) return false;
Type *parent_type = parent_type_info->type;
if (!type_may_have_sub_elements(parent_type))
if (!type_may_have_method(parent_type))
{
SEMA_ERROR(parent_type_info,
"Methods can not be associated with '%s'",
@@ -2186,17 +2131,6 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl)
{
if (!sema_analyse_macro_method(context, decl)) return decl_poison(decl);
}
else
{
if (decl->func_decl.attr_floatvec)
{
vec_add(context->unit->module->floatvec_extensions, decl);
}
if (decl->func_decl.attr_intvec)
{
vec_add(context->unit->module->intvec_extensions, decl);
}
}
decl->type = type_void;
return true;
}
@@ -2394,17 +2328,17 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
decl->extname = scratch_buffer_copy();
}
bool type_is_inferred = decl->type->type_kind == TYPE_INFERRED_ARRAY;
if (!decl->var.init_expr && type_is_inferred)
bool infer_len = type_len_is_inferred(decl->type);
if (!decl->var.init_expr && infer_len)
{
SEMA_ERROR(decl->var.type_info, "Size of the array cannot be inferred without an initializer.");
SEMA_ERROR(decl->var.type_info, "The length cannot be inferred without an initializer.");
return false;
}
if (decl->var.init_expr)
{
Expr *init = decl->var.init_expr;
if (!type_is_inferred)
if (!infer_len)
{
// Pre resolve to avoid problem with recursive definitions.
decl->resolve_status = RESOLVE_DONE;
@@ -2420,12 +2354,18 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local)
}
context->current_function = function;
if (type_is_inferred)
if (infer_len)
{
Type *right_side_type = init->type->canonical;
assert(right_side_type->type_kind == TYPE_ARRAY);
if (right_side_type->type_kind == TYPE_ARRAY)
{
decl->type = type_get_array(decl->type->array.base, right_side_type->array.len);
}
else
{
decl->type = type_get_vector(decl->type->array.base, right_side_type->array.len);
}
}
Expr *init_expr = decl->var.init_expr;

View File

@@ -1811,7 +1811,6 @@ static inline bool sema_expr_analyse_call_invocation(SemaContext *context, Expr
// 7. Loop through the parameters.
for (unsigned i = 0; i < num_args; i++)
{
Expr *arg = args[i];
// 10. If we exceed the function parameter count (remember we reduced this by one
@@ -1903,7 +1902,10 @@ static inline bool sema_expr_analyse_call_invocation(SemaContext *context, Expr
case VARDECL_ERASE:
UNREACHABLE
}
if (param && !type) param->type = type_no_optional(arg->type);
if (param && type_len_is_inferred(type))
{
param->type = type_no_optional(arg->type);
}
}
return true;
}
@@ -2282,6 +2284,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
if (rtype)
{
bool inferred_len = type_len_is_inferred(rtype);
VECEACH(macro_context.returns, i)
{
Ast *return_stmt = macro_context.returns[i];
@@ -2298,7 +2301,21 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
return SCOPE_POP_ERROR();
}
Type *type = ret_expr->type;
if (!cast_may_implicit(type, rtype, true, may_failable))
if (inferred_len)
{
Type *flattened = type_flatten(type);
if (flattened->type_kind == TYPE_ARRAY && rtype->type_kind == TYPE_INFERRED_ARRAY)
{
rtype = type_get_array(rtype->array.base, flattened->array.len);
inferred_len = false;
}
else if (flattened->type_kind == TYPE_VECTOR && rtype->type_kind == TYPE_INFERRED_VECTOR)
{
rtype = type_get_vector(rtype->array.base, flattened->array.len);
inferred_len = false;
}
}
if (!cast_may_implicit(type, rtype, true, may_failable) || inferred_len)
{
SEMA_ERROR(ret_expr, "Expected %s, not %s.", type_quoted_error_string(rtype),
type_quoted_error_string(type));
@@ -2973,12 +2990,6 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr)
switch (decl->decl_kind)
{
case DECL_MACRO:
if (decl->func_decl.attr_intvec || decl->func_decl.attr_floatvec)
{
struct_var = func_expr->access_expr.parent;
break;
}
FALLTHROUGH;
case DECL_FUNC:
struct_var = func_expr->access_expr.parent;
if (decl->func_decl.signature.params[0]->type->type_kind == TYPE_POINTER)
@@ -3779,6 +3790,7 @@ static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type
case TYPE_FAULTTYPE:
len = vec_size(type->decl->enums.values);
break;
case TYPE_SCALED_VECTOR:
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SUBARRAY:
@@ -3810,6 +3822,8 @@ static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Typ
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SUBARRAY:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_VECTOR:
inner = type->array.base;
break;
@@ -4234,25 +4248,34 @@ CHECK_DEEPER:
}
}
if (type_flat_is_vector(type))
{
Type *vec = type_flatten(type);
assert(vec->type_kind == TYPE_VECTOR);
Type *base = vec->array.base;
Decl *func = sema_find_vec_operator(context, kw, base, expr->span);
if (!decl_ok(func)) return false;
if (func)
{
expr->access_expr.ref = func;
return true;
}
}
// 9. At this point we may only have distinct, struct, union, error, enum
if (!type_may_have_sub_elements(type))
{
Decl *ambiguous = NULL;
Decl *private = NULL;
Decl *method = sema_resolve_type_method(context->unit, type, kw, &ambiguous, &private);
if (private)
{
SEMA_ERROR(expr, "The method '%s' has private visibility.", kw);
return false;
}
if (ambiguous)
{
SEMA_ERROR(expr, "'%s' is an ambiguous name and so cannot be resolved, it may refer to method defined in '%s' or one in '%s'",
kw, method->unit->module->name->module, ambiguous->unit->module->name->module);
return false;
}
if (!method)
{
SEMA_ERROR(expr, "There is no member or method '%s' on '%s'", kw, type_to_error_string(type));
return false;
}
expr->access_expr.parent = current_parent;
expr->type = method->type ? type_add_optional(method->type, failable) : NULL;
expr->access_expr.ref = method;
if (method->decl_kind == DECL_FUNC) unit_register_external_symbol(context->compilation_unit, method);
return true;
}
// 10. Dump all members and methods into the scope.
Decl *decl = type->decl;
@@ -4413,6 +4436,7 @@ static Type *sema_find_type_of_element(SemaContext *context, Type *type, Designa
switch (type_flattened->type_kind)
{
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
len = MAX_ARRAYINDEX;
base = type_flattened->array.base;
break;
@@ -5331,9 +5355,9 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ext
// 3. Zero size init will initialize to empty.
if (init_expression_count == 0)
{
if (external_type->type_kind == TYPE_INFERRED_ARRAY)
if (type_len_is_inferred(external_type))
{
SEMA_ERROR(expr, "Zero length arrays are not permitted.");
SEMA_ERROR(expr, "Zero length arrays / vectors are not permitted.");
return false;
}
external_type = sema_type_lower_by_size(external_type, 0);
@@ -5362,6 +5386,7 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ext
if (assigned->type_kind == TYPE_UNTYPED_LIST ||
assigned->type_kind == TYPE_ARRAY ||
assigned->type_kind == TYPE_INFERRED_ARRAY ||
assigned->type_kind == TYPE_INFERRED_VECTOR ||
assigned->type_kind == TYPE_SUBARRAY ||
assigned->type_kind == TYPE_VECTOR)
{
@@ -5384,6 +5409,7 @@ static inline bool sema_expr_analyse_initializer_list(SemaContext *context, Type
case TYPE_ARRAY:
case TYPE_BITSTRUCT:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_VECTOR:
return sema_expr_analyse_initializer(context, to, assigned, expr);
case TYPE_SUBARRAY:
@@ -5404,6 +5430,9 @@ static inline bool sema_expr_analyse_initializer_list(SemaContext *context, Type
if (!sema_analyse_expr(context, expr)) return false;
return cast(expr, to);
}
case TYPE_SCALED_VECTOR:
SEMA_ERROR(expr, "Scaled vectors cannot be initialized using an initializer list, since the length is not known at compile time.");
return false;
case TYPE_POINTER:
SEMA_ERROR(expr, "Pointers cannot be initialized using an initializer list, instead you need to take the address of an array.");
return false;
@@ -7867,6 +7896,21 @@ RETRY:
if (!type_ok(type)) return type;
return type_get_inferred_array(type);
}
case TYPE_INFO_INFERRED_VECTOR:
{
// If it's a vector, make sure we can resolve the length
Type *type = sema_expr_check_type_exists(context, type_info->array.base);
if (!type) return NULL;
if (!type_ok(type)) return type;
return type_get_inferred_vector(type);
}
case TYPE_INFO_SCALED_VECTOR:
{
Type *type = sema_expr_check_type_exists(context, type_info->array.base);
if (!type) return NULL;
if (!type_ok(type)) return type;
return type_get_scaled_vector(type);
}
case TYPE_INFO_POINTER:
{
// If it's an array, make sure we can resolve the length

View File

@@ -73,7 +73,6 @@ void sema_analysis_pass_ct_assert(Module *module);
void sema_analysis_pass_functions(Module *module);
void sema_analyze_stage(Module *module, AnalysisStage stage);
Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload operator_overload);
Decl *sema_find_vec_operator(SemaContext *context, const char *kw, Type *base_type, SourceSpan span);
bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *method_decl, Expr *parent, Expr **arguments);
bool sema_analyse_expr_lvalue(SemaContext *context, Expr *expr);
bool sema_analyse_expr_lvalue_fold_const(SemaContext *context, Expr *expr);

View File

@@ -616,10 +616,15 @@ Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_
if (method_name == func->name) return func;
}
Type *actual_type = type->type;
return sema_resolve_type_method(unit, type->type, method_name, ambiguous_ref, private_ref);
}
Decl *sema_resolve_type_method(CompilationUnit *unit, Type *type, const char *method_name, Decl **ambiguous_ref, Decl **private_ref)
{
assert(type == type->canonical);
Decl *private = NULL;
Decl *ambiguous = NULL;
Decl *found = sema_resolve_method_in_module(unit->module, actual_type, method_name, &private, &ambiguous, METHOD_SEARCH_CURRENT);
Decl *found = sema_resolve_method_in_module(unit->module, type, method_name, &private, &ambiguous, METHOD_SEARCH_CURRENT);
if (ambiguous)
{
*ambiguous_ref = ambiguous;
@@ -633,7 +638,7 @@ Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_
Decl *import = unit->imports[i];
if (import->import.module->is_generic) continue;
Decl *new_found = sema_resolve_method_in_module(import->import.module, actual_type, method_name,
Decl *new_found = sema_resolve_method_in_module(import->import.module, type, method_name,
&private, &ambiguous,
import->import.private
? METHOD_SEARCH_PRIVATE_IMPORTED
@@ -652,6 +657,21 @@ Decl *sema_resolve_method(CompilationUnit *unit, Decl *type, const char *method_
}
}
if (private) *private_ref = private;
if (!found)
{
if (type->type_kind == TYPE_ARRAY)
{
Type *inferred_array = type_get_inferred_array(type->array.base);
found = sema_resolve_type_method(unit, inferred_array, method_name, ambiguous_ref, private_ref);
if (found) *private_ref = NULL;
}
else if (type->type_kind == TYPE_VECTOR)
{
Type *inferred_vector = type_get_inferred_vector(type->array.base);
found = sema_resolve_type_method(unit, inferred_vector, method_name, ambiguous_ref, private_ref);
if (found) *private_ref = NULL;
}
}
return found;
}

View File

@@ -95,6 +95,12 @@ static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type,
case TYPE_INFO_INFERRED_ARRAY:
type->type = type_get_inferred_array(type->array.base->type);
break;
case TYPE_INFO_INFERRED_VECTOR:
type->type = type_get_inferred_vector(type->array.base->type);
break;
case TYPE_INFO_SCALED_VECTOR:
type->type = type_get_scaled_vector(type->array.base->type);
break;
case TYPE_INFO_VECTOR:
{
ArraySize width;
@@ -113,7 +119,6 @@ static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type,
UNREACHABLE
}
assert(!type->array.len || type->array.len->expr_kind == EXPR_CONST);
if (type->array.base)
type->resolve_status = RESOLVE_DONE;
return true;
}
@@ -222,6 +227,8 @@ bool sema_resolve_type(SemaContext *context, Type *type)
case TYPE_SUBARRAY:
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_SCALED_VECTOR:
return sema_resolve_type(context, type->array.base);
case TYPE_FAILABLE:
return sema_resolve_type(context, type->failable);
@@ -314,12 +321,15 @@ RETRY:
goto APPEND_QUALIFIERS;
}
case TYPE_INFO_INFERRED_ARRAY:
case TYPE_INFO_INFERRED_VECTOR:
if (!allow_inferred_type)
{
SEMA_ERROR(type_info, "Inferred array types can only be used in declarations with initializers.");
SEMA_ERROR(type_info, "Inferred %s types can only be used in declarations with initializers and as macro parameters.",
type_info->kind == TYPE_INFO_INFERRED_VECTOR ? "vector" : "array");
return type_info_poison(type_info);
}
FALLTHROUGH;
case TYPE_INFO_SCALED_VECTOR:
case TYPE_INFO_SUBARRAY:
case TYPE_INFO_ARRAY:
case TYPE_INFO_VECTOR:
@@ -363,7 +373,13 @@ APPEND_QUALIFIERS:
Type *sema_type_lower_by_size(Type *type, ArraySize element_size)
{
if (type->type_kind != TYPE_INFERRED_ARRAY) return type;
switch (type->type_kind)
{
case TYPE_INFERRED_ARRAY:
return type_get_array(type->array.base, element_size);
case TYPE_INFERRED_VECTOR:
return type_get_vector(type->array.base, element_size);
default:
return type;
}
}

View File

@@ -60,14 +60,12 @@ const char *kw_elementat;
const char *kw_elementref;
const char *kw_elementset;
const char *kw_elements;
const char *kw_floatvec;
const char *kw_in;
const char *kw_incr;
const char *kw_inf;
const char *kw_inline;
const char *kw_inner;
const char *kw_inout;
const char *kw_intvec;
const char *kw_kind;
const char *kw_len;
const char *kw_mainstub;
@@ -150,14 +148,12 @@ void symtab_init(uint32_t capacity)
kw_elementref = KW_DEF("elementref");
kw_elementset = KW_DEF("elementset");
kw_elements = KW_DEF("elements");
kw_floatvec = KW_DEF("floatvec");
kw_in = KW_DEF("in");
kw_incr = KW_DEF("incr");
kw_inf = KW_DEF("inf");
kw_inline = KW_DEF("inline");
kw_inner = KW_DEF("inner");
kw_inout = KW_DEF("inout");
kw_intvec = KW_DEF("intvec");
kw_kind = KW_DEF("kind");
kw_len = KW_DEF("len");
kw_mainstub = KW_DEF("_$mainstub");

View File

@@ -53,8 +53,10 @@ static AlignSize max_alignment_vector;
#define INFERRED_ARRAY_OFFSET 1
#define FLEXIBLE_ARRAY_OFFSET 2
#define SUB_ARRAY_OFFSET 3
#define FAILABLE_OFFSET 4
#define ARRAY_OFFSET 5
#define SCALED_VECTOR_OFFSET 4
#define INFERRED_VECTOR_OFFSET 5
#define FAILABLE_OFFSET 6
#define ARRAY_OFFSET 7
Type *type_cint;
Type *type_cuint;
@@ -141,22 +143,13 @@ static void type_append_name_to_scratch(Type *type)
case TYPE_FLEXIBLE_ARRAY:
type_append_name_to_scratch(type->array.base);
scratch_buffer_append("[*]");
case TYPE_SCALED_VECTOR:
type_append_name_to_scratch(type->array.base);
scratch_buffer_append("[<>]");
case TYPE_VOID:
case TYPE_BOOL:
case TYPE_I8:
case TYPE_I16:
case TYPE_I32:
case TYPE_I64:
case TYPE_I128:
case TYPE_U8:
case TYPE_U16:
case TYPE_U32:
case TYPE_U64:
case TYPE_U128:
case TYPE_F16:
case TYPE_F32:
case TYPE_F64:
case TYPE_F128:
case ALL_INTS:
case ALL_FLOATS:
case TYPE_TYPEID:
case TYPE_ANYERR:
case TYPE_ANY:
@@ -165,6 +158,7 @@ static void type_append_name_to_scratch(Type *type)
break;
case TYPE_UNTYPED_LIST:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_TYPEINFO:
UNREACHABLE
break;
@@ -229,6 +223,10 @@ const char *type_to_error_string(Type *type)
scratch_buffer_clear();
type_append_func_to_scratch(type->function.prototype);
return str_printf("fn %s", scratch_buffer_to_string());
case TYPE_INFERRED_VECTOR:
return str_printf("%s[<*>]", type_to_error_string(type->array.base));
case TYPE_SCALED_VECTOR:
return str_printf("%s[<>]", type_to_error_string(type->array.base));
case TYPE_VECTOR:
return str_printf("%s[<%llu>]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
case TYPE_TYPEINFO:
@@ -281,6 +279,7 @@ RETRY:
}
case CT_TYPES:
UNREACHABLE;
case TYPE_SCALED_VECTOR:
case TYPE_FLEXIBLE_ARRAY:
return 0;
case TYPE_FAILABLE:
@@ -392,8 +391,10 @@ bool type_is_abi_aggregate(Type *type)
return true;
case TYPE_TYPEINFO:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_UNTYPED_LIST:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
UNREACHABLE
}
UNREACHABLE
@@ -478,6 +479,7 @@ void type_mangle_introspect_name_to_buffer(Type *type)
case TYPE_POISONED:
case TYPE_TYPEINFO:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_UNTYPED_LIST:
case TYPE_FAILABLE_ANY:
UNREACHABLE
@@ -512,6 +514,10 @@ void type_mangle_introspect_name_to_buffer(Type *type)
scratch_buffer_append_char('$');
type_mangle_introspect_name_to_buffer(type->array.base);
return;
case TYPE_SCALED_VECTOR:
scratch_buffer_append("vn$");
type_mangle_introspect_name_to_buffer(type->array.base);
return;
case TYPE_ARRAY:
scratch_buffer_append_char('a');
scratch_buffer_append_unsigned_int(type->array.len);
@@ -575,9 +581,12 @@ AlignSize type_abi_alignment(Type *type)
case TYPE_BITSTRUCT:
type = type->decl->bitstruct.base_type->type;
goto RETRY;
case TYPE_INFERRED_VECTOR:
case TYPE_VECTOR:
{
ByteSize width = type_size(type->array.base) * (uint32_t)type->array.len;
ArraySize len = type->array.len;
if (!len) len = 1;
ByteSize width = type_size(type->array.base) * len;
AlignSize alignment = (AlignSize)(int32_t)width;
if (alignment & (alignment - 1))
{
@@ -622,6 +631,8 @@ AlignSize type_abi_alignment(Type *type)
goto RETRY;
case TYPE_SUBARRAY:
return alignment_subarray;
case TYPE_SCALED_VECTOR:
TODO
}
UNREACHABLE
}
@@ -737,6 +748,32 @@ static Type *type_generate_inferred_array(Type *arr_type, bool canonical)
return arr;
}
static Type *type_generate_inferred_vector(Type *arr_type, bool canonical)
{
if (canonical) arr_type = arr_type->canonical;
if (!arr_type->type_cache)
{
create_type_cache(arr_type);
}
Type *arr = arr_type->type_cache[INFERRED_VECTOR_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_INFERRED_VECTOR, str_printf("%s[<*>]", arr_type->name));
arr->array.base = arr_type;
arr_type->type_cache[INFERRED_VECTOR_OFFSET] = arr;
if (arr_type == arr_type->canonical)
{
arr->canonical = arr;
}
else
{
arr->canonical = type_generate_inferred_vector(arr_type->canonical, true);
}
}
return arr;
}
static Type *type_generate_flexible_array(Type *arr_type, bool canonical)
{
if (canonical) arr_type = arr_type->canonical;
@@ -764,6 +801,33 @@ static Type *type_generate_flexible_array(Type *arr_type, bool canonical)
return arr;
}
static Type *type_generate_scaled_vector(Type *arr_type, bool canonical)
{
if (canonical) arr_type = arr_type->canonical;
if (!arr_type->type_cache)
{
create_type_cache(arr_type);
}
Type *arr = arr_type->type_cache[SCALED_VECTOR_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_SCALED_VECTOR, str_printf("%s[<>]", arr_type->name));
arr->array.base = arr_type;
arr->array.len = 0;
arr_type->type_cache[SCALED_VECTOR_OFFSET] = arr;
if (arr_type == arr_type->canonical)
{
arr->canonical = arr;
}
else
{
arr->canonical = type_generate_scaled_vector(arr_type->canonical, true);
}
}
return arr;
}
Type *type_get_ptr_recurse(Type *ptr_type)
{
@@ -798,11 +862,21 @@ Type *type_get_inferred_array(Type *arr_type)
return type_generate_inferred_array(arr_type, false);
}
Type *type_get_inferred_vector(Type *arr_type)
{
return type_generate_inferred_vector(arr_type, false);
}
Type *type_get_flexible_array(Type *arr_type)
{
return type_generate_flexible_array(arr_type, false);
}
Type *type_get_scaled_vector(Type *arr_type)
{
return type_generate_scaled_vector(arr_type, false);
}
static inline bool array_structurally_equivalent_to_struct(Type *array, Type *type)
{
assert(array->type_kind == TYPE_ARRAY);
@@ -920,6 +994,8 @@ Type *type_get_indexed_type(Type *type)
case TYPE_ARRAY:
case TYPE_SUBARRAY:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_VECTOR:
return type->array.base;
@@ -1343,6 +1419,7 @@ bool type_is_scalar(Type *type)
case TYPE_FAILABLE_ANY:
case TYPE_ANY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
return false;
case TYPE_BOOL:
case ALL_INTS:
@@ -1455,6 +1532,46 @@ Type *type_from_token(TokenType type)
}
}
bool type_may_have_method(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type)
switch (kind)
{
case TYPE_DISTINCT:
case TYPE_UNION:
case TYPE_STRUCT:
case TYPE_ENUM:
case TYPE_FAULTTYPE:
case TYPE_BITSTRUCT:
case ALL_FLOATS:
case ALL_INTS:
case TYPE_ANY:
case TYPE_ANYERR:
case TYPE_TYPEID:
case TYPE_ARRAY:
case TYPE_SUBARRAY:
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_VECTOR:
case TYPE_BOOL:
case TYPE_SCALED_VECTOR:
return true;
case TYPE_TYPEDEF:
UNREACHABLE
case TYPE_POISONED:
case TYPE_VOID:
case TYPE_POINTER:
case TYPE_FUNC:
case TYPE_UNTYPED_LIST:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
case TYPE_TYPEINFO:
return false;
}
UNREACHABLE
}
bool type_may_have_sub_elements(Type *type)
{
DECL_TYPE_KIND_REAL(kind, type)
@@ -1604,6 +1721,7 @@ Type *type_find_max_type(Type *type, Type *other)
switch (type->type_kind)
{
case TYPE_INFERRED_ARRAY:
case TYPE_INFERRED_VECTOR:
case TYPE_POISONED:
case TYPE_FAILABLE:
case TYPE_FAILABLE_ANY:
@@ -1614,6 +1732,7 @@ Type *type_find_max_type(Type *type, Type *other)
case TYPE_ANY:
case TYPE_BITSTRUCT:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_SCALED_VECTOR:
return NULL;
case ALL_INTS:
if (other->type_kind == TYPE_DISTINCT && type_underlying_is_numeric(other)) return other;
@@ -1790,6 +1909,8 @@ unsigned type_get_introspection_kind(TypeKind kind)
case TYPE_SUBARRAY:
return INTROSPECT_TYPE_SUBARRAY;
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_INFERRED_VECTOR:
return INTROSPECT_TYPE_VECTOR;
case TYPE_UNTYPED_LIST:
case TYPE_FAILABLE_ANY:
@@ -1835,6 +1956,8 @@ Module *type_base_module(Type *type)
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
case TYPE_VECTOR:
case TYPE_SCALED_VECTOR:
case TYPE_INFERRED_VECTOR:
type = type->array.base;
goto RETRY;
case TYPE_FAILABLE:

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.46"
#define COMPILER_VERSION "0.3.47"

View File

@@ -1,3 +1,3 @@
define Abc = int[*]; // #error: Inferred array types can only be used in declarations with initializers.
define Abc = int[*]; // #error: Inferred array types can only
define Bcd = anyerr; // #error: 'anyerr' may not be aliased.
define Efd = variant; // #error: 'variant' may not be aliased.

View File

@@ -1,4 +1,4 @@
fn void test()
{
int[*] a = {}; // #error: Zero length arrays are not permitted.
int[*] a = {}; // #error: Zero length
}

View File

@@ -10,7 +10,7 @@ fn void main()
int d = $$max(a, b);
io::printfln("%d %d", c, d);
char z = 0b1101_1101;
io::printfln("%b %b %b", z, rotr(z, (char)1), rotl(z, (char)1));
io::printfln("%b %b %b", z, z.rotr(1), z.rotl(1));
}
/* #expect: test.ll

View File

@@ -1,7 +0,0 @@
struct Foo { int x; }
fn void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) can only be used with macros.
fn void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) can only be used with macros.
macro void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) cannot be used with methods
macro void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) cannot be used with methods

View File

@@ -1,3 +1,3 @@
define Abc = int[*]; // #error: Inferred array types can only be used in declarations with initializers.
define Abc = int[*]; // #error: Inferred array types can only
define Bcd = anyerr; // #error: 'anyerr' may not be aliased.
define Efd = variant; // #error: 'variant' may not be aliased.

View File

@@ -1,4 +1,4 @@
fn void test()
{
int[*] a = {}; // #error: Zero length arrays are not permitted.
int[*] a = {}; // #error: Zero length
}

View File

@@ -10,7 +10,7 @@ fn void main()
int d = $$max(a, b);
io::printfln("%d %d", c, d);
char z = 0b1101_1101;
io::printfln("%b %b %b", z, rotr(z, (char)1), rotl(z, (char)1));
io::printfln("%b %b %b", z, z.rotr(1), z.rotl(1));
}
/* #expect: test.ll

View File

@@ -1,7 +0,0 @@
struct Foo { int x; }
fn void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) can only be used with macros.
fn void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) can only be used with macros.
macro void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) cannot be used with methods
macro void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) cannot be used with methods