[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: event handler for table initialization
- From: Nilson <nilson.brazil@...>
- Date: Tue, 21 Sep 2010 16:15:41 -0300
On Tue, Sep 21, 2010 at 1:54 PM, Javier Guerra Giraldez
<javier@guerrag.com> wrote:
> On Tue, Sep 21, 2010 at 2:47 AM, Nilson <nilson.brazil@gmail.com> wrote:
>> Using function calls and tables arguments to describe structures like
>> the example below
>>
>> Computer{
>> brand = 'XYZ';
>> Motherboard{
>> Processor{type = 'Pentium'};
>> Memory{size = '512MB'}
>> };
>> Harddisk{capacity='120GB'}
>> };
>>
>> will generate function calls in an order completely different of reading order.
>> In the example: Processor, Memory, Motherboard, Harddisk, Computer.
>
>
> when you want to reorder things in time, the usual answer is to pass
> around closures. in your case, the easiest would be to write your
> functions as:
>
Javier, I think I didn't make myself clear (it was 5 am).
The actual issue is: when we make a function call using f { }, Lua
creates and initializes the table without notifying f. The function f
is called only when table is completely initialized.
So, although the function f, in many cases intents to describe the
table created, it is only a passive receiver of a defined table.
The idea is to allow a function f to be more active, receiving events
during the table initialization, eventually inserting or replacing
data and performing early detection of errors.
This could be done using a table event handler.
Example 1 (draft - beware: fresh ideas inside)
--
-- Implements an unquoted string feature
-- if does not exists a entry with name Name in _G, return the Name as string
--
local enum_mt = {}
enum_mt.__index = function (tab,Name)
local value = rawget(tab,Name)
if value == nil then return Name end
return value
end
function enum{arg} -- <--- NEW: language change: using { } instead
of ( ) meaning a table event handler
local evt = table.getevent -- NEW function to get the current event
if evt ==nil then
-- normal processing (usually an after processing)
return arg
elseif evt.type = 'begin' then -- begin of table creation
old_mt = getmetatable(_G);
setmetatable(_G,enum_mt) -- installs unquoted string
table.listen('e'); -- NEW: informs what to listen. here, listens
to end events (default behaviour)
elseif evt.type = 'end' then -- end of table creation
setmetatable(old_mt) -- resume the old one
-- other usage
--[[
elseif evt.type = 'key' then -- new field with key defined
print("with key",evt.key,evt.value)
else if evt.type = 'field' then -- new field without a key
print("without key",evt.key,evt.value)
evt.key = 'autokey_'..evt.key -- prefix the keys with autokey_
-- new idea: this event occurs when the compiler has a field value
composed by a simple name
-- and cannot locate the name in the environments.
-- It emulates a kind of table environment. evt.value has the
unresolved name.
elseif evt.type = 'name' then
return evt.value -- returns the name as value, implementing an
unquoted string
--]]
end
end
-- Usage. Note the absence of quotes
Color = enum{ red, black, white, yellow, blue }
Example 2
Parsing example
w = require('html.description')
w.html{
w.head{ w.title { "Hello" }
} --
w.body{
onload = "onload()";
onsubmit = "/main.html"; -- this is an error because onsubmit is
not allowed here
-- huge description of tables, divs etc.
} -- body{
}
function w.body{ arg }
local evt = table.getevent
if evt == nil then
-- normal processing (usually after processing)
return arg
elseif evt.type = 'begin' then -- begin of table creation
table.listen('k'); -- listen to key events
elseif evt.type = 'key' then -- new field with key
if evt.value = 'onsubmit' then
error('Invalid argument: '..evt.value..' field#: '..evt.fieldno);
-- early error detection: save time and memory and
eventually informs the line of file where the error occurred.
end
end
end
---
Nilson