lua-users home
lua-l archive

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


On Tue, Oct 10, 2006 at 01:06:21PM +0100, David Jones wrote:
> [sorry, weekends often interrupt my train of thought]
> 
> On 6 Oct 2006, at 18:10, Glenn Maynard wrote:
> 
> >On Fri, Oct 06, 2006 at 11:39:32AM +0100, David Jones wrote:
> >>What mystic forces locates "code snippets" can arrange that when a
> >>located code snippet wants to "source in" another chunk the mystic
> >>invocation that it uses to do that "source in" the other code chunk
> >>is able to find the code chunk using the information that was
> >>obtained when the first code snippet was located.
> >
> >I'm not sure what information you're referring to.  If I load a chunk:
> >
> >return { a = "file", parts = { loadfile("tail.lua"), loadfile 
> >("nose.lua") } };
> >
> >with luaL_loadfile(L, "asset/path/dog/dog.lua", and evaluate it later
> >on, I can't see any way at that point to discover "asset/path/dog/",
> >other than by parsing it out of debug info.
> 
> Right, I see what you're trying to do now, I think.
> 
> If everything's done in Lua then you can do it by a horrible hack  
> which I'll try and describe.

I thought about using environments, but I didn't like how much
infrastructure it put in, making small reimplementations hard (eg.
Lua-based validators) and complicating things.

> This almost works but in general a chunk can't get a reference to  
> itself.  You either have to explicitly pass the chunk to itself every  
> time you called it, or modify the chunk's environment so that the  
> chunk was always available at some well known free variable.  Or use  
> the debug API to get the executing chunk, but then that doesn't avoid  
> the debug API.

It would work for the case of finding floating pathnames (eg. PNGs),
which is done in C, I think, but not so well for the loadfile() case.

> You could impose a convention that no chunk was allowed to create  
> tables except via a special, newtable, function.  But that sucks.   
> Apart from that there's no way to tell from a table who created it.   
> Which makes me think that...

I've implemented this:

  http://stepmania.cvs.sourceforge.net/stepmania/stepmania/Themes/default/BGAnimations/ScreenCompany%20background/default.lua?view=markup

Def.Actor is a function that annotates the table passed to it with the
file, directory and line of the caller (line optional); the directory
is used for finding eg. "white.png", and the file and line are used
for error messages.  It seems to work well, though I'm not using it
widely yet.  I only recently realized that this was a practical use
of the func { table } shorthand for func({table}), which I had previously
not seen the point of.

If you're curious, the Def table is defined at the bottom of:

  http://stepmania.cvs.sourceforge.net/stepmania/stepmania/Themes/default/Scripts/Actor.lua?view=markup

some of which may be hidden away in C later, and the prior format
which this is replacing is:

  http://stepmania.cvs.sourceforge.net/stepmania/stepmania/Themes/default/BGAnimations/ScreenCompany%20background/default.xml?revision=1.3&view=markup

which works, but is limiting.

> Wouldn't it be nice if the creation of tables (and possibly other  
> allocated objects like userdata and functions) was somehow hookable  
> or metatableised?  Then you could arrange that every table created by  
> module foo was branded as being created by foo.

That's interesting, but one nice thing about this scheme is that whoever
calls the Def function is branded as the creator.  For example, if a
function elsewhere returns a table:

   function func() return { File = "file.png" } end

and one of these chunks uses it: "Def.Actor(func())", then error
messages point to the calling chunk, and not the generic low-level
function, which may be used in many places.

(I'm not satisfied, cosmetically, with "Def", or that it's a global,
but this will be used widely and I don't want something cumbersome
to type.)

-- 
Glenn Maynard