mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
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:
committed by
Christoffer Lerno
parent
28f2247602
commit
81a2474f75
217
lib/std/bits.c3
217
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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.3.46"
|
||||
#define COMPILER_VERSION "0.3.47"
|
||||
@@ -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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fn void test()
|
||||
{
|
||||
int[*] a = {}; // #error: Zero length arrays are not permitted.
|
||||
int[*] a = {}; // #error: Zero length
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fn void test()
|
||||
{
|
||||
int[*] a = {}; // #error: Zero length arrays are not permitted.
|
||||
int[*] a = {}; // #error: Zero length
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user