From 6487b5b5301f6cb37c95c3571578d5a42adb2a1a Mon Sep 17 00:00:00 2001 From: hachem Date: Sat, 19 Sep 2026 20:50:28 +0200 Subject: feat: declval --- ast.h | 1 + eval.c | 9 +++++++ examples/fibonacci.sfinae | 68 +++++++++++++++++++++++++++++++++++++++++++++++ sfinae.l | 1 + sfinae.y | 3 +++ 5 files changed, 82 insertions(+) create mode 100644 examples/fibonacci.sfinae diff --git a/ast.h b/ast.h index e8d4c45..2da24d8 100644 --- a/ast.h +++ b/ast.h @@ -33,6 +33,7 @@ enum NodeKind VALUE_INTEGRAL_CONSTANT, VALUE_CONDITIONAL, VALUE_VARIABLE, + VALUE_DECLVAL, COND_TRUE, COND_FALSE, diff --git a/eval.c b/eval.c index c872c90..aeae982 100644 --- a/eval.c +++ b/eval.c @@ -121,6 +121,15 @@ static int evaluate_value(struct Machine* machine, const struct Node* node, int6 *out = variable->value; return 0; + case VALUE_DECLVAL: + if (evaluate_type(machine, node->first, &type)) + return 1; + + if (type.kind != KIND_VALUE) + return complain(node, "declval of a type with no value in it, what did you expect"); + + *out = type.number; + return 0; case VALUE_CONDITIONAL: if (evaluate_condition(machine, node->first, &truth)) return 1; diff --git a/examples/fibonacci.sfinae b/examples/fibonacci.sfinae new file mode 100644 index 0000000..844aa69 --- /dev/null +++ b/examples/fibonacci.sfinae @@ -0,0 +1,68 @@ +// fib(0) to fib(10), each line a tuple: some characters, the counter, and the call +// ::declval() pulls the value back out of a call result so it can go into ::sum + +::define< + ::name<'f', 'i', 'b'>, + ::parameters<::name<'n'>>, + ::sequence< + ::enable_if_t< + ::less<::value_of<::name<'n'>>, ::difference<'C', 'A'>>::value, + ::sequence<::return<::decltype(::value_of<::name<'n'>>)>::commit> + >::commit, + ::return< + ::decltype( + ::sum< + ::declval< + ::invoke_result_t< + ::name<'f', 'i', 'b'>, + ::arguments< + ::decltype(::sum<::value_of<::name<'n'>>, ::difference<'A', 'B'>>) + > + > + >(), + ::declval< + ::invoke_result_t< + ::name<'f', 'i', 'b'>, + ::arguments< + ::decltype(::sum<::value_of<::name<'n'>>, ::difference<'A', 'C'>>) + > + > + >() + > + ) + >::commit + > +>::commit; + +::declare<::name<'i'>, ::decltype(::difference<'A', 'A'>)>::commit; + +::repeat< + ::difference<'L', 'A'>, + ::sequence< + ::emit< + ::tuple< + ::integral_constant<::char, ::difference<'f', '\0'>>, + ::integral_constant<::char, ::difference<'i', '\0'>>, + ::integral_constant<::char, ::difference<'b', '\0'>>, + ::integral_constant<::char, ::difference<'(', '\0'>>, + ::decltype(::value_of<::name<'i'>>), + ::integral_constant<::char, ::difference<')', '\0'>>, + ::integral_constant<::char, ::difference<' ', '\0'>>, + ::integral_constant<::char, ::difference<'-', '\0'>>, + ::integral_constant<::char, ::difference<'>', '\0'>>, + ::integral_constant<::char, ::difference<' ', '\0'>>, + ::invoke_result_t< + ::name<'f', 'i', 'b'>, + ::arguments<::decltype(::value_of<::name<'i'>>)> + > + > + >::commit, + ::declare< + ::name<'n', 'e', 'x', 't'>, + ::decltype(::sum<::value_of<::name<'i'>>, ::difference<'B', 'A'>>) + >::commit, + ::undeclare<::name<'i'>>::commit, + ::declare<::name<'i'>, ::decltype(::value_of<::name<'n', 'e', 'x', 't'>>)>::commit, + ::undeclare<::name<'n', 'e', 'x', 't'>>::commit + > +>::commit; diff --git a/sfinae.l b/sfinae.l index 63314c9..7157b7f 100644 --- a/sfinae.l +++ b/sfinae.l @@ -47,6 +47,7 @@ static int fail(const char* message) "sequence" return TOK_SEQUENCE; "name" return TOK_NAME; "value_of" return TOK_VALUE_OF; +"declval" return TOK_DECLVAL; "void" return TOK_VOID; "int32_t" return TOK_INT32; "byte" return TOK_BYTE; diff --git a/sfinae.y b/sfinae.y index 4e366a8..14eb5f8 100644 --- a/sfinae.y +++ b/sfinae.y @@ -33,6 +33,7 @@ void yyerror(const char* message); %token TOK_SEQUENCE %token TOK_NAME %token TOK_VALUE_OF +%token TOK_DECLVAL %token TOK_VOID %token TOK_INT32 %token TOK_BYTE @@ -197,6 +198,8 @@ value { $$ = node_binary(VALUE_QUOTIENT, $4, $6); } | TOK_COLONCOLON TOK_VALUE_OF '<' name '>' { $$ = node_named(VALUE_VARIABLE, &$4, NULL); } + | TOK_COLONCOLON TOK_DECLVAL '<' type '>' '(' ')' + { $$ = node_unary(VALUE_DECLVAL, $4); } | TOK_COLONCOLON TOK_EXTENT '<' type '>' TOK_COLONCOLON TOK_VALUE { $$ = node_unary(VALUE_EXTENT, $4); } | TOK_COLONCOLON TOK_TUPLE_SIZE '<' type '>' TOK_COLONCOLON TOK_VALUE -- cgit v1.3