mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
- Make foo.$abc implicitly mean foo.eval("$abc").
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
- Module-based generics using {} is deprecated.
|
||||
- Create optional with `~` instead of `?`. `return io::EOF?;` becomes `return io::EOF~`.
|
||||
- Deprecated use of `?` to create optional.
|
||||
- Make `foo.$abc` implicitly mean `foo.eval("$abc")`.
|
||||
|
||||
### Fixes
|
||||
- Regression with npot vector in struct triggering an assert #2219.
|
||||
|
||||
@@ -1756,6 +1756,13 @@ typedef enum
|
||||
PARAM_RW_EXPAND_ELEMENTS,
|
||||
} ParamRewrite;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CT_EVAL_TYPE,
|
||||
CT_EVAL_IDENTIFIER,
|
||||
CT_EVAL_IMPLICIT_IDENTIFIER
|
||||
} CtEvalKind;
|
||||
|
||||
// -- Arch helper macros
|
||||
#define ARCH_UNSUPPORTED ARCH_TYPE_AARCH64_32: case ARCH_TYPE_BPFEL: case ARCH_TYPE_BPFEB: case ARCH_TYPE_SPARCEL: \
|
||||
case ARCH_TYPE_LE64: case ARCH_TYPE_AMDIL: case ARCH_TYPE_AMDIL64: case ARCH_TYPE_HSAIL: case ARCH_TYPE_HSAIL64: \
|
||||
|
||||
@@ -400,13 +400,22 @@ NO_PATH:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Expr *sema_ct_eval_expr(SemaContext *context, bool is_type_eval, Expr *inner, bool report_missing)
|
||||
Expr *sema_ct_eval_expr(SemaContext *context, CtEvalKind eval_kind, Expr *inner, bool report_missing)
|
||||
{
|
||||
if (!sema_analyse_ct_expr(context, inner)) return NULL;
|
||||
if (!expr_is_const_string(inner))
|
||||
{
|
||||
SEMA_ERROR(inner, "'%s' expects a constant string as the argument.", is_type_eval ? "$evaltype" : "$eval");
|
||||
return poisoned_expr;
|
||||
switch (eval_kind)
|
||||
{
|
||||
case CT_EVAL_TYPE:
|
||||
RETURN_VAL_SEMA_ERROR(poisoned_expr, inner, "'$evaltype' expects a constant string as the argument.");
|
||||
case CT_EVAL_IDENTIFIER:
|
||||
RETURN_VAL_SEMA_ERROR(poisoned_expr, inner, "'$eval' expects a constant string as the argument.");
|
||||
case CT_EVAL_IMPLICIT_IDENTIFIER:
|
||||
RETURN_VAL_SEMA_ERROR(poisoned_expr, inner, "A constant string was expected as the argument.");
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
return sema_resolve_string_ident(context, inner, report_missing);
|
||||
}
|
||||
@@ -4847,7 +4856,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr)
|
||||
* 3. .@foo -> It is a macro.
|
||||
* 4. .#bar -> It is an identifier to resolve as a member or a function
|
||||
* 5. .$eval(...) -> resolve the eval and retry.
|
||||
* 6. .$ident -> It is a child to resolve as CT param
|
||||
* 6. .$ident -> resolve as `$eval($ident)`
|
||||
* 7. .$Type -> It is a child to resolve as CT type param
|
||||
*/
|
||||
Expr *sema_expr_resolve_access_child(SemaContext *context, Expr *child, bool *missing)
|
||||
@@ -4876,8 +4885,17 @@ RETRY:
|
||||
if (child->unresolved_ident_expr.path) break;
|
||||
return child;
|
||||
case EXPR_CT_IDENT:
|
||||
if (child->resolve_status == RESOLVE_DONE) goto ALREADY_RESOLVED;
|
||||
return child;
|
||||
{
|
||||
Expr *result = sema_ct_eval_expr(context, CT_EVAL_IMPLICIT_IDENTIFIER, child, missing == NULL);
|
||||
if (!expr_ok(result)) return NULL;
|
||||
if (!result)
|
||||
{
|
||||
if (missing) *missing = true;
|
||||
return NULL;
|
||||
}
|
||||
expr_replace(child, result);
|
||||
goto RETRY;
|
||||
}
|
||||
case EXPR_TYPEINFO:
|
||||
if (child->type_expr->kind == TYPE_INFO_CT_IDENTIFIER) return child;
|
||||
break;
|
||||
@@ -4885,7 +4903,7 @@ RETRY:
|
||||
{
|
||||
ASSERT_SPAN(child, child->resolve_status != RESOLVE_DONE);
|
||||
// Only report missing if missing var is NULL
|
||||
Expr *result = sema_ct_eval_expr(context, false, child->inner_expr, missing == NULL);
|
||||
Expr *result = sema_ct_eval_expr(context, CT_EVAL_IDENTIFIER, child->inner_expr, missing == NULL);
|
||||
if (!expr_ok(result)) return NULL;
|
||||
if (!result)
|
||||
{
|
||||
@@ -10529,7 +10547,7 @@ RETRY:
|
||||
case TYPE_INFO_EVALTYPE:
|
||||
{
|
||||
Expr *expr = type_info->unresolved_type_expr;
|
||||
expr = sema_ct_eval_expr(context, true, expr, false);
|
||||
expr = sema_ct_eval_expr(context, CT_EVAL_TYPE, expr, false);
|
||||
if (!expr_ok(expr)) return poisoned_type;
|
||||
if (!expr) return NULL;
|
||||
if (expr->expr_kind != EXPR_TYPEINFO)
|
||||
@@ -11088,7 +11106,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
}
|
||||
case EXPR_CT_EVAL:
|
||||
{
|
||||
Expr *eval = sema_ct_eval_expr(active_context, "$eval", main_expr->inner_expr, false);
|
||||
Expr *eval = sema_ct_eval_expr(active_context, CT_EVAL_IDENTIFIER, main_expr->inner_expr, false);
|
||||
if (!expr_ok(eval)) return false;
|
||||
if (eval)
|
||||
{
|
||||
@@ -11499,7 +11517,7 @@ static inline bool sema_expr_analyse_ct_stringify(SemaContext *context, Expr *ex
|
||||
|
||||
static inline bool sema_expr_resolve_ct_eval(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *result = sema_ct_eval_expr(context, false, expr->inner_expr, true);
|
||||
Expr *result = sema_ct_eval_expr(context, CT_EVAL_IDENTIFIER, expr->inner_expr, true);
|
||||
if (!result) return false;
|
||||
if (result->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
|
||||
@@ -108,7 +108,8 @@ void sema_add_methods_to_decl_stack(SemaContext *context, Decl *decl);
|
||||
|
||||
bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *struct_var, Decl *decl, bool call_var_optional, bool *no_match_ref);
|
||||
Expr *sema_expr_analyse_ct_arg_index(SemaContext *context, Expr *index_expr, unsigned *index_ref);
|
||||
Expr *sema_ct_eval_expr(SemaContext *context, bool is_type_eval, Expr *inner, bool report_missing);
|
||||
|
||||
Expr *sema_ct_eval_expr(SemaContext *context, CtEvalKind eval_kind, Expr *inner, bool report_missing);
|
||||
Expr *sema_resolve_string_ident(SemaContext *context, Expr *inner, bool report_missing);
|
||||
bool sema_analyse_asm(SemaContext *context, AsmInlineBlock *block, Ast *asm_stmt);
|
||||
bool sema_expr_analyse_sprintf(SemaContext *context, Expr *expr, Expr *format_string, Expr **args, unsigned num_args);
|
||||
|
||||
@@ -300,7 +300,7 @@ INLINE bool sema_resolve_evaltype(SemaContext *context, TypeInfo *type_info, Res
|
||||
{
|
||||
SEMA_DEPRECATED(type_info, "$evaltype is deprecated, use $typefrom instead.");
|
||||
Expr *expr = type_info->unresolved_type_expr;
|
||||
Expr *inner = sema_ct_eval_expr(context, true, expr, true);
|
||||
Expr *inner = sema_ct_eval_expr(context, CT_EVAL_TYPE, expr, true);
|
||||
if (!inner || !expr_ok(inner)) return type_info_poison(type_info);
|
||||
if (inner->expr_kind != EXPR_TYPEINFO)
|
||||
{
|
||||
|
||||
23
test/test_suite/compile_time/implicit_eval_access.c3t
Normal file
23
test/test_suite/compile_time/implicit_eval_access.c3t
Normal file
@@ -0,0 +1,23 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
struct Bar
|
||||
{
|
||||
struct { union { struct { char z1; } } }
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
var $x = "alignof";
|
||||
int a = Bar.z1.offsetof;
|
||||
int b = Bar.z1.$x;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
entry:
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
store i32 0, ptr %a, align 4
|
||||
store i32 1, ptr %b, align 4
|
||||
ret void
|
||||
}
|
||||
Reference in New Issue
Block a user