mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Type capture in macros
This commit is contained in:
@@ -6,10 +6,10 @@ import std::collections::pair, std::io;
|
||||
|
||||
@param [in] array
|
||||
@param [in] element
|
||||
@require @typekind(array) == SLICE || @typekind(array) == ARRAY
|
||||
@require @typematch(array[0], element) : "array and element must have the same type"
|
||||
@require $Arr.kindof == SLICE || $Arr.kindof == ARRAY
|
||||
@require $Arr.inner == $Type : "array and element must have the same type"
|
||||
*>
|
||||
macro bool contains(array, element)
|
||||
macro bool contains($Arr array, $Type element)
|
||||
{
|
||||
foreach (&item : array)
|
||||
{
|
||||
|
||||
@@ -91,10 +91,10 @@ bitstruct UInt128LE : uint128 @littleendian
|
||||
@require @is_array_or_slice_of_char(bytes) : "argument must be an array, a pointer to an array or a slice of char"
|
||||
@require is_bitorder($Type) : "type must be a bitorder integer"
|
||||
*>
|
||||
macro read(bytes, $Type)
|
||||
macro read($Val bytes, $Type)
|
||||
{
|
||||
char[] s;
|
||||
$switch @typekind(bytes):
|
||||
$switch $Val.kindof:
|
||||
$case POINTER:
|
||||
s = (*bytes)[:$Type.sizeof];
|
||||
$default:
|
||||
|
||||
@@ -623,11 +623,11 @@ macro uint hash_array(array_ptr) @local
|
||||
}
|
||||
|
||||
<*
|
||||
@require @typekind(vec) == VECTOR
|
||||
@require $Vec.typeof == VECTOR
|
||||
*>
|
||||
macro uint hash_vec(vec) @local
|
||||
macro uint hash_vec($Vec vec) @local
|
||||
{
|
||||
var $len = $sizeof(vec.len * $typeof(vec).inner.sizeof);
|
||||
var $len = $sizeof(vec.len * $Vec.inner.sizeof);
|
||||
|
||||
$if $len > 16:
|
||||
return (uint)komi::hash(((char*)&&vec)[:$len]);
|
||||
|
||||
@@ -232,11 +232,10 @@ macro usz? read_varint(stream, x_ptr)
|
||||
}
|
||||
<*
|
||||
@require @is_outstream(stream)
|
||||
@require @typekind(x).is_int()
|
||||
@require $Type.kindof.is_int()
|
||||
*>
|
||||
macro usz? write_varint(stream, x)
|
||||
macro usz? write_varint(stream, $Type x)
|
||||
{
|
||||
var $Type = $typeof(x);
|
||||
const MAX = MAX_VARS[$Type.sizeof];
|
||||
char[MAX] buffer @noinit;
|
||||
usz i;
|
||||
|
||||
@@ -69,14 +69,14 @@ enum RoundingMode : int
|
||||
faultdef OVERFLOW, MATRIX_INVERSE_DOESNT_EXIST;
|
||||
|
||||
<*
|
||||
@require types::is_numerical($typeof(x)) : `The input must be a numerical value or numerical vector`
|
||||
@require types::is_numerical($Num) : `The input must be a numerical value or numerical vector`
|
||||
*>
|
||||
macro deg_to_rad(x) => x * PI / 180;
|
||||
macro deg_to_rad($Num x) => x * PI / 180;
|
||||
|
||||
<*
|
||||
@require types::is_numerical($typeof(x)) : `The input must be a numerical value or numerical vector`
|
||||
@require types::is_numerical($Num) : `The input must be a numerical value or numerical vector`
|
||||
*>
|
||||
macro abs(x) => $$abs(x);
|
||||
macro abs($Num x) => $$abs(x);
|
||||
|
||||
<*
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
@@ -103,13 +103,12 @@ macro is_approx_rel(x, y, eps)
|
||||
<*
|
||||
@require values::@is_int(x) : `The input must be an integer`
|
||||
*>
|
||||
macro sign(x)
|
||||
macro $Num sign($Num x)
|
||||
{
|
||||
var $Type = $typeof(x);
|
||||
$if $Type.kindof == UNSIGNED_INT:
|
||||
return ($Type)(x > 0);
|
||||
$if $Num.kindof == UNSIGNED_INT:
|
||||
return ($Num)(x > 0);
|
||||
$else
|
||||
return ($Type)(x > 0) - ($Type)(x < 0);
|
||||
return ($Num)(x > 0) - ($Num)(x < 0);
|
||||
$endif
|
||||
}
|
||||
|
||||
@@ -117,9 +116,9 @@ macro sign(x)
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
@require values::@is_int(y) || values::@is_float(y) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro atan2(x, y)
|
||||
macro atan2($Num1 x, $Num2 y)
|
||||
{
|
||||
$if @typeis(x, float) && @typeis(y, float):
|
||||
$if $Num1 == float || $Num2 == float:
|
||||
return _atan2f(x, y);
|
||||
$else
|
||||
return _atan2(x, y);
|
||||
@@ -132,12 +131,12 @@ macro atan2(x, y)
|
||||
@require @typematch(sinp, cosp) : "Expected sinp and cosp to have the same type"
|
||||
@require $defined(*sinp = x) : "Expected x and sinp/cosp to have the same type"
|
||||
*>
|
||||
macro sincos_ref(x, sinp, cosp)
|
||||
macro void sincos_ref($Num x, $Num* sinp, $Num* cosp)
|
||||
{
|
||||
$if @typeis(sinp, float*.typeid):
|
||||
return _sincosf(x, sinp, cosp);
|
||||
$if $Num == float:
|
||||
_sincosf(x, sinp, cosp);
|
||||
$else
|
||||
return _sincos(x, sinp, cosp);
|
||||
_sincos(x, sinp, cosp);
|
||||
$endif
|
||||
}
|
||||
|
||||
@@ -147,9 +146,9 @@ macro sincos_ref(x, sinp, cosp)
|
||||
@param x : `the angle in radians`
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro sincos(x)
|
||||
macro sincos($Num x)
|
||||
{
|
||||
$if @typeis(x, float):
|
||||
$if $Num == float:
|
||||
float[<2>] v @noinit;
|
||||
_sincosf(x, &v[0], &v[1]);
|
||||
$else
|
||||
@@ -162,9 +161,9 @@ macro sincos(x)
|
||||
<*
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro atan(x)
|
||||
macro atan($Num x)
|
||||
{
|
||||
$if @typeis(x, float):
|
||||
$if $Num == float:
|
||||
return _atanf(x);
|
||||
$else
|
||||
return _atan(x);
|
||||
@@ -174,9 +173,9 @@ macro atan(x)
|
||||
<*
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro atanh(x)
|
||||
macro atanh($Num x)
|
||||
{
|
||||
$if @typeis(x, float):
|
||||
$if $Num == float:
|
||||
return _atanhf(x);
|
||||
$else
|
||||
return _atanh(x);
|
||||
@@ -186,9 +185,9 @@ macro atanh(x)
|
||||
<*
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro acos(x)
|
||||
macro acos($Num x)
|
||||
{
|
||||
$if @typeis(x, float):
|
||||
$if $Num == float:
|
||||
return _acosf(x);
|
||||
$else
|
||||
return _acos(x);
|
||||
@@ -198,9 +197,9 @@ macro acos(x)
|
||||
<*
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro acosh(x)
|
||||
macro acosh($Num x)
|
||||
{
|
||||
$if @typeis(x, float):
|
||||
$if $Num == float:
|
||||
return _acoshf(x);
|
||||
$else
|
||||
return _acosh(x);
|
||||
@@ -210,9 +209,9 @@ macro acosh(x)
|
||||
<*
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro asin(x)
|
||||
macro asin($Num x)
|
||||
{
|
||||
$if @typeis(x, float):
|
||||
$if $Num == float:
|
||||
return _asinf(x);
|
||||
$else
|
||||
return _asin(x);
|
||||
@@ -222,9 +221,9 @@ macro asin(x)
|
||||
<*
|
||||
@require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value"
|
||||
*>
|
||||
macro asinh(x)
|
||||
macro asinh($Num x)
|
||||
{
|
||||
$if @typeis(x, float):
|
||||
$if $Num == float:
|
||||
return _asinhf(x);
|
||||
$else
|
||||
return _asinh(x);
|
||||
@@ -1111,23 +1110,23 @@ fn float _frexpf(float x, int* e)
|
||||
}
|
||||
}
|
||||
|
||||
macro overflow_add_helper(x, y) @local
|
||||
macro $Num overflow_add_helper($Num x, $Num y) @local
|
||||
{
|
||||
$typeof(x) res @noinit;
|
||||
$Num res @noinit;
|
||||
if ($$overflow_add(x, y, &res)) return OVERFLOW?;
|
||||
return res;
|
||||
}
|
||||
|
||||
macro overflow_sub_helper(x, y) @local
|
||||
macro $Num overflow_sub_helper($Num x, $Num y) @local
|
||||
{
|
||||
$typeof(x) res @noinit;
|
||||
$Num res @noinit;
|
||||
if ($$overflow_sub(x, y, &res)) return OVERFLOW?;
|
||||
return res;
|
||||
}
|
||||
|
||||
macro overflow_mul_helper(x, y) @local
|
||||
macro $Num overflow_mul_helper($Num x, $Num y) @local
|
||||
{
|
||||
$typeof(x) res @noinit;
|
||||
$Num res @noinit;
|
||||
if ($$overflow_mul(x, y, &res)) return OVERFLOW?;
|
||||
return res;
|
||||
}
|
||||
@@ -1135,29 +1134,23 @@ macro overflow_mul_helper(x, y) @local
|
||||
<*
|
||||
@param [&out] out : "Where the result of the addition is stored"
|
||||
@return "Whether the addition resulted in an integer overflow"
|
||||
@require @typematch(a, b) : "a and b must be the same type"
|
||||
@require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based"
|
||||
@require $defined(*out) &&& @typematch(*out, a) : "out must be a pointer of the same type as a and b"
|
||||
*>
|
||||
macro bool overflow_add(a, b, out) => $$overflow_add(a, b, out);
|
||||
*>
|
||||
macro bool overflow_add($Num a, $Num b, $Num* out) => $$overflow_add(a, b, out);
|
||||
|
||||
<*
|
||||
@param [&out] out : "Where the result of the subtraction is stored"
|
||||
@return "Whether the subtraction resulted in an integer overflow"
|
||||
@require @typematch(a, b) : "a and b must be the same type"
|
||||
@require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based"
|
||||
@require $defined(*out) &&& @typematch(*out, a) : "out must be a pointer of the same type as a and b"
|
||||
*>
|
||||
macro bool overflow_sub(a, b, out) => $$overflow_sub(a, b, out);
|
||||
*>
|
||||
macro bool overflow_sub($Num a, $Num b, $Num* out) => $$overflow_sub(a, b, out);
|
||||
|
||||
<*
|
||||
@param [&out] out : "Where the result of the multiplication is stored"
|
||||
@return "Whether the multiplication resulted in an integer overflow"
|
||||
@require @typematch(a, b) : "a and b must be the same type"
|
||||
@require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based"
|
||||
@require $defined(*out) &&& @typematch(*out, a) : "out must be a pointer of the same type as a and b"
|
||||
*>
|
||||
macro bool overflow_mul(a, b, out) => $$overflow_mul(a, b, out);
|
||||
macro bool overflow_mul($Num a, $Num b, $Num* out) => $$overflow_mul(a, b, out);
|
||||
|
||||
<*
|
||||
@require types::is_vector($Type) || ($Type.kindof == ARRAY &&& types::is_numerical($typefrom($Type.inner)))
|
||||
@@ -1171,10 +1164,9 @@ macro iota($Type)
|
||||
return $val;
|
||||
}
|
||||
|
||||
macro mul_div_helper(val, mul, div) @private
|
||||
macro $Num mul_div_helper($Num val, $Num mul, $Num div) @private
|
||||
{
|
||||
var $Type = $typeof(val);
|
||||
return ($Type)(($Type)mul * (val / ($Type)div) + ($Type)mul * (val % ($Type)div) / ($Type)div);
|
||||
return mul * (val / div) + mul * (val % div) / div;
|
||||
}
|
||||
macro char char.muldiv(self, char mul, char div) => mul_div_helper(self, mul, div);
|
||||
macro ichar ichar.muldiv(self, ichar mul, ichar div) => mul_div_helper(self, mul, div);
|
||||
@@ -1194,49 +1186,49 @@ macro bool @is_same_vector_or_scalar(#vector_value, #vector_or_scalar) @private
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro char[<*>] char[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro char[<*>] char[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro ichar[<*>] ichar[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro ichar[<*>] ichar[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro short[<*>] short[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro short[<*>] short[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro ushort[<*>] ushort[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro ushort[<*>] ushort[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro int[<*>] int[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro int[<*>] int[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro uint[<*>] uint[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro uint[<*>] uint[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro long[<*>] long[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro long[<*>] long[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require @is_same_vector_or_scalar(self, mul) : `mul must be a vector of the same type as self, or be an integer scalar`
|
||||
@require @is_same_vector_or_scalar(self, div) : `div must be a vector of the same type as self, or be an integer scalar`
|
||||
*>
|
||||
macro ulong[<*>] ulong[<*>].muldiv(self, mul, div) => mul_div_helper(self, mul, div);
|
||||
macro ulong[<*>] ulong[<*>].muldiv(self, mul, div) => mul_div_helper(self, ($typeof(self))mul, ($typeof(self))div);
|
||||
|
||||
<*
|
||||
@require types::is_int($typeof(a)) : `The input must be an integer`
|
||||
|
||||
@@ -458,6 +458,7 @@ typedef struct VarDecl_
|
||||
bool is_written : 1;
|
||||
bool is_addr : 1;
|
||||
bool self_addr : 1;
|
||||
bool is_typecapture : 1;
|
||||
bool is_threadlocal : 1;
|
||||
bool no_init : 1;
|
||||
bool no_alias : 1;
|
||||
@@ -537,6 +538,7 @@ struct Signature_
|
||||
bool is_macro : 1;
|
||||
bool is_at_macro : 1;
|
||||
bool is_safemacro : 1;
|
||||
bool is_capture_return : 1;
|
||||
Variadic variadic : 3;
|
||||
CallABI abi : 8;
|
||||
unsigned vararg_index;
|
||||
@@ -3528,6 +3530,7 @@ INLINE Decl *decl_flatten(Decl *decl)
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
||||
static inline DeclKind decl_from_token(TokenType type)
|
||||
{
|
||||
if (type == TOKEN_STRUCT) return DECL_STRUCT;
|
||||
|
||||
@@ -1314,11 +1314,11 @@ typedef enum
|
||||
{
|
||||
TYPE_COMPRESSED_NONE = 0,
|
||||
TYPE_COMPRESSED_PTR = 1,
|
||||
TYPE_COMPRESSED_SUB = 2,
|
||||
TYPE_COMPRESSED_SUBPTR = 3,
|
||||
TYPE_COMPRESSED_SLICE = 2,
|
||||
TYPE_COMPRESSED_SLICEPTR = 3,
|
||||
TYPE_COMPRESSED_PTRPTR = 4,
|
||||
TYPE_COMPRESSED_PTRSUB = 5,
|
||||
TYPE_COMPRESSED_SUBSUB = 6,
|
||||
TYPE_COMPRESSED_PTRSLICE = 5,
|
||||
TYPE_COMPRESSED_SLICESLICE = 6,
|
||||
} TypeInfoCompressedKind;
|
||||
|
||||
typedef enum
|
||||
|
||||
@@ -187,19 +187,19 @@ void print_type(FILE *file, TypeInfo *type)
|
||||
case TYPE_COMPRESSED_PTR:
|
||||
fputs("*", file);
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUB:
|
||||
case TYPE_COMPRESSED_SLICE:
|
||||
fputs("[]", file);
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUBPTR:
|
||||
case TYPE_COMPRESSED_SLICEPTR:
|
||||
fputs("[]*", file);
|
||||
break;
|
||||
case TYPE_COMPRESSED_PTRPTR:
|
||||
fputs("**", file);
|
||||
break;
|
||||
case TYPE_COMPRESSED_PTRSUB:
|
||||
case TYPE_COMPRESSED_PTRSLICE:
|
||||
fputs("*[]", file);
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUBSUB:
|
||||
case TYPE_COMPRESSED_SLICESLICE:
|
||||
fputs("[][]", file);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -561,13 +561,13 @@ static inline TypeInfo *parse_array_type_index(ParseContext *c, TypeInfo *type)
|
||||
switch (type->subtype)
|
||||
{
|
||||
case TYPE_COMPRESSED_NONE:
|
||||
type->subtype = TYPE_COMPRESSED_SUB;
|
||||
type->subtype = TYPE_COMPRESSED_SLICE;
|
||||
break;
|
||||
case TYPE_COMPRESSED_PTR:
|
||||
type->subtype = TYPE_COMPRESSED_PTRSUB;
|
||||
type->subtype = TYPE_COMPRESSED_PTRSLICE;
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUB:
|
||||
type->subtype = TYPE_COMPRESSED_SUBSUB;
|
||||
case TYPE_COMPRESSED_SLICE:
|
||||
type->subtype = TYPE_COMPRESSED_SLICESLICE;
|
||||
break;
|
||||
default:
|
||||
goto DIRECT_SLICE;
|
||||
@@ -653,8 +653,8 @@ static inline TypeInfo *parse_type_with_base_maybe_generic(ParseContext *c, Type
|
||||
case TYPE_COMPRESSED_PTR:
|
||||
type_info->subtype = TYPE_COMPRESSED_PTRPTR;
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUB:
|
||||
type_info->subtype = TYPE_COMPRESSED_SUBPTR;
|
||||
case TYPE_COMPRESSED_SLICE:
|
||||
type_info->subtype = TYPE_COMPRESSED_SLICEPTR;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@@ -1451,13 +1451,25 @@ static bool parse_next_is_typed_parameter(ParseContext *c, ParameterParseKind pa
|
||||
case TOKEN_CT_VATYPE:
|
||||
return parse_kind == PARAM_PARSE_LAMBDA || parse_kind == PARAM_PARSE_CALL;
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
if (parse_kind == PARAM_PARSE_LAMBDA) return true;
|
||||
if (parse_kind != PARAM_PARSE_CALL) return false;
|
||||
switch (parse_kind)
|
||||
{
|
||||
case PARAM_PARSE_MACRO:
|
||||
case PARAM_PARSE_CALL:
|
||||
break;
|
||||
case PARAM_PARSE_FUNC:
|
||||
case PARAM_PARSE_BODY:
|
||||
case PARAM_PARSE_ATTR:
|
||||
return false;
|
||||
case PARAM_PARSE_LAMBDA:
|
||||
return true;
|
||||
}
|
||||
switch (peek(c))
|
||||
{
|
||||
case TOKEN_IDENT:
|
||||
case TOKEN_HASH_IDENT:
|
||||
case TOKEN_CT_IDENT:
|
||||
case TOKEN_LBRACKET:
|
||||
case TOKEN_STAR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -1517,8 +1529,10 @@ bool parse_parameters(ParseContext *c, Decl ***params_ref, Variadic *variadic, i
|
||||
|
||||
// Now we have the following possibilities: "foo", "Foo foo", "Foo... foo", "foo...", "Foo"
|
||||
TypeInfo *type = NULL;
|
||||
bool is_type_capture = false;
|
||||
if (parse_next_is_typed_parameter(c, parse_kind))
|
||||
{
|
||||
is_type_capture = parse_kind == PARAM_PARSE_MACRO && tok_is(c, TOKEN_CT_TYPE_IDENT);
|
||||
// Parse the type,
|
||||
ASSIGN_TYPE_OR_RET(type, parse_optional_type(c), false);
|
||||
ellipsis = try_consume(c, TOKEN_ELLIPSIS);
|
||||
@@ -1669,6 +1683,7 @@ bool parse_parameters(ParseContext *c, Decl ***params_ref, Variadic *variadic, i
|
||||
}
|
||||
Decl *param = decl_new_var(name, span, type, param_kind);
|
||||
param->var.type_info = type ? type_infoid(type) : 0;
|
||||
if (is_type_capture) param->var.is_typecapture = true;
|
||||
param->var.self_addr = ref;
|
||||
if (!parse_attributes(c, ¶m->attributes, NULL, NULL, NULL)) return false;
|
||||
if (!no_name)
|
||||
@@ -2370,6 +2385,10 @@ static inline bool parse_func_macro_header(ParseContext *c, Decl *decl)
|
||||
{
|
||||
RETURN_PRINT_ERROR_HERE("This is a reserved keyword and can't be used as a macro name.");
|
||||
}
|
||||
if (is_macro && tok_is(c, TOKEN_CT_TYPE_IDENT))
|
||||
{
|
||||
decl->func_decl.signature.is_capture_return = true;
|
||||
}
|
||||
ASSIGN_TYPE_OR_RET(rtype, parse_optional_type(c), false);
|
||||
|
||||
// 4. We might have a type here, if so then we read it.
|
||||
|
||||
@@ -1103,13 +1103,14 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig,
|
||||
bool is_macro = sig->is_macro;
|
||||
bool is_macro_at_name = sig->is_at_macro || sig->is_safemacro;
|
||||
// Check return type
|
||||
ASSERT(sig->rtype || sig->is_macro);
|
||||
TypeInfoId sig_rtype = sig->is_capture_return ? 0 : sig->rtype;
|
||||
ASSERT(sig_rtype || sig->is_macro);
|
||||
Type *rtype = NULL;
|
||||
int format_index = (int)sig->attrs.format - 1;
|
||||
if (sig->rtype)
|
||||
if (sig_rtype)
|
||||
{
|
||||
TypeInfo *rtype_info = type_infoptr(sig->rtype);
|
||||
if (!sema_resolve_type_info(context, type_infoptr(sig->rtype),
|
||||
TypeInfo *rtype_info = type_infoptr(sig_rtype);
|
||||
if (!sema_resolve_type_info(context, rtype_info,
|
||||
is_macro ? RESOLVE_TYPE_ALLOW_INFER
|
||||
: RESOLVE_TYPE_DEFAULT)) return false;
|
||||
rtype = rtype_info->type;
|
||||
@@ -1272,7 +1273,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig,
|
||||
param->unit = context->unit;
|
||||
ASSERT(param->decl_kind == DECL_VAR);
|
||||
VarDeclKind var_kind = param->var.kind;
|
||||
TypeInfo *type_info = type_infoptrzero(param->var.type_info);
|
||||
TypeInfo *type_info = param->var.is_typecapture ? NULL: type_infoptrzero(param->var.type_info);
|
||||
if (type_info)
|
||||
{
|
||||
if (!sema_resolve_type_info(context, type_info,
|
||||
@@ -1835,7 +1836,7 @@ static bool sema_analyse_operator_common(SemaContext *context, Decl *method, Typ
|
||||
RETURN_SEMA_ERROR(method, "Not enough parameters, '%s' requires %u.", method->name, (unsigned)parameters);
|
||||
}
|
||||
|
||||
if (!signature->rtype) RETURN_SEMA_ERROR(method, "The return value must be explicitly typed for '%s'.", method->name);
|
||||
if (signature->is_capture_return || !signature->rtype) RETURN_SEMA_ERROR(method, "The return value must be explicitly typed for '%s'.", method->name);
|
||||
|
||||
FOREACH(Decl *, param, params)
|
||||
{
|
||||
@@ -2055,7 +2056,7 @@ static inline bool sema_analyse_operator_arithmetics(SemaContext *context, Decl
|
||||
{
|
||||
RETURN_SEMA_ERROR(method, "Not enough parameters, '%s' requires 2 parameters.", method->name);
|
||||
}
|
||||
if (!signature->rtype) RETURN_SEMA_ERROR(method, "The return value must be explicitly typed for '%s'.", method->name);
|
||||
if (signature->is_capture_return || !signature->rtype) RETURN_SEMA_ERROR(method, "The return value must be explicitly typed for '%s'.", method->name);
|
||||
TypeInfo *rtype = type_infoptr(signature->rtype);
|
||||
if (IS_OPTIONAL(rtype))
|
||||
{
|
||||
@@ -2673,6 +2674,7 @@ static inline Decl *sema_find_interface_for_method(SemaContext *context, Canonic
|
||||
*/
|
||||
static inline bool sema_compare_method_with_interface(SemaContext *context, Decl *decl, Decl *implemented_method)
|
||||
{
|
||||
assert(decl->decl_kind == DECL_FUNC);
|
||||
Signature interface_sig = implemented_method->func_decl.signature;
|
||||
Signature this_sig = decl->func_decl.signature;
|
||||
Type *any_rtype = typeget(interface_sig.rtype);
|
||||
|
||||
@@ -157,7 +157,7 @@ static inline bool sema_call_analyse_func_invocation(SemaContext *context, Decl
|
||||
Expr *struct_var,
|
||||
bool optional, const char *name, bool *no_match_ref);
|
||||
static inline bool sema_call_check_invalid_body_arguments(SemaContext *context, Expr *call, CalledDecl *callee);
|
||||
static inline bool sema_call_evaluate_arguments(SemaContext *context, CalledDecl *callee, Expr *call, bool *optional, bool *no_match_ref);
|
||||
static inline bool sema_call_evaluate_arguments(SemaContext *context, CalledDecl *callee, Expr *call, bool *optional, bool *no_match_ref, Decl **type_capture);
|
||||
static inline bool sema_call_check_contract_param_match(SemaContext *context, Decl *param, Expr *expr);
|
||||
static bool sema_call_analyse_body_expansion(SemaContext *macro_context, Expr *call);
|
||||
static bool sema_slice_index_is_in_range(SemaContext *context, Type *type, Expr *index_expr, bool end_index, bool from_end, bool *remove_from_end, bool check_valid);
|
||||
@@ -1497,13 +1497,166 @@ static inline bool sema_call_check_invalid_body_arguments(SemaContext *context,
|
||||
|
||||
#define RETURN_ERR_WITH_DEFINITION do { if (compiler.context.errors_found != errors) SEMA_NOTE(definition, "The definition is here."); return false; } while (0)
|
||||
|
||||
|
||||
static Decl *sema_macro_capture_type(SemaContext *context, Decl *param, Expr *arg)
|
||||
{
|
||||
Type *param_type = arg->type;
|
||||
TypeInfo *type = type_infoptr(param->var.type_info);
|
||||
while (true)
|
||||
{
|
||||
param_type = param_type->canonical;
|
||||
switch (type->subtype)
|
||||
{
|
||||
case TYPE_COMPRESSED_NONE:
|
||||
break;
|
||||
case TYPE_COMPRESSED_PTR:
|
||||
if (param_type->type_kind != TYPE_POINTER) goto NO_MATCH;
|
||||
param_type = param_type->pointer;
|
||||
type->subtype = TYPE_COMPRESSED_NONE;
|
||||
continue;
|
||||
case TYPE_COMPRESSED_SLICE:
|
||||
if (param_type->type_kind != TYPE_SLICE) goto NO_MATCH;
|
||||
param_type = param_type->array.base;
|
||||
type->subtype = TYPE_COMPRESSED_NONE;
|
||||
continue;
|
||||
case TYPE_COMPRESSED_SLICEPTR:
|
||||
if (param_type->type_kind != TYPE_POINTER) goto NO_MATCH;
|
||||
param_type = param_type->pointer;
|
||||
type->subtype = TYPE_COMPRESSED_SLICE;
|
||||
continue;
|
||||
case TYPE_COMPRESSED_PTRPTR:
|
||||
if (param_type->type_kind != TYPE_POINTER) goto NO_MATCH;
|
||||
param_type = param_type->pointer;
|
||||
type->subtype = TYPE_COMPRESSED_PTR;
|
||||
continue;
|
||||
case TYPE_COMPRESSED_PTRSLICE:
|
||||
if (param_type->type_kind != TYPE_SLICE) goto NO_MATCH;
|
||||
param_type = param_type->array.base;
|
||||
type->subtype = TYPE_COMPRESSED_PTR;
|
||||
continue;
|
||||
case TYPE_COMPRESSED_SLICESLICE:
|
||||
if (param_type->type_kind != TYPE_SLICE) goto NO_MATCH;
|
||||
param_type = param_type->array.base;
|
||||
type->subtype = TYPE_COMPRESSED_SLICE;
|
||||
continue;
|
||||
}
|
||||
ASSERT(type->subtype == TYPE_COMPRESSED_NONE);
|
||||
switch (type->kind)
|
||||
{
|
||||
case TYPE_INFO_POISON: return NULL;
|
||||
case TYPE_INFO_TYPEOF:
|
||||
case TYPE_INFO_VATYPE:
|
||||
case TYPE_INFO_EVALTYPE:
|
||||
case TYPE_INFO_TYPEFROM:
|
||||
case TYPE_INFO_GENERIC:
|
||||
case TYPE_INFO_IDENTIFIER: UNREACHABLE;
|
||||
case TYPE_INFO_CT_IDENTIFIER: goto DO_MATCH;
|
||||
case TYPE_INFO_ARRAY:
|
||||
if (param_type->type_kind != TYPE_ARRAY) goto NO_MATCH;
|
||||
goto LEN_CHECK;
|
||||
case TYPE_INFO_VECTOR:
|
||||
if (param_type->type_kind != TYPE_VECTOR) goto NO_MATCH;
|
||||
LEN_CHECK:
|
||||
{
|
||||
ArraySize size;
|
||||
if (!sema_resolve_array_like_len(context, type, &size)) return false;
|
||||
if (param_type->array.len != size) goto NO_MATCH;
|
||||
param_type = param_type->array.base;
|
||||
type = type->array.base;
|
||||
continue;
|
||||
}
|
||||
case TYPE_INFO_INFERRED_ARRAY:
|
||||
if (param_type->type_kind != TYPE_ARRAY) goto NO_MATCH;
|
||||
param_type = param_type->array.base;
|
||||
type = type->array.base;
|
||||
continue;
|
||||
case TYPE_INFO_INFERRED_VECTOR:
|
||||
if (param_type->type_kind != TYPE_VECTOR) goto NO_MATCH;
|
||||
param_type = param_type->array.base;
|
||||
type = type->array.base;
|
||||
continue;
|
||||
case TYPE_INFO_SLICE:
|
||||
if (param_type->type_kind != TYPE_SLICE) goto NO_MATCH;
|
||||
param_type = param_type->array.base;
|
||||
type = type->array.base;
|
||||
continue;
|
||||
case TYPE_INFO_POINTER:
|
||||
if (param_type->type_kind != TYPE_POINTER) goto NO_MATCH;
|
||||
param_type = param_type->pointer;
|
||||
type = type->pointer;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
DO_MATCH:;
|
||||
const char *name = type->unresolved.name;
|
||||
Decl *new_param = decl_new_var(name, arg->span, NULL, VARDECL_PARAM_CT_TYPE);
|
||||
new_param->var.init_expr = expr_new_const_typeid(param->span, param_type);
|
||||
return new_param;
|
||||
NO_MATCH:
|
||||
RETURN_SEMA_ERROR(arg, "Type is not valid %s", type_quoted_error_string(arg->type));
|
||||
return NULL;
|
||||
}
|
||||
static bool sema_patch_captured_type(TypeInfo *type, Decl **captured)
|
||||
{
|
||||
assert(type->resolve_status != RESOLVE_DONE);
|
||||
if (!captured || !captured[0]) return false;
|
||||
while (true)
|
||||
{
|
||||
switch (type->kind)
|
||||
{
|
||||
case TYPE_INFO_ARRAY:
|
||||
case TYPE_INFO_VECTOR:
|
||||
case TYPE_INFO_SLICE:
|
||||
case TYPE_INFO_INFERRED_ARRAY:
|
||||
case TYPE_INFO_INFERRED_VECTOR:
|
||||
type = type->array.base;
|
||||
continue;
|
||||
case TYPE_INFO_POINTER:
|
||||
type = type->pointer;
|
||||
continue;
|
||||
case TYPE_INFO_CT_IDENTIFIER:
|
||||
{
|
||||
Decl *d;
|
||||
const char *name = type->unresolved.name;
|
||||
while ((d = *captured) != NULL)
|
||||
{
|
||||
if (d->name == name)
|
||||
{
|
||||
type->kind = TYPE_INFO_TYPEFROM;
|
||||
type->unresolved_type_expr = d->var.init_expr;
|
||||
return true;
|
||||
}
|
||||
captured++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param, Decl *definition, bool *optional_ref,
|
||||
bool *no_match_ref, bool macro, bool is_method_target)
|
||||
bool *no_match_ref, bool macro, bool is_method_target, Decl **type_capture)
|
||||
{
|
||||
VarDeclKind kind = param->var.kind;
|
||||
Type *type = param->type;
|
||||
// 16. Analyse a regular argument.
|
||||
unsigned errors = compiler.context.errors_found;
|
||||
bool try_capture = false;
|
||||
if (type_capture && param->var.is_typecapture)
|
||||
{
|
||||
if (sema_patch_captured_type(type_infoptr(param->var.type_info), type_capture))
|
||||
{
|
||||
if (!sema_resolve_type_info(context, type_infoptr(param->var.type_info), RESOLVE_TYPE_ALLOW_INFER)) return false;
|
||||
param->type = typeget(param->var.type_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
try_capture = true;
|
||||
}
|
||||
}
|
||||
Type *type = param->type;
|
||||
switch (kind)
|
||||
{
|
||||
case VARDECL_PARAM:
|
||||
@@ -1607,11 +1760,25 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param,
|
||||
{
|
||||
param->type = type_no_optional(arg->type);
|
||||
}
|
||||
if (try_capture)
|
||||
{
|
||||
Decl *new_param = sema_macro_capture_type(context, param, arg);
|
||||
if (!new_param) return false;
|
||||
for (int i = 0; i < MAX_PARAMS; i++)
|
||||
{
|
||||
if (!type_capture[i])
|
||||
{
|
||||
type_capture[i] = new_param;
|
||||
type_capture[i + 1] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee, Expr *call, Decl *param,
|
||||
bool *no_match_ref, Expr **expr_ref, bool *optional)
|
||||
bool *no_match_ref, Expr **expr_ref, bool *optional, Decl **type_capture)
|
||||
{
|
||||
Expr *init_expr = param->var.init_expr;
|
||||
if (!init_expr) return true;
|
||||
@@ -1627,7 +1794,7 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee,
|
||||
: call->span.row;
|
||||
new_context->original_module = context->original_module;
|
||||
success = sema_analyse_parameter(new_context, arg, param, callee->definition, optional, no_match_ref,
|
||||
callee->macro, false);
|
||||
callee->macro, false, type_capture);
|
||||
SCOPE_END;
|
||||
sema_context_destroy(&default_context);
|
||||
if (no_match_ref && *no_match_ref) return true;
|
||||
@@ -1643,7 +1810,7 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee,
|
||||
param->var.defaulted = true;
|
||||
if (parameter_checked) return true;
|
||||
return sema_analyse_parameter(context, arg, param, callee->definition, optional, no_match_ref,
|
||||
callee->macro, false);
|
||||
callee->macro, false, type_capture);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1655,7 +1822,7 @@ INLINE bool sema_set_default_argument(SemaContext *context, CalledDecl *callee,
|
||||
*expr_ref = function_scope_arg;
|
||||
if (parameter_checked) return true;
|
||||
return sema_analyse_parameter(context, function_scope_arg, param, callee->definition, optional, no_match_ref,
|
||||
callee->macro, false);
|
||||
callee->macro, false, type_capture);
|
||||
}
|
||||
|
||||
|
||||
@@ -1738,7 +1905,7 @@ INLINE Type *sema_get_va_type(SemaContext *context, Expr *expr, Variadic variadi
|
||||
}
|
||||
|
||||
INLINE bool sema_call_evaluate_arguments(SemaContext *context, CalledDecl *callee, Expr *call, bool *optional,
|
||||
bool *no_match_ref)
|
||||
bool *no_match_ref, Decl **type_capture)
|
||||
{
|
||||
// Check body arguments (for macro calls, or possibly broken
|
||||
if (!sema_call_check_invalid_body_arguments(context, call, callee)) return false;
|
||||
@@ -1896,7 +2063,7 @@ SPLAT_NORMAL:;
|
||||
if (!sema_set_default_argument(context, callee, call,
|
||||
params[j], no_match_ref,
|
||||
&actual_args[j],
|
||||
optional))
|
||||
optional, type_capture))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1906,7 +2073,7 @@ SPLAT_NORMAL:;
|
||||
|
||||
actual_args[index] = arg->named_argument_expr.value;
|
||||
if (!sema_analyse_parameter(context, actual_args[index], param, callee->definition, optional, no_match_ref,
|
||||
callee->macro, false)) return false;
|
||||
callee->macro, false, type_capture)) return false;
|
||||
continue;
|
||||
}
|
||||
if (call->call_expr.va_is_splat)
|
||||
@@ -1983,7 +2150,7 @@ SPLAT_NORMAL:;
|
||||
vec_add(call->call_expr.varargs, arg);
|
||||
continue;
|
||||
}
|
||||
if (!sema_analyse_parameter(context, arg, params[i], callee->definition, optional, no_match_ref, callee->macro, callee->struct_var && i == 0)) return false;
|
||||
if (!sema_analyse_parameter(context, arg, params[i], callee->definition, optional, no_match_ref, callee->macro, callee->struct_var && i == 0, type_capture)) return false;
|
||||
actual_args[i] = arg;
|
||||
}
|
||||
if (num_args) last = args[num_args - 1];
|
||||
@@ -1996,7 +2163,7 @@ SPLAT_NORMAL:;
|
||||
if (i == vaarg_index && variadic != VARIADIC_NONE) continue;
|
||||
|
||||
if (!sema_set_default_argument(context, callee, call, params[i], no_match_ref, &actual_args[i],
|
||||
optional)) return false;
|
||||
optional, type_capture)) return false;
|
||||
}
|
||||
for (int i = 0; i < func_param_count; i++)
|
||||
{
|
||||
@@ -2289,7 +2456,7 @@ static inline bool sema_call_analyse_func_invocation(SemaContext *context, Decl
|
||||
|
||||
if (sig->attrs.noreturn) expr->call_expr.no_return = true;
|
||||
|
||||
if (!sema_call_evaluate_arguments(context, &callee, expr, &optional, no_match_ref)) return false;
|
||||
if (!sema_call_evaluate_arguments(context, &callee, expr, &optional, no_match_ref, NULL)) return false;
|
||||
|
||||
Type *rtype = type->function.prototype->rtype;
|
||||
if (expr->call_expr.is_dynamic_dispatch)
|
||||
@@ -2564,6 +2731,8 @@ static inline bool sema_expr_setup_call_analysis(SemaContext *context, CalledDec
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl,
|
||||
bool call_var_optional, bool *no_match_ref)
|
||||
{
|
||||
@@ -2620,7 +2789,9 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
};
|
||||
|
||||
bool has_optional_arg = call_var_optional;
|
||||
if (!sema_call_evaluate_arguments(context, &callee, call_expr, &has_optional_arg, no_match_ref)) return false;
|
||||
Decl *captured_types[MAX_PARAMS + 1];
|
||||
captured_types[0] = NULL;
|
||||
if (!sema_call_evaluate_arguments(context, &callee, call_expr, &has_optional_arg, no_match_ref, captured_types)) return false;
|
||||
|
||||
unsigned vararg_index = sig->vararg_index;
|
||||
Expr **args = call_expr->call_expr.arguments;
|
||||
@@ -2743,7 +2914,18 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
context_change_scope_with_flags(context, SCOPE_NONE);
|
||||
SemaContext macro_context;
|
||||
|
||||
Type *rtype = typeget(sig->rtype);
|
||||
TypeInfo *rtype_info = type_infoptrzero(sig->rtype);
|
||||
if (sig->is_capture_return)
|
||||
{
|
||||
rtype_info = copy_type_info_single(rtype_info);
|
||||
if (!sema_patch_captured_type(rtype_info, captured_types))
|
||||
{
|
||||
SEMA_ERROR(rtype_info, "The return type could not be inferred from any captured types, are you sure it's a captured parameter?");
|
||||
goto EXIT_FAIL;
|
||||
}
|
||||
if (!sema_resolve_type_info(context, rtype_info, RESOLVE_TYPE_DEFAULT)) goto EXIT_FAIL;
|
||||
}
|
||||
Type *rtype = rtype_info ? rtype_info->type : NULL;
|
||||
bool optional_return = rtype && type_is_optional(rtype);
|
||||
bool may_be_optional = !rtype || optional_return;
|
||||
if (rtype) rtype = type_no_optional(rtype);
|
||||
@@ -2758,6 +2940,12 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
goto EXIT_FAIL;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < MAX_PARAMS; idx++)
|
||||
{
|
||||
if (!captured_types[idx]) break;
|
||||
if (!sema_add_local(¯o_context, captured_types[idx])) return false;
|
||||
}
|
||||
|
||||
AstId assert_first = 0;
|
||||
AstId* next = &assert_first;
|
||||
|
||||
@@ -2769,7 +2957,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s
|
||||
if (param->var.init_expr)
|
||||
{
|
||||
Type *param_type = param->type;
|
||||
if (param_type && param->var.type_info && (param->var.out_param || param->var.not_null))
|
||||
if (param->var.type_info && (param->var.out_param || param->var.not_null))
|
||||
{
|
||||
param_type = type_flatten(param_type);
|
||||
if (param_type->type_kind != TYPE_POINTER && param_type->type_kind != TYPE_SLICE && param_type->type_kind != TYPE_INTERFACE && param_type->type_kind != TYPE_ANY)
|
||||
@@ -3028,7 +3216,7 @@ static bool sema_call_analyse_body_expansion(SemaContext *macro_context, Expr *c
|
||||
{
|
||||
Decl *param = params[i];
|
||||
Expr *expr = args[i];
|
||||
if (!sema_analyse_parameter(macro_context, expr, param, body_decl, &has_optional_arg, NULL, true, false))
|
||||
if (!sema_analyse_parameter(macro_context, expr, param, body_decl, &has_optional_arg, NULL, true, false, NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -499,12 +499,12 @@ static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info,
|
||||
{
|
||||
case TYPE_COMPRESSED_NONE:
|
||||
case TYPE_COMPRESSED_PTR:
|
||||
case TYPE_COMPRESSED_SUBPTR:
|
||||
case TYPE_COMPRESSED_SLICEPTR:
|
||||
case TYPE_COMPRESSED_PTRPTR:
|
||||
case TYPE_COMPRESSED_PTRSUB:
|
||||
case TYPE_COMPRESSED_PTRSLICE:
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUB:
|
||||
case TYPE_COMPRESSED_SUBSUB:
|
||||
case TYPE_COMPRESSED_SLICE:
|
||||
case TYPE_COMPRESSED_SLICESLICE:
|
||||
resolve_kind = resolve_kind & ~RESOLVE_TYPE_NO_CHECK_DISTINCT;
|
||||
break;
|
||||
}
|
||||
@@ -562,20 +562,20 @@ APPEND_QUALIFIERS:
|
||||
case TYPE_COMPRESSED_PTR:
|
||||
type_info->type = type_get_ptr(type_info->type);
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUB:
|
||||
case TYPE_COMPRESSED_SLICE:
|
||||
if (!sema_check_array_type(context, type_info, type_info->type, TYPE_INFO_SLICE, 0, &type_info->type)) return type_info_poison(type_info);
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUBPTR:
|
||||
case TYPE_COMPRESSED_SLICEPTR:
|
||||
if (!sema_check_array_type(context, type_info, type_info->type, TYPE_INFO_SLICE, 0, &type_info->type)) return type_info_poison(type_info);
|
||||
type_info->type = type_get_ptr(type_info->type);
|
||||
break;
|
||||
case TYPE_COMPRESSED_PTRPTR:
|
||||
type_info->type = type_get_ptr(type_get_ptr(type_info->type));
|
||||
break;
|
||||
case TYPE_COMPRESSED_PTRSUB:
|
||||
case TYPE_COMPRESSED_PTRSLICE:
|
||||
type_info->type = type_get_slice(type_get_ptr(type_info->type));
|
||||
break;
|
||||
case TYPE_COMPRESSED_SUBSUB:
|
||||
case TYPE_COMPRESSED_SLICESLICE:
|
||||
if (!sema_check_array_type(context, type_info, type_info->type, TYPE_INFO_SLICE, 0, &type_info->type)) return type_info_poison(type_info);
|
||||
type_info->type = type_get_slice(type_info->type);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user