hachem.wtf
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-19 16:15:50 +0200
committerhachem <im@hachem.wtf>2026-09-19 16:15:50 +0200
commit0a9605b6b13f2e066a69662f5802b397f8b89424 (patch)
treefe063a37fb8de67f3e176ec99cc4a1cc1cadf21d
parentbe43ea893018090044cd411bc5b50787b99087b8 (diff)
feat: char and integral_constant types
-rw-r--r--ast.h2
-rw-r--r--eval.c9
-rw-r--r--eval.h2
-rw-r--r--examples/chars.sfinae16
-rw-r--r--sfinae.l1
-rw-r--r--sfinae.y5
6 files changed, 35 insertions, 0 deletions
diff --git a/ast.h b/ast.h
index e18b5d9..da409be 100644
--- a/ast.h
+++ b/ast.h
@@ -17,6 +17,8 @@ enum NodeKind
TYPE_ARRAY,
TYPE_CONDITIONAL,
TYPE_DECLTYPE,
+ TYPE_CHAR,
+ TYPE_CHAR_CONSTANT,
VALUE_DIFFERENCE,
VALUE_SUM,
VALUE_PRODUCT,
diff --git a/eval.c b/eval.c
index 2f79a5d..170b122 100644
--- a/eval.c
+++ b/eval.c
@@ -130,6 +130,13 @@ static int evaluate_type(struct Machine* machine, const struct Node* node, struc
case TYPE_INT32: out->kind = KIND_INT32; return 0;
case TYPE_BYTE: out->kind = KIND_BYTE; return 0;
case TYPE_SIZE: out->kind = KIND_SIZE; return 0;
+ case TYPE_CHAR: out->kind = KIND_CHAR; return 0;
+ case TYPE_CHAR_CONSTANT:
+ if (evaluate_value(machine, node->first, &out->number))
+ return 1;
+
+ out->kind = KIND_CHAR_CONSTANT;
+ return 0;
case TYPE_REMOVE_CV: return evaluate_type(machine, node->first, out);
case TYPE_ARRAY:
if (evaluate_type(machine, node->first, &element) ||
@@ -248,6 +255,8 @@ static enum RunStatus emit(struct Machine* machine, const struct Node* node)
case KIND_BYTE: (void)printf("byte\n"); break;
case KIND_SIZE: (void)printf("size_t\n"); break;
case KIND_ARRAY: (void)printf("array[%" PRId64 "]\n", type.number); break;
+ case KIND_CHAR: (void)printf("char\n"); break;
+ case KIND_CHAR_CONSTANT: (void)printf("%c\n", (char)type.number); break;
case KIND_VALUE: (void)printf("%" PRId64 "\n", type.number); break;
}
diff --git a/eval.h b/eval.h
index eba8244..eb3fe1d 100644
--- a/eval.h
+++ b/eval.h
@@ -14,6 +14,8 @@ enum TypeKind
KIND_BYTE,
KIND_SIZE,
KIND_ARRAY,
+ KIND_CHAR,
+ KIND_CHAR_CONSTANT,
KIND_VALUE
};
diff --git a/examples/chars.sfinae b/examples/chars.sfinae
new file mode 100644
index 0000000..b38118b
--- /dev/null
+++ b/examples/chars.sfinae
@@ -0,0 +1,16 @@
+// ::integral_constant<::char, V> is a type that says one character
+// there are no character values, so it says its own distance from '\0'
+
+::emit<::integral_constant<::char, ::difference<'h', '\0'>>>::commit;
+::emit<::integral_constant<::char, ::difference<'i', '\0'>>>::commit;
+
+// ::char on its own is a type like any other, and says its name
+::emit<::remove_cv_t<::char>>::commit;
+
+// two character types are the same type when they say the same thing
+::static_assert<
+ ::is_same<
+ ::integral_constant<::char, ::difference<'a', '\0'>>,
+ ::integral_constant<::char, ::sum<::difference<'a', 'b'>, ::difference<'b', '\0'>>>
+ >::value
+>::commit;
diff --git a/sfinae.l b/sfinae.l
index c8099c9..f5b9cf1 100644
--- a/sfinae.l
+++ b/sfinae.l
@@ -46,6 +46,7 @@ static int fail(const char* message)
"int32_t" return TOK_INT32;
"byte" return TOK_BYTE;
"size_t" return TOK_SIZE_T;
+"char" return TOK_CHAR_T;
"remove_cv_t" return TOK_REMOVE_CV;
"decltype" return TOK_DECLTYPE;
"difference" return TOK_DIFFERENCE;
diff --git a/sfinae.y b/sfinae.y
index 341be36..aa7650b 100644
--- a/sfinae.y
+++ b/sfinae.y
@@ -32,6 +32,7 @@ void yyerror(const char* message);
%token TOK_INT32
%token TOK_BYTE
%token TOK_SIZE_T
+%token TOK_CHAR_T
%token TOK_REMOVE_CV
%token TOK_DECLTYPE
%token TOK_DIFFERENCE
@@ -138,6 +139,10 @@ type
{ $$ = node_ternary(TYPE_CONDITIONAL, $4, $6, $8); }
| TOK_COLONCOLON TOK_DECLTYPE '(' value ')'
{ $$ = node_unary(TYPE_DECLTYPE, $4); }
+ | TOK_COLONCOLON TOK_CHAR_T
+ { $$ = node_leaf(TYPE_CHAR); }
+ | TOK_COLONCOLON TOK_INTEGRAL_CONSTANT '<' TOK_COLONCOLON TOK_CHAR_T ',' value '>'
+ { $$ = node_unary(TYPE_CHAR_CONSTANT, $7); }
;
value