mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1b1ca4266 |
@@ -128,28 +128,28 @@ macro Type Atomic.clear(&self, AtomicOrdering ordering = SEQ_CONSISTENT) @if(typ
|
||||
return @atomic_exec_no_arg(atomic::flag_clear, data, ordering);
|
||||
}
|
||||
|
||||
macro @atomic_exec(#func, data, value, ordering) @local
|
||||
macro @atomic_exec(@func, data, value, ordering) @local
|
||||
{
|
||||
switch(ordering)
|
||||
{
|
||||
case RELAXED: return #func(data, value, RELAXED);
|
||||
case ACQUIRE: return #func(data, value, ACQUIRE);
|
||||
case RELEASE: return #func(data, value, RELEASE);
|
||||
case ACQUIRE_RELEASE: return #func(data, value, ACQUIRE_RELEASE);
|
||||
case SEQ_CONSISTENT: return #func(data, value, SEQ_CONSISTENT);
|
||||
case RELAXED: return @func(data, value, RELAXED);
|
||||
case ACQUIRE: return @func(data, value, ACQUIRE);
|
||||
case RELEASE: return @func(data, value, RELEASE);
|
||||
case ACQUIRE_RELEASE: return @func(data, value, ACQUIRE_RELEASE);
|
||||
case SEQ_CONSISTENT: return @func(data, value, SEQ_CONSISTENT);
|
||||
default: unreachable("Ordering may not be non-atomic or unordered.");
|
||||
}
|
||||
}
|
||||
|
||||
macro @atomic_exec_no_arg(#func, data, ordering) @local
|
||||
macro @atomic_exec_no_arg(@func, data, ordering) @local
|
||||
{
|
||||
switch(ordering)
|
||||
{
|
||||
case RELAXED: return #func(data, RELAXED);
|
||||
case ACQUIRE: return #func(data, ACQUIRE);
|
||||
case RELEASE: return #func(data, RELEASE);
|
||||
case ACQUIRE_RELEASE: return #func(data, ACQUIRE_RELEASE);
|
||||
case SEQ_CONSISTENT: return #func(data, SEQ_CONSISTENT);
|
||||
case RELAXED: return @func(data, RELAXED);
|
||||
case ACQUIRE: return @func(data, ACQUIRE);
|
||||
case RELEASE: return @func(data, RELEASE);
|
||||
case ACQUIRE_RELEASE: return @func(data, ACQUIRE_RELEASE);
|
||||
case SEQ_CONSISTENT: return @func(data, SEQ_CONSISTENT);
|
||||
default: unreachable("Ordering may not be non-atomic or unordered.");
|
||||
}
|
||||
}
|
||||
@@ -157,9 +157,9 @@ macro @atomic_exec_no_arg(#func, data, ordering) @local
|
||||
module std::atomic;
|
||||
import std::math;
|
||||
|
||||
macro bool @is_native_atomic_value(#value) @private
|
||||
macro bool @is_native_atomic_value(@value) @private
|
||||
{
|
||||
return is_native_atomic_type($typeof(#value));
|
||||
return is_native_atomic_type($typeof(@value));
|
||||
}
|
||||
|
||||
macro bool is_native_atomic_type($Type)
|
||||
|
||||
@@ -405,6 +405,26 @@ bool decl_needs_prefix(Decl *decl)
|
||||
switch (decl->decl_kind)
|
||||
{
|
||||
case DECL_VAR:
|
||||
switch (decl->var.kind)
|
||||
{
|
||||
case VARDECL_CONST:
|
||||
case VARDECL_GLOBAL:
|
||||
case VARDECL_UNWRAPPED:
|
||||
case VARDECL_ERASE:
|
||||
case VARDECL_REWRAPPED:
|
||||
break;
|
||||
case VARDECL_LOCAL:
|
||||
case VARDECL_PARAM:
|
||||
case VARDECL_MEMBER:
|
||||
case VARDECL_BITMEMBER:
|
||||
case VARDECL_PARAM_EXPR:
|
||||
case VARDECL_PARAM_CT:
|
||||
case VARDECL_PARAM_CT_TYPE:
|
||||
case VARDECL_LOCAL_CT:
|
||||
case VARDECL_LOCAL_CT_TYPE:
|
||||
return false;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case DECL_ALIAS:
|
||||
case DECL_FUNC:
|
||||
case DECL_MACRO:
|
||||
|
||||
@@ -948,11 +948,12 @@ typedef struct
|
||||
TypeProperty property;
|
||||
} ExprTypeCall;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Path *path;
|
||||
const char *ident;
|
||||
bool is_const;
|
||||
IdentType ident_type;
|
||||
} ExprUnresolvedIdentifier;
|
||||
|
||||
typedef struct
|
||||
@@ -3733,7 +3734,6 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc)
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
case EXPR_GENERIC_IDENT:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_IDENTIFIER:
|
||||
case EXPR_LAMBDA:
|
||||
case EXPR_LAST_FAULT:
|
||||
|
||||
@@ -432,7 +432,6 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
|
||||
}
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
case EXPR_CT_IDENT:
|
||||
case EXPR_HASH_IDENT:
|
||||
ASSERT(expr->resolve_status != RESOLVE_DONE);
|
||||
return expr;
|
||||
case EXPR_BENCHMARK_HOOK:
|
||||
|
||||
@@ -772,7 +772,6 @@ typedef enum
|
||||
EXPR_FORCE_UNWRAP,
|
||||
EXPR_FLOAT_TO_INT,
|
||||
EXPR_GENERIC_IDENT,
|
||||
EXPR_HASH_IDENT,
|
||||
EXPR_IDENTIFIER,
|
||||
EXPR_INITIALIZER_LIST,
|
||||
EXPR_INT_TO_FLOAT,
|
||||
@@ -831,6 +830,14 @@ typedef enum
|
||||
EXPR_LAST = EXPR_VASPLAT
|
||||
} ExprKind;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IDENT_NORMAL,
|
||||
IDENT_AT,
|
||||
IDENT_CONST,
|
||||
IDENT_HASH
|
||||
} IdentType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FLOAT_ABI_NONE,
|
||||
@@ -1669,7 +1676,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_CT_IDENT: \
|
||||
case EXPR_COMPILER_CONST: case EXPR_CT_CALL: \
|
||||
case EXPR_SPLAT: case EXPR_STRINGIFY: case EXPR_TYPECALL: \
|
||||
case EXPR_CT_EVAL
|
||||
|
||||
@@ -50,7 +50,6 @@ const char *expr_kind_to_string(ExprKind kind)
|
||||
case EXPR_FORCE_UNWRAP: return "force_unwrap";
|
||||
case EXPR_FLOAT_TO_INT: return "float_to_int";
|
||||
case EXPR_GENERIC_IDENT: return "generic_ident";
|
||||
case EXPR_HASH_IDENT: return "hash_ident";
|
||||
case EXPR_IDENTIFIER: return "identifier";
|
||||
case EXPR_UNRESOLVED_IDENTIFIER: return "unresolved_identifier";
|
||||
case EXPR_INITIALIZER_LIST: return "initializer_list";
|
||||
@@ -480,7 +479,6 @@ bool expr_is_runtime_const(Expr *expr)
|
||||
return false;
|
||||
case EXPR_CT_CALL:
|
||||
case EXPR_TYPEINFO:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_CT_IDENT:
|
||||
case EXPR_POISONED:
|
||||
case EXPR_CT_ARG:
|
||||
@@ -876,7 +874,6 @@ bool expr_is_pure(Expr *expr)
|
||||
case EXPR_DECL:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_RETHROW:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_MACRO_BLOCK:
|
||||
case EXPR_NAMED_ARGUMENT:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
|
||||
@@ -672,7 +672,7 @@ static Expr *parse_ct_stringify(ParseContext *c, Expr *left, SourceSpan lhs_star
|
||||
ASSIGN_EXPR_OR_RET(Expr *inner, parse_expr(c), poisoned_expr);
|
||||
const char *end = c->lexer.lexing_start - 1;
|
||||
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr);
|
||||
if (inner->expr_kind == EXPR_HASH_IDENT || (inner->expr_kind == EXPR_CT_ARG && inner->ct_arg_expr.type == TOKEN_CT_VAEXPR))
|
||||
if ((inner->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && (inner->unresolved_ident_expr.ident_type == IDENT_AT || inner->unresolved_ident_expr.ident_type == IDENT_HASH)) || (inner->expr_kind == EXPR_CT_ARG && inner->ct_arg_expr.type == TOKEN_CT_VAEXPR))
|
||||
{
|
||||
Expr *expr = expr_new(EXPR_STRINGIFY, start_span);
|
||||
expr->inner_expr = inner;
|
||||
@@ -1123,17 +1123,6 @@ static Expr *parse_ct_ident(ParseContext *c, Expr *left, SourceSpan lhs_span UNU
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
static Expr *parse_hash_ident(ParseContext *c, Expr *left, SourceSpan lhs_span UNUSED)
|
||||
{
|
||||
ASSERT(!left && "Unexpected left hand side");
|
||||
Expr *expr = EXPR_NEW_TOKEN(EXPR_HASH_IDENT);
|
||||
expr->ct_ident_expr.identifier = symstr(c);
|
||||
advance_and_verify(c, TOKEN_HASH_IDENT);
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ct_eval ::= CT_EVAL '(' expr ')'
|
||||
*/
|
||||
@@ -1304,7 +1293,23 @@ static Expr *parse_identifier(ParseContext *c, Expr *left, SourceSpan lhs_start)
|
||||
}
|
||||
Expr *expr = EXPR_NEW_TOKEN(EXPR_UNRESOLVED_IDENTIFIER);
|
||||
expr->unresolved_ident_expr.ident = symstr(c);
|
||||
expr->unresolved_ident_expr.is_const = tok_is(c, TOKEN_CONST_IDENT);
|
||||
switch (c->tok)
|
||||
{
|
||||
case TOKEN_CONST_IDENT:
|
||||
expr->unresolved_ident_expr.ident_type = IDENT_CONST;
|
||||
break;
|
||||
case TOKEN_AT_IDENT:
|
||||
expr->unresolved_ident_expr.ident_type = IDENT_AT;
|
||||
break;
|
||||
case TOKEN_HASH_IDENT:
|
||||
expr->unresolved_ident_expr.ident_type = IDENT_HASH;
|
||||
break;
|
||||
case TOKEN_IDENT:
|
||||
expr->unresolved_ident_expr.ident_type = IDENT_NORMAL;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
advance(c);
|
||||
return expr;
|
||||
}
|
||||
@@ -2158,7 +2163,7 @@ ParseRule rules[TOKEN_EOF + 1] = {
|
||||
[TOKEN_CONST_IDENT] = { parse_identifier, NULL, PREC_NONE },
|
||||
[TOKEN_CT_CONST_IDENT] = { parse_ct_ident, NULL, PREC_NONE },
|
||||
[TOKEN_CT_TYPE_IDENT] = { parse_type_identifier, NULL, PREC_NONE },
|
||||
[TOKEN_HASH_IDENT] = { parse_hash_ident, NULL, PREC_NONE },
|
||||
[TOKEN_HASH_IDENT] = { parse_identifier, NULL, PREC_NONE },
|
||||
[TOKEN_AT_IDENT] = { parse_identifier, NULL, PREC_NONE },
|
||||
[TOKEN_ELLIPSIS] = { parse_splat, NULL, PREC_NONE },
|
||||
[TOKEN_FN] = { parse_lambda, NULL, PREC_NONE },
|
||||
|
||||
@@ -1632,6 +1632,17 @@ bool parse_parameters(ParseContext *c, Decl ***params_ref, Variadic *variadic, i
|
||||
}
|
||||
param_kind = VARDECL_PARAM_EXPR;
|
||||
break;
|
||||
case TOKEN_AT_IDENT:
|
||||
// expression @foo
|
||||
name = symstr(c);
|
||||
advance_and_verify(c, TOKEN_AT_IDENT);
|
||||
if (ellipsis || tok_is(c, TOKEN_ELLIPSIS))
|
||||
{
|
||||
PRINT_ERROR_LAST("Expression parameters may not be varargs, use untyped macro varargs '...' instead.");
|
||||
return false;
|
||||
}
|
||||
param_kind = VARDECL_PARAM_EXPR;
|
||||
break;
|
||||
// Compile time type $Type
|
||||
case TOKEN_CT_TYPE_IDENT:
|
||||
name = symstr(c);
|
||||
@@ -2164,15 +2175,18 @@ static inline Decl *parse_alias_type(ParseContext *c)
|
||||
type_info = expr->type_expr;
|
||||
break;
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
if (expr->unresolved_ident_expr.is_const)
|
||||
switch (expr->unresolved_ident_expr.ident_type)
|
||||
{
|
||||
print_error_at(decl->span, "A constant may not have a type name alias, it must have an all caps name.");
|
||||
case IDENT_CONST:
|
||||
print_error_at(decl->span, "A constant may not have a type name alias, it must have an all caps name.");
|
||||
return poisoned_decl;
|
||||
case IDENT_AT:
|
||||
case IDENT_HASH:
|
||||
case IDENT_NORMAL:
|
||||
print_error_at(decl->span, "An identifier may not be aliased with type name, it must start with a lower case letter.");
|
||||
return poisoned_decl;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error_at(decl->span, "An identifier may not be aliased with type name, it must start with a lower case letter.");
|
||||
}
|
||||
return poisoned_decl;
|
||||
UNREACHABLE;
|
||||
default:
|
||||
PRINT_ERROR_HERE("Expected a type to alias here.");
|
||||
return poisoned_decl;
|
||||
|
||||
@@ -323,35 +323,39 @@ Expr *sema_resolve_string_ident(SemaContext *context, Expr *inner, bool report_m
|
||||
ASSERT_SPAN(inner, expr_is_const_string(inner));
|
||||
Path *path = NULL;
|
||||
const char *interned_version = NULL;
|
||||
TokenType token = sema_splitpathref(inner->const_expr.bytes.ptr, inner->const_expr.bytes.len, &path, &interned_version);
|
||||
const char *bytes = inner->const_expr.bytes.ptr;
|
||||
size_t len = inner->const_expr.bytes.len;
|
||||
TokenType token = sema_splitpathref(bytes, len, &path, &interned_version);
|
||||
switch (token)
|
||||
{
|
||||
case TOKEN_CONST_IDENT:
|
||||
inner->unresolved_ident_expr.is_const = true;
|
||||
inner->unresolved_ident_expr.ident_type = IDENT_CONST;
|
||||
goto IDENT_CHECK;
|
||||
break;
|
||||
case TOKEN_HASH_IDENT:
|
||||
if (path) goto NO_PATH;
|
||||
inner->expr_kind = EXPR_HASH_IDENT;
|
||||
inner->ct_ident_expr.identifier = interned_version;
|
||||
inner->resolve_status = RESOLVE_NOT_DONE;
|
||||
return inner;
|
||||
case TOKEN_CT_IDENT:
|
||||
if (path) goto NO_PATH;
|
||||
inner->expr_kind = EXPR_CT_IDENT;
|
||||
inner->ct_ident_expr.identifier = interned_version;
|
||||
inner->resolve_status = RESOLVE_NOT_DONE;
|
||||
return inner;
|
||||
case TOKEN_HASH_IDENT:
|
||||
if (path) goto NO_PATH;
|
||||
inner->unresolved_ident_expr.ident_type = IDENT_HASH;
|
||||
goto IDENT_CHECK;
|
||||
case TOKEN_AT_IDENT:
|
||||
inner->unresolved_ident_expr.ident_type = IDENT_AT;
|
||||
goto IDENT_CHECK;
|
||||
case TOKEN_IDENT:
|
||||
inner->unresolved_ident_expr.ident_type = IDENT_NORMAL;
|
||||
IDENT_CHECK:
|
||||
if (!interned_version)
|
||||
{
|
||||
if (report_missing)
|
||||
{
|
||||
SEMA_ERROR(inner, "'%.*s' could not be found, did you spell it right?", (int)inner->const_expr.bytes.len, inner->const_expr.bytes.ptr);
|
||||
SEMA_ERROR(inner, "'%.*s' could not be found, did you spell it right?", (int)len, bytes);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
inner->unresolved_ident_expr.is_const = false;
|
||||
break;
|
||||
case TYPE_TOKENS:
|
||||
{
|
||||
@@ -670,7 +674,6 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
|
||||
if (failed_ref) goto FAILED_REF;
|
||||
RETURN_SEMA_ERROR(top_expr, "You cannot assign to a constant expression.");
|
||||
case EXPR_CT_ARG:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_POISONED:
|
||||
case EXPR_ADDR_CONVERSION:
|
||||
case EXPR_ASM:
|
||||
@@ -825,8 +828,6 @@ static bool expr_may_ref(Expr *expr)
|
||||
case EXPR_SLICE:
|
||||
case EXPR_SUBSCRIPT_ADDR:
|
||||
return true;
|
||||
case EXPR_HASH_IDENT:
|
||||
return false;
|
||||
case EXPR_TWO:
|
||||
return expr_may_ref(expr->two_expr.last);
|
||||
case EXPR_EXPRESSION_LIST:
|
||||
@@ -1181,7 +1182,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to,
|
||||
// Rerun if we can't do inference.
|
||||
if (!decl)
|
||||
{
|
||||
if (!expr->unresolved_ident_expr.path && expr->unresolved_ident_expr.is_const && (!to || to->canonical->type_kind != TYPE_ENUM))
|
||||
if (!expr->unresolved_ident_expr.path && expr->unresolved_ident_expr.ident_type == IDENT_CONST && (!to || to->canonical->type_kind != TYPE_ENUM))
|
||||
{
|
||||
CompilationUnit **units = context->unit->module->units;
|
||||
FOREACH (CompilationUnit *, unit, units)
|
||||
@@ -1369,7 +1370,7 @@ EVAL_BOTH:
|
||||
static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *left, Expr *right)
|
||||
{
|
||||
// Special handling of f = FOO_BAR
|
||||
if (right->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && right->unresolved_ident_expr.is_const)
|
||||
if (right->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && right->unresolved_ident_expr.ident_type == IDENT_CONST)
|
||||
{
|
||||
if (!sema_analyse_expr(context, left)) return false;
|
||||
switch (type_flatten(left->type)->type_kind)
|
||||
@@ -1382,7 +1383,7 @@ static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *left,
|
||||
}
|
||||
}
|
||||
// Special handling of f = FOO_BAR
|
||||
if (left->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && left->unresolved_ident_expr.is_const)
|
||||
if (left->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && left->unresolved_ident_expr.ident_type == IDENT_CONST)
|
||||
{
|
||||
if (!sema_analyse_expr(context, right)) return false;
|
||||
switch (type_flatten(right->type)->type_kind)
|
||||
@@ -4482,11 +4483,6 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, Che
|
||||
RETRY:
|
||||
switch (child->expr_kind)
|
||||
{
|
||||
case EXPR_HASH_IDENT:
|
||||
SEMA_DEPRECATED(child, "Using 'abc.#foo' access style is deprecated. Use 'abc.eval($foo)' instead.");
|
||||
if (!sema_expr_fold_hash(context, child)) return NULL;
|
||||
in_hash = true;
|
||||
goto RETRY;
|
||||
case EXPR_OTHER_CONTEXT:
|
||||
{
|
||||
Expr *inner = child->expr_other_context.inner;
|
||||
@@ -4499,6 +4495,13 @@ RETRY:
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
// A path is not allowed.
|
||||
if (child->unresolved_ident_expr.path) break;
|
||||
if (child->unresolved_ident_expr.ident_type == IDENT_HASH)
|
||||
{
|
||||
SEMA_DEPRECATED(child, "Using 'abc.#foo' access style is deprecated. Use 'abc.eval($foo)' instead.");
|
||||
if (!sema_expr_fold_hash(context, child)) return child;
|
||||
in_hash = true;
|
||||
goto RETRY;
|
||||
}
|
||||
return child;
|
||||
case EXPR_CT_IDENT:
|
||||
if (child->resolve_status == RESOLVE_DONE) goto ALREADY_RESOLVED;
|
||||
@@ -4645,9 +4648,9 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
||||
ASSERT_SPAN(expr, identifier->expr_kind == EXPR_UNRESOLVED_IDENTIFIER);
|
||||
Type *canonical = parent_type->canonical;
|
||||
const char *name = identifier->unresolved_ident_expr.ident;
|
||||
bool is_const = identifier->unresolved_ident_expr.is_const;
|
||||
IdentType ident_type = identifier->unresolved_ident_expr.ident_type;
|
||||
|
||||
if (!is_const)
|
||||
if (ident_type != IDENT_CONST)
|
||||
{
|
||||
TypeProperty property = type_property_by_name(name);
|
||||
if (sema_type_property_is_valid_for_type(canonical, property))
|
||||
@@ -4674,7 +4677,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
||||
{
|
||||
case DECL_ENUM:
|
||||
case DECL_CONST_ENUM:
|
||||
if (is_const)
|
||||
if (ident_type == IDENT_CONST)
|
||||
{
|
||||
if (!sema_expr_analyse_enum_constant(context, expr, name, decl))
|
||||
{
|
||||
@@ -4740,9 +4743,9 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e
|
||||
|
||||
Decl *decl = parent->const_expr.member.decl;
|
||||
const char *name = identifier->unresolved_ident_expr.ident;
|
||||
bool is_const = identifier->unresolved_ident_expr.is_const;
|
||||
IdentType ident_type = identifier->unresolved_ident_expr.ident_type;
|
||||
|
||||
if (is_const)
|
||||
if (ident_type == IDENT_CONST)
|
||||
{
|
||||
if (missing_ref) goto MISSING_REF;
|
||||
RETURN_SEMA_ERROR(expr, "There is no member '%s' for %s.", name, type_to_error_string(decl->type));
|
||||
@@ -6682,22 +6685,31 @@ static bool sema_expr_analyse_ct_subscript_assign(SemaContext *context, Expr *ex
|
||||
|
||||
static bool sema_expr_fold_hash(SemaContext *context, Expr *expr)
|
||||
{
|
||||
assert(expr->expr_kind == EXPR_HASH_IDENT);
|
||||
while (expr->expr_kind == EXPR_HASH_IDENT)
|
||||
bool did_fold = false;
|
||||
while (expr->expr_kind == EXPR_UNRESOLVED_IDENTIFIER && (expr->unresolved_ident_expr.ident_type == IDENT_HASH || expr->unresolved_ident_expr.ident_type == IDENT_AT))
|
||||
{
|
||||
ASSERT(expr && expr->hash_ident_expr.identifier);
|
||||
DEBUG_LOG("Resolving identifier '%s'", expr->hash_ident_expr.identifier);
|
||||
Decl *decl = sema_resolve_symbol(context, expr->hash_ident_expr.identifier, NULL, expr->span);
|
||||
ASSERT(expr && expr->unresolved_ident_expr.ident);
|
||||
DEBUG_LOG("Resolving identifier '%s'", expr->unresolved_ident_expr.ident);
|
||||
Decl *decl = sema_find_path_symbol(context, expr->unresolved_ident_expr.ident, NULL);
|
||||
|
||||
|
||||
// Already handled
|
||||
if (!decl) return expr_poison(expr);
|
||||
|
||||
if (!decl)
|
||||
{
|
||||
return BOOL_FALSE;
|
||||
}
|
||||
if (decl->decl_kind != DECL_VAR) break;
|
||||
ASSERT_SPAN(expr, decl->decl_kind == DECL_VAR);
|
||||
DEBUG_LOG("Replacing expr (%p) with '%s' (%p) expression resolve: %d", expr, expr_kind_to_string(decl->var.init_expr->expr_kind), decl->var.init_expr, decl->var.init_expr->resolve_status);
|
||||
expr_replace(expr, copy_expr_single(decl->var.init_expr));
|
||||
REMINDER("Handle inlining at");
|
||||
if (decl->var.kind == VARDECL_PARAM_EXPR)
|
||||
{
|
||||
DEBUG_LOG("Replacing expr (%p) with '%s' (%p) expression resolve: %d", expr, expr_kind_to_string(decl->var.init_expr->expr_kind), decl->var.init_expr, decl->var.init_expr->resolve_status);
|
||||
expr_replace(expr, copy_expr_single(decl->var.init_expr));
|
||||
did_fold = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return expr_ok(expr);
|
||||
return expr_ok(expr) ? (did_fold ? BOOL_TRUE : BOOL_FALSE) : BOOL_ERR;
|
||||
}
|
||||
/**
|
||||
* Analyse a = b
|
||||
@@ -8412,6 +8424,10 @@ RETRY:;
|
||||
{
|
||||
case EXPR_POISONED:
|
||||
return false;
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
if (inner->unresolved_ident_expr.ident_type != IDENT_AT && inner->unresolved_ident_expr.ident_type != IDENT_HASH) break;
|
||||
if (sema_expr_fold_hash(context, inner)) goto RETRY;
|
||||
break;
|
||||
case EXPR_OTHER_CONTEXT:
|
||||
{
|
||||
Expr *inner_c = inner->expr_other_context.inner;
|
||||
@@ -8419,9 +8435,6 @@ RETRY:;
|
||||
expr_replace(inner, inner_c);
|
||||
return sema_expr_analyse_addr(c2, expr, failed_ref, check);
|
||||
}
|
||||
case EXPR_HASH_IDENT:
|
||||
if (!sema_expr_fold_hash(context, inner)) return false;
|
||||
goto RETRY;
|
||||
case EXPR_SUBSCRIPT:
|
||||
inner->expr_kind = EXPR_SUBSCRIPT_ADDR;
|
||||
if (failed_ref)
|
||||
@@ -10254,7 +10267,7 @@ static inline bool sema_expr_analyse_ct_feature(SemaContext *context, Expr *expr
|
||||
Expr *inner = expr->ct_call_expr.main_var;
|
||||
if (expr->ct_call_expr.flat_path) goto ERROR;
|
||||
if (inner->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) goto ERROR;
|
||||
if (!inner->unresolved_ident_expr.is_const) goto ERROR;
|
||||
if (inner->unresolved_ident_expr.ident_type != IDENT_CONST) goto ERROR;
|
||||
|
||||
const char *name = inner->unresolved_ident_expr.ident;
|
||||
void *value = htable_get(&compiler.context.features, (void *)name);
|
||||
@@ -10311,6 +10324,11 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
{
|
||||
Decl *decl = sema_find_path_symbol(active_context, main_expr->unresolved_ident_expr.ident, main_expr->unresolved_ident_expr.path);
|
||||
if (!decl_ok(decl)) goto FAIL;
|
||||
if (decl && decl->decl_kind == DECL_VAR && decl->var.kind == VARDECL_PARAM_EXPR)
|
||||
{
|
||||
main_expr = copy_expr_single(decl->var.init_expr);
|
||||
goto RETRY;
|
||||
}
|
||||
success = decl != NULL;
|
||||
break;
|
||||
}
|
||||
@@ -10342,13 +10360,6 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
||||
success = eval != NULL;
|
||||
break;
|
||||
}
|
||||
case EXPR_HASH_IDENT:
|
||||
{
|
||||
Decl *decl = sema_resolve_symbol(active_context, main_expr->hash_ident_expr.identifier, NULL, main_expr->span);
|
||||
if (!decl) goto FAIL;
|
||||
main_expr = copy_expr_single(decl->var.init_expr);
|
||||
goto RETRY;
|
||||
}
|
||||
case EXPR_SUBSCRIPT:
|
||||
{
|
||||
if (!sema_expr_analyse_subscript(active_context, main_expr, CHECK_VALUE, true))
|
||||
@@ -10682,13 +10693,9 @@ static inline bool sema_expr_analyse_ct_stringify(SemaContext *context, Expr *ex
|
||||
context = inner->expr_other_context.context;
|
||||
inner = inner->expr_other_context.inner;
|
||||
continue;
|
||||
case EXPR_HASH_IDENT:
|
||||
{
|
||||
Decl *decl = sema_resolve_symbol(context, inner->ct_ident_expr.identifier, NULL, inner->span);
|
||||
if (!decl) return false;
|
||||
inner = decl->var.init_expr;
|
||||
continue;
|
||||
}
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
if (sema_expr_fold_hash(context, inner)) continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -10697,7 +10704,7 @@ static inline bool sema_expr_analyse_ct_stringify(SemaContext *context, Expr *ex
|
||||
const char *desc = span_to_string(inner->span);
|
||||
if (!desc)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "Failed to stringify hash variable contents - they must be a single line and not exceed 255 characters.");
|
||||
RETURN_SEMA_ERROR(expr, "Failed to stringify expr variable contents - they must be a single line and not exceed 255 characters.");
|
||||
}
|
||||
expr_rewrite_const_string(expr, desc);
|
||||
return true;
|
||||
@@ -10976,9 +10983,6 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
|
||||
return sema_expr_analyse_builtin(context, expr, true);
|
||||
case EXPR_CT_CALL:
|
||||
return sema_expr_analyse_ct_call(context, expr);
|
||||
case EXPR_HASH_IDENT:
|
||||
if (!sema_expr_fold_hash(context, expr)) return false;
|
||||
return sema_analyse_expr_check(context, expr, check);
|
||||
case EXPR_CT_IDENT:
|
||||
return sema_expr_analyse_ct_identifier(context, expr);
|
||||
case EXPR_OPTIONAL:
|
||||
@@ -11025,6 +11029,10 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
|
||||
case EXPR_IDENTIFIER:
|
||||
UNREACHABLE
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
if (sema_expr_fold_hash(context, expr))
|
||||
{
|
||||
return sema_analyse_expr_check(context, expr, check);
|
||||
}
|
||||
return sema_expr_analyse_identifier(context, NULL, expr);
|
||||
case EXPR_CALL:
|
||||
return sema_expr_analyse_call(context, expr, NULL);
|
||||
@@ -11280,10 +11288,6 @@ static inline bool sema_analyse_expr_lvalue_dispatch(SemaContext *context, Expr
|
||||
RETRY:
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_HASH_IDENT:
|
||||
DEBUG_LOG("Expand hash ident");
|
||||
if (!sema_expr_fold_hash(context, expr)) return false;
|
||||
goto RETRY;
|
||||
case EXPR_CT_IDENT:
|
||||
return sema_expr_resolve_ct_identifier(context, expr);
|
||||
case EXPR_SUBSCRIPT:
|
||||
@@ -11313,6 +11317,7 @@ RETRY:
|
||||
if (!sema_analyse_expr_dispatch(context, expr, CHECK_VALUE)) return false;
|
||||
goto IDENT_CHECK;
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
if (sema_expr_fold_hash(context, expr)) goto RETRY;
|
||||
if (!sema_analyse_expr_dispatch(context, expr, CHECK_VALUE)) return false;
|
||||
FALLTHROUGH;
|
||||
case EXPR_IDENTIFIER:
|
||||
@@ -11638,9 +11643,6 @@ RETRY:
|
||||
expr->resolve_status = RESOLVE_RUNNING;
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_HASH_IDENT:
|
||||
if (!sema_expr_fold_hash(context, expr)) return false;
|
||||
goto RETRY;
|
||||
case EXPR_OTHER_CONTEXT:
|
||||
{
|
||||
InliningSpan *new_span = context->inlined_at;
|
||||
@@ -11657,6 +11659,7 @@ RETRY:
|
||||
if (!sema_expr_analyse_initializer_list(context, to, expr)) return expr_poison(expr);
|
||||
break;
|
||||
case EXPR_UNRESOLVED_IDENTIFIER:
|
||||
if (sema_expr_fold_hash(context, expr)) goto RETRY;
|
||||
if (!sema_expr_analyse_identifier(context, to, expr)) return expr_poison(expr);
|
||||
break;
|
||||
case EXPR_LAMBDA:
|
||||
|
||||
@@ -798,7 +798,6 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
|
||||
case EXPR_MACRO_BLOCK:
|
||||
case EXPR_OPTIONAL:
|
||||
case EXPR_FORCE_UNWRAP:
|
||||
case EXPR_HASH_IDENT:
|
||||
case EXPR_IDENTIFIER:
|
||||
case EXPR_INITIALIZER_LIST:
|
||||
case EXPR_LAMBDA:
|
||||
@@ -911,7 +910,7 @@ static inline bool sema_analyse_try_unwrap(SemaContext *context, Expr *expr)
|
||||
if (ident->expr_kind != EXPR_UNRESOLVED_IDENTIFIER) RETURN_SEMA_ERROR(ident, "A variable name was expected here.");
|
||||
ASSERT(ident->resolve_status != RESOLVE_DONE);
|
||||
if (ident->unresolved_ident_expr.path) RETURN_SEMA_ERROR(ident->unresolved_ident_expr.path, "The variable may not have a path.");
|
||||
if (ident->unresolved_ident_expr.is_const) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter.");
|
||||
if (ident->unresolved_ident_expr.ident_type != IDENT_NORMAL) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter.");
|
||||
const char *ident_name = ident->unresolved_ident_expr.ident;
|
||||
|
||||
// Special check for `if (try a = a)`
|
||||
@@ -996,7 +995,7 @@ static inline bool sema_analyse_catch_unwrap(SemaContext *context, Expr *expr)
|
||||
}
|
||||
|
||||
if (ident->unresolved_ident_expr.path) RETURN_SEMA_ERROR(ident->unresolved_ident_expr.path, "The variable may not have a path.");
|
||||
if (ident->unresolved_ident_expr.is_const) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter.");
|
||||
if (ident->unresolved_ident_expr.ident_type != IDENT_NORMAL) RETURN_SEMA_ERROR(ident, "Expected a variable starting with a lower case letter.");
|
||||
|
||||
// 4d. A new declaration is created.
|
||||
decl = decl_new_var(ident->unresolved_ident_expr.ident, ident->span, type, VARDECL_LOCAL);
|
||||
@@ -3247,7 +3246,7 @@ static bool sema_analyse_optional_returns(SemaContext *context, Ast *directive)
|
||||
{
|
||||
if (ret->contract_fault.resolved) continue;
|
||||
Expr *expr = ret->contract_fault.expr;
|
||||
if (expr->expr_kind != EXPR_UNRESOLVED_IDENTIFIER && !expr->unresolved_ident_expr.is_const)
|
||||
if (expr->expr_kind != EXPR_UNRESOLVED_IDENTIFIER || expr->unresolved_ident_expr.ident_type != IDENT_CONST)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "Expected a fault name here.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user