From 81a2474f75eee09e07297a1868c66c55ac83464c Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 17 Sep 2022 17:07:24 +0200 Subject: [PATCH] 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 --- lib/std/bits.c3 | 217 +++++++++++++----- lib/std/math.c3 | 64 ++---- src/compiler/ast.c | 2 + src/compiler/codegen_general.c | 1 + src/compiler/compiler_internal.h | 17 +- src/compiler/copying.c | 2 + src/compiler/enums.h | 6 +- src/compiler/headers.c | 1 + src/compiler/llvm_codegen_c_abi_x64.c | 5 + src/compiler/llvm_codegen_c_abi_x86.c | 4 + src/compiler/llvm_codegen_debug_info.c | 2 + src/compiler/llvm_codegen_expr.c | 1 + src/compiler/llvm_codegen_type.c | 5 + src/compiler/parse_global.c | 16 +- src/compiler/parse_stmt.c | 3 +- src/compiler/sema_casts.c | 20 +- src/compiler/sema_decls.c | 188 ++++++--------- src/compiler/sema_expr.c | 96 +++++--- src/compiler/sema_internal.h | 1 - src/compiler/sema_name_resolution.c | 26 ++- src/compiler/sema_types.c | 26 ++- src/compiler/symtab.c | 4 - src/compiler/types.c | 157 +++++++++++-- src/version.h | 2 +- test/test_suite/define/forbidden_defines.c3 | 2 +- .../initializer_lists/zero_inferred_array.c3 | 2 +- test/test_suite/literals/bin_literal.c3t | 2 +- test/test_suite/operators/invalid_op_vec.c3 | 7 - test/test_suite2/define/forbidden_defines.c3 | 2 +- .../initializer_lists/zero_inferred_array.c3 | 2 +- test/test_suite2/literals/bin_literal.c3t | 2 +- test/test_suite2/operators/invalid_op_vec.c3 | 7 - 32 files changed, 573 insertions(+), 319 deletions(-) delete mode 100644 test/test_suite/operators/invalid_op_vec.c3 delete mode 100644 test/test_suite2/operators/invalid_op_vec.c3 diff --git a/lib/std/bits.c3 b/lib/std/bits.c3 index f4de89f87..862e8435f 100644 --- a/lib/std/bits.c3 +++ b/lib/std/bits.c3 @@ -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); diff --git a/lib/std/math.c3 b/lib/std/math.c3 index a6ab90af4..c3931318b 100644 --- a/lib/std/math.c3 +++ b/lib/std/math.c3 @@ -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 diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 84a04f1f2..3553c62be 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -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); diff --git a/src/compiler/codegen_general.c b/src/compiler/codegen_general.c index 710548df1..bb2b054ea 100644 --- a/src/compiler/codegen_general.c +++ b/src/compiler/codegen_general.c @@ -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. diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 566fc2117..3e6adae1a 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -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); diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 4a557a68b..454cfa656 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -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; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index f28e1298f..4c7e89838 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -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 diff --git a/src/compiler/headers.c b/src/compiler/headers.c index 8db22a829..5af8581a3 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -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: diff --git a/src/compiler/llvm_codegen_c_abi_x64.c b/src/compiler/llvm_codegen_c_abi_x64.c index 19d43a5c7..9221c3068 100644 --- a/src/compiler/llvm_codegen_c_abi_x64.c +++ b/src/compiler/llvm_codegen_c_abi_x64.c @@ -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); diff --git a/src/compiler/llvm_codegen_c_abi_x86.c b/src/compiler/llvm_codegen_c_abi_x86.c index 82778a5fb..25cfad13b 100644 --- a/src/compiler/llvm_codegen_c_abi_x86.c +++ b/src/compiler/llvm_codegen_c_abi_x86.c @@ -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 } diff --git a/src/compiler/llvm_codegen_debug_info.c b/src/compiler/llvm_codegen_debug_info.c index 74fe70398..d0a44f621 100644 --- a/src/compiler/llvm_codegen_debug_info.c +++ b/src/compiler/llvm_codegen_debug_info.c @@ -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 } diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index f00c6537e..a8bd71583 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -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: diff --git a/src/compiler/llvm_codegen_type.c b/src/compiler/llvm_codegen_type.c index b1a6b410e..8a4ba7cac 100644 --- a/src/compiler/llvm_codegen_type.c +++ b/src/compiler/llvm_codegen_type.c @@ -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 } \ No newline at end of file diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 036c2c068..91ec79ebb 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -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; - ASSIGN_EXPR_OR_RET(vector->array.len, parse_expr(c), poisoned_type_info); - CONSUME_OR_RET(TOKEN_RVEC, poisoned_type_info); + 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; } diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index f4ac5680a..c66f25206 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -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); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 65a0a47aa..e803ebeaf 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -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); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 522f7c725..28cf40cc2 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -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,11 +2354,17 @@ 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); - decl->type = type_get_array(decl->type->array.base, right_side_type->array.len); + 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; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 23b21b25d..2a9db91e0 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -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,24 +4248,33 @@ 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)) { - SEMA_ERROR(expr, "There is no member or method '%s' on '%s'", kw, type_to_error_string(type)); - return false; + 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. @@ -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 diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 6f44235db..37f45fc70 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -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); diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index ceb8bd43b..60e9bf674 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -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; } diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 0a7311562..9b2933f2a 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -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; - - return type_get_array(type->array.base, element_size); + 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; + } } diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 8a3332e62..02e9f004e 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -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"); diff --git a/src/compiler/types.c b/src/compiler/types.c index 3fe2c6ad3..23ef0e444 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -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: diff --git a/src/version.h b/src/version.h index 681550cfa..e3324351a 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.46" \ No newline at end of file +#define COMPILER_VERSION "0.3.47" \ No newline at end of file diff --git a/test/test_suite/define/forbidden_defines.c3 b/test/test_suite/define/forbidden_defines.c3 index 78fc1ce82..86a7ca17d 100644 --- a/test/test_suite/define/forbidden_defines.c3 +++ b/test/test_suite/define/forbidden_defines.c3 @@ -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. diff --git a/test/test_suite/initializer_lists/zero_inferred_array.c3 b/test/test_suite/initializer_lists/zero_inferred_array.c3 index 91d1492b7..4c41938f1 100644 --- a/test/test_suite/initializer_lists/zero_inferred_array.c3 +++ b/test/test_suite/initializer_lists/zero_inferred_array.c3 @@ -1,4 +1,4 @@ fn void test() { - int[*] a = {}; // #error: Zero length arrays are not permitted. + int[*] a = {}; // #error: Zero length } \ No newline at end of file diff --git a/test/test_suite/literals/bin_literal.c3t b/test/test_suite/literals/bin_literal.c3t index a700c08b6..a76d59103 100644 --- a/test/test_suite/literals/bin_literal.c3t +++ b/test/test_suite/literals/bin_literal.c3t @@ -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 diff --git a/test/test_suite/operators/invalid_op_vec.c3 b/test/test_suite/operators/invalid_op_vec.c3 deleted file mode 100644 index f4c98cb5e..000000000 --- a/test/test_suite/operators/invalid_op_vec.c3 +++ /dev/null @@ -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 - diff --git a/test/test_suite2/define/forbidden_defines.c3 b/test/test_suite2/define/forbidden_defines.c3 index 78fc1ce82..86a7ca17d 100644 --- a/test/test_suite2/define/forbidden_defines.c3 +++ b/test/test_suite2/define/forbidden_defines.c3 @@ -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. diff --git a/test/test_suite2/initializer_lists/zero_inferred_array.c3 b/test/test_suite2/initializer_lists/zero_inferred_array.c3 index 91d1492b7..4c41938f1 100644 --- a/test/test_suite2/initializer_lists/zero_inferred_array.c3 +++ b/test/test_suite2/initializer_lists/zero_inferred_array.c3 @@ -1,4 +1,4 @@ fn void test() { - int[*] a = {}; // #error: Zero length arrays are not permitted. + int[*] a = {}; // #error: Zero length } \ No newline at end of file diff --git a/test/test_suite2/literals/bin_literal.c3t b/test/test_suite2/literals/bin_literal.c3t index 8505efd07..731c923be 100644 --- a/test/test_suite2/literals/bin_literal.c3t +++ b/test/test_suite2/literals/bin_literal.c3t @@ -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 diff --git a/test/test_suite2/operators/invalid_op_vec.c3 b/test/test_suite2/operators/invalid_op_vec.c3 deleted file mode 100644 index f4c98cb5e..000000000 --- a/test/test_suite2/operators/invalid_op_vec.c3 +++ /dev/null @@ -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 -