lua-users home
lua-l archive

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


I once had the idea to create a standard way of describing values in Lua. The purpose was to automatically validate values at runtime (mostly function parameters and return values), as well as provide built-in documentation. I imagined that a module should come with documentation and contract (as in "design by contract"). A possible GUI tool (like an IDE) could load a module and diplay in a tree view all of the types (classes) and functions it exposes, along with their contract and documentation. The formal description of the contract (e.g. allowed ranges for numerical values, regexp patterns for string values, is nil accepted or not, etc.) allows for easy automatic validation at runtime.

I wrote some Lua code about that and it worked OK. Here's how a descriptor for a module looked like:

-- first comes the module code

...

-- at the end come the descriptors

public.desc = { types = {}, interface = {} }

public.desc.docs = [[
General module documentation comes here...
]]

public.desc.types.testResults = desc
{
"A table describing the current state of the tests",   -- short description
"table",         -- type or list of possible types
content =        -- for tables - descriptors of the content
{
  nTests = desc { "Total number of tests", "int", min = 0 },
  nOK = desc { "Number of successful tests", "int", min = 0 },
  nFailed = desc { "Number of failed tests", "int", min = 0 },
  log = desc { "Log of the test results", "string" },
  coverage = desc { "Table of line coverage", "table" },
}
docs = [[
Detailed documentation comes here...
]]
}

public.desc.interface.testModule = desc
{
"Loads a whole module and runs the tests it contains, which must be contained in the __tests field",

public.testModule,          -- the function itself

returns =                   -- function return value(s) descriptors
{
  desc { "True if the test run was successful", "boolean" },
  desc { "Error message if the test run failed, or a table of test results",
         { "string", public.desc.types.testResults }
       },
},

params =                    -- function parameter descriptors
{
  desc { "Module filename", "string" },
  desc { "Output filename for the coverage HTML file", "string", allowNil = true }
}

docs = [[
Detailed documentation comes here...
]]
}

The descriptor module provided a validator function which could be set as a call hook and validate the parameters and return values for each function call (of course, that can be done only in testing mode, if speed is important). The examples are from the simple testing module I wrote, which is the natural extension of the descriptors module - it simply loads a given module and runs the list of tests it contains (with the validator function enabled).

I don't have time for Lua at the moment (since I finally decided against using it for the things I'm doing at the moment - C++ is still the best tool), so I'm just throwing the idea... I think Lua's convenient and powerful data description abilities can (and should) be used for detailed reflection/introspection.

Regards,
Ivan