Fixes to $defined implementation.

This commit is contained in:
Christoffer Lerno
2023-07-23 23:55:38 +02:00
parent de9bb1d0cc
commit 9e477056ed
10 changed files with 105 additions and 52 deletions

View File

@@ -313,7 +313,7 @@ fn usz! List.index_of(&self, Type type) @if(ELEMENT_IS_EQUATABLE)
{
foreach (i, v : self)
{
if (v == type) return i;
if (equals(v, type)) return i;
}
return SearchResult.MISSING?;
}
@@ -322,7 +322,7 @@ fn usz! List.rindex_of(&self, Type type) @if(ELEMENT_IS_EQUATABLE)
{
foreach_r (i, v : self)
{
if (v == type) return i;
if (equals(v, type)) return i;
}
return SearchResult.MISSING?;
}
@@ -332,7 +332,7 @@ fn bool List.equals(&self, List other_list) @if(ELEMENT_IS_EQUATABLE)
if (self.size != other_list.size) return false;
foreach (i, v : self)
{
if (v != other_list.entries[i]) return false;
if (!equals(v, other_list.entries[i])) return false;
}
return true;
}
@@ -348,7 +348,7 @@ fn bool List.contains(&self, Type value) @if(ELEMENT_IS_EQUATABLE)
{
foreach (i, v : self)
{
if (v == value) return true;
if (equals(v, value)) return true;
}
return false;
}
@@ -364,7 +364,7 @@ fn usz List.remove(&self, Type value) @if(ELEMENT_IS_EQUATABLE)
usz size = self.size;
for (usz i = size; i > 0; i--)
{
if (self.entries[i - 1] != value) continue;
if (!equals(self.entries[i - 1], value)) continue;
for (usz j = i; j < size; j++)
{
self.entries[j - 1] = self.entries[j];

View File

@@ -426,6 +426,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
case EXPR_STRINGIFY:
case EXPR_CT_EVAL:
case EXPR_CT_CHECKS:
case EXPR_CT_DEFINED:
MACRO_COPY_EXPR(expr->inner_expr);
return expr;
case EXPR_TYPEID_INFO:

View File

@@ -160,7 +160,7 @@ typedef enum
case DECL_FINALIZE: case DECL_CT_ECHO: case DECL_CT_INCLUDE: case DECL_GLOBALS
#define NON_RUNTIME_EXPR EXPR_DESIGNATOR: case EXPR_POISONED: \
case EXPR_CT_CHECKS: \
case EXPR_CT_CHECKS: case EXPR_CT_DEFINED: \
case EXPR_CT_ARG: case EXPR_TYPEINFO: case EXPR_CT_IDENT: case EXPR_HASH_IDENT: \
case EXPR_COMPILER_CONST: case EXPR_CT_CALL: \
case EXPR_ANYSWITCH: case EXPR_STRINGIFY: case EXPR_CT_EVAL
@@ -220,6 +220,7 @@ typedef enum
EXPR_CT_ARG,
EXPR_CT_CALL,
EXPR_CT_CHECKS,
EXPR_CT_DEFINED,
EXPR_CT_EVAL,
EXPR_CT_IDENT,
EXPR_DECL,

View File

@@ -82,6 +82,7 @@ bool expr_may_addr(Expr *expr)
return true;
case EXPR_TEST_HOOK:
return false;
case NON_RUNTIME_EXPR:
case EXPR_ASM:
case EXPR_BINARY:
case EXPR_BITASSIGN:
@@ -90,36 +91,26 @@ bool expr_may_addr(Expr *expr)
case EXPR_CALL:
case EXPR_CAST:
case EXPR_CATCH_UNWRAP:
case EXPR_COMPILER_CONST:
case EXPR_COMPOUND_LITERAL:
case EXPR_COND:
case EXPR_CONST:
case EXPR_CT_ARG:
case EXPR_CT_CALL:
case EXPR_CT_CHECKS:
case EXPR_CT_EVAL:
case EXPR_CT_IDENT:
case EXPR_DECL:
case EXPR_DESIGNATED_INITIALIZER_LIST:
case EXPR_DESIGNATOR:
case EXPR_EXPRESSION_LIST:
case EXPR_INITIALIZER_LIST:
case EXPR_EXPR_BLOCK:
case EXPR_OPTIONAL:
case EXPR_FORCE_UNWRAP:
case EXPR_HASH_IDENT:
case EXPR_INITIALIZER_LIST:
case EXPR_MACRO_BLOCK:
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_NOP:
case EXPR_OPERATOR_CHARS:
case EXPR_POINTER_OFFSET:
case EXPR_POISONED:
case EXPR_POST_UNARY:
case EXPR_RETHROW:
case EXPR_RETVAL:
case EXPR_SLICE_ASSIGN:
case EXPR_SLICE_COPY:
case EXPR_STRINGIFY:
case EXPR_SUBSCRIPT_ADDR:
case EXPR_SUBSCRIPT_ASSIGN:
case EXPR_TERNARY:
@@ -127,9 +118,7 @@ bool expr_may_addr(Expr *expr)
case EXPR_TRY_UNWRAP_CHAIN:
case EXPR_TYPEID:
case EXPR_TYPEID_INFO:
case EXPR_TYPEINFO:
case EXPR_ANY:
case EXPR_ANYSWITCH:
case EXPR_VASPLAT:
case EXPR_SWIZZLE:
case EXPR_LAMBDA:
@@ -203,6 +192,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case EXPR_OPERATOR_CHARS:
case EXPR_STRINGIFY:
case EXPR_CT_CHECKS:
case EXPR_CT_DEFINED:
case EXPR_LAMBDA:
case EXPR_EMBED:
return true;
@@ -664,6 +654,7 @@ bool expr_is_pure(Expr *expr)
case EXPR_CT_ARG:
case EXPR_OPERATOR_CHARS:
case EXPR_CT_CHECKS:
case EXPR_CT_DEFINED:
case EXPR_LAMBDA:
case EXPR_EMBED:
return true;

View File

@@ -1032,6 +1032,17 @@ static Expr *parse_ct_eval(ParseContext *c, Expr *left)
return expr;
}
static Expr *parse_ct_defined(ParseContext *c, Expr *left)
{
assert(!left && "Unexpected left hand side");
Expr *defined = expr_new(EXPR_CT_DEFINED, c->span);
advance(c);
CONSUME_OR_RET(TOKEN_LPAREN, poisoned_expr);
ASSIGN_EXPR_OR_RET(defined->inner_expr, parse_expr(c), poisoned_expr);
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr);
return defined;
}
/**
* ct_sizeof ::= CT_SIZEOF '(' expr ')'
*
@@ -1093,7 +1104,7 @@ static Expr *parse_ct_embed(ParseContext *c, Expr *left)
}
/**
* ct_call ::= (ALIGNOF | DEFINED | EXTNAMEOF | OFFSETOF | NAMEOF | QNAMEOF) '(' flat_path ')'
* ct_call ::= (ALIGNOF | EXTNAMEOF | OFFSETOF | NAMEOF | QNAMEOF) '(' flat_path ')'
* flat_path ::= expr ('.' primary) | '[' expr ']')*
*/
static Expr *parse_ct_call(ParseContext *c, Expr *left)
@@ -1894,7 +1905,7 @@ ParseRule rules[TOKEN_EOF + 1] = {
[TOKEN_FN] = { parse_lambda, NULL, PREC_NONE },
[TOKEN_CT_SIZEOF] = { parse_ct_sizeof, NULL, PREC_NONE },
[TOKEN_CT_ALIGNOF] = { parse_ct_call, NULL, PREC_NONE },
[TOKEN_CT_DEFINED] = { parse_ct_call, NULL, PREC_NONE },
[TOKEN_CT_DEFINED] = { parse_ct_defined, NULL, PREC_NONE },
[TOKEN_CT_CHECKS] = { parse_ct_checks, NULL, PREC_NONE },
[TOKEN_CT_EMBED] = { parse_ct_embed, NULL, PREC_NONE },
[TOKEN_CT_EVAL] = { parse_ct_eval, NULL, PREC_NONE },

View File

@@ -483,6 +483,7 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr)
case EXPR_CT_ARG:
case EXPR_CT_CALL:
case EXPR_CT_CHECKS:
case EXPR_CT_DEFINED:
case EXPR_CT_EVAL:
case EXPR_DECL:
case EXPR_DESIGNATED_INITIALIZER_LIST:
@@ -594,6 +595,7 @@ static bool expr_may_ref(Expr *expr)
case EXPR_CT_ARG:
case EXPR_CT_CALL:
case EXPR_CT_CHECKS:
case EXPR_CT_DEFINED:
case EXPR_CT_EVAL:
case EXPR_DECL:
case EXPR_DESIGNATED_INITIALIZER_LIST:
@@ -6788,7 +6790,7 @@ RETRY:
case TYPE_INFO_POISON:
return poisoned_type;
case TYPE_INFO_GENERIC:
TODO
return poisoned_type;
case TYPE_INFO_VECTOR:
{
ArraySize size;
@@ -6820,6 +6822,7 @@ RETRY:
Decl *decl = sema_find_path_symbol(context, type_info->unresolved.name, type_info->unresolved.path);
if (!decl) return NULL;
if (!decl_ok(decl)) return poisoned_type;
if (type_info->kind == TYPE_INFO_CT_IDENTIFIER) return decl->var.init_expr->type_expr->type->canonical;
return decl->type->canonical;
}
case TYPE_INFO_VATYPE:
@@ -7224,9 +7227,15 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
{
if (expr->resolve_status == RESOLVE_DONE) return expr_ok(expr);
Expr *main_var = expr->ct_call_expr.main_var;
Type *type = NULL;
Decl *decl = NULL;
Expr *inner = expr->inner_expr;
Expr *main_var = inner;
while (main_var->expr_kind == EXPR_ACCESS)
{
main_var = main_var->access_expr.parent;
}
Decl *decl;
RETRY:
switch (main_var->expr_kind)
{
@@ -7237,51 +7246,46 @@ RETRY:
if (!decl_ok(decl)) return false;
// 2b. If it's missing, goto not defined
if (!decl) goto NOT_DEFINED;
type = decl->type;
break;
case EXPR_COMPILER_CONST:
if (!sema_expr_analyse_compiler_const(context, main_var, false)) goto NOT_DEFINED;
break;
case EXPR_TYPEINFO:
{
type = sema_expr_check_type_exists(context, main_var->type_expr);
Type *type = sema_expr_check_type_exists(context, main_var->type_expr);
if (!type) goto NOT_DEFINED;
if (!type_ok(type)) return false;
main_var->type_expr = type_info_new_base(type, main_var->span);
break;
}
case EXPR_BUILTIN:
if (!sema_expr_analyse_builtin(context, main_var, false)) goto NOT_DEFINED;
break;
case EXPR_CT_EVAL:
main_var = sema_ct_eval_expr(context, "$eval", main_var->inner_expr, false);
if (!main_var) goto NOT_DEFINED;
{
Expr *eval = sema_ct_eval_expr(context, "$eval", main_var->inner_expr, false);
if (!eval) goto NOT_DEFINED;
expr_replace(main_var, eval);
goto RETRY;
}
default:
SEMA_ERROR(main_var, "Expected an identifier here.");
return false;
}
FOREACH_BEGIN_IDX(i, DesignatorElement *element, expr->ct_call_expr.flat_path)
Decl *member = NULL;
ArraySize index;
Type *ret_type;
bool missing = false;
if (!sema_expr_analyse_decl_element(context,
element,
type,
&member,
&index,
&ret_type,
i,
i == 0 ? main_var->span : expr->span,
&missing))
if (main_var != inner)
{
if (missing) goto NOT_DEFINED;
return false;
bool suppress_error = global_context.suppress_errors;
global_context.suppress_errors = true;
CallEnvKind eval_kind = context->call_env.kind;
context->call_env.kind = CALL_ENV_CHECKS;
bool success;
SCOPE_START_WITH_FLAGS(SCOPE_CHECKS);
success = sema_analyse_expr_lvalue(context, inner);
SCOPE_END;
context->call_env.kind = eval_kind;
global_context.suppress_errors = suppress_error;
if (!success) goto NOT_DEFINED;
}
type = ret_type;
FOREACH_END();
expr_rewrite_const_bool(expr, type_bool, true);
return true;
@@ -7588,6 +7592,8 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr)
return sema_expr_analyse_generic_ident(context, expr);
case EXPR_LAMBDA:
return sema_expr_analyse_lambda(context, NULL, expr);
case EXPR_CT_DEFINED:
return sema_expr_analyse_ct_defined(context, expr);
case EXPR_CT_CHECKS:
return sema_expr_analyse_ct_checks(context, expr);
case EXPR_CT_ARG:

View File

@@ -253,6 +253,7 @@ RETRY:
case EXPR_CT_ARG:
case EXPR_CT_CALL:
case EXPR_CT_CHECKS:
case EXPR_CT_DEFINED:
case EXPR_CT_EVAL:
case EXPR_CT_IDENT:
case EXPR_ANYSWITCH:

View File

@@ -991,6 +991,7 @@ bool type_is_user_defined(Type *type)
case TYPE_UNION:
case TYPE_FAULTTYPE:
case TYPE_DISTINCT:
case TYPE_BITSTRUCT:
return true;
case TYPE_TYPEDEF:
return type->decl != NULL;

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.578"
#define COMPILER_VERSION "0.4.579"

View File

@@ -0,0 +1,41 @@
module testing;
import std::io;
fn void! main()
{
Bits b1;
Bits b2;
bool x = equals(b1, b2);
}
bitstruct Bits : char
{
bool flag;
}
fn bool Bits.equals(a, Bits b)
{
return a.flag == b.flag;
}
/* #expect: testing.ll
define i64 @testing.main() #0 {
entry:
%b1 = alloca i8, align 1
%b2 = alloca i8, align 1
%x = alloca i8, align 1
%a = alloca i8, align 1
%b = alloca i8, align 1
store i8 0, ptr %b1, align 1
store i8 0, ptr %b2, align 1
%0 = load i8, ptr %b1, align 1
store i8 %0, ptr %a, align 1
%1 = load i8, ptr %b2, align 1
store i8 %1, ptr %b, align 1
%2 = load i8, ptr %a, align 1
%3 = load i8, ptr %b, align 1
%4 = call i8 @testing.Bits.equals(i8 zeroext %2, i8 zeroext %3)
store i8 %4, ptr %x, align 1
ret i64 0
}