hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-19 15:51:57 +0200
committerhachem <im@hachem.wtf>2026-09-19 15:51:57 +0200
commitbe43ea893018090044cd411bc5b50787b99087b8 (patch)
tree379af1300ee53afa0a7029835257f254aaccfce2
parent6d8b0392bb0c0df82285eec1b0f692113e66eb1a (diff)
feat: add reapts and loops
-rw-r--r--ast.h1
-rw-r--r--eval.c18
-rw-r--r--examples/countdown.sfinae23
-rw-r--r--sfinae.l1
-rw-r--r--sfinae.y3
5 files changed, 46 insertions, 0 deletions
diff --git a/ast.h b/ast.h
index 4a5db15..e18b5d9 100644
--- a/ast.h
+++ b/ast.h
@@ -34,6 +34,7 @@ enum NodeKind
STMT_DECLARE,
STMT_UNDECLARE,
STMT_ENABLE_IF,
+ STMT_REPEAT,
STMT_EMIT,
STMT_STATIC_ASSERT
};
diff --git a/eval.c b/eval.c
index 3f27fa2..2f79a5d 100644
--- a/eval.c
+++ b/eval.c
@@ -266,6 +266,23 @@ static enum RunStatus enable_if(struct Machine* machine, const struct Node* node
return execute(machine, node->body);
}
+// runs the body count times. no index, no condition, no break. you wanted a loop
+static enum RunStatus repeat(struct Machine* machine, const struct Node* node)
+{
+ int64_t count = 0;
+ if (evaluate_value(machine, node->first, &count))
+ return RUN_FAILED;
+
+ for (int64_t index = 0; index < count; index++)
+ {
+ enum RunStatus status = execute(machine, node->body);
+ if (status != RUN_DONE)
+ return status;
+ }
+
+ return RUN_DONE;
+}
+
static enum RunStatus static_assert_statement(struct Machine* machine, const struct Node* node)
{
bool truth = false;
@@ -288,6 +305,7 @@ static enum RunStatus execute_one(struct Machine* machine, const struct Node* no
case STMT_DECLARE: return declare(machine, node);
case STMT_UNDECLARE: return undeclare(machine, node);
case STMT_ENABLE_IF: return enable_if(machine, node);
+ case STMT_REPEAT: return repeat(machine, node);
case STMT_EMIT: return emit(machine, node);
case STMT_STATIC_ASSERT: return static_assert_statement(machine, node);
default: break;
diff --git a/examples/countdown.sfinae b/examples/countdown.sfinae
new file mode 100644
index 0000000..bd7c4a3
--- /dev/null
+++ b/examples/countdown.sfinae
@@ -0,0 +1,23 @@
+// count from 3 down to 1, then make sure we got to 0
+// ::repeat runs its sequence a number of times, and that is the whole loop
+
+::declare<::name<'i'>, ::decltype(::difference<'D', 'A'>)>::commit;
+
+::repeat<
+ ::value_of<::name<'i'>>,
+ ::sequence<
+ ::emit<::decltype(::value_of<::name<'i'>>)>::commit,
+ ::declare<
+ ::name<'n', 'e', 'x', 't'>,
+ ::decltype(::sum<::value_of<::name<'i'>>, ::difference<'A', 'B'>>)
+ >::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;
+
+::static_assert<::equal<::value_of<::name<'i'>>, ::difference<'A', 'A'>>::value>::commit;
+
+// a negative count runs nothing, which is the only sensible thing it could do
+::repeat<::difference<'A', 'D'>, ::sequence<::static_assert<::false_type::value>::commit>>::commit;
diff --git a/sfinae.l b/sfinae.l
index 0ab1eeb..c8099c9 100644
--- a/sfinae.l
+++ b/sfinae.l
@@ -38,6 +38,7 @@ static int fail(const char* message)
"declare" return TOK_DECLARE;
"undeclare" return TOK_UNDECLARE;
"enable_if_t" return TOK_ENABLE_IF;
+"repeat" return TOK_REPEAT;
"sequence" return TOK_SEQUENCE;
"name" return TOK_NAME;
"value_of" return TOK_VALUE_OF;
diff --git a/sfinae.y b/sfinae.y
index f97147f..341be36 100644
--- a/sfinae.y
+++ b/sfinae.y
@@ -24,6 +24,7 @@ void yyerror(const char* message);
%token TOK_DECLARE
%token TOK_UNDECLARE
%token TOK_ENABLE_IF
+%token TOK_REPEAT
%token TOK_SEQUENCE
%token TOK_NAME
%token TOK_VALUE_OF
@@ -79,6 +80,8 @@ statement
{ $$ = node_named(STMT_UNDECLARE, &$4, NULL); }
| TOK_COLONCOLON TOK_ENABLE_IF '<' condition ',' sequence '>' TOK_COLONCOLON TOK_COMMIT
{ $$ = node_block(STMT_ENABLE_IF, $4, $6); }
+ | TOK_COLONCOLON TOK_REPEAT '<' value ',' sequence '>' TOK_COLONCOLON TOK_COMMIT
+ { $$ = node_block(STMT_REPEAT, $4, $6); }
;
// the statements inside are committed one by one, without the semicolons