[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....