Refactoring: make CT_IDENT and unresolved expression.

This commit is contained in:
Christoffer Lerno
2026-02-12 16:38:18 +01:00
parent acc4a900f5
commit 3f279b2f1c
5 changed files with 66 additions and 44 deletions

View File

@@ -1027,7 +1027,6 @@ typedef struct
const char *identifier;
bool is_ref : 1;
bool is_rvalue : 1;
Decl *decl;
} ExprIdentifierRaw;
typedef struct
@@ -4600,6 +4599,34 @@ 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_ct_ident(Expr *expr)
{
ASSERT(expr->resolve_status == RESOLVE_DONE);
if (expr->expr_kind != EXPR_IDENTIFIER) return false;
Decl *decl = expr->ident_expr;
if (decl->decl_kind != DECL_VAR) return false;
switch (decl->var.kind)
{
case VARDECL_CONST:
case VARDECL_GLOBAL:
case VARDECL_LOCAL:
case VARDECL_PARAM:
case VARDECL_MEMBER:
case VARDECL_BITMEMBER:
case VARDECL_PARAM_EXPR:
case VARDECL_UNWRAPPED:
case VARDECL_ERASE:
case VARDECL_REWRAPPED:
return false;
case VARDECL_PARAM_CT:
case VARDECL_PARAM_CT_TYPE:
case VARDECL_LOCAL_CT:
case VARDECL_LOCAL_CT_TYPE:
return true;
}
UNREACHABLE;
}
INLINE bool expr_is_const_typeid(Expr *expr)
{
ASSERT(expr->resolve_status == RESOLVE_DONE);

View File

@@ -1791,7 +1791,7 @@ typedef enum
#define NON_RUNTIME_EXPR EXPR_POISONED: \
case EXPR_CT_DEFINED: \
case EXPR_CT_ASSIGNABLE: case EXPR_CT_IS_CONST: \
case EXPR_CT_ARG: case EXPR_TYPEINFO: case EXPR_CT_IDENT: case EXPR_HASH_IDENT: \
case EXPR_CT_ARG: case EXPR_TYPEINFO: case EXPR_HASH_IDENT: \
case EXPR_COMPILER_CONST: case EXPR_CT_CALL: \
case EXPR_SPLAT: case EXPR_STRINGIFY: case EXPR_TYPECALL: \
case EXPR_CT_EVAL: case EXPR_MAYBE_DEREF
@@ -1842,5 +1842,5 @@ case TYPE_U8: case TYPE_U16: case TYPE_U32: case TYPE_U64: case TYPE_U128
#define UNRESOLVED_EXPRS EXPR_TRY_UNRESOLVED: case EXPR_ACCESS_UNRESOLVED: \
case EXPR_CATCH_UNRESOLVED: case EXPR_UNRESOLVED_IDENTIFIER: case EXPR_CAST: \
case EXPR_TYPEID: case EXPR_EMBED: case EXPR_VASPLAT: case EXPR_OTHER_CONTEXT: \
case EXPR_IOTA_DECL: case EXPR_LENGTHOF: \
case EXPR_IOTA_DECL: case EXPR_LENGTHOF: case EXPR_CT_IDENT: \
case EXPR_GENERIC_IDENT: case EXPR_COMPOUND_LITERAL: case EXPR_MACRO_BODY: case EXPR_CT_SUBSCRIPT

View File

@@ -200,8 +200,6 @@ bool expr_may_addr(Expr *expr)
decl = decl_raw(decl);
switch (decl->var.kind)
{
case VARDECL_LOCAL_CT:
case VARDECL_LOCAL_CT_TYPE:
case VARDECL_LOCAL:
case VARDECL_GLOBAL:
case VARDECL_PARAM:
@@ -211,6 +209,8 @@ bool expr_may_addr(Expr *expr)
case VARDECL_BITMEMBER:
case VARDECL_PARAM_CT:
case VARDECL_PARAM_CT_TYPE:
case VARDECL_LOCAL_CT:
case VARDECL_LOCAL_CT_TYPE:
case VARDECL_PARAM_EXPR:
return false;
case VARDECL_UNWRAPPED:
@@ -485,7 +485,6 @@ bool expr_is_runtime_const(Expr *expr)
case EXPR_CT_CALL:
case EXPR_TYPEINFO:
case EXPR_HASH_IDENT:
case EXPR_CT_IDENT:
case EXPR_POISONED:
case EXPR_CT_ARG:
case EXPR_ASM:
@@ -846,7 +845,6 @@ bool expr_is_pure(Expr *expr)
case EXPR_CT_DEFINED:
case EXPR_CT_IS_CONST:
case EXPR_CT_EVAL:
case EXPR_CT_IDENT:
case EXPR_IDENTIFIER:
case EXPR_LAMBDA:
case EXPR_NOP:

View File

@@ -645,8 +645,6 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
case EXPR_LAMBDA:
if (failed_ref) goto FAILED_REF;
RETURN_SEMA_ERROR(expr, "This expression is a value and cannot be assigned to.");
case EXPR_CT_IDENT:
return true;
case EXPR_EXT_TRUNC:
case EXPR_INT_TO_BOOL:
case EXPR_DISCARD:
@@ -799,7 +797,6 @@ static bool expr_may_ref(Expr *expr)
{
case EXPR_SWIZZLE:
case EXPR_LAMBDA:
case EXPR_CT_IDENT:
case EXPR_DEFAULT_ARG:
case EXPR_TYPECALL:
case EXPR_MEMBER_GET:
@@ -835,18 +832,18 @@ static bool expr_may_ref(Expr *expr)
decl = decl_raw(decl);
switch (decl->var.kind)
{
case VARDECL_LOCAL_CT:
case VARDECL_LOCAL_CT_TYPE:
case VARDECL_LOCAL:
case VARDECL_GLOBAL:
case VARDECL_PARAM:
case VARDECL_PARAM_CT:
case VARDECL_PARAM_CT_TYPE:
return true;
case VARDECL_CONST:
case VARDECL_PARAM_EXPR:
case VARDECL_MEMBER:
case VARDECL_BITMEMBER:
case VARDECL_LOCAL_CT:
case VARDECL_LOCAL_CT_TYPE:
case VARDECL_PARAM_CT:
case VARDECL_PARAM_CT_TYPE:
return false;
case VARDECL_UNWRAPPED:
case VARDECL_ERASE:
@@ -1035,15 +1032,14 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr)
}
return true;
case VARDECL_PARAM_EXPR:
case VARDECL_ERASE:
case VARDECL_REWRAPPED:
UNREACHABLE
case VARDECL_PARAM_CT_TYPE:
case VARDECL_PARAM_CT:
case VARDECL_LOCAL_CT:
case VARDECL_LOCAL_CT_TYPE:
case VARDECL_ERASE:
case VARDECL_REWRAPPED:
// Impossible to reach this, they are already unfolded
UNREACHABLE
return sema_cast_ct_ident_rvalue(context, expr);
case VARDECL_LOCAL:
if (decl->var.copy_const && decl->var.init_expr && expr_is_const(decl->var.init_expr))
{
@@ -1393,9 +1389,9 @@ static inline bool sema_expr_resolve_ct_identifier(SemaContext *context, Expr *e
ASSERT_SPAN(expr, decl->resolve_status == RESOLVE_DONE);
decl->var.is_read = true;
expr->ct_ident_expr.decl = decl;
expr->type = decl->type;
expr->ident_expr = decl;
expr->expr_kind = EXPR_IDENTIFIER;
return true;
}
@@ -4095,7 +4091,7 @@ static inline bool sema_expr_resolve_subscript_index(SemaContext *context, Expr
}
ArrayIndex size;
bool check_len = !context->call_env.in_no_eval || current_type == type_untypedlist;
Expr *len_expr = current_expr->expr_kind == EXPR_CT_IDENT ? current_expr->ct_ident_expr.decl->var.init_expr : current_expr;
Expr *len_expr = expr_is_ct_ident(current_expr) ? current_expr->ident_expr->var.init_expr : current_expr;
if (sema_cast_const(index) && expr_is_const_int(index) && (size = sema_len_from_expr(len_expr)) >= 0)
{
// 4c. And that it's in range.
@@ -4219,7 +4215,7 @@ DEFAULT:
}
// 4. If we are indexing into a complist
if (current_expr->expr_kind == EXPR_CT_IDENT)
if (expr_is_ct_ident(current_expr))
{
if (index_value == -1)
{
@@ -4227,7 +4223,7 @@ DEFAULT:
RETURN_SEMA_ERROR(index, "Assigning to a compile time constant requires a constant index.");
}
expr->expr_kind = EXPR_CT_SUBSCRIPT;
expr->ct_subscript_expr = (ExprCtSubscript) { .var = current_expr->ct_ident_expr.decl, .index = (ArrayIndex)index_value };
expr->ct_subscript_expr = (ExprCtSubscript) { .var = current_expr->ident_expr, .index = (ArrayIndex)index_value };
expr->type = NULL;
return true;
}
@@ -4327,7 +4323,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr,
RETURN_SEMA_ERROR(subscripted, "You need to use && to take the address of a temporary.");
}
// 4a. This may either be an initializer list or a CT value
while (current_expr->expr_kind == EXPR_CT_IDENT) current_expr = current_expr->ct_ident_expr.decl->var.init_expr;
while (expr_is_ct_ident(current_expr)) current_expr = current_expr->ident_expr->var.init_expr;
// 4b. Now we need to check that we actually have a valid type.
if (index_value < 0)
@@ -7085,7 +7081,7 @@ static bool sema_expr_analyse_ct_identifier_assign(SemaContext *context, Expr *e
if (failed_ref) return *failed_ref = true, false;
RETURN_SEMA_ERROR(right, "You can only assign constants to a compile time variable.");
}
Decl *ident = left->ct_ident_expr.decl;
Decl *ident = left->ident_expr;
ident->var.init_expr = right;
expr_replace(expr, right);
@@ -7194,7 +7190,8 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef
if (!sema_analyse_expr_lvalue(context, left, failed_ref)) return false;
switch (left->expr_kind)
{
case EXPR_CT_IDENT:
case EXPR_IDENTIFIER:
if (!expr_is_ct_ident(left)) break;
// $foo = ...
return sema_expr_analyse_ct_identifier_assign(context, expr, left, right, failed_ref);
case EXPR_CT_SUBSCRIPT:
@@ -7258,9 +7255,9 @@ static bool sema_expr_analyse_assign(SemaContext *context, Expr *expr, Expr *lef
*/
static bool sema_binary_analyse_ct_op_assign(SemaContext *context, Expr *expr, Expr *left)
{
ASSERT_SPAN(left, left->expr_kind == EXPR_CT_IDENT);
ASSERT_SPAN(left, expr_is_ct_ident(left));
Decl *left_var = left->ct_ident_expr.decl;
Decl *left_var = left->ident_expr;
if (!sema_cast_ct_ident_rvalue(context, left)) return false;
expr->binary_expr.operator = binaryop_assign_base_op(expr->binary_expr.operator);
@@ -7508,7 +7505,8 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr *
switch (left->expr_kind)
{
case EXPR_CT_IDENT:
case EXPR_IDENTIFIER:
if (!expr_is_ct_ident(left)) break;
return sema_binary_analyse_ct_op_assign(context, expr, left);
case EXPR_CT_SUBSCRIPT:
return sema_binary_analyse_ct_subscript_op_assign(context, expr, left);
@@ -9037,8 +9035,7 @@ static inline const char *sema_addr_may_take_of_var(Expr *expr, Decl *decl)
case VARDECL_PARAM_CT_TYPE:
case VARDECL_LOCAL_CT_TYPE:
case VARDECL_LOCAL_CT:
// May not be reached due to EXPR_CT_IDENT being handled elsewhere.
UNREACHABLE
return "It's not possible to take the address of a compile time value.";
case VARDECL_MEMBER:
case VARDECL_BITMEMBER:
case VARDECL_UNWRAPPED:
@@ -9086,8 +9083,6 @@ static const char *sema_addr_check_may_take(Expr *inner)
{
case UNRESOLVED_EXPRS:
UNREACHABLE
case EXPR_CT_IDENT:
return "It's not possible to take the address of a compile time value.";
case EXPR_IDENTIFIER:
return sema_addr_may_take_of_ident(inner);
case EXPR_UNARY:
@@ -9159,17 +9154,21 @@ RETRY:;
case EXPR_ACCESS_UNRESOLVED:
inner->access_unresolved_expr.is_ref = true;
break;
case EXPR_CT_IDENT:
RETURN_SEMA_ERROR(expr, "It's not possible to take the address of a compile time value.");
default:
break;
}
RESOLVED:
if (inner->expr_kind == EXPR_CT_IDENT)
if (!sema_analyse_expr(context, inner)) return false;
RESOLVED:
if (expr_is_ct_ident(inner))
{
RETURN_SEMA_ERROR(expr, "It's not possible to take the address of a compile time value.");
}
if (!sema_analyse_expr(context, inner)) return false;
// 2. Take the address.
const char *error = sema_addr_check_may_take(inner);
if (error)
@@ -9439,9 +9438,9 @@ static inline bool sema_expr_analyse_ct_subscript_incdec(SemaContext *context, E
static inline bool sema_expr_analyse_ct_incdec(SemaContext *context, Expr *expr, Expr *inner)
{
ASSERT_SPAN(expr, inner->expr_kind == EXPR_CT_IDENT);
ASSERT_SPAN(expr, expr_is_ct_ident(inner));
Decl *var = inner->ct_ident_expr.decl;
Decl *var = inner->ident_expr;
Expr *start_value = var->var.init_expr;
if (!expr_is_const_int(start_value))
{
@@ -9565,7 +9564,7 @@ static inline bool sema_expr_analyse_incdec(SemaContext *context, Expr *expr)
if (!sema_expr_check_assign(context, inner, NULL)) return false;
// 3. This might be a $foo, if to handle it.
if (inner->expr_kind == EXPR_CT_IDENT)
if (expr_is_ct_ident(inner))
{
return sema_expr_analyse_ct_incdec(context, expr, inner);
}
@@ -12079,7 +12078,7 @@ NO_MATCH_REF:
static inline bool sema_cast_ct_ident_rvalue(SemaContext *context, Expr *expr)
{
Decl *decl = expr->ct_ident_expr.decl;
Decl *decl = expr->ident_expr;
Expr *copy = copy_expr_single(decl->var.init_expr);
if (!copy)
{
@@ -12137,8 +12136,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat
}
UNREACHABLE
case EXPR_CT_IDENT:
if (mutate && !sema_cast_ct_ident_rvalue(context, expr)) return false;
break;
UNREACHABLE
case EXPR_IDENTIFIER:
if (mutate && !sema_cast_ident_rvalue(context, expr)) return false;
break;

View File

@@ -798,7 +798,6 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
case EXPR_CT_IS_CONST:
case EXPR_CT_DEFINED:
case EXPR_CT_EVAL:
case EXPR_CT_IDENT:
case EXPR_NAMED_ARGUMENT:
UNREACHABLE
case EXPR_BINARY: