poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] pkl: add support for suffix for integral arrays


From: Mohammad-Reza Nabipoor
Subject: [PATCH 2/2] pkl: add support for suffix for integral arrays
Date: Sun, 24 Mar 2024 21:44:52 +0100

With this commit user can specify a suffix for integral array
literals:
        [1,2,3]UB == [1UB,2UB,3UB]
        [1,0xff,-1]U == [1U,0xffU,0xffffffffU]

All suffixes for integers are supported:
        t, T, n, N, b, B, h, H, l, L
        ut, UT, un, UN, ub, UB, uh, UH, ul, UL

2024-03-24  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>

        * doc/poke.texi (Array Literals): Document new feature.
        * libpoke/pkl-ast.h (PKL_AST_ARRAY_TYPE_TO_CAST): New accessor
        macro.
        (type_to_cast): New field which contains the type which should
        be the target of the cast.
        * libpoke/pkl-ast.c (pkl_ast_node_free_1): Handle new field.
        * libpoke/pkl-lex.l (parse_integer_literal_suffix): New function.
        ("]"{IS}): New rule to support array literals with suffix, e.g.,
        `[1,2,3]UB' to be the same as `[1UB,2UB,3UB]'.
        (integral literals rule): Use `parse_integer_literal_suffix'.
        * libpoke/pkl-tab.y (ARRSUF): New token for closing bracket with
        suffix: ]U, ]UB, etc.
        (array): Add support for suffix for array literals.
        * libpoke/pkl-typify.c (pkl_typify1_ps_array): Add check to verify
        user is using suffix only for integral arrays.
        * libpoke/pkl-promo.c (pkl_promo_ps_array): New phase to add casts
        to all elements of the array if array has a suffix.
        (pkl_phase_promo): Register `pkl_promo_ps_array).
        * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
        * testsuite/poke.pkl/array-4.pk: New test.
        * testsuite/poke.pkl/array-5.pk: Likewise.
        * testsuite/poke.pkl/array-6.pk: Likewise.
        * testsuite/poke.pkl/array-7.pk: Likewise.
        * testsuite/poke.pkl/array-8.pk: Likewise.
        * testsuite/poke.pkl/array-9.pk: Likewise.
        * testsuite/poke.pkl/array-10.pk: Likewise.
---
 ChangeLog                      | 29 ++++++++++++++
 doc/poke.texi                  | 12 ++++++
 libpoke/pkl-ast.c              |  2 +
 libpoke/pkl-ast.h              |  2 +
 libpoke/pkl-lex.l              | 73 +++++++++++++++++++++++-----------
 libpoke/pkl-promo.c            | 36 +++++++++++++++++
 libpoke/pkl-tab.y              | 11 +++++
 libpoke/pkl-typify.c           | 14 +++++++
 testsuite/Makefile.am          |  7 ++++
 testsuite/poke.pkl/array-10.pk | 13 ++++++
 testsuite/poke.pkl/array-4.pk  |  9 +++++
 testsuite/poke.pkl/array-5.pk  |  9 +++++
 testsuite/poke.pkl/array-6.pk  |  9 +++++
 testsuite/poke.pkl/array-7.pk  |  9 +++++
 testsuite/poke.pkl/array-8.pk  | 13 ++++++
 testsuite/poke.pkl/array-9.pk  |  9 +++++
 16 files changed, 233 insertions(+), 24 deletions(-)
 create mode 100644 testsuite/poke.pkl/array-10.pk
 create mode 100644 testsuite/poke.pkl/array-4.pk
 create mode 100644 testsuite/poke.pkl/array-5.pk
 create mode 100644 testsuite/poke.pkl/array-6.pk
 create mode 100644 testsuite/poke.pkl/array-7.pk
 create mode 100644 testsuite/poke.pkl/array-8.pk
 create mode 100644 testsuite/poke.pkl/array-9.pk

diff --git a/ChangeLog b/ChangeLog
index d1f2ffca..9c8d028a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2024-03-24  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
+
+       * doc/poke.texi (Array Literals): Document new feature.
+       * libpoke/pkl-ast.h (PKL_AST_ARRAY_TYPE_TO_CAST): New accessor
+       macro.
+       (type_to_cast): New field which contains the type which should
+       be the target of the cast.
+       * libpoke/pkl-ast.c (pkl_ast_node_free_1): Handle new field.
+       * libpoke/pkl-lex.l (parse_integer_literal_suffix): New function.
+       ("]"{IS}): New rule to support array literals with suffix, e.g.,
+       `[1,2,3]UB' to be the same as `[1UB,2UB,3UB]'.
+       (integral literals rule): Use `parse_integer_literal_suffix'.
+       * libpoke/pkl-tab.y (ARRSUF): New token for closing bracket with
+       suffix: ]U, ]UB, etc.
+       (array): Add support for suffix for array literals.
+       * libpoke/pkl-typify.c (pkl_typify1_ps_array): Add check to verify
+       user is using suffix only for integral arrays.
+       * libpoke/pkl-promo.c (pkl_promo_ps_array): New phase to add casts
+       to all elements of the array if array has a suffix.
+       (pkl_phase_promo): Register `pkl_promo_ps_array).
+       * testsuite/Makefile.am (EXTRA_DIST): Add new tests.
+       * testsuite/poke.pkl/array-4.pk: New test.
+       * testsuite/poke.pkl/array-5.pk: Likewise.
+       * testsuite/poke.pkl/array-6.pk: Likewise.
+       * testsuite/poke.pkl/array-7.pk: Likewise.
+       * testsuite/poke.pkl/array-8.pk: Likewise.
+       * testsuite/poke.pkl/array-9.pk: Likewise.
+       * testsuite/poke.pkl/array-10.pk: Likewise.
+
 2024-03-24  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
 
        * libpoke/pkl-fold.c (pkl_fold_ps_cast): Fix integer cast by
diff --git a/doc/poke.texi b/doc/poke.texi
index 9e347357..8301a4d9 100644
--- a/doc/poke.texi
+++ b/doc/poke.texi
@@ -10828,6 +10828,18 @@ a compilation-time error if evaluated, are:
 Array literals must contain at least one element.  Accordingly,
 @code{[]} is not a valid array literal.
 
+A set of suffixes can be used to construct array literals of integers
+of certain types.  @code{L} or @code{l} is for array of 64-bit integers.
+@code{H} or @code{h} is for array of 16-bit integers, @code{B} or @code{b}
+is for array of 8-bit integers, @code{n} or @code{N} is for array of
+4-bit integers and @code{t} or @code{T} is for array of 1-bit integers.
+
+@example
+[1,2,3]UB == [1UB,2UB,3UB]
+[1,2]UL == [1UL,2UL]
+[-1,-2,-3]UB == [0xffUB,0xfeUB,0xfdUB]
+@end example
+
 @cindex matrices
 This is how a @code{3x3} matrix could be constructed using an array of
 arrays:
diff --git a/libpoke/pkl-ast.c b/libpoke/pkl-ast.c
index c43118b2..96648375 100644
--- a/libpoke/pkl-ast.c
+++ b/libpoke/pkl-ast.c
@@ -2612,6 +2612,8 @@ pkl_ast_node_free_1 (gl_set_t visitations, pkl_ast_node 
ast)
           n = PKL_AST_CHAIN (t);
           PKL_AST_NODE_FREE (t);
         }
+      if (PKL_AST_ARRAY_TYPE_TO_CAST (ast))
+        PKL_AST_NODE_FREE (PKL_AST_ARRAY_TYPE_TO_CAST (ast));
 
       break;
 
diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
index 60ac9aff..0cfde5bc 100644
--- a/libpoke/pkl-ast.h
+++ b/libpoke/pkl-ast.h
@@ -371,6 +371,7 @@ pkl_ast_node pkl_ast_make_string (pkl_ast ast,
 #define PKL_AST_ARRAY_NELEM(AST) ((AST)->array.nelem)
 #define PKL_AST_ARRAY_NINITIALIZER(AST) ((AST)->array.ninitializer)
 #define PKL_AST_ARRAY_INITIALIZERS(AST) ((AST)->array.initializers)
+#define PKL_AST_ARRAY_TYPE_TO_CAST(AST) ((AST)->array.type_to_cast)
 
 struct pkl_ast_array
 {
@@ -379,6 +380,7 @@ struct pkl_ast_array
   size_t nelem;
   size_t ninitializer;
   union pkl_ast_node *initializers;
+  union pkl_ast_node *type_to_cast;
 };
 
 pkl_ast_node pkl_ast_make_array (pkl_ast ast,
diff --git a/libpoke/pkl-lex.l b/libpoke/pkl-lex.l
index 856509e6..a7ec56d3 100644
--- a/libpoke/pkl-lex.l
+++ b/libpoke/pkl-lex.l
@@ -136,10 +136,46 @@ pkl_lex_get_base (const char *str, int *offset)
   return base;
 }
 
+/* Parse the suffix for integer literals.
+
+   If there's no [uU] chars, set *SIGNED_P to 0, otherwise 1.
+   If there's no [tTnNbBhHlL] chars, set *WIDTH to 0, otherwise set
+   *WIDTH to corresponding width.  */
+
+void
+parse_integer_literal_suffix (int *signed_p, int *width, const char *end)
+{
+  *signed_p = 1;
+  if (*end == 'u' || *end == 'U'
+      || (*end != '\0' && (*(end + 1) == 'u' || *(end + 1) == 'U')))
+    *signed_p = 0;
+  else if (*end == 't' || *end == 'T'
+      || ((*end != '\0') && (*(end + 1) == 't' || *(end + 1) == 'T')))
+    *signed_p = 0;
+
+  *width = 0;
+  if (*end == 'l' || *end == 'L'
+      || ((*end != '\0') && (*(end + 1) == 'l' || *(end + 1) == 'L')))
+    *width = 64;
+  else  if (*end == 'h' || *end == 'H'
+      || ((*end != '\0') && (*(end + 1) == 'h' || *(end + 1) == 'H')))
+    *width = 16;
+  else  if (*end == 'b' || *end == 'B'
+      || ((*end != '\0') && (*(end + 1) == 'b' || *(end + 1) == 'B')))
+    *width = 8;
+  else if (*end == 'n' || *end == 'N'
+      || ((*end != '\0') && (*(end + 1) == 'n' || *(end + 1) == 'N')))
+    *width = 4;
+  else if (*end == 't' || *end == 'T'
+      || ((*end != '\0') && (*(end + 1) == 't' || *(end + 1) == 'T')))
+    *width = 1;
+}
+
 /* If the width is not already known (e.g., based on the suffix),
    the type of the integer constant is the smallest signed or unsigned
    integer capable of holding it, starting with 32 bits, in steps of
    power of two and up to 64 bits.  But note these are positive values!  */
+
 static int
 integer_literal_width (uint64_t value, int signed_p)
 {
@@ -156,6 +192,7 @@ integer_literal_width (uint64_t value, int signed_p)
    If the bit kidth of VALUE is not known, choose a proper width.
 
    Return 1 on detection of overflow, otherwise 0.  */
+
 static int
 integer_literal_overflow_handling (uint64_t *value, int signed_p, int width)
 {
@@ -342,6 +379,17 @@ GT >
 "--"                { return DEC; }
 "->"                { return IND; }
 
+"]"{IS} {
+  int signed_p, width;
+
+  parse_integer_literal_suffix (&signed_p, &width, &yytext[1]);
+  if (!width)
+    width = 32;
+  yylval->ast = pkl_ast_make_integral_type (yyextra->ast, width, signed_p);
+  yylval->ast = ASTREF (yylval->ast);
+  return ARRSUF;
+}
+
 "["                { return '['; }
 "]"                { return ']'; }
 "("                { return '('; }
@@ -570,30 +618,7 @@ GT >
       return LEXER_EXCEPTION;
     }
 
-  signed_p = 1;
-  if (*end == 'u' || *end == 'U'
-      || (*end != '\0' && (*(end + 1) == 'u' || *(end + 1) == 'U')))
-    signed_p = 0;
-  else if (*end == 't' || *end == 'T'
-      || ((*end != '\0') && (*(end + 1) == 't' || *(end + 1) == 'T')))
-    signed_p = 0;
-
-  width = 0;
-  if (*end == 'l' || *end == 'L'
-      || ((*end != '\0') && (*(end + 1) == 'l' || *(end + 1) == 'L')))
-    width = 64;
-  else  if (*end == 'h' || *end == 'H'
-      || ((*end != '\0') && (*(end + 1) == 'h' || *(end + 1) == 'H')))
-    width = 16;
-  else  if (*end == 'b' || *end == 'B'
-      || ((*end != '\0') && (*(end + 1) == 'b' || *(end + 1) == 'B')))
-    width = 8;
-  else if (*end == 'n' || *end == 'N'
-      || ((*end != '\0') && (*(end + 1) == 'n' || *(end + 1) == 'N')))
-    width = 4;
-  else if (*end == 't' || *end == 'T'
-      || ((*end != '\0') && (*(end + 1) == 't' || *(end + 1) == 'T')))
-    width = 1;
+  parse_integer_literal_suffix (&signed_p, &width, end);
 
   if (width == 0)
     width = integer_literal_width (value, signed_p);
diff --git a/libpoke/pkl-promo.c b/libpoke/pkl-promo.c
index 7745c127..f9158a12 100644
--- a/libpoke/pkl-promo.c
+++ b/libpoke/pkl-promo.c
@@ -1067,6 +1067,41 @@ PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_array_initializer)
 }
 PKL_PHASE_END_HANDLER
 
+/* If array has a literal suffix, cast all the elements to specified
+   type.  */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_promo_ps_array)
+{
+  pkl_ast_node node = PKL_PASS_NODE;
+  pkl_ast_node target_type = PKL_AST_ARRAY_TYPE_TO_CAST (node);
+  pkl_ast_node tmp, type;
+  int restart = 0;
+
+  if (!target_type)
+    /* Nothing to promote.  */
+    PKL_PASS_DONE;
+
+  for (tmp = PKL_AST_ARRAY_INITIALIZERS (node); tmp != NULL;
+       tmp = PKL_AST_CHAIN (tmp))
+    {
+      pkl_ast_node exp = PKL_AST_ARRAY_INITIALIZER_EXP (tmp);
+
+      if (!promote_node (PKL_PASS_AST, &exp, target_type, &restart))
+        {
+          PKL_ICE (PKL_AST_LOC (exp), "couldn't promote to target type");
+          PKL_PASS_ERROR;
+        }
+      PKL_AST_ARRAY_INITIALIZER_EXP (tmp) = exp;
+    }
+
+  type = PKL_AST_TYPE (node);
+  pkl_ast_node_free (PKL_AST_TYPE_A_ETYPE (type));
+  PKL_AST_TYPE_A_ETYPE (type) = ASTREF (target_type);
+
+  PKL_PASS_RESTART = 1;
+}
+PKL_PHASE_END_HANDLER
+
 /* In assignments, the r-value should be promoted to the type of the
    l-value, if that is suitable.  */
 
@@ -1842,6 +1877,7 @@ struct pkl_phase pkl_phase_promo =
    PKL_PHASE_PS_HANDLER (PKL_AST_INDEXER, pkl_promo_ps_indexer),
    PKL_PHASE_PS_HANDLER (PKL_AST_TRIMMER, pkl_promo_ps_trimmer),
    PKL_PHASE_PS_HANDLER (PKL_AST_ARRAY_INITIALIZER, 
pkl_promo_ps_array_initializer),
+   PKL_PHASE_PS_HANDLER (PKL_AST_ARRAY, pkl_promo_ps_array),
    PKL_PHASE_PS_HANDLER (PKL_AST_FUNCALL, pkl_promo_ps_funcall),
    PKL_PHASE_PS_HANDLER (PKL_AST_ASS_STMT, pkl_promo_ps_ass_stmt),
    PKL_PHASE_PS_HANDLER (PKL_AST_RETURN_STMT, pkl_promo_ps_return_stmt),
diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
index 45c5810a..611dfdbd 100644
--- a/libpoke/pkl-tab.y
+++ b/libpoke/pkl-tab.y
@@ -522,6 +522,8 @@ load_module (struct pkl_parser *parser,
 %token UNSIGNED         _("keyword `unsigned'")
 %token THREEDOTS        _("varargs indicator")
 
+%token <ast> ARRSUF     _("array suffix")
+
 /* This is for the dangling ELSE.  */
 
 %precedence THEN
@@ -1391,6 +1393,15 @@ array:
                                              $2);
                     PKL_AST_LOC ($$) = @$;
                 }
+        | '[' array_initializer_list opt_comma ARRSUF
+                {
+                    $$ = pkl_ast_make_array (pkl_parser->ast,
+                                             0 /* nelem */,
+                                             0 /* ninitializer */,
+                                             $2);
+                    PKL_AST_ARRAY_TYPE_TO_CAST ($$) = $4;
+                    PKL_AST_LOC ($$) = @$;
+                }
         ;
 
 array_initializer_list:
diff --git a/libpoke/pkl-typify.c b/libpoke/pkl-typify.c
index 7eac80f8..e157dccc 100644
--- a/libpoke/pkl-typify.c
+++ b/libpoke/pkl-typify.c
@@ -1095,6 +1095,20 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_array)
         }
     }
 
+  /* If array has a literal suffix, check that element type is integral.  */
+  if (PKL_AST_ARRAY_TYPE_TO_CAST (array))
+    {
+      if (PKL_AST_TYPE_CODE (type) != PKL_TYPE_INTEGRAL)
+        {
+          PKL_ERROR (PKL_AST_LOC (array),
+                     "arrays with literal suffix are only supported for "
+                     "integers");
+          PKL_TYPIFY_PAYLOAD->errors++;
+          PKL_PASS_ERROR;
+        }
+      assert (PKL_AST_TYPE_I_SIZE (type) != 0);
+    }
+
   /* Build the type of the array.  The arrays built from array
      literals are bounded by number of elements, and this number is
      always constant.  */
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 0147d714..0106703e 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -777,6 +777,13 @@ EXTRA_DIST = \
   poke.pkl/array-1.pk \
   poke.pkl/array-2.pk \
   poke.pkl/array-3.pk \
+  poke.pkl/array-4.pk \
+  poke.pkl/array-5.pk \
+  poke.pkl/array-6.pk \
+  poke.pkl/array-7.pk \
+  poke.pkl/array-8.pk \
+  poke.pkl/array-9.pk \
+  poke.pkl/array-10.pk \
   poke.pkl/array-bound-1.pk \
   poke.pkl/array-bound-2.pk \
   poke.pkl/array-bound-3.pk \
diff --git a/testsuite/poke.pkl/array-10.pk b/testsuite/poke.pkl/array-10.pk
new file mode 100644
index 00000000..6f88f426
--- /dev/null
+++ b/testsuite/poke.pkl/array-10.pk
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+
+var a = [-1, -2, 0, 1, 0xffff_ffffU as int<32>]UL,
+    b = [-1, -2, 0, 1, 0xffff_ffffU as int<32>]L;
+
+assert (a isa uint<64>[5]);
+assert (b isa int<64>[5]);
+
+/* { dg-command {.set obase 10} } */
+/* { dg-command { a == [-1UL, -2UL, 0UL, 1UL, -1UL] } } */
+/* { dg-output {1} } */
+/* { dg-command { b == [-1L, -2L, 0L, 1L, -1L]} } */
+/* { dg-output {\n1} } */
diff --git a/testsuite/poke.pkl/array-4.pk b/testsuite/poke.pkl/array-4.pk
new file mode 100644
index 00000000..16c33a00
--- /dev/null
+++ b/testsuite/poke.pkl/array-4.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+var a = [1,2,3]UB;
+
+assert (a isa uint<8>[3]);
+
+/* { dg-command {.set obase 10} } */
+/* { dg-command { a } } */
+/* { dg-output {\[1UB,2UB,3UB]} } */
diff --git a/testsuite/poke.pkl/array-5.pk b/testsuite/poke.pkl/array-5.pk
new file mode 100644
index 00000000..79a376ad
--- /dev/null
+++ b/testsuite/poke.pkl/array-5.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+var a = [[1,2,3]UB, [4UB,5UB,6UB]];
+
+assert (a isa uint<8>[3][2]);
+
+/* { dg-command {.set obase 10} } */
+/* { dg-command { a } } */
+/* { dg-output {\[\[1UB,2UB,3UB],\[4UB,5UB,6UB]]} } */
diff --git a/testsuite/poke.pkl/array-6.pk b/testsuite/poke.pkl/array-6.pk
new file mode 100644
index 00000000..a22fa2e4
--- /dev/null
+++ b/testsuite/poke.pkl/array-6.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+var a = [256, 255, 254]B; /* No overflow detection happens.  */
+
+assert (a isa int<8>[3]);
+
+/* { dg-command {.set obase 10} } */
+/* { dg-command { a } } */
+/* { dg-output {\[0B,-1B,-2B]} } */
diff --git a/testsuite/poke.pkl/array-7.pk b/testsuite/poke.pkl/array-7.pk
new file mode 100644
index 00000000..0281bc09
--- /dev/null
+++ b/testsuite/poke.pkl/array-7.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+var a = [0xfUL, 0xeUL, 0xdUL, 0xcUL]N;
+
+assert (a isa int<4>[4]);
+
+/* { dg-command {.set obase 10} } */
+/* { dg-command { a } } */
+/* { dg-output {\[-1N,-2N,-3N,-4N]} } */
diff --git a/testsuite/poke.pkl/array-8.pk b/testsuite/poke.pkl/array-8.pk
new file mode 100644
index 00000000..0c90e92a
--- /dev/null
+++ b/testsuite/poke.pkl/array-8.pk
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+
+var a = [-1, -2, 0, 1]UH,
+    b = [-1, -2, 0, 1]H;
+
+assert (a isa uint<16>[4]);
+assert (b isa int<16>[4]);
+
+/* { dg-command {.set obase 10} } */
+/* { dg-command { a == [0xffffUH, 0xfffeUH, 0UH, 1UH] } } */
+/* { dg-output {1} } */
+/* { dg-command { b } } */
+/* { dg-output {\n\[-1H,-2H,0H,1H]} } */
diff --git a/testsuite/poke.pkl/array-9.pk b/testsuite/poke.pkl/array-9.pk
new file mode 100644
index 00000000..c6e655e8
--- /dev/null
+++ b/testsuite/poke.pkl/array-9.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+var a = [-1, -2, 0, 1, 0xffff_ffffU as int<32>]U;
+
+assert (a isa uint<32>[4]);
+
+/* { dg-command {.set obase 10} } */
+/* { dg-command { a == [-1U, -2U, 0U, -1U] } } */
+/* { dg-output {1} } */
-- 
2.43.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]