From b20c46c555986a99be70de61d91bc225e53f31d2 Mon Sep 17 00:00:00 2001 From: hachem Date: Sat, 19 Sep 2026 11:52:25 +0200 Subject: eval: sum product and quotient --- ast.h | 3 +++ eval.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- eval.h | 4 +++- examples/sums.sfinae | 3 +++ sfinae.l | 3 +++ sfinae.y | 9 +++++++++ 6 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 examples/sums.sfinae diff --git a/ast.h b/ast.h index 1a6f159..778a765 100644 --- a/ast.h +++ b/ast.h @@ -5,6 +5,9 @@ enum NodeKind NODE_CHAR, TYPE_DECLTYPE, VALUE_DIFFERENCE, + VALUE_SUM, + VALUE_PRODUCT, + VALUE_QUOTIENT, STMT_EMIT }; diff --git a/eval.c b/eval.c index 5841566..f9f47b6 100644 --- a/eval.c +++ b/eval.c @@ -1,14 +1,54 @@ #include +#include #include #include "eval.h" -static int evaluate_value(const struct Node* node, long* out) +static int evaluate_value(const struct Node* node, int64_t* out); + +static int complain(const struct Node* node, const char* message) +{ + (void)fprintf(stderr, "line %d: %s\n", node->line, message); + return 1; +} + +static int evaluate_operands(const struct Node* node, int64_t* left, int64_t* right) { + if (evaluate_value(node->first, left)) + return 1; + + return evaluate_value(node->second, right); +} + +static int evaluate_value(const struct Node* node, int64_t* out) +{ + int64_t left = 0; + int64_t right = 0; switch (node->kind) { case VALUE_DIFFERENCE: - *out = (long)node->first->character - (long)node->second->character; + *out = (int64_t)node->first->character - (int64_t)node->second->character; + return 0; + case VALUE_SUM: + if (evaluate_operands(node, &left, &right)) + return 1; + + *out = left + right; + return 0; + case VALUE_PRODUCT: + if (evaluate_operands(node, &left, &right)) + return 1; + + *out = left * right; + return 0; + case VALUE_QUOTIENT: + if (evaluate_operands(node, &left, &right)) + return 1; + + if (right == 0) + return complain(node, "division by zero"); + + *out = left / right; return 0; default: break; } @@ -42,7 +82,7 @@ static enum RunStatus emit(const struct Node* node) return RUN_FAILED; if (type.kind == KIND_VALUE) - (void)printf("%ld\n", type.number); + (void)printf("%" PRId64 "\n", type.number); return RUN_DONE; } diff --git a/eval.h b/eval.h index 8b4a5f6..49101f1 100644 --- a/eval.h +++ b/eval.h @@ -2,6 +2,8 @@ #include "ast.h" +#include + enum TypeKind { KIND_VOID, @@ -11,7 +13,7 @@ enum TypeKind struct Type { enum TypeKind kind; - long number; + int64_t number; }; enum RunStatus diff --git a/examples/sums.sfinae b/examples/sums.sfinae new file mode 100644 index 0000000..b5ffb62 --- /dev/null +++ b/examples/sums.sfinae @@ -0,0 +1,3 @@ +::emit<::decltype(::sum<::difference<'F', 'A'>, ::difference<'C', 'A'>>)>::commit; +::emit<::decltype(::product<::difference<'D', 'A'>, ::difference<'E', 'A'>>)>::commit; +::emit<::decltype(::quotient<::difference<'H', 'A'>, ::difference<'C', 'A'>>)>::commit; diff --git a/sfinae.l b/sfinae.l index 5c67f3c..5857a2b 100644 --- a/sfinae.l +++ b/sfinae.l @@ -36,6 +36,9 @@ static int fail(const char* message) "commit" return TOK_COMMIT; "decltype" return TOK_DECLTYPE; "difference" return TOK_DIFFERENCE; +"sum" return TOK_SUM; +"product" return TOK_PRODUCT; +"quotient" return TOK_QUOTIENT; [<>(),;] return yytext[0]; '\\.' yylval.character = unescape(yytext[2]); return TOK_CHAR; '.' yylval.character = yytext[1]; return TOK_CHAR; diff --git a/sfinae.y b/sfinae.y index 2e91b23..3e7c9b1 100644 --- a/sfinae.y +++ b/sfinae.y @@ -20,6 +20,9 @@ void yyerror(const char* message); %token TOK_COMMIT %token TOK_DECLTYPE %token TOK_DIFFERENCE +%token TOK_SUM +%token TOK_PRODUCT +%token TOK_QUOTIENT %token TOK_CHAR %type statements statement type value @@ -51,6 +54,12 @@ type value : TOK_COLONCOLON TOK_DIFFERENCE '<' TOK_CHAR ',' TOK_CHAR '>' { $$ = node_binary(VALUE_DIFFERENCE, node_char($4), node_char($6)); } + | TOK_COLONCOLON TOK_SUM '<' value ',' value '>' + { $$ = node_binary(VALUE_SUM, $4, $6); } + | TOK_COLONCOLON TOK_PRODUCT '<' value ',' value '>' + { $$ = node_binary(VALUE_PRODUCT, $4, $6); } + | TOK_COLONCOLON TOK_QUOTIENT '<' value ',' value '>' + { $$ = node_binary(VALUE_QUOTIENT, $4, $6); } ; %% -- cgit v1.3