hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-19 11:52:25 +0200
committerhachem <im@hachem.wtf>2026-09-19 11:52:25 +0200
commitb20c46c555986a99be70de61d91bc225e53f31d2 (patch)
tree7c3b94ca7cd894e0597bcef65f5f19ea9f1e7ecd
parentdd52ccd9319aa847cddc486519075b806c9e9092 (diff)
eval: sum product and quotient
-rw-r--r--ast.h3
-rw-r--r--eval.c46
-rw-r--r--eval.h4
-rw-r--r--examples/sums.sfinae3
-rw-r--r--sfinae.l3
-rw-r--r--sfinae.y9
6 files changed, 64 insertions, 4 deletions
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 <assert.h>
+#include <inttypes.h>
#include <stdio.h>
#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 <stdint.h>
+
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 <character> TOK_CHAR
%type <node> 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); }
;
%%