>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.
No, just how funcrefs work. I bet it is easier then you think, but harder then
I do (I expect problems only in one point: deref_func_name; this can’t be
really
true).
>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 =).
It changes mostly in the same places where you want to change. Except
deref_func_name, there is no way how you propose touches this. But no matter
what will you do, please, make all C function arguments the same as in
func_call
except the first one (first is function name which you obviously don’t need).
Then if I succeed implementation will be easy to change.
>> 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).
I did not say it is impossible. I said it is easier. More, “easier” is wrong
word: with my proposal you won’t need to change *anything* in python code after
it was changed to use new funcrefs.
>> 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.
Yes, it is a problem (but this one is solvable): when you define s: function in
your script “s:” is translated to “<SNR>{snr}_”, but not when you create
a funcref. I was actually not precise here: it may call s:ScriptLocal function
*that is defined in another plugin*. If it is defined, of course.
>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.
If both suggestions are merged (your libcall with your original proposal and my
new function references) we will end up in having another two unconsistent
things. I am more convinced in investing time in new funcrefs.
>> 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.
There is: C plugins can be Python/ruby/lua modules :)
It is subjectable whether it is a bug: “delfunction” does its job and deletes
a function thus it is no more accessible. I don’t like the idea, I want to be
sure that if I received a funcref I am able to call it. *Like I do if I use
“anonymous” functions*. Anonymous functions can be deleted by just the same
command, but consequences of the deletion when I reported them were considered
as a bug. Not fixed yet as “delfunction” is not likely to be used for funcrefs
and I know where the problem lies but unsure what is the proper fix.
>> 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.
That is why I suggest to start implementing things you have to do in any case
and wait for reply from Bram. These things are library for handling internal
types and fd_* functions: even if my proposal is not accepted they are still
can
be used for implementing f_libcallex and others.
>> 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.
Lets wait for Bram before you proceed this way.
- Maybe (but, I think, unlikely) he accepts two new types.
- Maybe there will be just one type, similar to lua userdata.
- Maybe you will go on with holding everything in internal dictionaries and
using their keys for lib* functions.
- Or maybe my proposal is accepted.
In any case you will be able to make use of fd_* functions (except for fd_print
and, maybe, fd_string) and in any case you need typval library. So start with
them.
>> 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
>
--
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