Author Topic: GH/Lua "standard library"  (Read 680 times)

Offline PlaintextMan

  • Veteran
  • ***
  • Posts: 175
    • View Profile
GH/Lua "standard library"
« on: April 23, 2012, 12:21:05 pm »
I'm only just beginning to wrap my head around all this, and only starting out with Lua, but anyhow,
I'm going to try refactoring and extending the "standard functions" and metatables provided gh_functions.lua and gh_init.lua. I'm planning on making a neat, usable "stdlib" for GH Lua scripting.

First off, I introduced the gear:SetLink function (Lua_RawSetLink at the Pascal side of things*), which acts as a counterpoint to FollowLink. This is the building block that allows manipulating Inv and Sub lists.

I'm working on a proper lua-side gear browser that can traverse links and list attributes. I'm thinking things like these could all go into a "lua utilities/experiments" directory, and eg. yellow.lua can be modified to dofile() if one wants to invoke any of them. Anyway, while making this browser I ran into the following issue.

I noticed that the mechanism for manipulating NAtts (however exactly those things work) and SAtts are quite different. NAtts have to be manipulated with add/del/get/set functions, whereas SAtts can conveniently be manipulated as a Lua table of strings. Since NAtts seem to be indexed by a 2-tuple of integers (G, S) I'm thinking that I should try to make it possible to manipulate NAtt Values as a table indexed by tuples (I can use someone's tuple code or make my own).

I'm assuming doing all this is a good idea, but if anyone has a better idea regarding how to organize/approach any of the things I mentioned or where to start from, please speak up.

* Oh the horror! The horror! I touched the Pascal! :P

Offline magic.coding.fairy.peridot

  • Veteran
  • ***
  • Posts: 197
    • View Profile
Re: GH/Lua "standard library"
« Reply #1 on: April 23, 2012, 01:08:21 pm »
This is a good idea; I started working towards such a thing. The only thing to be careful of is that it's going to be vary hard to tell what's a good design until you start having some code that uses it. I intentionally stopped developing a gh-lua stdlib because I wanted to see how people were going to actually use the lua first. So maybe it makes sense to implement some more content first?

In particular, I think adding all the cities would be good but wouldn't ask much from the lua. On the other hand, implementing quests - even just city-defense or sewer-clearing - would be an educational experience, and would make it much easier to tell what a good lua interface would look like. I'd recommend writing a few such quests at first using arenascript, augmented by whatever lua hacks are necessary. Then once we can see what's needed, get into redesigning the lua interface.

On a more technical note, there are two basic ways of exposing Pascal objects to lua. The first, light_userdata, amounts to handing lua a pointer to the memory. Lua does no memory management, and the object has no associated tables, no type safety, or any of that lua-level stuff. The second way is to make the object into userdata, a full-fledged lua object, allocated from lua and garbage-collected when appropriate. Such an object does have things like type checking and whatnot. As it stands now, gears are represented using light_userdata. For each gear, a lua table is (supposed to be) constructed to supply additional attributes and functions.  This is implemented by having a registry of all gears that maps from the pointer to the associated lua table. I can't point to any specific problems this causes - though it's why there are all those "double registration" messages - but it seems like a very brittle mechanism. Many things that you might naturally try to do with lua objects are going to cause confusion when using this mechanism. (As a concrete example, it's not totally clear to me what is the right way to duplicate a gear - you presumably need to trigger a Pascal-level copy of the gear object, followed by a duplication of the associated lua structure. You probably also need to do something about the next, sub, and inv pointers.)

All this is to say, don't invest too much time in designing the Right Way to manipulate GH from lua, because we don't really know what our requirements are going to be yet.

Offline PlaintextMan

  • Veteran
  • ***
  • Posts: 175
    • View Profile
Re: GH/Lua "standard library"
« Reply #2 on: April 26, 2012, 06:53:28 am »
Quote from: Peridot
All this is to say, don't invest too much time in designing the Right Way to manipulate GH from lua, because we don't really know what our requirements are going to be yet.

I know, I know. But I was thinking of this because the current messy proto-implementation is hard to work with as I'm experimenting. I'm having trouble getting things done. Many requirements will change, but many won't. An example is having a gear:SetLink(link_type, gear_to) foundational function. The requirements of such basic things that are missing won't change, so might as well go ahead and do them right now instead of waiting until all requirements are "finalized".

I might very well go ahead with trying to make the Lua gear interface tidier, consistent and more comprehensive. If only to help my experimenting, but I do think it could benifit everyone who uses GH Lua.

Quote from: Peridot
On a more technical note, there are two basic ways of exposing Pascal objects to lua. The first, light_userdata, amounts to handing lua a pointer to the memory. Lua does no memory management, and the object has no associated tables, no type safety, or any of that lua-level stuff. The second way is to make the object into userdata, a full-fledged lua object, allocated from lua and garbage-collected when appropriate. Such an object does have things like type checking and whatnot. As it stands now, gears are represented using light_userdata. For each gear, a lua table is (supposed to be) constructed to supply additional attributes and functions.  This is implemented by having a registry of all gears that maps from the pointer to the associated lua table. I can't point to any specific problems this causes - though it's why there are all those "double registration" messages - but it seems like a very brittle mechanism. Many things that you might naturally try to do with lua objects are going to cause confusion when using this mechanism. (As a concrete example, it's not totally clear to me what is the right way to duplicate a gear - you presumably need to trigger a Pascal-level copy of the gear object, followed by a duplication of the associated lua structure. You probably also need to do something about the next, sub, and inv pointers.)

I agree, it seems like a brittle mechanism. Made just to "get it out there". But at least it is functional. I for one wouldn't propose making gears "full userdata" and burdening the Lua with all of the details of handling gear internals. In either case, encapsulate all interaction with the user data into the Gear class and its friends and family.

You've probably looked into it more than I have, but I'd suppose duplicating a gear would be similiar to duplicating any data structure into which others are composited and can't be unlinked from. ie. pretty much what you said; create new gear, copy over the original one's atts to it (at both pascal and lua level, though this symmetry should be automatic) and repeatedly do the same for its component lists. I'd say the whole thing should rather be called cloning than copying.

Offline PlaintextMan

  • Veteran
  • ***
  • Posts: 175
    • View Profile
Re: GH/Lua "standard library"
« Reply #3 on: April 28, 2012, 08:14:04 am »
I'm making a Lua Gear class (refactor of proto_gear) and am almost done with it. I'm aiming for something as generic as possible, that will make manipulating gears from lua side as easy as from pascal side. Here's what it should be like:

-Userdata pointer to gear is passed to gear upon instantiation.
-Gear:stat is a table that encapsulates get/set of stat attributes.
-There are the usual methods like Gear:USE.
-There is a property handler metatable for Gear that makes property-style syntax for gear properties available: eg. gear:X = 10 or local sib = gear:Next or gh_Print('first inv name: ' .. g:InvCom:Name) or gear:Parent = newparent.
-(still looking into this) SAtt and NAtts can be manipulated as Lua tables. eg. something like gear:NAtt[T(g,s)] = v or even gear:SAtt = {'a', 'b', 'c'} and gear:SAtt:insert('somestring')

I plan on exposing more of the Pascal gear manipulator functions (eg. for setting link values, searching gears) to Lua and then making the property handler use those where appliccable.

Thoughts?
« Last Edit: April 28, 2012, 08:18:44 am by PlaintextMan »

Offline magic.coding.fairy.peridot

  • Veteran
  • ***
  • Posts: 197
    • View Profile
Re: GH/Lua "standard library"
« Reply #4 on: April 28, 2012, 12:13:39 pm »
I plan on exposing more of the Pascal gear manipulator functions (eg. for setting link values, searching gears) to Lua and then making the property handler use those where appliccable.

Thoughts?


I'd say expose functions that are as basic as possible; for example, gear searching code can be written in Lua, which allows it to take advantage of the flexibility of Lua in selecting gears. That's why I wrote iterators to walk trees of gears (well, and I wanted to try out Lua's coroutines). It makes sense to me to have a layer of Lua plumbing between the nice API you're aiming for and the Pascal code underneath.

Offline PlaintextMan

  • Veteran
  • ***
  • Posts: 175
    • View Profile
Re: GH/Lua "standard library"
« Reply #5 on: April 29, 2012, 06:10:13 am »
I'd say expose functions that are as basic as possible; for example, gear searching code can be written in Lua, which allows it to take advantage of the flexibility of Lua in selecting gears.

That seems to make the most sense, then.