poke-devel
[Top][All Lists]
Advanced

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

Re: [PATCH] pkl: re-work re-declaration


From: Jose E. Marchesi
Subject: Re: [PATCH] pkl: re-work re-declaration
Date: Mon, 26 Jun 2023 19:29:19 +0200
User-agent: Gnus/5.13 (Gnus v5.13)

Hi Mohammad.
Thanks for the patch.

> diff --git a/bootstrap.conf b/bootstrap.conf
> index c5cf0452..7a8e0cec 100644
> --- a/bootstrap.conf
> +++ b/bootstrap.conf
> @@ -106,6 +106,7 @@ libpoke_modules="
>    tmpdir
>    vasprintf-posix
>    vsnprintf-posix
> +  xvasprintf-posix

Wouldn't it be worth to try to use vasprintf instead of xvasprintf,
handling the EOM error in a library (avoiding an abort) friendly way?

>    xalloc
>    strstr
>    lib-symbol-visibility
> diff --git a/libpoke/pkl-ast.c b/libpoke/pkl-ast.c
> index 7c2dc7ab..ef170706 100644
> --- a/libpoke/pkl-ast.c
> +++ b/libpoke/pkl-ast.c
> @@ -1500,7 +1500,18 @@ pkl_type_append_to (pkl_ast_node type, int 
> use_given_name,
>    if (use_given_name
>        && PKL_AST_TYPE_NAME (type))
>      {
> -      sb_append (buffer, PKL_AST_IDENTIFIER_POINTER (PKL_AST_TYPE_NAME 
> (type)));
> +      char *name = PKL_AST_IDENTIFIER_POINTER (PKL_AST_TYPE_NAME (type));
> +      char *dollar = strchr (name, '$');
> +
> +      if (dollar)
> +        {
> +          sb_append (buffer, "a previous declaration of ");
> +          *dollar = '\0';
> +          sb_append (buffer, name);
> +          *dollar = '$';
> +        }
> +      else
> +        sb_append (buffer, name);
>        return;
>      }
>  

Ok so the printed representation of a re-defined type name will always
be "a previous declaration of WHATEVER".  Does this work well in every
place where use display type names generated using this function?

> @@ -2608,7 +2619,7 @@ pkl_ast_node_free_1 (gl_set_t visitations, pkl_ast_node 
> ast)
>        VISIT_AND_FREE (PKL_AST_DECL_SOURCE (ast));
>        PKL_AST_NODE_FREE (PKL_AST_DECL_NAME (ast));
>        PKL_AST_NODE_FREE (PKL_AST_DECL_INITIAL (ast));
> -      free (PKL_AST_DECL_PREV_NAME (ast));
> +      PKL_AST_NODE_FREE (PKL_AST_DECL_PREV_DECL (ast));
>        break;
>  
>      case PKL_AST_OFFSET:
> @@ -3488,9 +3499,8 @@ pkl_ast_print_1 (FILE *fp, pkl_ast_node ast, int indent)
>        if (PKL_AST_DECL_SOURCE (ast))
>          PRINT_AST_IMM (source, DECL_SOURCE, "'%s'");
>        PRINT_AST_SUBAST (name, DECL_NAME);
> -      if (PKL_AST_DECL_PREV_NAME (ast))
> -        PRINT_AST_IMM (prev_name, DECL_PREV_NAME, "'%s'");
>        PRINT_AST_SUBAST (initial, DECL_INITIAL);
> +      PRINT_AST_SUBAST (prev_decl, DECL_PREV_DECL);
>        break;
>  
>      case PKL_AST_OFFSET:
> diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
> index c276e1dc..716d2771 100644
> --- a/libpoke/pkl-ast.h
> +++ b/libpoke/pkl-ast.h
> @@ -1139,10 +1139,6 @@ pkl_ast_node pkl_ast_type_incr_step (pkl_ast ast, 
> pkl_ast_node type);
>     NAME is PKL_AST_IDENTIFIER node containing the name in the
>     association.
>  
> -   PREV_NAME is used in order to cache the name in the declaration
> -   when the later is set to "" in re-definition of non-immutable
> -   global objects.  See pkl-env.c to see how this field is used.
> -
>     INITIAL is the initial value of the entity.  The kind of node
>     depends on what is being declared:
>     - An expression node for a variable.
> @@ -1150,6 +1146,13 @@ pkl_ast_node pkl_ast_type_incr_step (pkl_ast ast, 
> pkl_ast_node type);
>     - A PKL_AST_FUNC for a function.
>     - A constant expression node for an unit.
>  
> +   PREV_DECL is used to keep track of previous declaration with the
> +   same name.  See pkl-env.c to see how this field is used.
> +
> +   REDECL_CHAIN is used to form a transient sibling relationships among
> +   re-declared non-immutable global entities in a compilation session.
> +   See pkl-env to see how this field is used.
> +
>     ORDER is the order of the declaration in its containing
>     compile-time environment.  It is filled up when the declaration is
>     registered in an environment.
> @@ -1169,13 +1172,14 @@ pkl_ast_node pkl_ast_type_incr_step (pkl_ast ast, 
> pkl_ast_node type);
>  
>  #define PKL_AST_DECL_KIND(AST) ((AST)->decl.kind)
>  #define PKL_AST_DECL_NAME(AST) ((AST)->decl.name)
> -#define PKL_AST_DECL_PREV_NAME(AST) ((AST)->decl.prev_name)
>  #define PKL_AST_DECL_INITIAL(AST) ((AST)->decl.initial)
> +#define PKL_AST_DECL_PREV_DECL(AST) ((AST)->decl.prev_decl)
>  #define PKL_AST_DECL_ORDER(AST) ((AST)->decl.order)
>  #define PKL_AST_DECL_SOURCE(AST) ((AST)->decl.source)
>  #define PKL_AST_DECL_STRUCT_FIELD_P(AST) ((AST)->decl.struct_field_p)
>  #define PKL_AST_DECL_IN_STRUCT_P(AST) ((AST)->decl.in_struct_p)
>  #define PKL_AST_DECL_IMMUTABLE_P(AST) ((AST)->decl.immutable_p)
> +#define PKL_AST_DECL_REDECL_CHAIN(AST) ((AST)->decl.redecl_chain)
>  
>  #define PKL_AST_DECL_KIND_ANY 0
>  #define PKL_AST_DECL_KIND_VAR 1
> @@ -1192,9 +1196,10 @@ struct pkl_ast_decl
>    int in_struct_p;
>    int immutable_p;
>    char *source;
> -  char *prev_name;
>    union pkl_ast_node *name;
>    union pkl_ast_node *initial;
> +  union pkl_ast_node *prev_decl;
> +  union pkl_ast_node *redecl_chain;
>    int order;
>  };
>  
> diff --git a/libpoke/pkl-env.c b/libpoke/pkl-env.c
> index e45a20cf..fa40f908 100644
> --- a/libpoke/pkl-env.c
> +++ b/libpoke/pkl-env.c
> @@ -20,6 +20,7 @@
>  
>  #include <stdlib.h>
>  #include <xalloc.h>
> +#include <xvasprintf.h>
>  #include <string.h>
>  #include <assert.h>
>  
> @@ -40,16 +41,21 @@
>     - A separated namespace for offset units.  UNITS_HASH_TABLE is used
>       to store declarations for these.
>  
> +   REDECLS is used to keep track of re-defined declarations in order to
> +   be able to rollback them.  See env_redecls_free function.
> +
>     UP is a link to the immediately enclosing frame.  This is NULL for
>     the top-level frame.  */
>  
>  #define HASH_TABLE_SIZE 1008
>  typedef pkl_ast_node pkl_hash[HASH_TABLE_SIZE];
>  
> +
>  struct pkl_env
>  {
>    pkl_hash hash_table;
>    pkl_hash units_hash_table;
> +  pkl_ast_node redecls;
>  
>    int num_types;
>    int num_vars;
> @@ -120,20 +126,66 @@ get_registered (pkl_hash hash_table, const char *name)
>    return NULL;
>  }
>  
> +static void
> +decl_rollback (pkl_ast_node decl)

This function needs a comment block explaining the purpose of the
function and what does it do to DECL.

> +{
> +  pkl_ast_node prev_decl, prev_decl_name;
> +  char *name;
> +
> +  assert (decl != NULL);
> +  prev_decl = PKL_AST_DECL_PREV_DECL (decl);
> +  assert (prev_decl != NULL);
> +  prev_decl_name = PKL_AST_DECL_NAME (prev_decl);
> +
> +  name = PKL_AST_IDENTIFIER_POINTER (prev_decl_name);
> +  name = strchr (name, '$');
> +  assert (name != NULL);
> +  *name = '\0';
> +
> +  prev_decl = ASTDEREF (prev_decl);
> +  PKL_AST_DECL_PREV_DECL (decl) = NULL;
> +}
> +
> +static void
> +env_redecls_free (pkl_env env, int rollback_p)

Could we have a comment block explaining what the function does and the
purpose of both ENV and ROLLBACK_P?

> +{
> +  pkl_ast_node t, n = env->redecls;
> +
> +  while (n)
> +    {
> +      if (rollback_p)
> +        decl_rollback (n);
> +
> +      t = PKL_AST_DECL_REDECL_CHAIN (n);
> +      PKL_AST_DECL_REDECL_CHAIN (n) = NULL;
> +      n = t;
> +    }
> +  env->redecls = NULL;
> +}
> +
>  static int
> -register_decl (int top_level_p,
> +register_decl (pkl_env env,
>                 pkl_hash hash_table,
>                 const char *name,
>                 pkl_ast_node decl)
>  {
>    int hash;
>    pkl_ast_node found_decl;
> +  int top_level_p = env->up == NULL;
>  
>    /* Check if DECL is already registered in the given hash table.
>  
> -     If we are in the global environment then we allow "redefining" by
> -     changing the name of the previous declaration to "", provided
> -     that previous declaration is _not_ declared as immutable.
> +     If we are in the top-level environment, then "redefining" is
> +     allowd for non-immutable declarations.
> +     The trick is to rename the previous declaration to something
> +     that is not accessible through the language; so the old
> +     entities continue to work, and it's impossible for the Poke
> +     user to combine unrelated entities together (despite the fact
> +     that they were defined with the same name).
> +
> +     We rename the previous declaration to <name>$<generation>.
> +     Because of '$' character, Poke user cannot refer to this
> +     declaration anymore. The <generation> is a number in base 10.
>  
>       Otherwise we don't register DECL, as it is already defined.  */
>  
> @@ -142,11 +194,32 @@ register_decl (int top_level_p,
>      {
>        if (top_level_p && !PKL_AST_DECL_IMMUTABLE_P (found_decl))
>          {
> -          pkl_ast_node decl_name = PKL_AST_DECL_NAME (found_decl);
> +          int generation = 0;
> +          char *new_name;
> +
> +          /* Calculate the generation number for found_decl.  */
> +          if (PKL_AST_DECL_PREV_DECL (found_decl))
> +            {
> +              pkl_ast_node prev_decl = PKL_AST_DECL_PREV_DECL (found_decl);
> +              pkl_ast_node prev_decl_name = PKL_AST_DECL_NAME (prev_decl);
> +              char *name = PKL_AST_IDENTIFIER_POINTER (prev_decl_name);
> +              char *generation_str = strchr (name, '$');
> +
> +              assert (generation_str != NULL);
> +              generation = atoi (generation_str + 1);
> +              assert (generation != 0);
> +            }
> +
> +          new_name = xasprintf ("%s$%d", name, generation + 1);
> +          assert (new_name != NULL);
> +          free (PKL_AST_IDENTIFIER_POINTER (PKL_AST_DECL_NAME (found_decl)));
> +          PKL_AST_IDENTIFIER_POINTER (PKL_AST_DECL_NAME (found_decl)) = 
> new_name;
>  
> -          PKL_AST_DECL_PREV_NAME (found_decl)
> -            = PKL_AST_IDENTIFIER_POINTER (decl_name);
> -          PKL_AST_IDENTIFIER_POINTER (decl_name) = strdup ("");
> +          PKL_AST_DECL_PREV_DECL (decl) = ASTREF (found_decl);
> +
> +          /* Register DECL in re-defined declarations list.  */
> +          PKL_AST_DECL_REDECL_CHAIN (decl) = env->redecls;
> +          env->redecls = decl;
>          }
>        else
>          return 0;
> @@ -194,6 +267,7 @@ pkl_env_free (pkl_env env)
>    if (env)
>      {
>        pkl_env_free (env->up);
> +      env_redecls_free (env, /*rollback_p*/ 1);
>        free_hash_table (env->hash_table);
>        free_hash_table (env->units_hash_table);
>        free (env);
> @@ -230,7 +304,7 @@ pkl_env_register (pkl_env env,
>  {
>    pkl_hash *table = get_ns_table (env, namespace);
>  
> -  if (register_decl (env->up == NULL, *table, name, decl))
> +  if (register_decl (env, *table, name, decl))

Is that first argument supposed to be top_level_p?  Otherwise, this is a
logic change.  Is it intended?

>      {
>        switch (PKL_AST_DECL_KIND (decl))
>          {
> @@ -320,14 +394,24 @@ pkl_env_toplevel_p (pkl_env env)
>    return env->up == NULL;
>  }
>  
> +/* Return non-zero value if DECL has already been re-defined, otherwise 
> return
> +   zero.  */
> +
> +static int
> +is_prev_decl_p (pkl_ast_node decl)

I think it would be clearer to call this function decl_redefined_p.

> +{
> +  pkl_ast_node name = PKL_AST_DECL_NAME (decl);
> +
> +  return strchr (PKL_AST_IDENTIFIER_POINTER (name), '$') != NULL;
> +}
> +
>  void
>  pkl_env_iter_begin (pkl_env env, struct pkl_ast_node_iter *iter)
>  {
>    iter->bucket = 0;
>    iter->node = env->hash_table[iter->bucket];
>    /* Note that we skip re-defined declarations.  */
> -  while (iter->node == NULL
> -         || *PKL_AST_IDENTIFIER_POINTER (PKL_AST_DECL_NAME (iter->node)) == 
> '\0')
> +  while (iter->node == NULL || is_prev_decl_p (iter->node))
>      {
>        iter->bucket++;
>        if (iter->bucket >= HASH_TABLE_SIZE)
> @@ -343,8 +427,7 @@ pkl_env_iter_next (pkl_env env, struct pkl_ast_node_iter 
> *iter)
>  
>    iter->node = PKL_AST_CHAIN2 (iter->node);
>    /* Note that we skip re-defined declarations.  */
> -  while (iter->node == NULL
> -         || *PKL_AST_IDENTIFIER_POINTER (PKL_AST_DECL_NAME (iter->node)) == 
> '\0')
> +  while (iter->node == NULL || is_prev_decl_p (iter->node))
>      {
>        iter->bucket++;
>        if (iter->bucket >= HASH_TABLE_SIZE)
> @@ -438,36 +521,14 @@ pkl_env_get_next_matching_decl (pkl_env env, struct 
> pkl_ast_node_iter *iter,
>    return NULL;
>  }
>  
> -static void
> -pkl_env_rollback_renames_1 (pkl_hash hash_table)
> +void
> +pkl_env_commit_renames (pkl_env env)
>  {
> -  int i;
> -  for (i = 0; i < HASH_TABLE_SIZE; ++i)
> -    {
> -      pkl_ast_node t;
> -      pkl_ast_node decl = hash_table[i];
> -
> -      for (t = decl; t; t = PKL_AST_CHAIN2 (t))
> -        {
> -          pkl_ast_node decl_name = PKL_AST_DECL_NAME (t);
> -
> -          if (PKL_AST_DECL_PREV_NAME (t))
> -            {
> -              assert (decl_name
> -                      && STREQ (PKL_AST_IDENTIFIER_POINTER (decl_name), ""));
> -
> -              free (PKL_AST_IDENTIFIER_POINTER (decl_name));
> -              PKL_AST_IDENTIFIER_POINTER (decl_name)
> -                = PKL_AST_DECL_PREV_NAME (t);
> -              PKL_AST_DECL_PREV_NAME (t) = NULL;
> -            }
> -        }
> -    }
> +  env_redecls_free (env, /*rollback_p*/ 0);
>  }
>  
>  void
>  pkl_env_rollback_renames (pkl_env env)
>  {
> -  pkl_env_rollback_renames_1 (env->hash_table);
> -  pkl_env_rollback_renames_1 (env->units_hash_table);
> +  env_redecls_free (env, /*rollback_p*/ 1);
>  }
> diff --git a/libpoke/pkl-env.h b/libpoke/pkl-env.h
> index 1bc4f9dd..41a3bd4d 100644
> --- a/libpoke/pkl-env.h
> +++ b/libpoke/pkl-env.h
> @@ -162,7 +162,12 @@ void pkl_env_map_decls (pkl_env env,
>                          pkl_map_decl_fn cb,
>                          void *data);
>  
> -/* Function to rollback/undo redefinitions/renames of global objects
> +/* Function to commit the redefinitions/renames of global objects
> +   in the given environment.  */
> +
> +void pkl_env_commit_renames (pkl_env env);
> +
> +/* Function to rollback/undo the redefinitions/renames of global objects
>     in the given environment.  */
>  
>  void pkl_env_rollback_renames (pkl_env env);
> diff --git a/libpoke/pkl.c b/libpoke/pkl.c
> index 9da052ed..8367d536 100644
> --- a/libpoke/pkl.c
> +++ b/libpoke/pkl.c
> @@ -348,11 +348,13 @@ pkl_execute_buffer (pkl_compiler compiler,
>      {
>        pkl_env_free (compiler->env);
>        compiler->env = env;
> +      pkl_env_commit_renames (compiler->env);
>      }
> +  else
> +    pkl_env_rollback_renames (env);
>    return 1;
>  
>   error:
> -  pkl_env_rollback_renames (compiler->env);
>    pkl_env_free (env);
>    return 0;

Hmm, so the rollback is no longer necessary when some error condition
leading to this label happen?

>  }
> @@ -403,11 +405,13 @@ pkl_execute_statement (pkl_compiler compiler,
>      {
>        pkl_env_free (compiler->env);
>        compiler->env = env;
> +      pkl_env_commit_renames (compiler->env);
>      }
> +  else
> +    pkl_env_rollback_renames (env);
>    return 1;
>  
>   error:
> -  pkl_env_rollback_renames (compiler->env);
>    pkl_env_free (env);
>    return 0;
>  }
> @@ -445,12 +449,12 @@ pkl_compile_expression (pkl_compiler compiler,
>  
>     pkl_env_free (compiler->env);
>     compiler->env = env;
> +   pkl_env_commit_renames (compiler->env);
>     pvm_program_make_executable (program);
>  
>     return program;
>  
>   error:
> -   pkl_env_rollback_renames (compiler->env);
>     pkl_env_free (env);
>     return NULL;
>  }
> @@ -501,11 +505,13 @@ pkl_execute_expression (pkl_compiler compiler,
>      {
>        pkl_env_free (compiler->env);
>        compiler->env = env;
> +      pkl_env_commit_renames (compiler->env);
>      }
> +  else
> +    pkl_env_rollback_renames (env);
>    return 1;
>  
>   error:
> -  pkl_env_rollback_renames (compiler->env);
>    pkl_env_free (env);
>    return 0;
>  }
> @@ -554,12 +560,14 @@ pkl_execute_file (pkl_compiler compiler, const char 
> *fname,
>      {
>        pkl_env_free (compiler->env);
>        compiler->env = env;
> +      pkl_env_commit_renames (compiler->env);
>      }
> +  else
> +    pkl_env_rollback_renames (env);
>    return 1;
>  
>   error:
>    fclose (fp);
> -  pkl_env_rollback_renames (compiler->env);

Likewise?

>    pkl_env_free (env);
>    return 0;
>  }
> diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
> index acb0220b..0ea3536e 100644
> --- a/testsuite/Makefile.am
> +++ b/testsuite/Makefile.am
> @@ -2256,9 +2256,16 @@ EXTRA_DIST = \
>    poke.pkl/redef-diag-1.pk \
>    poke.pkl/redef-diag-2.pk \
>    poke.pkl/redef-diag-3.pk \
> +  poke.pkl/redef-diag-4.pk \
> +  poke.pkl/redef-diag-5.pk \
> +  poke.pkl/redef-diag-6.pk \
>    poke.pkl/redef-1.pk \
>    poke.pkl/redef-2.pk \
>    poke.pkl/redef-3.pk \
> +  poke.pkl/redef-4.pk \
> +  poke.pkl/redef-5.pk \
> +  poke.pkl/redef-6.pk \
> +  poke.pkl/redef-7.pk \
>    poke.pkl/reduce-array-1.pk \
>    poke.pkl/reduce-array-2.pk \
>    poke.pkl/return-1.pk \
> diff --git a/testsuite/poke.pkl/redef-4.pk b/testsuite/poke.pkl/redef-4.pk
> new file mode 100644
> index 00000000..0765e41a
> --- /dev/null
> +++ b/testsuite/poke.pkl/redef-4.pk
> @@ -0,0 +1,9 @@
> +/* { dg-do run } */
> +
> +type Foo = struct { };
> +fun foo = (Foo a) void: { print "foo\n"; }
> +var f = Foo {};
> +type Foo = struct { };
> +
> +/* { dg-command {foo (f)} } */
> +/* { dg-output "foo\n" } */
> diff --git a/testsuite/poke.pkl/redef-5.pk b/testsuite/poke.pkl/redef-5.pk
> new file mode 100644
> index 00000000..a8930f97
> --- /dev/null
> +++ b/testsuite/poke.pkl/redef-5.pk
> @@ -0,0 +1,13 @@
> +/* { dg-do run } */
> +
> +type Foo = struct { int<32> i32; };
> +
> +/* { dg-command { .set obase 10 } } */
> +/* { dg-command { .set omode flat } } */
> +/* { dg-command { 2#Foo } } */
> +/* { dg-output "2#32" } */
> +/* { dg-command {unit Foo = 33} } */
> +/* { dg-command {3#Foo} } */
> +/* { dg-output "\n3#33" } */
> +/* { dg-command {Foo {}} } */
> +/* { dg-output "\nFoo {i32=0}" } */
> diff --git a/testsuite/poke.pkl/redef-6.pk b/testsuite/poke.pkl/redef-6.pk
> new file mode 100644
> index 00000000..696320f4
> --- /dev/null
> +++ b/testsuite/poke.pkl/redef-6.pk
> @@ -0,0 +1,11 @@
> +/* { dg-do run } */
> +
> +type Foo = struct { int<32> i32; };
> +
> +/* { dg-command {.set obase 10} } */
> +/* { dg-command {.set omode flat} } */
> +/* { dg-command {Foo {}} } */
> +/* { dg-output "Foo {i32=0}" } */
> +/* { dg-command {type Foo = struct { int<64> i64; }} } */
> +/* { dg-command {Foo {}} } */
> +/* { dg-output "\nFoo {i64=0L}" } */
> diff --git a/testsuite/poke.pkl/redef-7.pk b/testsuite/poke.pkl/redef-7.pk
> new file mode 100644
> index 00000000..6f9fa344
> --- /dev/null
> +++ b/testsuite/poke.pkl/redef-7.pk
> @@ -0,0 +1,10 @@
> +/* { dg-do run } */
> +
> +var x = "Hello";
> +
> +/* { dg-command {x} } */
> +/* { dg-output {"Hello"} } */
> +/* { dg-command {var x = 1, y = lambda string: {printf "x:%i32d\n", x; raise 
> E_elem; return "";} ()} } */
> +/* { dg-output {\nx:1\nunhandled .*} } */
> +/* { dg-command {x} } */
> +/* { dg-output {\n"Hello"} } */
> diff --git a/testsuite/poke.pkl/redef-diag-4.pk 
> b/testsuite/poke.pkl/redef-diag-4.pk
> new file mode 100644
> index 00000000..4288df2a
> --- /dev/null
> +++ b/testsuite/poke.pkl/redef-diag-4.pk
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +
> +type Foo = struct { };
> +fun foo = (Foo a) void: { print "foo\n"; }
> +var f1 = Foo {};
> +type Foo = struct { };
> +var f2 = Foo {};
> +
> +foo (f1);
> +foo (f2); /* { dg-error "invalid value for function argument.*\n.*expected a 
> previous declaration of Foo, got Foo" } */
> diff --git a/testsuite/poke.pkl/redef-diag-5.pk 
> b/testsuite/poke.pkl/redef-diag-5.pk
> new file mode 100644
> index 00000000..b8f1cbb2
> --- /dev/null
> +++ b/testsuite/poke.pkl/redef-diag-5.pk
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +
> +type Foo = struct { };
> +fun foo = (Foo a) void: { print "foo1\n"; }
> +var f1 = Foo {};
> +
> +foo (f1);
> +
> +type Foo = struct { };
> +var f2 = Foo {};
> +
> +fun foo = (Foo a) void: { print "foo2\n"; }
> +
> +foo (f2);
> +foo (f1); /* { dg-error "invalid value for function argument.*\n.*expected 
> Foo, got a previous declaration of Foo" } */
> diff --git a/testsuite/poke.pkl/redef-diag-6.pk 
> b/testsuite/poke.pkl/redef-diag-6.pk
> new file mode 100644
> index 00000000..2461937b
> --- /dev/null
> +++ b/testsuite/poke.pkl/redef-diag-6.pk
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +
> +type Foo = struct { };
> +fun foo = (Foo a) void: { print "foo1\n"; }
> +var f1 = Foo {};
> +
> +foo (f1);
> +
> +type Foo = struct { };
> +var f2 = Foo {};
> +
> +fun foo = (Foo a) void: { print "foo2\n"; }
> +
> +type Foo = struct { };
> +var f3 = Foo {};
> +
> +fun foo = (Foo a) void: { print "foo3\n"; }
> +
> +foo (f3);
> +foo (f2); /* { dg-error "invalid value for function argument.*\n.*expected 
> Foo, got a previous declaration of Foo" } */



reply via email to

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