On 14/09/2012, at 01:54, ZyX <[email protected]> wrote:
> If I were doing this thing I would change function references to have type
>
> typedef struct funcref_S funcref_T;
> struct funcref_S {
> void *fv_data;
> funcdef_T *fv_func_def;
> int fv_refcount;
> int fv_copyid;
> funcref_T *fv_used_prev;
> funcref_T *fv_used_next;
> }
> typedef struct {
> int (*fd_call) __ARGS((void *data, typval_T *argvars, dict_T
> *selfdict, typval_T *rettv));
> char_u *(*fd_string) __ARGS((void *data)); /* string() implementation
> */
> void (*fd_print) __ARGS((void *data)); /* :function Funcref output
> * Maybe it is worth being
> * char ** (*fd_print)(void
> *)
> */
> int (*fd_free) __ARGS((void *data)); /* Called when there are no
> more references left */
> } funcdef_T;
> There is a reason behind exactly this interface:
> 1. This avoids useless dictionary (user functions) or even binary (built-in
> functions) searches when using the funcref.
Just to be clear, here you are suggesting to change all the way how VIM
implement VIM Script functions (user and internal)
beyond my aim of better native call support.
This seems a big and non isolated change compared to what I'm proposing, I
really prefer do it the simpler way although if
implemented it could benefit overall in the end, but, anyway, adding the new
kinds of variables was trivial, some may say
it may look ugly, but these new types only show up in the context of native
plugin development, so I don't see it as a big
problem. I know I can apply this design, the data structure, reference counting
(I though of that initially), etc, for the
native calls only, but it's much less trivial to implement =).
> 2. This makes it much easier to implement equivalent of
> vim.bindeval('function("tr")')("a", "b", "c") # Python
> vim.funcref("tr")("a", "b", "c") -- Lua, if I did not mistake anything
> -- Requires recent patches from Luis
> Carvalho
> for vimscript.
Sounds neat although I see it still possible by <whatever>.bindeval(<whatever>)
returning Libfunc vars (to call C functions to do job with
python).
> 3. Being implemented properly this purges out the situations like
>
> function s:ScriptLocal()
> endfunction
> let d={'f': function('s:ScriptLocal')}
> call FunctionFromAnotherPlugin(d.f) " An error: there is no script-local
> " function with this name
> " in another plugin
If FunctionFromAnotherPlugin is a Libfunc var (got after libload, libfunc),
what should happen here (if native calls is implemented
through call) is just a simple call to the C function pointed by the var. A
simple C call will be in the same context as the current line
of the script, if it receives a Funcref and is able to make calls to it, there
should be no problem of undefinition.
Did I got the point here? because I'm just talking about a possibility of the
implementation I described, not about the overall benefits
to VIM Script of your idea. I think you may be talking about a current problem
in VIM Script, I'm not sure.
I like the Idea of having an special function for libcall's because it turns
things clear and isolated. But too, having an uniform
call syntax looks good… but my primary aim is just the aim of the current
libcall, just without the problems and limitations.
> and
> function Func()
> endfunction
> let d={'f': function('Func')}
> delfunction Func
> call d.f() " The error: function no longer exists
Is this a problem in VIM script? I really don't know, I've not played with it
too much yet. And the truth is that I'm not minding with these current
weak implementation spots to just do the enhanced native call. I'm trying to be
modest and objective with this propose because the current
libcall is just too limited and there's no good way to build C plugins.
> Unfortunately I currently do not have time for such a change (more true, I do
> not want to invest it in what I do not believe will be accepted, comments
> from Bram are needed on the subject). With this interface I get the second
> (and hence will implement funcrefs calling python functions) and everybody
> get first and last as a benefits.
Yes, to me it sounds cool too, but I'm afraid if I'd gone that way it would be
barred indeed, or at last, it would take much longer to be
accepted (and longer to implement).
I'm just afraid of being barred with my current propose. I hope it'll not.
> You then will have no need in one of new data types and remove the need in
> libcall/libcallex/call (the latter will do the trick for all types of
> functions). You can also remove a need in the second one if you do the
> following instead:
> 1. Add libfunc(path_to_lib, function_name). It should do the following:
> 1. Normalize path_to_lib and lookup it in special dictionary with library
> handles. If it is found export symbol from there and return.
> 2. If not, get library handle.
> 3. Then get symbol "vim_init" or whatever and use it to initialize.
> 4. Then get function_name, return.
> In returned structure reference to the symbol, its name and a structure
> describing library are stored. It assumes library itself does not have any
> global state, all state is to be stored in arguments if needed. If you do
> want to support state skip this point (except the description of what is
> stored in void *fv_data) and go on with libload+libinit.
> 2. fd_call should just do the following:
> int
> fd_call (data, argvars, selfdict, rettv)
> struct {
> int (*func) (typval_T *, typval_T *, typval_T *);
> char_u *name;
> struct {
> void *libhandle;
> char_u *path;
> /* GC stuff here */
> } *libhandle;
> } *data;
> int (*data) (typval_T *, typval_T *, typval_T *);
> typval_T *argvars;
> typval_T *selfdict;
> typval_T *rettv;
> {
> return data->func(argvars, selfdict, rettv);
> }
> 3. fd_string emits "libfunc(path, name)".
> 4. fd_print prints path to library and symbol name.
> 5. fd_free is freeing data and unreferencing opened library, unloading if
> needed. Unreferencing and unloading in both cases: whether you stick to
> internal dictionary with already opened libraries or use libload+..., it only
> makes a difference at the first point.
Ok, so since I'm not going the funcref_S way, I know I could apply the effort
of dictionaries, reference counting and vanish
with the two extra variable kinds. It looks a bit as (over?)engineering just to
eliminate them, but, anyway, I may look further
at similar options, thanks.
> As you see here adding external libraries support is trivial. What is less
> trivial is changing every piece when funcrefs are involved.
It's trivial to see the idea, but implementing is another history =)
Thanks for all the discussion, it brings a lot of things to light. Indeed, a
lot I wasn't even remotely thinking about, but I feel it's
a lot more to cover.
Best Regards
---
Francisco
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php