poke-devel
[Top][All Lists]
Advanced

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

[COMMITTED] pkl: support for post-{increment,decrement} in integers and


From: Jose E. Marchesi
Subject: [COMMITTED] pkl: support for post-{increment,decrement} in integers and offsets
Date: Sun, 22 Nov 2020 18:56:28 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

2020-11-22  Jose E. Marchesi  <jemarch@gnu.org>

        * libpoke/pkl-ast.h (enum pkl_ast_code): Add PKL_AST_INCRDECR.
        (struct pkl_ast_incrdecr): New type.
        (PKL_AST_INCRDECR_ORDER): Define.
        (PKL_AST_INCRDECR_SIGN): Likewise.
        (PKL_AST_INCRDECR_EXP): Likewise.
        (PKL_AST_INCRDECR_ASS_STMT): Likewise.
        (PKL_AST_PRE): Likewise.
        (PKL_AST_POST): Likewise.
        (PKL_AST_INCR): Likewise.
        (PKL_AST_DECR): Likewise.
        (pkl_ast_make_incrdecr): New prototype.
        (pkl_ast_type_incr_step): Likewise.
        (union pkl_ast_node): New field incrdecr.
        * libpoke/pkl-ast.c (pkl_ast_make_incrdecr): New function.
        (pkl_ast_type_incr_step): Likewise.
        (pkl_ast_node_free): Handle PKL_AST_INCRDECR nodes.
        * libpoke/pkl-pass.c (pkl_do_pass_1): LIkewise.
        * libpoke/pkl-tab.y (primary): syntax for INCRDECR.
        * libpoke/pkl-typify.c (pkl_typify1_ps_incrdecr): New handler.
        (pkl_phase_typify1): Register handler.
        * libpoke/pkl-anal.c (pkl_analf_ps_incrdecr): New handler.
        (pkl_phase_analf): Install handler.
        * libpoke/pkl-trans.c (pkl_trans1_ps_incrdecr): New handler.
        (pkl_phase_trans1): Install handler.
        * libpoke/pkl-gen.c (pkl_gen_pr_incrdecr): New handler.
        (pkl_phase_gen): Install handler.
        * testsuite/poke.pkl/postincr-diag-1.pk: New test.
        * testsuite/poke.pkl/postincr-diag-2.pk: Likewise.
        * testsuite/poke.pkl/postincr-diag-3.pk: Likewise.
        * testsuite/poke.pkl/postincr-diag-4.pk: Likewise.
        * testsuite/poke.pkl/postincr-diag-5.pk: Likewise.
        * testsuite/poke.pkl/postdecr-diag-1.pk: Likewise.
        * testsuite/poke.pkl/postdecr-diag-2.pk: Likewise.
        * testsuite/poke.pkl/postdecr-diag-3.pk: Likewise.
        * testsuite/poke.pkl/postdecr-diag-4.pk: Likewise.
        * testsuite/poke.pkl/postdecr-diag-5.pk: Likewise.
        * testsuite/poke.pkl/postincr-1.pk: Likewise.
        * testsuite/poke.pkl/postincr-2.pk: Likewise.
        * testsuite/poke.pkl/postdecr-1.pk: Likewise.
        * testsuite/poke.pkl/postdecr-2.pk: Likewise.
        * testsuite/poke.pkl/postincr-offset-1.pk: Likewise.
        * testsuite/poke.pkl/postincr-offset-2.pk: Likewise.
        * testsuite/poke.pkl/postdecr-offset-1.pk: Likewise.
        * testsuite/poke.pkl/postdecr-offset-2.pk: Likewise.
        * testsuite/poke.pkl/postincr-aelem-1.pk: Likewise.
        * testsuite/poke.pkl/postdecr-aelem-2.pk: Likewise.
        * testsuite/poke.pkl/postdecr-field-1.pk: Likewise.
        * testsuite/poke.pkl/postincr-field-1.pk: Likewise.
        * testsuite/Makefile.am (EXTRA_DIST): Update.
---
 ChangeLog                               | 52 +++++++++++++++++++
 libpoke/pkl-anal.c                      | 29 +++++++++++
 libpoke/pkl-ast.c                       | 69 +++++++++++++++++++++++++
 libpoke/pkl-ast.h                       | 43 +++++++++++++++
 libpoke/pkl-gen.c                       | 26 ++++++++++
 libpoke/pkl-pass.c                      |  5 ++
 libpoke/pkl-tab.y                       | 26 ++++++++++
 libpoke/pkl-trans.c                     | 35 +++++++++++++
 libpoke/pkl-typify.c                    | 32 ++++++++++++
 testsuite/Makefile.am                   | 22 ++++++++
 testsuite/poke.pkl/postdecr-1.pk        |  8 +++
 testsuite/poke.pkl/postdecr-2.pk        |  8 +++
 testsuite/poke.pkl/postdecr-aelem-1.pk  |  8 +++
 testsuite/poke.pkl/postdecr-diag-1.pk   |  3 ++
 testsuite/poke.pkl/postdecr-diag-2.pk   |  3 ++
 testsuite/poke.pkl/postdecr-diag-3.pk   |  3 ++
 testsuite/poke.pkl/postdecr-diag-4.pk   |  3 ++
 testsuite/poke.pkl/postdecr-diag-5.pk   |  3 ++
 testsuite/poke.pkl/postdecr-field-1.pk  |  9 ++++
 testsuite/poke.pkl/postdecr-offset-1.pk |  8 +++
 testsuite/poke.pkl/postdecr-offset-2.pk | 10 ++++
 testsuite/poke.pkl/postincr-1.pk        |  8 +++
 testsuite/poke.pkl/postincr-2.pk        |  8 +++
 testsuite/poke.pkl/postincr-aelem-1.pk  |  8 +++
 testsuite/poke.pkl/postincr-diag-1.pk   |  3 ++
 testsuite/poke.pkl/postincr-diag-2.pk   |  3 ++
 testsuite/poke.pkl/postincr-diag-3.pk   |  3 ++
 testsuite/poke.pkl/postincr-diag-4.pk   |  3 ++
 testsuite/poke.pkl/postincr-diag-5.pk   |  3 ++
 testsuite/poke.pkl/postincr-field-1.pk  |  9 ++++
 testsuite/poke.pkl/postincr-offset-1.pk |  8 +++
 testsuite/poke.pkl/postincr-offset-2.pk | 10 ++++
 32 files changed, 471 insertions(+)
 create mode 100644 testsuite/poke.pkl/postdecr-1.pk
 create mode 100644 testsuite/poke.pkl/postdecr-2.pk
 create mode 100644 testsuite/poke.pkl/postdecr-aelem-1.pk
 create mode 100644 testsuite/poke.pkl/postdecr-diag-1.pk
 create mode 100644 testsuite/poke.pkl/postdecr-diag-2.pk
 create mode 100644 testsuite/poke.pkl/postdecr-diag-3.pk
 create mode 100644 testsuite/poke.pkl/postdecr-diag-4.pk
 create mode 100644 testsuite/poke.pkl/postdecr-diag-5.pk
 create mode 100644 testsuite/poke.pkl/postdecr-field-1.pk
 create mode 100644 testsuite/poke.pkl/postdecr-offset-1.pk
 create mode 100644 testsuite/poke.pkl/postdecr-offset-2.pk
 create mode 100644 testsuite/poke.pkl/postincr-1.pk
 create mode 100644 testsuite/poke.pkl/postincr-2.pk
 create mode 100644 testsuite/poke.pkl/postincr-aelem-1.pk
 create mode 100644 testsuite/poke.pkl/postincr-diag-1.pk
 create mode 100644 testsuite/poke.pkl/postincr-diag-2.pk
 create mode 100644 testsuite/poke.pkl/postincr-diag-3.pk
 create mode 100644 testsuite/poke.pkl/postincr-diag-4.pk
 create mode 100644 testsuite/poke.pkl/postincr-diag-5.pk
 create mode 100644 testsuite/poke.pkl/postincr-field-1.pk
 create mode 100644 testsuite/poke.pkl/postincr-offset-1.pk
 create mode 100644 testsuite/poke.pkl/postincr-offset-2.pk

diff --git a/ChangeLog b/ChangeLog
index c2946380..1afdbb57 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+2020-11-22  Jose E. Marchesi  <jemarch@gnu.org>
+
+       * libpoke/pkl-ast.h (enum pkl_ast_code): Add PKL_AST_INCRDECR.
+       (struct pkl_ast_incrdecr): New type.
+       (PKL_AST_INCRDECR_ORDER): Define.
+       (PKL_AST_INCRDECR_SIGN): Likewise.
+       (PKL_AST_INCRDECR_EXP): Likewise.
+       (PKL_AST_INCRDECR_ASS_STMT): Likewise.
+       (PKL_AST_PRE): Likewise.
+       (PKL_AST_POST): Likewise.
+       (PKL_AST_INCR): Likewise.
+       (PKL_AST_DECR): Likewise.
+       (pkl_ast_make_incrdecr): New prototype.
+       (pkl_ast_type_incr_step): Likewise.
+       (union pkl_ast_node): New field incrdecr.
+       * libpoke/pkl-ast.c (pkl_ast_make_incrdecr): New function.
+       (pkl_ast_type_incr_step): Likewise.
+       (pkl_ast_node_free): Handle PKL_AST_INCRDECR nodes.
+       * libpoke/pkl-pass.c (pkl_do_pass_1): LIkewise.
+       * libpoke/pkl-tab.y (primary): syntax for INCRDECR.
+       * libpoke/pkl-typify.c (pkl_typify1_ps_incrdecr): New handler.
+       (pkl_phase_typify1): Register handler.
+       * libpoke/pkl-anal.c (pkl_analf_ps_incrdecr): New handler.
+       (pkl_phase_analf): Install handler.
+       * libpoke/pkl-trans.c (pkl_trans1_ps_incrdecr): New handler.
+       (pkl_phase_trans1): Install handler.
+       * libpoke/pkl-gen.c (pkl_gen_pr_incrdecr): New handler.
+       (pkl_phase_gen): Install handler.
+       * testsuite/poke.pkl/postincr-diag-1.pk: New test.
+       * testsuite/poke.pkl/postincr-diag-2.pk: Likewise.
+       * testsuite/poke.pkl/postincr-diag-3.pk: Likewise.
+       * testsuite/poke.pkl/postincr-diag-4.pk: Likewise.
+       * testsuite/poke.pkl/postincr-diag-5.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-diag-1.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-diag-2.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-diag-3.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-diag-4.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-diag-5.pk: Likewise.
+       * testsuite/poke.pkl/postincr-1.pk: Likewise.
+       * testsuite/poke.pkl/postincr-2.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-1.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-2.pk: Likewise.
+       * testsuite/poke.pkl/postincr-offset-1.pk: Likewise.
+       * testsuite/poke.pkl/postincr-offset-2.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-offset-1.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-offset-2.pk: Likewise.
+       * testsuite/poke.pkl/postincr-aelem-1.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-aelem-2.pk: Likewise.
+       * testsuite/poke.pkl/postdecr-field-1.pk: Likewise.
+       * testsuite/poke.pkl/postincr-field-1.pk: Likewise.
+       * testsuite/Makefile.am (EXTRA_DIST): Update.
+
 2020-11-22  Jose E. Marchesi  <jemarch@gnu.org>
 
        * libpoke/pkl-gen.pks (struct_printer): Print struct elements
diff --git a/libpoke/pkl-anal.c b/libpoke/pkl-anal.c
index efb34b2a..a32df76b 100644
--- a/libpoke/pkl-anal.c
+++ b/libpoke/pkl-anal.c
@@ -968,6 +968,34 @@ PKL_PHASE_BEGIN_HANDLER (pkl_analf_ps_ass_stmt)
 }
 PKL_PHASE_END_HANDLER
 
+/* Make sure that the argument to an incrdecr operator is of the right
+   kind, i.e. it is a valid lvalue.
+
+   XXX this shouldn't be necessary due to the check in ass_stmt!  */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_analf_ps_incrdecr)
+{
+  pkl_ast_node incrdecr = PKL_PASS_NODE;
+  pkl_ast_node incrdecr_exp = PKL_AST_INCRDECR_EXP (incrdecr);
+
+  if (!pkl_ast_lvalue_p (incrdecr_exp))
+    {
+      int incrdecr_order = PKL_AST_INCRDECR_ORDER (incrdecr);
+      int incrdecr_sign = PKL_AST_INCRDECR_SIGN (incrdecr);
+
+      if (!pkl_ast_lvalue_p (incrdecr_exp))
+        {
+          PKL_ERROR (PKL_AST_LOC (incrdecr_exp),
+                     "invalid operand to %s%s",
+                     incrdecr_order == PKL_AST_PRE ? "pre" : "post",
+                     incrdecr_sign == PKL_AST_INCR ? "increment" : 
"decrement");
+          PKL_ANAL_PAYLOAD->errors++;
+          PKL_PASS_ERROR;
+        }
+    }
+}
+PKL_PHASE_END_HANDLER
+
 struct pkl_phase pkl_phase_analf
   __attribute__ ((visibility ("hidden"))) =
   {
@@ -975,4 +1003,5 @@ struct pkl_phase pkl_phase_analf
    PKL_PHASE_PS_HANDLER (PKL_AST_PROGRAM, pkl_anal_ps_program),
    PKL_PHASE_PS_HANDLER (PKL_AST_OFFSET, pkl_analf_ps_array_initializer),
    PKL_PHASE_PS_HANDLER (PKL_AST_ASS_STMT, pkl_analf_ps_ass_stmt),
+   PKL_PHASE_PS_HANDLER (PKL_AST_INCRDECR, pkl_analf_ps_incrdecr),
   };
diff --git a/libpoke/pkl-ast.c b/libpoke/pkl-ast.c
index 144ec8a5..92ea1034 100644
--- a/libpoke/pkl-ast.c
+++ b/libpoke/pkl-ast.c
@@ -1566,6 +1566,26 @@ pkl_ast_make_var (pkl_ast ast, pkl_ast_node name,
   return var;
 }
 
+/* Build and return an AST node for an incrdecr expression.  */
+
+pkl_ast_node
+pkl_ast_make_incrdecr (pkl_ast ast,
+                       pkl_ast_node exp, int order, int sign)
+{
+  pkl_ast_node incrdecr = pkl_ast_make_node (ast,
+                                             PKL_AST_INCRDECR);
+
+  assert (order == PKL_AST_PRE || order == PKL_AST_POST);
+  assert (sign == PKL_AST_INCR || sign == PKL_AST_DECR);
+  assert (exp);
+
+  PKL_AST_INCRDECR_EXP (incrdecr) = ASTREF (exp);
+  PKL_AST_INCRDECR_ORDER (incrdecr) = order;
+  PKL_AST_INCRDECR_SIGN (incrdecr) = sign;
+
+  return incrdecr;
+}
+
 /* Build and return an AST node for a lambda expression.  */
 
 pkl_ast_node
@@ -2121,6 +2141,11 @@ pkl_ast_node_free (pkl_ast_node ast)
         pkl_ast_node_free (PKL_AST_VAR_DECL (ast));
       break;
 
+    case PKL_AST_INCRDECR:
+
+      pkl_ast_node_free (PKL_AST_INCRDECR_EXP (ast));
+      break;
+
     case PKL_AST_LAMBDA:
 
       pkl_ast_node_free (PKL_AST_LAMBDA_FUNCTION (ast));
@@ -2363,6 +2388,41 @@ pkl_ast_finish_breaks (pkl_ast_node entity, pkl_ast_node 
stmt)
   pkl_ast_finish_breaks_1 (entity, stmt, &nframes);
 }
 
+pkl_ast_node
+pkl_ast_type_incr_step (pkl_ast ast, pkl_ast_node type)
+{
+  pkl_ast_node step = NULL;
+
+  assert (PKL_AST_CODE (type) == PKL_AST_TYPE);
+
+  switch (PKL_AST_TYPE_CODE (type))
+    {
+    case PKL_TYPE_INTEGRAL:
+      {
+        /* The obvious step for integral types is 1, of the same
+           type.  */
+        step = pkl_ast_make_integer (ast, 1);
+        PKL_AST_TYPE (step) = ASTREF (type);
+        break;
+      }
+    case PKL_TYPE_OFFSET:
+      {
+        /* The step for an offset type is one unit.  */
+        pkl_ast_node one = pkl_ast_make_integer (ast, 1);
+
+        PKL_AST_TYPE (one) = PKL_AST_TYPE_O_BASE_TYPE (type);
+        step = pkl_ast_make_offset (ast, one,
+                                    PKL_AST_TYPE_O_UNIT (type));
+        PKL_AST_TYPE (step) = ASTREF (type);
+        break;
+      }
+    default:
+      break;
+    }
+
+  return step;
+}
+
 /* Annotate FUNCTIONs return statements with the function and their
    nest level within the function.
 
@@ -2921,6 +2981,15 @@ pkl_ast_print_1 (FILE *fp, pkl_ast_node ast, int indent)
       PRINT_AST_SUBAST (function, LAMBDA_FUNCTION);
       break;
 
+    case PKL_AST_INCRDECR:
+      IPRINTF ("INCRDECR::\n");
+
+      PRINT_COMMON_FIELDS;
+      PRINT_AST_IMM (order, INCRDECR_ORDER, "%d");
+      PRINT_AST_IMM (sign, INCRDECR_SIGN, "%d");
+      PRINT_AST_SUBAST (exp, INCRDECR_EXP);
+      break;
+
     case PKL_AST_COMP_STMT:
       IPRINTF ("COMP_STMT::\n");
 
diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
index eeaf4490..41348286 100644
--- a/libpoke/pkl-ast.h
+++ b/libpoke/pkl-ast.h
@@ -56,6 +56,7 @@ enum pkl_ast_code
   PKL_AST_FUNCALL_ARG,
   PKL_AST_VAR,
   PKL_AST_LAMBDA,
+  PKL_AST_INCRDECR,
   PKL_AST_GCD,
   PKL_AST_LAST_EXP = PKL_AST_GCD,
   /* Types.  */
@@ -1019,6 +1020,12 @@ char *pkl_type_str (pkl_ast_node type, int 
use_given_name);
 
 pkl_ast_node pkl_struct_type_traverse (pkl_ast_node type, const char *path);
 
+/* Return an expression that evaluates to an increment step for the
+   given TYPE.  If the provided type doesn't support the notion of
+   increment step this function returns NULL.  */
+
+pkl_ast_node pkl_ast_type_incr_step (pkl_ast ast, pkl_ast_node type);
+
 /* PKL_AST_DECL nodes represent the declaration of a named entity:
    function, type, variable....
 
@@ -1330,6 +1337,41 @@ struct pkl_ast_lambda
 
 pkl_ast_node pkl_ast_make_lambda (pkl_ast ast, pkl_ast_node function);
 
+/* PKL_AST_INCRDECR nodes represent {pre,post}{increment,decrement}
+   expressions.
+
+   ORDER is either PKL_AST_PRE or PKL_AST_POST.
+   SIGN is either PKL_AST_INCR or PKL_AST_DECR.
+   EXP is the expression to which the operator is applied.
+
+   ASS_STMT is an AST node that is used in a transformation phase in
+   order to hold an assignment statement.  */
+
+#define PKL_AST_INCRDECR_ORDER(AST) ((AST)->incrdecr.order)
+#define PKL_AST_INCRDECR_SIGN(AST) ((AST)->incrdecr.sign)
+#define PKL_AST_INCRDECR_EXP(AST) ((AST)->incrdecr.exp)
+#define PKL_AST_INCRDECR_ASS_STMT(AST) ((AST)->incrdecr.ass_stmt)
+
+#define PKL_AST_PRE 0
+#define PKL_AST_POST 1
+
+#define PKL_AST_INCR 0
+#define PKL_AST_DECR 1
+
+struct pkl_ast_incrdecr
+{
+  struct pkl_ast_common common;
+
+  int order;
+  int sign;
+  union pkl_ast_node *exp;
+  union pkl_ast_node *ass_stmt;
+};
+
+pkl_ast_node pkl_ast_make_incrdecr (pkl_ast ast,
+                                    pkl_ast_node exp, int order, int sign);
+
+
 /* PKL_AST_COMPOUND_STMT nodes represent compound statements in the
    language.
 
@@ -1774,6 +1816,7 @@ union pkl_ast_node
   struct pkl_ast_funcall_arg funcall_arg;
   struct pkl_ast_var var;
   struct pkl_ast_lambda lambda;
+  struct pkl_ast_incrdecr incrdecr;
   /* Types.  */
   struct pkl_ast_type type;
   struct pkl_ast_struct_type_field sct_type_elem;
diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
index 6a92c770..48f4e675 100644
--- a/libpoke/pkl-gen.c
+++ b/libpoke/pkl-gen.c
@@ -626,6 +626,31 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_comp_stmt)
 }
 PKL_PHASE_END_HANDLER
 
+/*
+ * INCRDECR
+ * | EXP
+ * | ASS_STMT
+ */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_incrdecr)
+{
+  pkl_ast_node incrdecr = PKL_PASS_NODE;
+  pkl_ast_node incrdecr_exp = PKL_AST_INCRDECR_EXP (incrdecr);
+  pkl_ast_node incrdecr_ass_stmt = PKL_AST_INCRDECR_ASS_STMT (incrdecr);
+  int incrdecr_order = PKL_AST_INCRDECR_ORDER (incrdecr);
+
+  if (incrdecr_order == PKL_AST_PRE)
+    PKL_PASS_SUBPASS (incrdecr_ass_stmt);
+
+  PKL_PASS_SUBPASS (incrdecr_exp);
+
+  if (incrdecr_order == PKL_AST_POST)
+    PKL_PASS_SUBPASS (incrdecr_ass_stmt);
+
+  PKL_PASS_BREAK;
+}
+PKL_PHASE_END_HANDLER
+
 /*
  * ASS_STMT
  * | EXP
@@ -3725,6 +3750,7 @@ struct pkl_phase pkl_phase_gen
    PKL_PHASE_PS_HANDLER (PKL_AST_COMP_STMT, pkl_gen_ps_comp_stmt),
    PKL_PHASE_PS_HANDLER (PKL_AST_NULL_STMT, pkl_gen_ps_null_stmt),
    PKL_PHASE_PR_HANDLER (PKL_AST_ASS_STMT, pkl_gen_pr_ass_stmt),
+   PKL_PHASE_PR_HANDLER (PKL_AST_INCRDECR, pkl_gen_pr_incrdecr),
    PKL_PHASE_PR_HANDLER (PKL_AST_IF_STMT, pkl_gen_pr_if_stmt),
    PKL_PHASE_PS_HANDLER (PKL_AST_BREAK_STMT, pkl_gen_ps_break_stmt),
    PKL_PHASE_PS_HANDLER (PKL_AST_CONTINUE_STMT, pkl_gen_ps_continue_stmt),
diff --git a/libpoke/pkl-pass.c b/libpoke/pkl-pass.c
index 090da852..07071741 100644
--- a/libpoke/pkl-pass.c
+++ b/libpoke/pkl-pass.c
@@ -574,6 +574,11 @@ pkl_do_pass_1 (pkl_compiler compiler,
     case PKL_AST_LAMBDA:
       PKL_PASS (PKL_AST_LAMBDA_FUNCTION (node));
       break;
+    case PKL_AST_INCRDECR:
+      PKL_PASS (PKL_AST_INCRDECR_EXP (node));
+      if (PKL_AST_INCRDECR_ASS_STMT (node))
+        PKL_PASS (PKL_AST_INCRDECR_ASS_STMT (node));
+      break;
     case PKL_AST_NULL_STMT:
     case PKL_AST_INTEGER:
     case PKL_AST_STRING:
diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
index a620f544..2a32269e 100644
--- a/libpoke/pkl-tab.y
+++ b/libpoke/pkl-tab.y
@@ -1002,6 +1002,32 @@ primary:
                   pkl_ast_finish_returns ($3);
                   $$ = pkl_ast_make_lambda (pkl_parser->ast, $3);
                 }
+        | expression INC
+                {
+                  $$ = pkl_ast_make_incrdecr (pkl_parser->ast, $1,
+                                              PKL_AST_POST, PKL_AST_INCR);
+                  PKL_AST_LOC ($$) = @$;
+                }
+        | expression DEC
+                {
+                  $$ = pkl_ast_make_incrdecr (pkl_parser->ast, $1,
+                                              PKL_AST_POST, PKL_AST_DECR);
+                  PKL_AST_LOC ($$) = @$;
+                }
+/*
+        | INC expression
+                {
+                  $$ = pkl_ast_make_incrdecr (pkl_parser->ast, $2,
+                                              PKL_AST_PRE, PKL_AST_INCR);
+                  PKL_AST_LOC ($$) = @$;
+                }
+        | DEC expression
+                {
+                  $$ = pkl_ast_make_incrdecr (pkl_parser->ast, $2,
+                                              PKL_AST_PRE, PKL_AST_DECR);
+                  PKL_AST_LOC ($$) = @$;
+                }
+*/
         ;
 
 funcall:
diff --git a/libpoke/pkl-trans.c b/libpoke/pkl-trans.c
index 09837224..e5fa2b3d 100644
--- a/libpoke/pkl-trans.c
+++ b/libpoke/pkl-trans.c
@@ -1298,6 +1298,40 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans2_ps_type_offset)
 }
 PKL_PHASE_END_HANDLER
 
+/* Add an assignment statement to INCRDECR expressions.  */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans2_ps_incrdecr)
+{
+  pkl_ast_node incrdecr = PKL_PASS_NODE;
+  pkl_ast_node incrdecr_stmt = PKL_AST_INCRDECR_ASS_STMT (incrdecr);
+
+  if (!incrdecr_stmt)
+    {
+      pkl_ast_node incrdecr_exp = PKL_AST_INCRDECR_EXP (incrdecr);
+      pkl_ast_node incrdecr_exp_type = PKL_AST_TYPE (incrdecr_exp);
+      int incrdecr_sign = PKL_AST_INCRDECR_SIGN (incrdecr);
+      pkl_ast_node step, ass_stmt, exp_plus_one;
+
+      int op = (incrdecr_sign == PKL_AST_INCR
+                ? PKL_AST_OP_ADD : PKL_AST_OP_SUB);
+
+      /* Get the step.  The type of the expression is safe as per
+         typify.  */
+      step = pkl_ast_type_incr_step (PKL_PASS_AST, incrdecr_exp_type);
+      assert (step); /* XXX turn to ICE.  */
+
+      /* Build a statement EXP = EXP +/- STEP  */
+      exp_plus_one = pkl_ast_make_binary_exp (PKL_PASS_AST, op,
+                                              incrdecr_exp, step);
+      PKL_AST_TYPE (exp_plus_one) = ASTREF (incrdecr_exp_type);
+      ass_stmt = pkl_ast_make_ass_stmt (PKL_PASS_AST,
+                                        incrdecr_exp, exp_plus_one);
+
+      PKL_AST_INCRDECR_ASS_STMT (incrdecr) = ASTREF (ass_stmt);
+      PKL_PASS_RESTART = 1;
+    }
+}
+PKL_PHASE_END_HANDLER
 
 struct pkl_phase pkl_phase_trans2
   __attribute__ ((visibility ("hidden"))) =
@@ -1311,6 +1345,7 @@ struct pkl_phase pkl_phase_trans2
    PKL_PHASE_PS_HANDLER (PKL_AST_STRUCT, pkl_trans2_ps_struct),
    PKL_PHASE_PS_HANDLER (PKL_AST_STRUCT_REF, pkl_trans2_ps_struct_ref),
    PKL_PHASE_PS_HANDLER (PKL_AST_CAST, pkl_trans2_ps_cast),
+   PKL_PHASE_PS_HANDLER (PKL_AST_INCRDECR, pkl_trans2_ps_incrdecr),
    PKL_PHASE_PS_TYPE_HANDLER (PKL_TYPE_OFFSET, pkl_trans2_ps_type_offset),
   };
 
diff --git a/libpoke/pkl-typify.c b/libpoke/pkl-typify.c
index e0010f06..5ab71bc4 100644
--- a/libpoke/pkl-typify.c
+++ b/libpoke/pkl-typify.c
@@ -2074,6 +2074,37 @@ PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_var)
 }
 PKL_PHASE_END_HANDLER
 
+/* The type of an incrdecr expression is the type of the expression it
+   applies to.  Not all types support this operations though.  */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_incrdecr)
+{
+  pkl_ast_node incrdecr = PKL_PASS_NODE;
+  pkl_ast_node incrdecr_exp = PKL_AST_INCRDECR_EXP (incrdecr);
+  pkl_ast_node incrdecr_exp_type = PKL_AST_TYPE (incrdecr_exp);
+  int incrdecr_order = PKL_AST_INCRDECR_ORDER (incrdecr);
+  int incrdecr_sign = PKL_AST_INCRDECR_SIGN (incrdecr);
+
+  /* Only values of certain types can be decremented/incremented.  */
+  switch (PKL_AST_TYPE_CODE (incrdecr_exp_type))
+    {
+    case PKL_TYPE_INTEGRAL:
+    case PKL_TYPE_OFFSET:
+      break;
+    default:
+      PKL_ERROR (PKL_AST_LOC (incrdecr),
+                 "invalid operand to %s%s",
+                 incrdecr_order == PKL_AST_PRE ? "pre" : "post",
+                 incrdecr_sign == PKL_AST_INCR ? "increment" : "decrement");
+      PKL_TYPIFY_PAYLOAD->errors++;
+      PKL_PASS_ERROR;
+    }
+
+  /* The type of the construction is the type of the expression.  */
+  PKL_AST_TYPE (incrdecr) = ASTREF (incrdecr_exp_type);
+}
+PKL_PHASE_END_HANDLER
+
 /* The type of a lambda node is the type of its function.  */
 
 PKL_PHASE_BEGIN_HANDLER (pkl_typify1_ps_lambda)
@@ -2810,6 +2841,7 @@ struct pkl_phase pkl_phase_typify1
    PKL_PHASE_PR_HANDLER (PKL_AST_PROGRAM, pkl_typify_pr_program),
    PKL_PHASE_PS_HANDLER (PKL_AST_VAR, pkl_typify1_ps_var),
    PKL_PHASE_PS_HANDLER (PKL_AST_LAMBDA, pkl_typify1_ps_lambda),
+   PKL_PHASE_PS_HANDLER (PKL_AST_INCRDECR, pkl_typify1_ps_incrdecr),
    PKL_PHASE_PS_HANDLER (PKL_AST_CAST, pkl_typify1_ps_cast),
    PKL_PHASE_PS_HANDLER (PKL_AST_ISA, pkl_typify1_ps_isa),
    PKL_PHASE_PS_HANDLER (PKL_AST_MAP, pkl_typify1_ps_map),
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index f05c8625..8e0b9ad3 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -457,6 +457,28 @@ EXTRA_DIST = \
   poke.map/trimmed-map-4.pk \
   poke.map/unmap-1.pk \
   poke.pkl/pkl.exp \
+  poke.pkl/postincr-1.pk \
+  poke.pkl/postincr-2.pk \
+  poke.pkl/postdecr-1.pk \
+  poke.pkl/postdecr-2.pk \
+  poke.pkl/postincr-offset-1.pk \
+  poke.pkl/postincr-offset-2.pk \
+  poke.pkl/postdecr-offset-1.pk \
+  poke.pkl/postdecr-offset-2.pk \
+  poke.pkl/postincr-aelem-1.pk \
+  poke.pkl/postdecr-aelem-1.pk \
+  poke.pkl/postincr-diag-1.pk \
+  poke.pkl/postincr-diag-2.pk \
+  poke.pkl/postincr-diag-3.pk \
+  poke.pkl/postincr-diag-4.pk \
+  poke.pkl/postincr-diag-5.pk \
+  poke.pkl/postdecr-diag-1.pk \
+  poke.pkl/postdecr-diag-2.pk \
+  poke.pkl/postdecr-diag-3.pk \
+  poke.pkl/postdecr-diag-4.pk \
+  poke.pkl/postdecr-diag-5.pk \
+  poke.pkl/postincr-field-1.pk \
+  poke.pkl/postdecr-field-1.pk \
   poke.pkl/acons-diag-1.pk \
   poke.pkl/acons-diag-2.pk \
   poke.pkl/acons-diag-3.pk \
diff --git a/testsuite/poke.pkl/postdecr-1.pk b/testsuite/poke.pkl/postdecr-1.pk
new file mode 100644
index 00000000..8a24e09b
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-1.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = 10;
+
+/* { dg-command {a--} } */
+/* { dg-output "10" } */
+/* { dg-command {a} } */
+/* { dg-output "\n9" } */
diff --git a/testsuite/poke.pkl/postdecr-2.pk b/testsuite/poke.pkl/postdecr-2.pk
new file mode 100644
index 00000000..e8072e44
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-2.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = 10L;
+
+/* { dg-command {a--} } */
+/* { dg-output "10L" } */
+/* { dg-command {a} } */
+/* { dg-output "\n9L" } */
diff --git a/testsuite/poke.pkl/postdecr-aelem-1.pk 
b/testsuite/poke.pkl/postdecr-aelem-1.pk
new file mode 100644
index 00000000..d808d22a
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-aelem-1.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = [1,2,3];
+
+/* { dg-command {a[1]--} } */
+/* { dg-output "2" } */
+/* { dg-command {a[1]} } */
+/* { dg-output "\n1" } */
diff --git a/testsuite/poke.pkl/postdecr-diag-1.pk 
b/testsuite/poke.pkl/postdecr-diag-1.pk
new file mode 100644
index 00000000..65b5312b
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-diag-1.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+"foo"--; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postdecr-diag-2.pk 
b/testsuite/poke.pkl/postdecr-diag-2.pk
new file mode 100644
index 00000000..2ff4621a
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-diag-2.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+[1,2,3]--; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postdecr-diag-3.pk 
b/testsuite/poke.pkl/postdecr-diag-3.pk
new file mode 100644
index 00000000..ef139dc9
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-diag-3.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+E_generic--; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postdecr-diag-4.pk 
b/testsuite/poke.pkl/postdecr-diag-4.pk
new file mode 100644
index 00000000..33b3c104
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-diag-4.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+lambda void:{}++; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postdecr-diag-5.pk 
b/testsuite/poke.pkl/postdecr-diag-5.pk
new file mode 100644
index 00000000..962ac43e
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-diag-5.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+23--; /* { dg-error "invalid" } */
diff --git a/testsuite/poke.pkl/postdecr-field-1.pk 
b/testsuite/poke.pkl/postdecr-field-1.pk
new file mode 100644
index 00000000..110cda71
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-field-1.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+type Foo = struct { int i; };
+var f = Foo { i = 10 };
+
+/* { dg-command { f.i-- } } */
+/* { dg-output "10" } */
+/* { dg-command { f.i } } *?
+/* { dg-output "\n9" } */
diff --git a/testsuite/poke.pkl/postdecr-offset-1.pk 
b/testsuite/poke.pkl/postdecr-offset-1.pk
new file mode 100644
index 00000000..e1ea25e5
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-offset-1.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = 10L#B;
+
+/* { dg-command {a--} } */
+/* { dg-output "10L#B" } */
+/* { dg-command {a} } */
+/* { dg-output "\n9L#B" } */
diff --git a/testsuite/poke.pkl/postdecr-offset-2.pk 
b/testsuite/poke.pkl/postdecr-offset-2.pk
new file mode 100644
index 00000000..cf80ef05
--- /dev/null
+++ b/testsuite/poke.pkl/postdecr-offset-2.pk
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+
+type Packet = struct { byte a; byte b; };
+
+var a = 10#Packet;
+
+/* { dg-command {a--} } */
+/* { dg-output "10#16" } */
+/* { dg-command {a} } */
+/* { dg-output "\n9#16" } */
diff --git a/testsuite/poke.pkl/postincr-1.pk b/testsuite/poke.pkl/postincr-1.pk
new file mode 100644
index 00000000..d60663d7
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-1.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = 0;
+
+/* { dg-command {a++} } */
+/* { dg-output "0" } */
+/* { dg-command {a} } */
+/* { dg-output "\n1" } */
diff --git a/testsuite/poke.pkl/postincr-2.pk b/testsuite/poke.pkl/postincr-2.pk
new file mode 100644
index 00000000..d4ef9b6a
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-2.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = 0L;
+
+/* { dg-command {a++} } */
+/* { dg-output "0L" } */
+/* { dg-command {a} } */
+/* { dg-output "\n1L" } */
diff --git a/testsuite/poke.pkl/postincr-aelem-1.pk 
b/testsuite/poke.pkl/postincr-aelem-1.pk
new file mode 100644
index 00000000..fe99b4ba
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-aelem-1.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = [1,2,3];
+
+/* { dg-command {a[1]++} } */
+/* { dg-output "2" } */
+/* { dg-command {a[1]} } */
+/* { dg-output "\n3" } */
diff --git a/testsuite/poke.pkl/postincr-diag-1.pk 
b/testsuite/poke.pkl/postincr-diag-1.pk
new file mode 100644
index 00000000..3c327eb3
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-diag-1.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+"foo"++; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postincr-diag-2.pk 
b/testsuite/poke.pkl/postincr-diag-2.pk
new file mode 100644
index 00000000..b5d5e3d3
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-diag-2.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+[1,2,3]++; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postincr-diag-3.pk 
b/testsuite/poke.pkl/postincr-diag-3.pk
new file mode 100644
index 00000000..21691360
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-diag-3.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+E_generic++; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postincr-diag-4.pk 
b/testsuite/poke.pkl/postincr-diag-4.pk
new file mode 100644
index 00000000..33b3c104
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-diag-4.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+lambda void:{}++; /* { dg-error "invalid operand" } */
diff --git a/testsuite/poke.pkl/postincr-diag-5.pk 
b/testsuite/poke.pkl/postincr-diag-5.pk
new file mode 100644
index 00000000..38d28873
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-diag-5.pk
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+23++; /* { dg-error "invalid" } */
diff --git a/testsuite/poke.pkl/postincr-field-1.pk 
b/testsuite/poke.pkl/postincr-field-1.pk
new file mode 100644
index 00000000..1e65ce9f
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-field-1.pk
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+
+type Foo = struct { int i; };
+var f = Foo {};
+
+/* { dg-command { f.i++ } } */
+/* { dg-output "0" } */
+/* { dg-command { f.i } } *?
+/* { dg-output "\n1" } */
diff --git a/testsuite/poke.pkl/postincr-offset-1.pk 
b/testsuite/poke.pkl/postincr-offset-1.pk
new file mode 100644
index 00000000..1b71b768
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-offset-1.pk
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+
+var a = 0L#B;
+
+/* { dg-command {a++} } */
+/* { dg-output "0L#B" } */
+/* { dg-command {a} } */
+/* { dg-output "\n1L#B" } */
diff --git a/testsuite/poke.pkl/postincr-offset-2.pk 
b/testsuite/poke.pkl/postincr-offset-2.pk
new file mode 100644
index 00000000..1d73b844
--- /dev/null
+++ b/testsuite/poke.pkl/postincr-offset-2.pk
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+
+type Packet = struct { byte a; byte b; };
+
+var a = 3#Packet;
+
+/* { dg-command {a++} } */
+/* { dg-output "3#16" } */
+/* { dg-command {a} } */
+/* { dg-output "\n4#16" } */
-- 
2.25.0.2.g232378479e




reply via email to

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