poke-devel
[Top][All Lists]
Advanced

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

Re: [PATCH v2] repl: Enable auto-completion for structs


From: Jose E. Marchesi
Subject: Re: [PATCH v2] repl: Enable auto-completion for structs
Date: Mon, 17 Feb 2020 16:10:50 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

Hi Carlo.

    Enable auto-completion for struct fields when a TAB is pressed after a
    '.' appended to the struct name (struct.<TAB>).
    
    Signed-off-by: Carlo Caione <address@hidden>

Very nice.  You achieved the same result without having to run PVM code!
:)

I would only suggest to change pkl_struct_traverse in order to have this
prototype:

  /* Given a struct type node AST and a string in the form BB.CC.CC.xx,
     check that the intermediate fields are valid struct refrecnes,
     and return  the pkl_ast_node corresponding to the type of the
     latest field CC.  */
  pkl_ast_node
  pkl_struct_type_traverse (pkl_ast_node ast, const char *path)

This way, we don't need to make the AST aware of the global
`poke_compiler'.  You can then lookup for the variable's type in the
compile-time environment in pk_complete_struct instead, and pass the AST
node to pkl_struct_traverse.  The later can also be useful for other
purposes, other than completing in the repl.

wdyt?

    
        * src/pk-repl.c (pk_complete_struct): new auto-complete function
        * src/pkl-ast.c (pkl_struct_traverse): new helper function
        * src/pkl-ast.h: likewise
    ---
     src/pk-repl.c | 61 +++++++++++++++++++++++++++++++++++++++++++++
     src/pkl-ast.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
     src/pkl-ast.h |  2 ++
     3 files changed, 132 insertions(+)
    
    diff --git a/src/pk-repl.c b/src/pk-repl.c
    index 574b9935..8357ff14 100644
    --- a/src/pk-repl.c
    +++ b/src/pk-repl.c
    @@ -35,6 +35,63 @@
     #include <signal.h>
     #include <unistd.h>
     
    +static char *
    +pk_complete_struct (int *idx, const char *x, size_t len, int state)
    +{
    +  static pkl_ast_node type;
    +  char *trunk;
    +  pkl_ast_node t;
    +  int j;
    +
    +  if (state == 0)
    +    {
    +      type = pkl_struct_traverse (x);
    +      if (type == NULL)
    +        return NULL;
    +    }
    +
    +  trunk = strndup (x, len - strlen (strrchr (x, '.')));
    +  t = PKL_AST_TYPE_S_ELEMS (type);
    +
    +  for (j = 0; j < (*idx); j++)
    +    t = PKL_AST_CHAIN (t);
    +
    +  for (; t; t = PKL_AST_CHAIN (t), (*idx)++)
    +    {
    +      pkl_ast_node ename;
    +      char *field, *name;
    +
    +      if (PKL_AST_CODE (t) != PKL_AST_STRUCT_TYPE_FIELD)
    +        continue;
    +
    +      ename = PKL_AST_STRUCT_TYPE_FIELD_NAME (t);
    +
    +      if (ename)
    +          field = PKL_AST_IDENTIFIER_POINTER (ename);
    +      else
    +          field = "<unnamed field>";
    +
    +      name = xmalloc (strlen (trunk) + strlen (field) + 2);
    +
    +      strcpy (name, trunk);
    +      strcat (name, ".");
    +      strcat (name, field);
    +
    +      if (0 != strncmp (x, name, len))
    +        {
    +          free (name);
    +          continue;
    +        }
    +
    +      (*idx)++;
    +      free (trunk);
    +      return name;
    +    }
    +
    +  free (trunk);
    +  return NULL;
    +}
    +
     static char *
     poke_completion_function (const char *x, int state)
     {
    @@ -55,6 +112,10 @@ poke_completion_function (const char *x, int state)
         }
     
       size_t len = strlen (x);
    +
    +  if ((x[0] != '.') && (strchr(x, '.') != NULL))
    +    return pk_complete_struct (&idx, x, len, state);
    +
       char *function_name;
       function_name = pkl_env_get_next_matching_decl (env, &iter, x, len);
       if (function_name)
    diff --git a/src/pkl-ast.c b/src/pkl-ast.c
    index 0ae30563..9f99cc79 100644
    --- a/src/pkl-ast.c
    +++ b/src/pkl-ast.c
    @@ -29,6 +29,8 @@
     #include "pvm-val.h" /* For PVM_NULL */
     #include "pvm-alloc.h" /* For pvm_alloc_{add/remove}_gc_roots */
     
    +#include "poke.h"
    +
     #define STREQ(a, b) (strcmp (a, b) == 0)
     
     /* Allocate and return a new AST node, with the given CODE.  The rest
    @@ -621,6 +623,73 @@ pkl_ast_dup_type (pkl_ast_node type)
       return new;
     }
     
    +/* Given a struct in the form AA.BB.CC.xx, checks that all the intermediate
    +   structs are valid and returns the pkl_ast_node corresponding to the 
latest
    +   struct CC */
    +
    +pkl_ast_node
    +pkl_struct_traverse (const char *path)
    +{
    +  char *trunk, *base, *r, *sub;
    +  pkl_ast_node decl, type;
    +  pkl_env compiler_env;
    +  int back, over;
    +
    +  trunk = strndup (path, strlen (path) - strlen (strrchr (path, '.')));
    +  base = strtok_r (trunk, ".", &r);
    +
    +  compiler_env = pkl_get_env (poke_compiler);
    +
    +  decl = pkl_env_lookup (compiler_env, base, &back, &over);
    +  if (decl == NULL)
    +    goto out;
    +
    +  type = PKL_AST_TYPE (PKL_AST_DECL_INITIAL (decl));
    +
    +  if (PKL_AST_TYPE_CODE (type) != PKL_TYPE_STRUCT)
    +    goto out;
    +
    +  while ((sub = strtok_r (NULL, ".", &r)) != NULL)
    +    {
    +      pkl_ast_node ename;
    +      pkl_ast_node etype, t;
    +      char *field;
    +
    +      etype = NULL;
    +
    +      if (PKL_AST_TYPE_CODE (type) != PKL_TYPE_STRUCT)
    +        goto out;
    +
    +      for (t = PKL_AST_TYPE_S_ELEMS (type); t;
    +           t = PKL_AST_CHAIN (t))
    +        {
    +          if (PKL_AST_CODE (t) != PKL_AST_STRUCT_TYPE_FIELD)
    +            continue;
    +      
    +          ename = PKL_AST_STRUCT_TYPE_FIELD_NAME (t);
    +          etype = PKL_AST_STRUCT_TYPE_FIELD_TYPE (t);
    +
    +          field = PKL_AST_IDENTIFIER_POINTER (ename);
    +
    +          if (STREQ (field, sub))
    +            {
    +              type = etype;
    +              break;
    +            }
    +        }
    +
    +      if (type != etype)
    +        goto out;
    +    }
    +
    +  free (trunk);
    +  return type;
    +
    +out:
    +  free (trunk);
    +  return NULL;
    +}
    +
     /* Return whether two given type AST nodes are equal, i.e. they denote
        the same type.  */
     
    diff --git a/src/pkl-ast.h b/src/pkl-ast.h
    index 114d6f14..8d30b958 100644
    --- a/src/pkl-ast.h
    +++ b/src/pkl-ast.h
    @@ -930,6 +930,8 @@ void pkl_print_type (FILE *out, pkl_ast_node type, int 
use_given_name);
     char *pkl_type_str (pkl_ast_node type, int use_given_name);
     int pkl_ast_func_all_optargs (pkl_ast_node type);
     int pkl_ast_type_mappable_p (pkl_ast_node type);
    +pkl_ast_node pkl_struct_traverse (const char *path);
    +
     
     /* PKL_AST_DECL nodes represent the declaration of a named entity:
        function, type, variable....



reply via email to

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