mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- $typefrom now also accepts a constant string, and so works like $evaltype.
- `$evaltype` is deprecated in favour of `$typefrom`.
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
## 0.7.3 Change list
|
||||
|
||||
### Changes / improvements
|
||||
- `$typefrom` now also accepts a constant string, and so works like `$evaltype`.
|
||||
- `$evaltype` is deprecated in favour of `$typefrom`.
|
||||
|
||||
### Fixes
|
||||
|
||||
|
||||
@@ -9975,7 +9975,7 @@ static inline bool sema_expr_resolve_ct_eval(SemaContext *context, Expr *expr)
|
||||
if (!result) return false;
|
||||
if (result->expr_kind == EXPR_TYPEINFO)
|
||||
{
|
||||
RETURN_SEMA_ERROR(result, "Evaluation to a type requires the use of '$evaltype' rather than '$eval'.");
|
||||
RETURN_SEMA_ERROR(result, "Evaluation to a type requires the use of '$typefrom' rather than '$eval'.");
|
||||
}
|
||||
expr_replace(expr, result);
|
||||
return true;
|
||||
|
||||
@@ -11,7 +11,7 @@ static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info,
|
||||
static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_type_kind);
|
||||
INLINE bool sema_resolve_vatype(SemaContext *context, TypeInfo *type_info);
|
||||
INLINE bool sema_resolve_evaltype(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind);
|
||||
INLINE bool sema_resolve_typefrom(SemaContext *context, TypeInfo *type_info);
|
||||
INLINE bool sema_resolve_typefrom(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind);
|
||||
INLINE bool sema_resolve_typeof(SemaContext *context, TypeInfo *type_info);
|
||||
static int compare_function(Signature *sig, FunctionPrototype *proto);
|
||||
|
||||
@@ -293,6 +293,7 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in
|
||||
// $evaltype("Foo")
|
||||
INLINE bool sema_resolve_evaltype(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind)
|
||||
{
|
||||
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);
|
||||
if (!inner) return type_info_poison(type_info);
|
||||
@@ -353,16 +354,69 @@ INLINE bool sema_resolve_typeof(SemaContext *context, TypeInfo *type_info)
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
INLINE bool sema_resolve_typefrom(SemaContext *context, TypeInfo *type_info)
|
||||
INLINE bool sema_resolve_typefrom(SemaContext *context, TypeInfo *type_info, ResolveTypeKind resolve_kind)
|
||||
{
|
||||
Expr *expr = type_info->unresolved_type_expr;
|
||||
if (!sema_analyse_expr(context, expr)) return false;
|
||||
if (!sema_cast_const(expr) || expr->const_expr.const_kind != CONST_TYPEID)
|
||||
if (!sema_cast_const(expr))
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "Expected a constant typeid value.");
|
||||
RETURN_SEMA_ERROR(expr, "Expected a constant value.");
|
||||
}
|
||||
type_info->type = expr->const_expr.typeid;
|
||||
return true;
|
||||
switch (expr->const_expr.const_kind)
|
||||
{
|
||||
case CONST_TYPEID:
|
||||
type_info->type = expr->const_expr.typeid;
|
||||
return true;
|
||||
case CONST_STRING:
|
||||
break;
|
||||
default:
|
||||
RETURN_SEMA_ERROR(expr, "Expected a constant string or typeid value.");
|
||||
}
|
||||
|
||||
Path *path = NULL;
|
||||
const char *interned_version = NULL;
|
||||
const char *bytes = expr->const_expr.bytes.ptr;
|
||||
ArraySize bytes_len = expr->const_expr.bytes.len;
|
||||
TokenType token = sema_splitpathref(bytes, bytes_len, &path, &interned_version);
|
||||
TypeInfo *info;
|
||||
switch (token)
|
||||
{
|
||||
case TOKEN_IDENT:
|
||||
if (slice_is_type(bytes, bytes_len))
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "'%.*s' could not be found, did you spell it right?", (int)bytes_len, bytes);
|
||||
}
|
||||
FALLTHROUGH;
|
||||
case TOKEN_CONST_IDENT:
|
||||
RETURN_SEMA_ERROR(expr, "Expected a type name, but the argument was \"%.*s\".", (int)bytes_len, bytes);
|
||||
case TYPE_TOKENS:
|
||||
type_info->type = type_from_token(token);
|
||||
return true;
|
||||
case TOKEN_TYPE_IDENT:
|
||||
info = type_info_new(TYPE_INFO_IDENTIFIER, expr->span);
|
||||
info->unresolved.name = interned_version;
|
||||
info->unresolved.path = path;
|
||||
info->resolve_status = RESOLVE_NOT_DONE;
|
||||
break;
|
||||
default:
|
||||
RETURN_SEMA_ERROR(expr, "Only valid types can be resolved with $typefrom. You passed the string \"%.*s\", which cannot be resolved as a type.", (int)bytes_len, bytes);
|
||||
}
|
||||
if (!sema_resolve_type(context, info, resolve_kind)) return false;
|
||||
switch (sema_resolve_storage_type(context, info->type))
|
||||
{
|
||||
case STORAGE_ERROR:
|
||||
return false;
|
||||
case STORAGE_VOID:
|
||||
case STORAGE_UNKNOWN:
|
||||
case STORAGE_NORMAL:
|
||||
type_info->type = info->type;
|
||||
return true;
|
||||
case STORAGE_WILDCARD:
|
||||
RETURN_SEMA_ERROR(expr, "$typefrom failed to resolve \"%.*s\" to a definite type.", (int)bytes_len, bytes);
|
||||
case STORAGE_COMPILE_TIME:
|
||||
RETURN_SEMA_ERROR(expr, "$typefrom does not support compile-time types.");
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
// $vatype(...)
|
||||
@@ -476,7 +530,7 @@ static inline bool sema_resolve_type(SemaContext *context, TypeInfo *type_info,
|
||||
if (!sema_resolve_typeof(context, type_info)) return type_info_poison(type_info);
|
||||
goto APPEND_QUALIFIERS;
|
||||
case TYPE_INFO_TYPEFROM:
|
||||
if (!sema_resolve_typefrom(context, type_info)) return type_info_poison(type_info);
|
||||
if (!sema_resolve_typefrom(context, type_info, resolve_kind)) return type_info_poison(type_info);
|
||||
goto APPEND_QUALIFIERS;
|
||||
case TYPE_INFO_INFERRED_VECTOR:
|
||||
case TYPE_INFO_INFERRED_ARRAY:
|
||||
|
||||
@@ -151,6 +151,7 @@ const char *str_unescape(char *string);
|
||||
bool str_is_identifier(const char *string);
|
||||
bool str_eq(const char *str1, const char *str2);
|
||||
bool str_is_type(const char *string);
|
||||
bool slice_is_type(const char *string, size_t);
|
||||
bool str_is_integer(const char *string);
|
||||
bool str_has_no_uppercase(const char *string);
|
||||
bool str_is_valid_module_name(const char *name);
|
||||
|
||||
@@ -103,6 +103,28 @@ bool str_is_type(const char *string)
|
||||
return found_lower;
|
||||
}
|
||||
|
||||
bool slice_is_type(const char *string, size_t len)
|
||||
{
|
||||
const char *begin = scan_past_underscore(string);
|
||||
if (!begin) return false;
|
||||
const char *end = string + len;
|
||||
if (begin == end) return false;
|
||||
char c = begin++[0];
|
||||
if (!char_is_upper(c)) return false;
|
||||
bool found_lower = false;
|
||||
while (begin != end)
|
||||
{
|
||||
c = begin++[0];
|
||||
if (char_is_lower(c))
|
||||
{
|
||||
found_lower = true;
|
||||
continue;
|
||||
}
|
||||
if (!char_is_alphanum_(c)) return false;
|
||||
}
|
||||
return found_lower;
|
||||
}
|
||||
|
||||
bool str_is_identifier(const char *string)
|
||||
{
|
||||
string = scan_past_underscore(string);
|
||||
|
||||
@@ -38,11 +38,11 @@ fn void main()
|
||||
x++;
|
||||
$counter++;
|
||||
$endif
|
||||
$if $defined($evaltype("Foo").$eval("ab")):
|
||||
$if $defined($typefrom("Foo").$eval("ab")):
|
||||
x++;
|
||||
$counter++;
|
||||
$endif
|
||||
$if $defined($evaltype("mymodule::Foo").$eval("bob")):
|
||||
$if $defined($typefrom("mymodule::Foo").$eval("bob")):
|
||||
x++;
|
||||
$counter++;
|
||||
$endif
|
||||
|
||||
@@ -10,11 +10,11 @@ int b;
|
||||
fn void main()
|
||||
{
|
||||
printf("%s\n", Foo.qnameof);
|
||||
printf("%s\n", $evaltype("Foo").qnameof);
|
||||
printf("%s\n", $typefrom("Foo").qnameof);
|
||||
printf("%s\n", Foo.nameof);
|
||||
printf("%s\n", $evaltype("mymodule::Foo").nameof);
|
||||
printf("%s\n", $typefrom("mymodule::Foo").nameof);
|
||||
printf("%s\n", Foo.extnameof);
|
||||
printf("%s\n", $evaltype("Foo").extnameof);
|
||||
printf("%s\n", $typefrom("Foo").extnameof);
|
||||
|
||||
printf("%s\n", $qnameof(b));
|
||||
printf("%s\n", $qnameof($eval("b")));
|
||||
|
||||
@@ -11,10 +11,10 @@ fn void main2()
|
||||
|
||||
fn void main3()
|
||||
{
|
||||
$evaltype("int").extnameof; // #error: 'int' does not have a property or method 'extnameof'
|
||||
$typefrom("int").extnameof; // #error: 'int' does not have a property or method 'extnameof'
|
||||
}
|
||||
|
||||
fn void main4()
|
||||
{
|
||||
$evaltype("foo::int").extnameof; // #error: Only valid types may be resolved with $evaltype.
|
||||
$typefrom("foo::int").extnameof; // #error: Only valid types can be resolved with $typefrom
|
||||
}
|
||||
|
||||
@@ -3,17 +3,17 @@ import bar;
|
||||
import bar::abc;
|
||||
|
||||
long x = Baz.sizeof;
|
||||
short y = $evaltype("Baz").sizeof;
|
||||
short y = $typefrom("Baz").sizeof;
|
||||
int z = bar::Baz.sizeof;
|
||||
int w = bar::Baz.sizeof;
|
||||
int v = bar::abc::Foo.sizeof;
|
||||
int x1 = $sizeof(x);
|
||||
int y1 = $sizeof($eval("y"));
|
||||
int a = Baz.y.sizeof;
|
||||
int b = $evaltype("Deep").a.$eval("b").sizeof;
|
||||
int b = $typefrom("Deep").a.$eval("b").sizeof;
|
||||
int c = Deep.a.b.c.sizeof;
|
||||
int d = Deep[][100].sizeof;
|
||||
int e = $evaltype("Deep")[][100]**[100][]*.sizeof;
|
||||
int e = $typefrom("Deep")[][100]**[100][]*.sizeof;
|
||||
int a2 = Baz.y.sizeof;
|
||||
int a3 = Baz.y.sizeof;
|
||||
int a4 = Baz.y.sizeof;
|
||||
|
||||
@@ -8,7 +8,7 @@ fn void a()
|
||||
|
||||
fn void b()
|
||||
{
|
||||
int x = $evaltype("Bazz").sizeof; // #error: 'Bazz' could not be found, did you spell it rig
|
||||
int x = $typefrom("Bazz").sizeof; // #error: 'Bazz' could not be found, did you spell it rig
|
||||
}
|
||||
|
||||
|
||||
@@ -19,17 +19,17 @@ fn void e()
|
||||
|
||||
fn void f()
|
||||
{
|
||||
int x = $evaltype("bar::Bazy").sizeof; // #error: 'bar::Bazy' could not be found
|
||||
int x = $typefrom("bar::Bazy").sizeof; // #error: 'bar::Bazy' could not be found
|
||||
}
|
||||
|
||||
fn void g()
|
||||
{
|
||||
int x = $evaltype("bar::").sizeof; // #error: Only valid types may be resolved with $evaltype
|
||||
int x = $typefrom("bar::").sizeof; // #error: Only valid types can be resolved with $typefrom
|
||||
}
|
||||
|
||||
fn void k()
|
||||
{
|
||||
int v = $evaltype("int").x.sizeof; // #error: 'x'.
|
||||
int v = $typefrom("int").x.sizeof; // #error: 'x'.
|
||||
}
|
||||
|
||||
fn void l()
|
||||
|
||||
Reference in New Issue
Block a user