lua-users home
lua-l archive

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


"Reuben Thomas,,,690081" wrote:
> 
> > Sigh, another example of the arg handling ad hockery...
> 
> Indeed; this is one of the several reasons I think it would be good for even
> the standard Lua libraries to be written using tolua (or a similar tool),
> and for this practice to be encouraged for everyone.

I wouldn't go that far.  IMHO, the wish for a tool like tolua for simple
tasks show that the API is too complex.

> The Lua API could probably be simplified even further if it were only
> intended for writers of binding tools, and the annoying bugs that tend
> to crop up (especially with stack handling) would go away.

In fact, I like the stack handling.  It's a simple concecpt that works
pretty well.  What's wrong is how arguments are passed and handled.  That
has already been simplified by moving the upvalues aways from the stack.
IMO the next step would be to make the arg-handling similar to that in
Lua itself (where it's simple enough, isn't it?).

The problem is, that C functions are always handled like Lua vararg
functions (function foo(...) body end) and that the C arg-fetching
functions check arg.n.  I.e luaL_opt_number works like this:

  function luaL_opt_number(args, argno, default)
    if args.n < argno then
      return args[argno]
    else
      return default
    end
  end

and used like this (strfind as an example):

  function strfind(...)
    ...
    local init = luaL_opt_number(arg, 3, 1)
    if arg.n > 3 ... then simple_string_search...
    ...
  end

Noone would do this in Lua.  You would write:

  function strfind(s,p,init,nopattern)
    ...
    init = init or 1
    if nopattern ... then simple_string_search...
    ...
  end

So why do it in C?  This is how I would change the C-API:

  - lua_pushcclosure gets an additional argument: the number of
    arguments expected by the functions.  This number (nargs) is
    saved in the closure structure for later use.
    (Associated functions/structures are changed too)

  - when calling a C function the VM checks whether there are less
    arguments on the stack then the closure wants (gettop<nargs).
    In that case it pushes additional nils on the stack until there
    are enough arguments (gettop==nargs).  If there are already
    enough or even more arguments on the stack it does nothing.
    Then the function is called.

  - All functions that check for optional arguments (like luaL_opt_-
    number) will decide that the argument is not present if it is nil.
    That is: no check against gettop>argno but against isnil(stack[argno]).

  - lua_isnull is removed.

That's all!  C functions behave the same as Lua functions.  Seems to
work pretty well in Sol ;-)


> > function strfind(a,b,c,d)
> >   c = c or 1  -- c has a similar problem...
> [...]
> I'll add the function above to my standard library, along with the
> wrapper for tinsert we discussed a while ago.

Then you have more to do.  Just a simple eye-grep over lbaselib gives
these functions that need this kind of wrapper:

  - tonumber
  - error
  - newtype
  - globals (even slightly buggy when called with no args)
  - settagmethod
  - collectgarbage
  - dostring
  - loadstring
  - dofile
  - loadfile
  - call
  - assert
  - tinsert
  - tremove
  - sort

There are more when considering luaL_check_any calls... 

Ciao, ET.