>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

Raspunde prin e-mail lui