lua-users home
lua-l archive

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


As an exercise in learning to program in lua, and because I
think it will be a useful library to have, I am writing a
library to manipulate linked lists.  The library will be
written in c, available to lua in the same manner as the
standard libraries.  Eventually I want to have a library
like this:

    list.null() -- returns a null list
    list.isnull(obj) -- returns boolean true if obj is a
                        list, and boolean false otherwise
    list.cons(obj,lst) -- returns a new list with obj
                          attached to the front of lst
    list.head(lst) -- returns the first item in lst
    list.tail(lst) -- returns the rest of lst after the
                      first item

My first question:  Is it possible to have list.null, a
value, instead of list.null(), a function that returns a
value?

The library starts with this little bit of code:

    typedef struct ListItem ListItem;

    struct ListItem {
        void     *item;
        ListItem *next;
    };

    ListItem *listNull(void) { return (ListItem *) NULL; }

    int listIsNull(ListItem *lst) { return lst == NULL; }

    ListItem *listCons(void *itm, ListItem *lst) {
        ListItem *newList;
        newList = (ListItem *) malloc(sizeof(ListItem));
        newList->item = itm;
        newList->next = lst;
        return newList; }

    void *listHead(ListItem *lst) { return lst->item; }

    ListItem *listTail(ListItem *lst) { return lst->next; }

This isn't particularly good code.  For instance, I don't
check the return from malloc, nor do listHead and listTail
check that their arguments are non-NULL.  This is a place
to start organizing my thoughts, not a final piece of code.

I've been reading sections 3.8 and 3.16 of the lua manual.
I understand that my functions will have different types
and different arguments than they do now, something like
this:

    static int listNull(lua_State *L)
    static int listIsNull(lua_State *L)
    static int listCons(lua_State *L)
    static int listHead(lua_State *L)
    static int listTail(lua_State *L)

Now I start writing the functions.  Here is my first attempt
at listCons:

    static int listCons(lua_State *L) {
        ListItem *newList;
        void *itm;
        ListItem *lst;
        if (lua_gettop(L) != 2) {
            lua_pushstring(L, "incorrect argument count");
            lua_error(L);
        }
        itm = lua_touserdata(L,1);
        lst = lua_touserdata(L,2);
        newList = (ListItem *) lua_newuserdata(L, (sizeof(ListItem));
        newList->item = itm;
        newList->next = lst;
        lua_pushuserdata(newList);
        return 1;
    }

But I'm pretty sure that's not right.  For instance, I
haven't checked anywhere that itm and lst have the proper
type; itm may take any lua type, lst must be a ListItem.
I haven't checked that lua_newuserdata finds memory, but
maybe the runtime system checks that.  And I realize that
lua_pushuserdata doesn't exist!

So the obvious questions are:  How do I check that the
type of an argument is a ListItem?  And how do I return
a value of type ListItem?  And perhaps a less obvious
question:  How can I arrange that "type(lst)" returns
"list", so that its type is disjoint from all other types?

I also want to know what I have to specify in my list.c
file.  Do I need a lua_open line?  How do I register my
c functions so they form a table like the system library?
Do I need to specify -llualib.h or any other libraries
when I compile?  Do I say "require list" in my lua program
to gain access to my list library?

The last question is a meta-question: I have the book on
order (arriving in about a week), I've scoured the tutorials
in the wiki, searched for lua_CFunction in the mailing list
archives, and even read some source code -- where on the web
would I find answers to my questions?

Many thanks for all assistance.

Phil