mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Implicitly convert from constant typeid to Type in $Type assignment, and $assignable.
- Make $Type parameters accept constant typeid values.
This commit is contained in:
@@ -175,7 +175,7 @@ macro bool is_native_atomic_type($Type)
|
||||
$case BOOL:
|
||||
return true;
|
||||
$case DISTINCT:
|
||||
return is_native_atomic_type($typefrom($Type.inner));
|
||||
return is_native_atomic_type($Type.inner);
|
||||
$default:
|
||||
return false;
|
||||
$endswitch
|
||||
@@ -240,7 +240,7 @@ macro fetch_mul(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
|
||||
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
|
||||
$endif
|
||||
|
||||
var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));
|
||||
var $StorageType = types::lower_to_atomic_compatible_type($typeof(*ptr));
|
||||
|
||||
$StorageType* storage_ptr = ($StorageType*)ptr;
|
||||
|
||||
@@ -280,7 +280,7 @@ macro fetch_div(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
|
||||
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
|
||||
$endif
|
||||
|
||||
var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));
|
||||
var $StorageType = types::lower_to_atomic_compatible_type($typeof(*ptr));
|
||||
|
||||
$StorageType* storage_ptr = ($StorageType*)ptr;
|
||||
|
||||
@@ -372,7 +372,7 @@ macro fetch_shift_right(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
|
||||
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
|
||||
$endif
|
||||
|
||||
var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));
|
||||
var $StorageType = types::lower_to_atomic_compatible_type($typeof(*ptr));
|
||||
|
||||
$StorageType* storage_ptr = ($StorageType*)ptr;
|
||||
|
||||
@@ -414,7 +414,7 @@ macro fetch_shift_left(ptr, y, AtomicOrdering $ordering = SEQ_CONSISTENT)
|
||||
$load_ordering = AtomicOrdering.SEQ_CONSISTENT;
|
||||
$endif
|
||||
|
||||
var $StorageType = $typefrom(types::lower_to_atomic_compatible_type($typeof(*ptr)));
|
||||
var $StorageType = types::lower_to_atomic_compatible_type($typeof(*ptr));
|
||||
|
||||
$StorageType* storage_ptr = ($StorageType*)ptr;
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ macro bool is_numerical($Type)
|
||||
{
|
||||
var $kind = $Type.kindof;
|
||||
$if $kind == TypeKind.DISTINCT:
|
||||
return is_numerical($typefrom($Type.inner));
|
||||
return is_numerical($Type.inner);
|
||||
$else
|
||||
return $kind == TypeKind.SIGNED_INT || $kind == TypeKind.UNSIGNED_INT || $kind == TypeKind.FLOAT
|
||||
|| $kind == TypeKind.VECTOR;
|
||||
@@ -135,7 +135,7 @@ macro bool is_signed($Type) @const
|
||||
$case FLOAT:
|
||||
return true;
|
||||
$case VECTOR:
|
||||
return is_signed($typefrom($Type.inner));
|
||||
return is_signed($Type.inner);
|
||||
$default:
|
||||
return false;
|
||||
$endswitch
|
||||
@@ -150,7 +150,7 @@ macro bool is_unsigned($Type) @const
|
||||
$case UNSIGNED_INT:
|
||||
return true;
|
||||
$case VECTOR:
|
||||
return is_unsigned($typefrom($Type.inner));
|
||||
return is_unsigned($Type.inner);
|
||||
$default:
|
||||
return false;
|
||||
$endswitch
|
||||
@@ -159,7 +159,7 @@ macro bool is_unsigned($Type) @const
|
||||
macro typeid flat_type($Type) @const
|
||||
{
|
||||
$if $Type.kindof == DISTINCT:
|
||||
return flat_type($typefrom($Type.inner));
|
||||
return flat_type($Type.inner);
|
||||
$else
|
||||
return $Type.typeid;
|
||||
$endif
|
||||
@@ -168,7 +168,7 @@ macro typeid flat_type($Type) @const
|
||||
macro TypeKind flat_kind($Type) @const
|
||||
{
|
||||
$if $Type.kindof == DISTINCT:
|
||||
return flat_type($typefrom($Type.inner));
|
||||
return flat_type($Type.inner);
|
||||
$else
|
||||
return $Type.kindof;
|
||||
$endif
|
||||
@@ -204,7 +204,7 @@ macro bool is_underlying_int($Type) @const
|
||||
$case UNSIGNED_INT:
|
||||
return true;
|
||||
$case DISTINCT:
|
||||
return is_underlying_int($typefrom($Type.inner));
|
||||
return is_underlying_int($Type.inner);
|
||||
$default:
|
||||
return false;
|
||||
$endswitch
|
||||
@@ -232,7 +232,7 @@ macro bool is_vector($Type) @const
|
||||
macro typeid inner_type($Type) @const
|
||||
{
|
||||
$if $Type.kindof == TypeKind.DISTINCT:
|
||||
return inner_type($typefrom($Type.inner));
|
||||
return inner_type($Type.inner);
|
||||
$else
|
||||
return $Type.typeid;
|
||||
$endif
|
||||
|
||||
@@ -41,7 +41,7 @@ macro usz? struct_to_format(value, Formatter* f, bool $force_dump)
|
||||
total += f.printf("%s: ", $member.nameof)!;
|
||||
$endif
|
||||
$if ($force_dump &&& $member.typeid.kindof == STRUCT) |||
|
||||
is_struct_with_default_print($typefrom($member.typeid)):
|
||||
is_struct_with_default_print($member.typeid):
|
||||
total += struct_to_format($member.get(value), f, $force_dump)!;
|
||||
$else
|
||||
total += f.printf("%s", $member.get(value))!;
|
||||
|
||||
@@ -191,7 +191,7 @@ const char[*] MAX_VARS @private = { [2] = 3, [4] = 5, [8] = 10 };
|
||||
*>
|
||||
macro usz? read_varint(stream, x_ptr)
|
||||
{
|
||||
var $Type = $typefrom($typeof(x_ptr).inner);
|
||||
var $Type = $typeof(x_ptr).inner;
|
||||
const MAX = MAX_VARS[$Type.sizeof];
|
||||
$Type x;
|
||||
uint shift;
|
||||
|
||||
@@ -32,7 +32,7 @@ alias Indexs @private = char[256];
|
||||
alias ElementType = $typeof((Type){}[0]);
|
||||
|
||||
const bool NO_KEY_FN @private = types::is_same(KeyFn, EmptySlot);
|
||||
const bool KEY_BY_VALUE @private = NO_KEY_FN ||| $assignable((Type){}[0], $typefrom(KeyFn.paramsof[0].type));
|
||||
const bool KEY_BY_VALUE @private = NO_KEY_FN ||| $assignable((Type){}[0], KeyFn.paramsof[0].type);
|
||||
const bool LIST_HAS_REF @private = $defined(&(Type){}[0]);
|
||||
|
||||
alias KeyFnReturnType @if(!NO_KEY_FN) = $typefrom(KeyFn.returns) ;
|
||||
|
||||
@@ -25,7 +25,7 @@ fn void isort(Type list, usz low, usz high, CmpFn comp, Context context)
|
||||
{
|
||||
var $has_cmp = @is_valid_macro_slot(comp);
|
||||
var $has_context = @is_valid_macro_slot(context);
|
||||
var $cmp_by_value = $has_cmp &&& $assignable(list[0], $typefrom(CmpFn.paramsof[0].type));
|
||||
var $cmp_by_value = $has_cmp &&& $assignable(list[0], CmpFn.paramsof[0].type);
|
||||
var $has_get_ref = $defined(&list[0]);
|
||||
for (usz i = low; i < high; ++i)
|
||||
{
|
||||
|
||||
@@ -115,7 +115,7 @@ macro @partition(Type list, isz l, isz h, CmpFn cmp, Context context)
|
||||
{
|
||||
var $has_cmp = @is_valid_macro_slot(cmp);
|
||||
var $has_context = @is_valid_macro_slot(context);
|
||||
var $cmp_by_value = $has_cmp &&& $assignable(list[0], $typefrom(CmpFn.paramsof[0].type));
|
||||
var $cmp_by_value = $has_cmp &&& $assignable(list[0], CmpFn.paramsof[0].type);
|
||||
|
||||
ElementType pivot = list[l];
|
||||
while (l < h)
|
||||
|
||||
@@ -39,7 +39,7 @@ macro int @sort_cmp(list, pos, cmp, ctx) @local
|
||||
{
|
||||
var $has_cmp = @is_valid_macro_slot(cmp);
|
||||
var $has_context = @is_valid_macro_slot(ctx);
|
||||
var $cmp_by_value = $has_cmp &&& $assignable(list[0], $typefrom($typeof(cmp).paramsof[0].type));
|
||||
var $cmp_by_value = $has_cmp &&& $assignable(list[0], $typeof(cmp).paramsof[0].type);
|
||||
|
||||
var a = list[pos];
|
||||
var b = list[pos+1];
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
- `$typefrom` now also accepts a constant string, and so works like `$evaltype`.
|
||||
- `$evaltype` is deprecated in favour of `$typefrom`.
|
||||
- `-0xFF` will now be a signed integer.
|
||||
- Implicitly convert from constant typeid to Type in `$Type` assignment, and `$assignable`.
|
||||
- Make $Type parameters accept constant typeid values.
|
||||
|
||||
### Fixes
|
||||
- `-2147483648`, MIN literals work correctly.
|
||||
|
||||
@@ -1089,7 +1089,7 @@ typedef struct
|
||||
{
|
||||
bool is_assign;
|
||||
ExprId expr;
|
||||
TypeInfoId type;
|
||||
ExprId type;
|
||||
} ExprCastable;
|
||||
|
||||
typedef struct
|
||||
@@ -4077,6 +4077,12 @@ INLINE bool expr_is_const_float(Expr *expr)
|
||||
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_FLOAT;
|
||||
}
|
||||
|
||||
INLINE bool expr_is_const_typeid(Expr *expr)
|
||||
{
|
||||
ASSERT(expr->resolve_status == RESOLVE_DONE);
|
||||
return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_TYPEID;
|
||||
}
|
||||
|
||||
INLINE bool expr_is_const_member(Expr *expr)
|
||||
{
|
||||
ASSERT(expr->resolve_status == RESOLVE_DONE);
|
||||
|
||||
@@ -471,7 +471,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
|
||||
UNREACHABLE
|
||||
case EXPR_CT_CASTABLE:
|
||||
MACRO_COPY_EXPRID(expr->castable_expr.expr);
|
||||
MACRO_COPY_TYPEID(expr->castable_expr.type);
|
||||
MACRO_COPY_EXPRID(expr->castable_expr.type);
|
||||
return expr;
|
||||
case EXPR_CT_EVAL:
|
||||
case EXPR_CT_IS_CONST:
|
||||
|
||||
@@ -1247,7 +1247,7 @@ static Expr *parse_ct_castable(ParseContext *c, Expr *left)
|
||||
CONSUME_OR_RET(TOKEN_LPAREN, poisoned_expr);
|
||||
ASSIGN_EXPRID_OR_RET(expr->castable_expr.expr, parse_expr(c), poisoned_expr);
|
||||
CONSUME_OR_RET(TOKEN_COMMA, poisoned_expr);
|
||||
ASSIGN_TYPEID_OR_RET(expr->castable_expr.type, parse_type(c), poisoned_expr);
|
||||
ASSIGN_EXPRID_OR_RET(expr->castable_expr.type, parse_expr(c), poisoned_expr);
|
||||
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr);
|
||||
RANGE_EXTEND_PREV(expr);
|
||||
return expr;
|
||||
|
||||
@@ -4322,8 +4322,13 @@ bool sema_analyse_var_decl_ct(SemaContext *context, Decl *decl)
|
||||
// Try to fold any constant into an lvalue.
|
||||
if (!sema_analyse_expr_value(context, init)) goto FAIL;
|
||||
|
||||
if (init->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
Type *type = init->type_expr->type;
|
||||
expr_rewrite_const_typeid(init, type);
|
||||
}
|
||||
// If this isn't a type, it's an error.
|
||||
if (init->expr_kind != EXPR_TYPEINFO)
|
||||
if (!expr_is_const_typeid(init))
|
||||
{
|
||||
SEMA_ERROR(decl->var.init_expr, "Expected a type assigned to %s.", decl->name);
|
||||
goto FAIL;
|
||||
|
||||
@@ -1364,7 +1364,13 @@ static bool sema_analyse_parameter(SemaContext *context, Expr *arg, Decl *param,
|
||||
case VARDECL_PARAM_CT_TYPE:
|
||||
// $Foo
|
||||
if (!sema_analyse_expr_value(context, arg)) return false;
|
||||
if (arg->expr_kind != EXPR_TYPEINFO)
|
||||
|
||||
if (arg->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
assert(arg->type_expr->resolve_status == RESOLVE_DONE);
|
||||
expr_rewrite_const_typeid(arg, arg->type_expr->type);
|
||||
}
|
||||
if (!sema_cast_const(arg) || !expr_is_const_typeid(arg))
|
||||
{
|
||||
RETURN_SEMA_FUNC_ERROR(definition, arg, "A type, like 'int' or 'double' was expected for the parameter '%s'.", param->name);
|
||||
}
|
||||
@@ -6158,7 +6164,11 @@ static bool sema_expr_analyse_ct_type_identifier_assign(SemaContext *context, Ex
|
||||
}
|
||||
|
||||
if (!sema_analyse_expr_value(context, right)) return false;
|
||||
if (right->expr_kind != EXPR_TYPEINFO) RETURN_SEMA_ERROR(right, "Expected a type here.");
|
||||
if (right->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
expr_rewrite_const_typeid(right, right->type_expr->type);
|
||||
}
|
||||
if (!expr_is_const_typeid(right)) RETURN_SEMA_ERROR(right, "Expected a type or constant typeid here.");
|
||||
|
||||
Decl *decl = sema_find_symbol(context, info->unresolved.name);
|
||||
if (!decl) RETURN_SEMA_ERROR(info, "'%s' is not defined in this scope yet.", info->unresolved.name);
|
||||
@@ -9313,8 +9323,8 @@ INLINE bool lambda_parameter_match(Decl **ct_lambda_params, Decl *candidate)
|
||||
{
|
||||
case VARDECL_LOCAL_CT_TYPE:
|
||||
case VARDECL_PARAM_CT_TYPE:
|
||||
if (ct_param->var.init_expr->type_expr->type->canonical !=
|
||||
param->var.init_expr->type_expr->type->canonical)
|
||||
if (ct_param->var.init_expr->const_expr.typeid->canonical !=
|
||||
param->var.init_expr->const_expr.typeid->canonical)
|
||||
return false;
|
||||
break;
|
||||
case VARDECL_LOCAL_CT:
|
||||
@@ -9931,11 +9941,39 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty
|
||||
static inline bool sema_expr_analyse_castable(SemaContext *context, Expr *expr)
|
||||
{
|
||||
ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_RUNNING);
|
||||
TypeInfo *type_info = type_infoptr(expr->castable_expr.type);
|
||||
Expr *type_expr = exprptr(expr->castable_expr.type);
|
||||
bool in_no_eval = context->call_env.in_no_eval;
|
||||
context->call_env.in_no_eval = true;
|
||||
Type *type;
|
||||
if (type_expr->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
TypeInfo *type_info = type_expr->type_expr;
|
||||
if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER)) goto FAILED;
|
||||
Type *type = type_info->type;
|
||||
type = type_info->type;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_expr_value(context, type_expr)) goto FAILED;
|
||||
switch (type_expr->expr_kind)
|
||||
{
|
||||
case EXPR_TYPEINFO:
|
||||
ASSERT_SPAN(expr, type_expr->type_expr->resolve_status == RESOLVE_DONE);
|
||||
type = type_expr->type_expr->type;
|
||||
break;
|
||||
case EXPR_CONST:
|
||||
if (type_expr->const_expr.const_kind == CONST_TYPEID)
|
||||
{
|
||||
type = type_expr->const_expr.typeid;
|
||||
break;
|
||||
}
|
||||
type = NULL;
|
||||
break;
|
||||
default:
|
||||
type = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!type) RETURN_SEMA_ERROR(type_expr, "Expected a type or constant typeid here.");
|
||||
Expr *inner = exprptr(expr->castable_expr.expr);
|
||||
if (!sema_analyse_inferred_expr(context, type, inner)) goto FAILED;
|
||||
bool ok = may_cast(context, inner, type, !expr->castable_expr.is_assign, true);
|
||||
|
||||
@@ -255,14 +255,14 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
|
||||
if (decl->var.kind == VARDECL_PARAM_CT_TYPE || decl->var.kind == VARDECL_LOCAL_CT_TYPE)
|
||||
{
|
||||
decl->var.is_read = true;
|
||||
if (!decl->var.init_expr)
|
||||
Expr *init_expr = decl->var.init_expr;
|
||||
if (!init_expr)
|
||||
{
|
||||
SEMA_ERROR(type_info, "You need to assign a type to '%s' before using it.", decl->name);
|
||||
return false;
|
||||
RETURN_SEMA_ERROR(type_info, "You need to assign a type to '%s' before using it.", decl->name);
|
||||
}
|
||||
ASSERT(decl->var.init_expr->expr_kind == EXPR_TYPEINFO);
|
||||
ASSERT(decl->var.init_expr->resolve_status == RESOLVE_DONE);
|
||||
*type_info = *decl->var.init_expr->type_expr;
|
||||
ASSERT_SPAN(init_expr, expr_is_const_typeid(init_expr));
|
||||
ASSERT_SPAN(init_expr, init_expr->resolve_status == RESOLVE_DONE);
|
||||
type_info->type = init_expr->const_expr.typeid;
|
||||
return true;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
|
||||
@@ -4,7 +4,7 @@ fn void Bar.xyz(&self) @tag("footag", 123) {}
|
||||
macro void Foo.tags(&self, other)
|
||||
{
|
||||
// inner to remove pointer
|
||||
var $Type = $typefrom($typeof(other).inner);
|
||||
var $Type = $typeof(other).inner;
|
||||
var $methodcount = $Type.methodsof.len;
|
||||
$for var $i = 0; $i < $methodcount; $i++:
|
||||
var $MethodType1 = $typeof($Type.$eval($Type.methodsof[$i]));
|
||||
|
||||
Reference in New Issue
Block a user