mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add $member.get(value) to replace value.$eval($member.nameof)
This commit is contained in:
@@ -35,6 +35,7 @@
|
|||||||
- `$exec` may now provide a stdin parameter.
|
- `$exec` may now provide a stdin parameter.
|
||||||
- Introduce `$vaarg[...]` syntax and deprecate the old `$vaarg(...)`.
|
- Introduce `$vaarg[...]` syntax and deprecate the old `$vaarg(...)`.
|
||||||
- Similar change to `$vasplat`: `$vasplat` and `$vasplat[1..]`.
|
- Similar change to `$vasplat`: `$vasplat` and `$vasplat[1..]`.
|
||||||
|
- Add `$member.get(value)` to replace `value.$eval($member.nameof)`
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
|||||||
@@ -1090,7 +1090,8 @@ struct Expr_
|
|||||||
Expr *inner_expr; // 8
|
Expr *inner_expr; // 8
|
||||||
Decl *lambda_expr; // 8
|
Decl *lambda_expr; // 8
|
||||||
ExprMacroBlock macro_block; // 24
|
ExprMacroBlock macro_block; // 24
|
||||||
ExprMacroBody macro_body_expr; // 16;
|
ExprMacroBody macro_body_expr; // 16
|
||||||
|
Decl *member_get_expr; // 8
|
||||||
OperatorOverload overload_expr; // 4
|
OperatorOverload overload_expr; // 4
|
||||||
ExprPointerOffset pointer_offset_expr;
|
ExprPointerOffset pointer_offset_expr;
|
||||||
ExprGuard rethrow_expr; // 16
|
ExprGuard rethrow_expr; // 16
|
||||||
@@ -3265,6 +3266,7 @@ INLINE void expr_set_span(Expr *expr, SourceSpan loc)
|
|||||||
case EXPR_MACRO_BODY:
|
case EXPR_MACRO_BODY:
|
||||||
case EXPR_DEFAULT_ARG:
|
case EXPR_DEFAULT_ARG:
|
||||||
case EXPR_TAGOF:
|
case EXPR_TAGOF:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,6 +317,9 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
|
|||||||
MACRO_COPY_DECL(expr->lambda_expr);
|
MACRO_COPY_DECL(expr->lambda_expr);
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
|
fixup_decl(c, &source_expr->member_get_expr);
|
||||||
|
break;
|
||||||
case EXPR_SWIZZLE:
|
case EXPR_SWIZZLE:
|
||||||
MACRO_COPY_EXPRID(expr->swizzle_expr.parent);
|
MACRO_COPY_EXPRID(expr->swizzle_expr.parent);
|
||||||
return expr;
|
return expr;
|
||||||
|
|||||||
@@ -788,6 +788,7 @@ typedef enum
|
|||||||
EXPR_MACRO_BLOCK,
|
EXPR_MACRO_BLOCK,
|
||||||
EXPR_MACRO_BODY,
|
EXPR_MACRO_BODY,
|
||||||
EXPR_MACRO_BODY_EXPANSION,
|
EXPR_MACRO_BODY_EXPANSION,
|
||||||
|
EXPR_MEMBER_GET,
|
||||||
EXPR_NOP,
|
EXPR_NOP,
|
||||||
EXPR_OPERATOR_CHARS,
|
EXPR_OPERATOR_CHARS,
|
||||||
EXPR_OPTIONAL,
|
EXPR_OPTIONAL,
|
||||||
@@ -1363,6 +1364,7 @@ typedef enum
|
|||||||
TYPE_PROPERTY_ASSOCIATED,
|
TYPE_PROPERTY_ASSOCIATED,
|
||||||
TYPE_PROPERTY_ELEMENTS,
|
TYPE_PROPERTY_ELEMENTS,
|
||||||
TYPE_PROPERTY_EXTNAMEOF,
|
TYPE_PROPERTY_EXTNAMEOF,
|
||||||
|
TYPE_PROPERTY_GET,
|
||||||
TYPE_PROPERTY_INF,
|
TYPE_PROPERTY_INF,
|
||||||
TYPE_PROPERTY_IS_EQ,
|
TYPE_PROPERTY_IS_EQ,
|
||||||
TYPE_PROPERTY_IS_ORDERED,
|
TYPE_PROPERTY_IS_ORDERED,
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ bool expr_may_addr(Expr *expr)
|
|||||||
return expr_may_addr(expr->access_expr.parent);
|
return expr_may_addr(expr->access_expr.parent);
|
||||||
case EXPR_SUBSCRIPT:
|
case EXPR_SUBSCRIPT:
|
||||||
case EXPR_SLICE:
|
case EXPR_SLICE:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
return true;
|
return true;
|
||||||
case EXPR_BENCHMARK_HOOK:
|
case EXPR_BENCHMARK_HOOK:
|
||||||
case EXPR_TEST_HOOK:
|
case EXPR_TEST_HOOK:
|
||||||
@@ -226,6 +227,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
|
|||||||
case EXPR_SLICE_COPY:
|
case EXPR_SLICE_COPY:
|
||||||
case EXPR_MACRO_BLOCK:
|
case EXPR_MACRO_BLOCK:
|
||||||
case EXPR_RETHROW:
|
case EXPR_RETHROW:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
return false;
|
return false;
|
||||||
case EXPR_IDENTIFIER:
|
case EXPR_IDENTIFIER:
|
||||||
{
|
{
|
||||||
@@ -704,6 +706,7 @@ bool expr_is_pure(Expr *expr)
|
|||||||
case EXPR_TYPEID:
|
case EXPR_TYPEID:
|
||||||
case EXPR_TYPEINFO:
|
case EXPR_TYPEINFO:
|
||||||
case EXPR_LAST_FAULT:
|
case EXPR_LAST_FAULT:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
return true;
|
return true;
|
||||||
case EXPR_VASPLAT:
|
case EXPR_VASPLAT:
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -7064,6 +7064,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
|
|||||||
case EXPR_MACRO_BODY:
|
case EXPR_MACRO_BODY:
|
||||||
case EXPR_OTHER_CONTEXT:
|
case EXPR_OTHER_CONTEXT:
|
||||||
case EXPR_DESIGNATOR:
|
case EXPR_DESIGNATOR:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
case EXPR_DEFAULT_ARG:
|
case EXPR_DEFAULT_ARG:
|
||||||
llvm_emit_default_arg(c, value, expr);
|
llvm_emit_default_arg(c, value, expr);
|
||||||
|
|||||||
@@ -593,6 +593,7 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
|
|||||||
case EXPR_GENERIC_IDENT:
|
case EXPR_GENERIC_IDENT:
|
||||||
case EXPR_MACRO_BODY:
|
case EXPR_MACRO_BODY:
|
||||||
case EXPR_LAST_FAULT:
|
case EXPR_LAST_FAULT:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
goto ERR;
|
goto ERR;
|
||||||
}
|
}
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
@@ -618,6 +619,7 @@ static bool expr_may_ref(Expr *expr)
|
|||||||
case EXPR_EMBED:
|
case EXPR_EMBED:
|
||||||
case EXPR_DEFAULT_ARG:
|
case EXPR_DEFAULT_ARG:
|
||||||
case EXPR_TAGOF:
|
case EXPR_TAGOF:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
return false;
|
return false;
|
||||||
case EXPR_OTHER_CONTEXT:
|
case EXPR_OTHER_CONTEXT:
|
||||||
return expr_may_ref(expr->expr_other_context.inner);
|
return expr_may_ref(expr->expr_other_context.inner);
|
||||||
@@ -2519,6 +2521,57 @@ NOT_FOUND:
|
|||||||
RETURN_SEMA_ERROR(expr, "The tag '%s' is not defined, always check with '.has_tagof'.", tagname);
|
RETURN_SEMA_ERROR(expr, "The tag '%s' is not defined, always check with '.has_tagof'.", tagname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE bool sema_call_may_not_have_attributes(SemaContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
if (expr->call_expr.attr_force_inline)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(expr, "'@inline' is not allowed here.");
|
||||||
|
}
|
||||||
|
if (expr->call_expr.attr_force_inline)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(expr, "'@noinline' is not allowed here.");
|
||||||
|
}
|
||||||
|
if (expr->call_expr.attr_force_inline)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(expr, "'@pure' is not allowed here.");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static inline bool sema_call_analyse_member_get(SemaContext *context, Expr *expr)
|
||||||
|
{
|
||||||
|
if (vec_size(expr->call_expr.arguments) != 1)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(expr, "Expected a single argument to '.get'.");
|
||||||
|
}
|
||||||
|
if (!sema_call_may_not_have_attributes(context, expr)) return false;
|
||||||
|
Expr *get = exprptr(expr->call_expr.function);
|
||||||
|
Expr *inner = expr->call_expr.arguments[0];
|
||||||
|
if (!sema_analyse_expr(context, inner)) return false;
|
||||||
|
Decl *decl = get->member_get_expr;
|
||||||
|
Type *type = type_flatten(inner->type);
|
||||||
|
if (type->type_kind != TYPE_STRUCT && type->type_kind != TYPE_UNION)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(inner, "This value does not match the member.");
|
||||||
|
}
|
||||||
|
Decl **members = type->decl->strukt.members;
|
||||||
|
ArrayIndex index = -1;
|
||||||
|
FOREACH_IDX(i, Decl *, member, members)
|
||||||
|
{
|
||||||
|
if (member == decl)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
RETURN_SEMA_ERROR(inner, "This value does not match the member.");
|
||||||
|
}
|
||||||
|
expr->expr_kind = EXPR_ACCESS;
|
||||||
|
expr->access_expr = (ExprAccess) { .parent = inner, .ref = decl };
|
||||||
|
expr->type = decl->type;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr, bool *no_match_ref)
|
static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr, bool *no_match_ref)
|
||||||
{
|
{
|
||||||
if (no_match_ref) *no_match_ref = true;
|
if (no_match_ref) *no_match_ref = true;
|
||||||
@@ -2528,6 +2581,10 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr, bool
|
|||||||
{
|
{
|
||||||
return sema_call_analyse_body_expansion(context, expr);
|
return sema_call_analyse_body_expansion(context, expr);
|
||||||
}
|
}
|
||||||
|
if (func_expr->expr_kind == EXPR_MEMBER_GET)
|
||||||
|
{
|
||||||
|
return sema_call_analyse_member_get(context, expr);
|
||||||
|
}
|
||||||
bool optional = func_expr->type && IS_OPTIONAL(func_expr);
|
bool optional = func_expr->type && IS_OPTIONAL(func_expr);
|
||||||
Decl *decl;
|
Decl *decl;
|
||||||
Expr *struct_var = NULL;
|
Expr *struct_var = NULL;
|
||||||
@@ -3442,6 +3499,11 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e
|
|||||||
expr->expr_kind = EXPR_TAGOF;
|
expr->expr_kind = EXPR_TAGOF;
|
||||||
expr->tag_of_expr = (ExprTagOf) { .type = decl, .property = type_property };
|
expr->tag_of_expr = (ExprTagOf) { .type = decl, .property = type_property };
|
||||||
return true;
|
return true;
|
||||||
|
case TYPE_PROPERTY_GET:
|
||||||
|
expr->expr_kind = EXPR_MEMBER_GET;
|
||||||
|
expr->member_get_expr = decl;
|
||||||
|
expr->type = type_void;
|
||||||
|
return true;
|
||||||
case TYPE_PROPERTY_NONE:
|
case TYPE_PROPERTY_NONE:
|
||||||
break;
|
break;
|
||||||
case TYPE_PROPERTY_QNAMEOF:
|
case TYPE_PROPERTY_QNAMEOF:
|
||||||
@@ -3910,25 +3972,26 @@ static bool sema_expr_rewrite_to_typeid_property(SemaContext *context, Expr *exp
|
|||||||
case TYPE_PROPERTY_NAMES:
|
case TYPE_PROPERTY_NAMES:
|
||||||
return sema_expr_rewrite_typeid_call(expr, typeid, TYPEID_INFO_NAMES, type_get_slice(type_string));
|
return sema_expr_rewrite_typeid_call(expr, typeid, TYPEID_INFO_NAMES, type_get_slice(type_string));
|
||||||
case TYPE_PROPERTY_ALIGNOF:
|
case TYPE_PROPERTY_ALIGNOF:
|
||||||
case TYPE_PROPERTY_INF:
|
|
||||||
case TYPE_PROPERTY_MIN:
|
|
||||||
case TYPE_PROPERTY_MAX:
|
|
||||||
case TYPE_PROPERTY_NAN:
|
|
||||||
case TYPE_PROPERTY_ELEMENTS:
|
|
||||||
case TYPE_PROPERTY_VALUES:
|
|
||||||
case TYPE_PROPERTY_RETURNS:
|
|
||||||
case TYPE_PROPERTY_PARAMS:
|
|
||||||
case TYPE_PROPERTY_MEMBERSOF:
|
|
||||||
case TYPE_PROPERTY_METHODSOF:
|
|
||||||
case TYPE_PROPERTY_EXTNAMEOF:
|
|
||||||
case TYPE_PROPERTY_TAGOF:
|
|
||||||
case TYPE_PROPERTY_HAS_TAGOF:
|
|
||||||
case TYPE_PROPERTY_NAMEOF:
|
|
||||||
case TYPE_PROPERTY_QNAMEOF:
|
|
||||||
case TYPE_PROPERTY_ASSOCIATED:
|
case TYPE_PROPERTY_ASSOCIATED:
|
||||||
|
case TYPE_PROPERTY_ELEMENTS:
|
||||||
|
case TYPE_PROPERTY_EXTNAMEOF:
|
||||||
|
case TYPE_PROPERTY_GET:
|
||||||
|
case TYPE_PROPERTY_HAS_TAGOF:
|
||||||
|
case TYPE_PROPERTY_INF:
|
||||||
case TYPE_PROPERTY_IS_EQ:
|
case TYPE_PROPERTY_IS_EQ:
|
||||||
case TYPE_PROPERTY_IS_ORDERED:
|
case TYPE_PROPERTY_IS_ORDERED:
|
||||||
case TYPE_PROPERTY_IS_SUBSTRUCT:
|
case TYPE_PROPERTY_IS_SUBSTRUCT:
|
||||||
|
case TYPE_PROPERTY_MAX:
|
||||||
|
case TYPE_PROPERTY_MEMBERSOF:
|
||||||
|
case TYPE_PROPERTY_METHODSOF:
|
||||||
|
case TYPE_PROPERTY_MIN:
|
||||||
|
case TYPE_PROPERTY_NAMEOF:
|
||||||
|
case TYPE_PROPERTY_NAN:
|
||||||
|
case TYPE_PROPERTY_PARAMS:
|
||||||
|
case TYPE_PROPERTY_QNAMEOF:
|
||||||
|
case TYPE_PROPERTY_RETURNS:
|
||||||
|
case TYPE_PROPERTY_TAGOF:
|
||||||
|
case TYPE_PROPERTY_VALUES:
|
||||||
// Not supported by dynamic typeid
|
// Not supported by dynamic typeid
|
||||||
case TYPE_PROPERTY_NONE:
|
case TYPE_PROPERTY_NONE:
|
||||||
return false;
|
return false;
|
||||||
@@ -4096,6 +4159,8 @@ static bool sema_type_property_is_valid_for_type(Type *original_type, TypeProper
|
|||||||
{
|
{
|
||||||
case TYPE_PROPERTY_NONE:
|
case TYPE_PROPERTY_NONE:
|
||||||
return false;
|
return false;
|
||||||
|
case TYPE_PROPERTY_GET:
|
||||||
|
return type == type_member;
|
||||||
case TYPE_PROPERTY_INF:
|
case TYPE_PROPERTY_INF:
|
||||||
case TYPE_PROPERTY_NAN:
|
case TYPE_PROPERTY_NAN:
|
||||||
return type_is_float(type);
|
return type_is_float(type);
|
||||||
@@ -4237,6 +4302,8 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
|||||||
expr->type = type;
|
expr->type = type;
|
||||||
expr->resolve_status = RESOLVE_DONE;
|
expr->resolve_status = RESOLVE_DONE;
|
||||||
return true;
|
return true;
|
||||||
|
case TYPE_PROPERTY_GET:
|
||||||
|
UNREACHABLE
|
||||||
case TYPE_PROPERTY_MEMBERSOF:
|
case TYPE_PROPERTY_MEMBERSOF:
|
||||||
{
|
{
|
||||||
AlignSize align;
|
AlignSize align;
|
||||||
@@ -8943,6 +9010,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
|
|||||||
case EXPR_TYPEID:
|
case EXPR_TYPEID:
|
||||||
case EXPR_TYPEID_INFO:
|
case EXPR_TYPEID_INFO:
|
||||||
case EXPR_TAGOF:
|
case EXPR_TAGOF:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
if (!sema_analyse_expr(active_context, main_expr)) return false;
|
if (!sema_analyse_expr(active_context, main_expr)) return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -9599,6 +9667,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr)
|
|||||||
case EXPR_SWIZZLE:
|
case EXPR_SWIZZLE:
|
||||||
case EXPR_MACRO_BODY:
|
case EXPR_MACRO_BODY:
|
||||||
case EXPR_DEFAULT_ARG:
|
case EXPR_DEFAULT_ARG:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
case EXPR_TAGOF:
|
case EXPR_TAGOF:
|
||||||
RETURN_SEMA_ERROR(expr, "Expected '()' after this.");
|
RETURN_SEMA_ERROR(expr, "Expected '()' after this.");
|
||||||
@@ -9900,6 +9969,8 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr)
|
|||||||
if (!expr_ok(expr)) return false;
|
if (!expr_ok(expr)) return false;
|
||||||
switch (expr->expr_kind)
|
switch (expr->expr_kind)
|
||||||
{
|
{
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
|
RETURN_SEMA_ERROR(expr, "Expected a parameter to 'get', e.g. '$member.get(value)'.");
|
||||||
case EXPR_MACRO_BODY_EXPANSION:
|
case EXPR_MACRO_BODY_EXPANSION:
|
||||||
if (!expr->body_expansion_expr.first_stmt)
|
if (!expr->body_expansion_expr.first_stmt)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ RETRY:
|
|||||||
case EXPR_EMBED:
|
case EXPR_EMBED:
|
||||||
case EXPR_MACRO_BODY:
|
case EXPR_MACRO_BODY:
|
||||||
case EXPR_OTHER_CONTEXT:
|
case EXPR_OTHER_CONTEXT:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
case EXPR_DESIGNATOR:
|
case EXPR_DESIGNATOR:
|
||||||
sema_trace_expr_liveness(expr->designator_expr.value);
|
sema_trace_expr_liveness(expr->designator_expr.value);
|
||||||
|
|||||||
@@ -632,6 +632,7 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
|
|||||||
case EXPR_TERNARY:
|
case EXPR_TERNARY:
|
||||||
case EXPR_LAST_FAULT:
|
case EXPR_LAST_FAULT:
|
||||||
case EXPR_TAGOF:
|
case EXPR_TAGOF:
|
||||||
|
case EXPR_MEMBER_GET:
|
||||||
return false;
|
return false;
|
||||||
case EXPR_BITACCESS:
|
case EXPR_BITACCESS:
|
||||||
case EXPR_BUILTIN:
|
case EXPR_BUILTIN:
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ void symtab_init(uint32_t capacity)
|
|||||||
type_property_list[TYPE_PROPERTY_ASSOCIATED] = KW_DEF("associated");
|
type_property_list[TYPE_PROPERTY_ASSOCIATED] = KW_DEF("associated");
|
||||||
type_property_list[TYPE_PROPERTY_ELEMENTS] = KW_DEF("elements");
|
type_property_list[TYPE_PROPERTY_ELEMENTS] = KW_DEF("elements");
|
||||||
type_property_list[TYPE_PROPERTY_EXTNAMEOF] = KW_DEF("extnameof");
|
type_property_list[TYPE_PROPERTY_EXTNAMEOF] = KW_DEF("extnameof");
|
||||||
|
type_property_list[TYPE_PROPERTY_GET] = KW_DEF("get");
|
||||||
type_property_list[TYPE_PROPERTY_INF] = KW_DEF("inf");
|
type_property_list[TYPE_PROPERTY_INF] = KW_DEF("inf");
|
||||||
type_property_list[TYPE_PROPERTY_INNER] = KW_DEF("inner");
|
type_property_list[TYPE_PROPERTY_INNER] = KW_DEF("inner");
|
||||||
type_property_list[TYPE_PROPERTY_IS_EQ] = KW_DEF("is_eq");
|
type_property_list[TYPE_PROPERTY_IS_EQ] = KW_DEF("is_eq");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ macro deep_print(a)
|
|||||||
io::print("{");
|
io::print("{");
|
||||||
$foreach ($i, $m : $typeof(a).membersof)
|
$foreach ($i, $m : $typeof(a).membersof)
|
||||||
if ($i > 0) io::print(", ");
|
if ($i > 0) io::print(", ");
|
||||||
deep_print(a.$eval($m.nameof));
|
deep_print($m.get(a));
|
||||||
$endforeach
|
$endforeach
|
||||||
io::print("}");
|
io::print("}");
|
||||||
$default:
|
$default:
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ fn void! TextTemplate.init(&self, String template, String tag_start = "{{", Stri
|
|||||||
.data = (String*)(data + $m.offsetof),
|
.data = (String*)(data + $m.offsetof),
|
||||||
};
|
};
|
||||||
$default:
|
$default:
|
||||||
$if $defined(self.data.$eval($m.nameof).as_stream):
|
$if $defined($m.get(self.data).as_stream):
|
||||||
return TextTag{
|
return TextTag{
|
||||||
.kind = TEMPLATE,
|
.kind = TEMPLATE,
|
||||||
.template = self.data.$eval($m.nameof).as_stream(),
|
.template = self.data.$eval($m.nameof).as_stream(),
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ fn void methodsof()
|
|||||||
Foo foo = { .i = 4, .b = true };
|
Foo foo = { .i = 4, .b = true };
|
||||||
assert(Foo.$eval(Foo.methodsof[2])(&foo) == true); // Foo.xyz
|
assert(Foo.$eval(Foo.methodsof[2])(&foo) == true); // Foo.xyz
|
||||||
assert(Foo.$eval(Foo.methodsof[1])(&foo, 2) == 8); // Foo.bar
|
assert(Foo.$eval(Foo.methodsof[1])(&foo, 2) == 8); // Foo.bar
|
||||||
|
assert(Foo.$eval(Foo.methodsof[2])(&foo) == true); // Foo.xyz
|
||||||
|
assert(Foo.$eval(Foo.methodsof[1])(&foo, 2) == 8); // Foo.bar
|
||||||
|
|
||||||
Foo foo2 = { .i = 2, .b = false };
|
Foo foo2 = { .i = 2, .b = false };
|
||||||
assert(foo2.$eval(Foo.methodsof[2])() == false); // Foo.xyz
|
assert(foo2.$eval(Foo.methodsof[2])() == false); // Foo.xyz
|
||||||
|
|||||||
Reference in New Issue
Block a user