lua-users home
lua-l archive

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


> This sounds like a good idea, is it for constant data or variables?
> Would you offer any more details, such as an example structure in Lua
> and the resulting C code?

The problem is to maintain a list of strings and associated arbitrary
integer labels, something like:

typedef enum _color_ {
    color_unknown=0,

    red  = 1,
    green = 2,
    blue = 3,

    end_of_colors
} color ;

static struct {
    color   c ;
    char  * name ;
} color_list[] = {

    {red, "RED label"},
    {green, "GREEN label"},
    {blue, "BLUE label"},

    {end_of_colors, NULL}
} ;

The nice thing about declaring something static like that, is that you can
write code once for all that iterates over all colors or all color strings
without having to know about the contents of the labels or the strings.
You can also write simple generic functions that will make the association
between the string and the integer without knowing about the struct
contents.

Something like:

char * color_get_name(color c)
{
    int i=0 ;
    while (color_list[i].c != end_of_colors) {
        if (color_list[i].c == c) {
            return color_list[i].name ;
        }
        i++ ;
    }
    return NULL ;
}
(NB: the reverse problem is simpler solved by hashing the string)

Problem now is maintaining the label name declaration in
two places. Sucks.

A solution is to use a Lua table like:

color = {
    red = "RED label",
    green = "GREEN label",
    blue = "BLUE label"
}

And then write a simple Lua script that will generate the above code
for you. Now adding/modifying one label involves only one line of code.

This trick can become even more interesting with hierarchically defined
labels, like:
    countries = {
        europe = {
            portugal = "P",
            uk = "UK"
        },
        america = {
            us = "US",
            brazil = "BR"
        }
    }

The generated labels would be something like:
    europe_portugal, "P"
    europe_uk, "uk"
    america_us, "US"
    america_brazil, "BR"

Now say you want to re-organize the country declaration into something
different, you only have to shuffle around your Lua tree. The Lua script
that parses the tree and generates the C code stays the same, and the
functions that handle the struct are also untouched. By modifying your
tree
you can now have something like:
    countries = {
        portuguese = {
            portugal = "P",
            brazil = "BR"
        },
        english = {
            uk = "UK",
            us = "US"
        }
    }
The generated labels are now:
    portuguese_portugal, "P"
    portuguese_brazil, "BR"
    english_uk, "UK"
    english_us, "US"

And you have only modified one source file, the Lua tree. The Lua
generation code and the C code handling the struct are still intact.

Going further: we usually store more than just an associated string,
making it possible to link together many more elements (e.g. the hash of
the associated string). Since we are controlling the Lua code that
generates the C, we also use special numbers in the enum to allow
deriving properties from the int itself. Example: enum that convert to an
odd int have property 1, enums that convert to an even int have property
2.

The idea behind all that is that you have a bunch of static data that you
want to convert to C code, making it easy to maintain and avoiding
re-programming of all the handling functions every time you modify the
data. This is one possible solution. There is nothing specific to Lua,
only that the table declaration syntax is simple to read, maintain, can be
written by anybody. The script generating the C code from the Lua table is
also quite simple (omitted here).

Cheers
-- 
Nicolas