lua-users home
lua-l archive

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


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