diff options
| author | hachem <im@hachem.wtf> | 2026-09-19 12:38:43 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-19 12:38:43 +0200 |
| commit | a79c97e04562b171780a24cba2cb1a71acfa4bbb (patch) | |
| tree | 412642f948a30eb220512c304b34d60356f23b42 | |
| parent | 74a8a2b10a0513f5346ec47aa9b463e30f2b972e (diff) | |
types: array, extent, tuple_size, integral_constant
| -rw-r--r-- | ast.h | 4 | ||||
| -rw-r--r-- | eval.c | 20 | ||||
| -rw-r--r-- | eval.h | 1 | ||||
| -rw-r--r-- | examples/xs.sfinae | 36 | ||||
| -rw-r--r-- | sfinae.l | 5 | ||||
| -rw-r--r-- | sfinae.y | 14 |
6 files changed, 80 insertions, 0 deletions
@@ -8,11 +8,15 @@ enum NodeKind TYPE_BYTE, TYPE_SIZE, TYPE_REMOVE_CV, + TYPE_ARRAY, TYPE_DECLTYPE, VALUE_DIFFERENCE, VALUE_SUM, VALUE_PRODUCT, VALUE_QUOTIENT, + VALUE_EXTENT, + VALUE_TUPLE_SIZE, + VALUE_INTEGRAL_CONSTANT, STMT_EMIT }; @@ -4,6 +4,7 @@ #include "eval.h" +static int evaluate_type(const struct Node* node, struct Type* out); static int evaluate_value(const struct Node* node, int64_t* out); static int complain(const struct Node* node, const char* message) @@ -24,6 +25,7 @@ static int evaluate_value(const struct Node* node, int64_t* out) { int64_t left = 0; int64_t right = 0; + struct Type type; switch (node->kind) { case VALUE_DIFFERENCE: @@ -50,6 +52,15 @@ static int evaluate_value(const struct Node* node, int64_t* out) *out = left / right; return 0; + case VALUE_EXTENT: + case VALUE_TUPLE_SIZE: + if (evaluate_type(node->first, &type)) + return 1; + + // a non-array has no extent, so it gets zero, exactly like the real thing + *out = type.kind == KIND_ARRAY ? type.number : 0; + return 0; + case VALUE_INTEGRAL_CONSTANT: return evaluate_value(node->first, out); default: break; } @@ -61,6 +72,7 @@ static int evaluate_type(const struct Node* node, struct Type* out) { out->kind = KIND_VOID; out->number = 0; + struct Type element; switch (node->kind) { case TYPE_VOID: return 0; @@ -68,6 +80,13 @@ static int evaluate_type(const struct Node* node, struct Type* out) case TYPE_BYTE: out->kind = KIND_BYTE; return 0; case TYPE_SIZE: out->kind = KIND_SIZE; return 0; case TYPE_REMOVE_CV: return evaluate_type(node->first, out); + case TYPE_ARRAY: + // the element type is evaluated for its side of the bargain, then forgotten + if (evaluate_type(node->first, &element) || evaluate_value(node->second, &out->number)) + return 1; + + out->kind = KIND_ARRAY; + return 0; case TYPE_DECLTYPE: if (evaluate_value(node->first, &out->number)) return 1; @@ -92,6 +111,7 @@ static enum RunStatus emit(const struct Node* node) case KIND_INT32: (void)printf("int32_t\n"); break; 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_VALUE: (void)printf("%" PRId64 "\n", type.number); break; } @@ -10,6 +10,7 @@ enum TypeKind KIND_INT32, KIND_BYTE, KIND_SIZE, + KIND_ARRAY, KIND_VALUE }; diff --git a/examples/xs.sfinae b/examples/xs.sfinae new file mode 100644 index 0000000..faae464 --- /dev/null +++ b/examples/xs.sfinae @@ -0,0 +1,36 @@ +// the original sin: how wide is int xs[20][20] + +::emit< + ::decltype( + ::extent< + ::array< + ::array< + ::remove_cv_t< + ::int32_t + >, + ::integral_constant< + ::size_t, + ::tuple_size< + ::array< + ::byte, + ::difference<'Z', 'F'> + > + >::value + >::value + >, + ::integral_constant< + ::size_t, + ::difference<'Z', 'F'> + >::value + > + >::value + ) +>::commit; + +// an array type says its extent, a bare type says its name +::emit< + ::array< + ::byte, + ::difference<'Z', 'F'> + > +>::commit; @@ -44,6 +44,11 @@ static int fail(const char* message) "sum" return TOK_SUM; "product" return TOK_PRODUCT; "quotient" return TOK_QUOTIENT; +"array" return TOK_ARRAY; +"extent" return TOK_EXTENT; +"tuple_size" return TOK_TUPLE_SIZE; +"integral_constant" return TOK_INTEGRAL_CONSTANT; +"value" return TOK_VALUE; [<>(),;] return yytext[0]; '\\.' yylval.character = unescape(yytext[2]); return TOK_CHAR; '.' yylval.character = yytext[1]; return TOK_CHAR; @@ -28,6 +28,11 @@ void yyerror(const char* message); %token TOK_SUM %token TOK_PRODUCT %token TOK_QUOTIENT +%token TOK_ARRAY +%token TOK_EXTENT +%token TOK_TUPLE_SIZE +%token TOK_INTEGRAL_CONSTANT +%token TOK_VALUE %token <character> TOK_CHAR %type <node> statements statement type value @@ -62,6 +67,8 @@ type { $$ = node_leaf(TYPE_SIZE); } | TOK_COLONCOLON TOK_REMOVE_CV '<' type '>' { $$ = node_unary(TYPE_REMOVE_CV, $4); } + | TOK_COLONCOLON TOK_ARRAY '<' type ',' value '>' + { $$ = node_binary(TYPE_ARRAY, $4, $6); } | TOK_COLONCOLON TOK_DECLTYPE '(' value ')' { $$ = node_unary(TYPE_DECLTYPE, $4); } ; @@ -75,6 +82,13 @@ value { $$ = node_binary(VALUE_PRODUCT, $4, $6); } | TOK_COLONCOLON TOK_QUOTIENT '<' value ',' value '>' { $$ = node_binary(VALUE_QUOTIENT, $4, $6); } + | TOK_COLONCOLON TOK_EXTENT '<' type '>' TOK_COLONCOLON TOK_VALUE + { $$ = node_unary(VALUE_EXTENT, $4); } + | TOK_COLONCOLON TOK_TUPLE_SIZE '<' type '>' TOK_COLONCOLON TOK_VALUE + { $$ = node_unary(VALUE_TUPLE_SIZE, $4); } + | TOK_COLONCOLON TOK_INTEGRAL_CONSTANT '<' TOK_COLONCOLON TOK_SIZE_T ',' value '>' + TOK_COLONCOLON TOK_VALUE + { $$ = node_unary(VALUE_INTEGRAL_CONSTANT, $7); } ; %% |
