implement lua_type
authorTero Marttila <terom@fixme.fi>
Sun, 19 Apr 2009 23:56:01 +0300
changeset 145 a5582e1a83da
parent 144 51f96539f9f3
child 146 24c0fc79d86a
implement lua_type
src/lua_func.c
src/lua_func.h
src/lua_irc.c
src/lua_objs.c
src/lua_type.c
src/lua_type.h
--- a/src/lua_func.c	Sun Apr 19 23:53:37 2009 +0300
+++ b/src/lua_func.c	Sun Apr 19 23:56:01 2009 +0300
@@ -126,10 +126,8 @@
     va_list vargs;
 
     // first, the obj argument
-    if (func->type) {
-        *obj_ptr = lua_obj_get_obj(L, func->name, func->type);
-        argidx++;
-    }
+    if (func->type)
+        *obj_ptr = lua_type_get(L, func->type, argidx++);
 
     // were we given a table of arguments?
     if (lua_istable(L, argidx))
--- a/src/lua_func.h	Sun Apr 19 23:53:37 2009 +0300
+++ b/src/lua_func.h	Sun Apr 19 23:56:01 2009 +0300
@@ -40,8 +40,8 @@
  * Function def
  */
 struct lua_func {
-    /** Type name, or NULL */
-    const char *type;
+    /** Object type, or NULL */
+    const struct lua_type *type;
 
     /** Function name */
     const char *name;
@@ -64,11 +64,12 @@
  */
 #define LUA_FUNC_ARG_STRING(name, def) { (name), LUA_ARG_STRING, { .string = (def) } }
 #define LUA_FUNC_ARG_BOOL(name, def) { (name), LUA_ARG_BOOL, { .boolean = (def) } }
+#define LUA_FUNC_ARG_END { NULL, 0, { 0 } }
 
 /**
  * Define a function
  */
-#define LUA_FUNC(type, name, help, ...) { (type), (name), (help), { __VA_ARGS__, { NULL, 0, { 0 } } } }
+#define LUA_FUNC(type, name, help, ...) { (type), (name), (help), { __VA_ARGS__, LUA_FUNC_ARG_END } }
 
 /**
  * Parse and return a string argument
--- a/src/lua_irc.c	Sun Apr 19 23:53:37 2009 +0300
+++ b/src/lua_irc.c	Sun Apr 19 23:56:01 2009 +0300
@@ -4,13 +4,15 @@
 #include <stdlib.h>
 #include <string.h>
 
+static struct lua_type lua_chan_type = LUA_TYPE("evirc.chan");
+
 /**
  * Create a lua_chan userdata from the given irc_chan and leave it on the stack, returning 1
  */
 static int lua_chan_create (lua_State *L, struct irc_chan *chan)
 {
     // create the new obj
-    struct lua_chan *lua_chan = lua_obj_create_obj(L, "evirc.chan", sizeof(*lua_chan));
+    struct lua_chan *lua_chan = lua_type_create(L, &lua_chan_type, sizeof(*lua_chan));
 
     // initialize
     lua_chan->chan = chan;
@@ -22,9 +24,17 @@
 /**
  * Return the channel name as a lua string
  */
-static int lua_chan_tostring (lua_State *L)
+static struct lua_func lua_chan__tostring_func = LUA_FUNC(&lua_chan_type, "__tostring",
+        "format using channel name",
+
+        LUA_FUNC_ARG_END
+    );
+
+static int lua_chan__tostring (lua_State *L)
 {
-    struct lua_chan *lua_chan = lua_obj_get_obj(L, __func__, "evirc.chan");
+    struct lua_chan *lua_chan;
+
+    lua_args_parse(L, &lua_chan__tostring_func, (void *) &lua_chan);
     
     lua_pushfstring(L, "<irc_chan %s>", irc_chan_name(lua_chan->chan));
 
@@ -34,14 +44,22 @@
 /**
  * Send a PRIVMSG to the channel
  */
+static struct lua_func lua_chan_say_func = LUA_FUNC(&lua_chan_type, "evirc.chan.say",
+        "send a message to a channel",
+
+        LUA_FUNC_ARG_STRING("message",      LUA_ARG_STRING_REQUIRED )
+    );
+
 static int lua_chan_say (lua_State *L)
 {
+    struct lua_chan *lua_chan;
     err_t err;
+    const char *message;
 
-    struct lua_chan *lua_chan = lua_obj_get_obj(L, __func__, "evirc.chan");
-    
-    // the message
-    const char *message = luaL_checkstring(L, 2);
+    // parse args
+    lua_args_parse(L, &lua_chan_say_func, (void *) &lua_chan,
+            &message
+        );
 
     // send
     if ((err = irc_chan_PRIVMSG(lua_chan->chan, message)))
@@ -51,19 +69,14 @@
     return 0;
 }
 
-static const struct luaL_Reg lua_chan_methods[] = {
-    {   "__tostring",       &lua_chan_tostring  },
-    {   "say",              &lua_chan_say       },
-    {   NULL,               NULL                },
-};
+static struct lua_method lua_chan_methods[] = LUA_METHODS(
+        LUA_METHOD("__tostring",    lua_chan__tostring, &lua_chan__tostring_func    ),
+        LUA_METHOD("say",           lua_chan_say,       &lua_chan_say_func          )
+    );
 
-/**
- * Initialize the lua_chan object type
- */
-static void lua_chan_init (lua_State *L)
-{
-    lua_obj_create_type(L, "evirc.chan", lua_chan_methods);
-}
+
+
+static struct lua_type lua_net_type = LUA_TYPE("evirc.net");
 
 /**
  * Create a lua_net userdata from the given irc_net and push it onto the stack, returning 1.
@@ -71,7 +84,7 @@
 static int lua_net_create (lua_State *L, struct irc_net *net)
 {
     // create the new obj
-    struct lua_net *lua_net = lua_obj_create_obj(L, "evirc.net", sizeof(*lua_net));
+    struct lua_net *lua_net = lua_type_create(L, &lua_net_type, sizeof(*lua_net));
 
     // initialize
     lua_net->net = net;
@@ -83,9 +96,17 @@
 /**
  * Return the network name as a lua string
  */
-static int lua_net_tostring (lua_State *L)
+static struct lua_func lua_net__tostring_func = LUA_FUNC(&lua_net_type, "__tostring",
+        "format using network name",
+
+        LUA_FUNC_ARG_END
+    );
+
+static int lua_net__tostring (lua_State *L)
 {
-    struct lua_net *lua_net = lua_obj_get_obj(L, __func__, "evirc.net");
+    struct lua_net *lua_net;
+
+    lua_args_parse(L, &lua_net__tostring_func, (void *) &lua_net);
     
     lua_pushfstring(L, "<irc_net %s>", irc_net_name(lua_net->net));
 
@@ -95,16 +116,24 @@
 /**
  * Join a new channel, returning the lua_chan
  */
+static struct lua_func lua_net_join_func = LUA_FUNC(&lua_net_type, "join",
+        "create a new channel and join it",
+
+        LUA_FUNC_ARG_STRING("channel",      LUA_ARG_STRING_REQUIRED)
+    );
+
+
 static int lua_net_join (lua_State *L)
 {
-    struct lua_net *lua_net = lua_obj_get_obj(L, __func__, "evirc.net");
+    struct lua_net *lua_net;
     struct irc_chan_info chan_info;
     struct irc_chan *chan;
     struct error_info err;
     
     // the channel name
-    // XXX: bad! bad! bad!
-    chan_info.channel = strdup(luaL_checkstring(L, 2));
+    lua_args_parse(L, &lua_net_join_func, (void *) &lua_net,
+            &chan_info.channel
+        );
     
     // add it
     if (irc_net_add_chan(lua_net->net, &chan, &chan_info, &err))
@@ -117,13 +146,22 @@
 /**
  * Look up a channel by name, returning the lua_chan
  */
+static struct lua_func lua_net_get_chan_func = LUA_FUNC(&lua_net_type, "channel",
+        "look up a channel by name",
+
+        LUA_FUNC_ARG_STRING("channel",      LUA_ARG_STRING_REQUIRED)
+    );
+
 static int lua_net_get_chan (lua_State *L)
 {
-    struct lua_net *lua_net = lua_obj_get_obj(L, __func__, "evirc.net");
+    struct lua_net *lua_net;
     struct irc_chan *chan;
-    
-    // the channel name
-    const char *channel = luaL_checkstring(L, 2);
+    const char *channel;
+
+    // parse args
+    lua_args_parse(L, &lua_net_get_chan_func, (void *) &lua_net,
+            &channel
+        );
     
     // lookup the irc_chan
     if ((chan = irc_net_get_chan(lua_net->net, channel)) == NULL)
@@ -133,22 +171,18 @@
     return lua_chan_create(L, chan);
 }
 
-static const struct luaL_Reg lua_net_methods[] = {
-    {   "__tostring",   &lua_net_tostring   },
-    {   "join",         &lua_net_join       },
-    {   "channel",      &lua_net_get_chan   },
-    {   NULL,           NULL                }
-};
+static struct lua_method lua_net_methods[] = LUA_METHODS(
+        LUA_METHOD("__tostring",    lua_net__tostring,  &lua_net__tostring_func ),
+        LUA_METHOD("join",          lua_net_join,       &lua_net_join_func      ),
+        LUA_METHOD("channel",       lua_net_get_chan,   &lua_net_get_chan_func  )
+    );
 
-/**
- * Initialize the lua_net object type
- */
-static void lua_net_init (lua_State *L)
-{
-    lua_obj_create_type(L, "evirc.net", lua_net_methods);
-}
 
-static struct lua_func lua_client_set_defaults_func = LUA_FUNC("evirc.client", "set_defaults", 
+
+static struct lua_type lua_client_type = LUA_TYPE("evirc.client");
+
+
+static struct lua_func lua_client_set_defaults_func = LUA_FUNC(&lua_client_type, "set_defaults", 
         "set the default settings to use for evirc.client.connect",
 
         LUA_FUNC_ARG_STRING("nickname",     LUA_ARG_STRING_REQUIRED ),
@@ -156,7 +190,7 @@
         LUA_FUNC_ARG_STRING("realname",     LUA_ARG_STRING_REQUIRED ),
         LUA_FUNC_ARG_STRING("service",      IRC_PORT                ),
         LUA_FUNC_ARG_STRING("service_ssl",  IRC_SSL_PORT            )
-);
+    );
 
 static int lua_client_set_defaults (lua_State *L)
 {
@@ -165,8 +199,8 @@
 
     // parse args
     lua_args_parse(L, &lua_client_set_defaults_func, (void *) &lua_client,
-        &nickname, &username, &realname, &service, &service_ssl
-    );
+            &nickname, &username, &realname, &service, &service_ssl
+        );
 
     // set
     struct irc_client_defaults defaults = {
@@ -187,7 +221,7 @@
     return 0;
 }
 
-static struct lua_func lua_client_connect_func = LUA_FUNC("evirc.client", "connect",
+static struct lua_func lua_client_connect_func = LUA_FUNC(&lua_client_type, "connect",
         "Create and return a new IRC network",
 
         LUA_FUNC_ARG_STRING("network",      LUA_ARG_STRING_REQUIRED ),
@@ -239,13 +273,22 @@
     return lua_net_create(L, net);
 }
 
+static struct lua_func lua_client_get_network_func = LUA_FUNC(&lua_client_type, "network",
+        "Lookup an existing network by name",
+
+        LUA_FUNC_ARG_STRING("network",  LUA_ARG_STRING_REQUIRED)
+    );
+
 static int lua_client_get_network (lua_State *L)
 {
-    struct lua_client *lua_client = lua_obj_get_obj(L, __func__, "evirc.client");
+    struct lua_client *lua_client;
     struct irc_net *net;
-    
-    // the network name
-    const char *network = luaL_checkstring(L, 2);
+    const char *network;
+
+    // parse args
+    lua_args_parse(L, &lua_client_get_network_func, (void *) &lua_client,
+            &network
+        );
     
     // lookup the irc_net
     if ((net = irc_client_get_net(lua_client->client, network)) == NULL)
@@ -255,13 +298,22 @@
     return lua_net_create(L, net);
 }
 
+static struct lua_func lua_client_quit_func = LUA_FUNC(&lua_client_type, "quit",
+        "Disconnect from all networks",
+
+        LUA_FUNC_ARG_STRING("message",  "Bye")
+    );
+
 static int lua_client_quit (lua_State *L)
 {
-    struct lua_client *lua_client = lua_obj_get_obj(L, __func__, "evirc.client");
+    struct lua_client *lua_client;
     err_t err;
-   
-    // the message
-    const char *message = luaL_checkstring(L, 2);
+    const char *message;
+
+    // parse args
+    lua_args_parse(L, &lua_client_quit_func, (void *) &lua_client,
+            &message
+        );
 
     // execute
     if ((err = irc_client_quit(lua_client->client, message)))
@@ -271,31 +323,23 @@
     return 0;
 }
 
-static const struct luaL_Reg lua_client_methods[] = {
-    {   "set_defaults", &lua_client_set_defaults    },
-    {   "connect",      &lua_client_connect         },
-    {   "network",      &lua_client_get_network     },
-    {   "quit",         &lua_client_quit            },
-    {   NULL,           NULL                        }
-};
-
-/**
- * Initialize the evirc.client type for lua_client, and registers an instance bound to the given irc_client at
- * 'client'.
- */
-static void lua_client_init (lua_State *L, struct irc_client *client)
-{
-    // allocate the global "client" object
-    struct lua_client *lua_client = lua_obj_create_global_type(L, "evirc.client", lua_client_methods, "client", sizeof(*lua_client));
-    
-    // initialize it
-    lua_client->client = client;
-}
+static struct lua_method lua_client_methods[] = LUA_METHODS(
+        LUA_METHOD("set_defaults",  lua_client_set_defaults,    &lua_client_set_defaults_func   ),
+        LUA_METHOD("connect",       lua_client_connect,         &lua_client_connect_func        ),
+        LUA_METHOD("network",       lua_client_get_network,     &lua_client_get_network_func    ),
+        LUA_METHOD("quit",          lua_client_quit,            &lua_client_quit_func           )
+    );
 
 void lua_irc_init (struct nexus_lua *lua)
 {
-    lua_client_init(lua->st, lua->nexus->client);
-    lua_net_init(lua->st);
-    lua_chan_init(lua->st);
+    // register types
+    lua_type_register(lua->st, &lua_chan_type, lua_chan_methods);
+    lua_type_register(lua->st, &lua_net_type, lua_net_methods);
+
+    // register the global "client" object
+    struct lua_client *lua_client = lua_type_register_global(lua->st, &lua_client_type, lua_client_methods, "client", sizeof(*lua_client));
+    
+    // initialize it
+    lua_client->client = lua->nexus->client;
 }
 
--- a/src/lua_objs.c	Sun Apr 19 23:53:37 2009 +0300
+++ b/src/lua_objs.c	Sun Apr 19 23:56:01 2009 +0300
@@ -12,6 +12,8 @@
     struct module *module;
 };
 
+static struct lua_type lua_module_type = LUA_TYPE("spbot.module");
+
 /**
  * Create a lua_module userdata from the given module and push it onto the stack, returning 1.
  *
@@ -20,7 +22,7 @@
 static int lua_module_create (lua_State *L, struct module *module)
 {
     // create the new obj
-    struct lua_module *lua_module = lua_obj_create_obj(L, "spbot.module", sizeof(*lua_module));
+    struct lua_module *lua_module = lua_type_create(L, &lua_module_type, sizeof(*lua_module));
 
     // initialize
     lua_module->module = module;
@@ -34,7 +36,7 @@
  */
 static int lua_module__gc (lua_State *L)
 {
-    struct lua_module *lua_module = lua_obj_get_obj(L, __func__, "spbot.module");
+    struct lua_module *lua_module = lua_type_get(L, &lua_module_type, 1);
     
     // put it
     module_put(lua_module->module);
@@ -44,7 +46,7 @@
 
 static int lua_module_conf (lua_State *L)
 {
-    struct lua_module *lua_module = lua_obj_get_obj(L, __func__, "spbot.module");
+    struct lua_module *lua_module = lua_type_get(L, &lua_module_type, 1);
     const struct config_option *option;
     struct error_info err;
     bool is_err = true;
@@ -170,7 +172,7 @@
 
 static int lua_module_unload (lua_State *L)
 {
-    struct lua_module *lua_module = lua_obj_get_obj(L, __func__, "spbot.module");
+    struct lua_module *lua_module = lua_type_get(L, &lua_module_type, 1);
     struct error_info err;
 
     // just unload it
@@ -181,20 +183,11 @@
     return 0;
 }
 
-static const struct luaL_Reg lua_module_methods[] = {
-    {   "__gc",         &lua_module__gc             },
-    {   "conf",         &lua_module_conf            },
-    {   "unload",       &lua_module_unload          },
-    {   NULL,           NULL                        }
-};
-
-/**
- * Initialize the lua_module object type
- */
-static void lua_module_init (lua_State *L)
-{
-    lua_obj_create_type(L, "spbot.module", lua_module_methods);
-}
+static struct lua_method lua_module_methods[] = LUA_METHODS(
+        LUA_METHOD("__gc",      lua_module__gc,     NULL    ),
+        LUA_METHOD("conf",      lua_module_conf,    NULL    ),
+        LUA_METHOD("unload",    lua_module_unload,  NULL    )
+);
 
 /**
  * Wrapper for modules
@@ -207,9 +200,11 @@
     char *path;
 };
 
+static struct lua_type lua_modules_type = LUA_TYPE("spbot.modules");
+
 static int lua_modules__gc (lua_State *L)
 {
-    struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules");
+    struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
     
     // remove the modules path if it was set by us
     if (lua_modules->path && modules_path(lua_modules->modules, NULL) == lua_modules->path)
@@ -224,7 +219,7 @@
 
 static int lua_modules_path (lua_State *L)
 {
-    struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules");
+    struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
     char *path = NULL;
     const char *old_path;
     
@@ -255,7 +250,7 @@
 
 static int lua_modules_load (lua_State *L)
 {
-    struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules");
+    struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
     struct module *module;
     struct module_info info;
     struct error_info err;
@@ -274,7 +269,7 @@
 
 static int lua_modules_module (lua_State *L)
 {
-    struct lua_modules *lua_modules = lua_obj_get_obj(L, __func__, "spbot.modules");
+    struct lua_modules *lua_modules = lua_type_get(L, &lua_modules_type, 1);
     struct module *module;
     
     // the module name
@@ -288,13 +283,14 @@
     return lua_module_create(L, module);
 }
 
-static const struct luaL_Reg lua_modules_methods[] = {
-    {   "__gc",         &lua_modules__gc            },
-    {   "path",         &lua_modules_path           },
-    {   "load",         &lua_modules_load           },
-    {   "module",       &lua_modules_module         },
-    {   NULL,           NULL                        }
-};
+static struct lua_method lua_modules_methods[] = LUA_METHODS(
+        LUA_METHOD("__gc",      lua_modules__gc,    NULL    ),
+        LUA_METHOD("path",      lua_modules_path,   NULL    ),
+        LUA_METHOD("load",      lua_modules_load,   NULL    ),
+        LUA_METHOD("module",    lua_modules_module, NULL    )
+    );
+
+
 
 /**
  * Initialize the spbot.modules type for lua_modules, and registers an instance bound to the given modules list at
@@ -303,7 +299,7 @@
 static void lua_modules_init (lua_State *L, struct modules *modules)
 {
     // allocate the global "modules" object
-    struct lua_modules *lua_modules = lua_obj_create_global_type(L, "spbot.modules", lua_modules_methods, "modules", sizeof(*lua_modules));
+    struct lua_modules *lua_modules = lua_type_register_global(L, &lua_modules_type, lua_modules_methods, "modules", sizeof(*lua_modules));
     
     // initialize it
     lua_modules->modules = modules;
@@ -316,9 +312,11 @@
     struct nexus *nexus;
 };
 
+static struct lua_type lua_nexus_type = LUA_TYPE("spbot.nexus");
+
 static int lua_nexus_shutdown (lua_State *L)
 {
-    struct lua_nexus *lua_nexus = lua_obj_get_obj(L, __func__, "spbot.nexus");
+    struct lua_nexus *lua_nexus = lua_type_get(L, &lua_nexus_type, 1);
 
     // just shut it down
     nexus_shutdown(lua_nexus->nexus);
@@ -328,7 +326,7 @@
 
 static int lua_nexus_load_config (lua_State *L)
 {
-    struct lua_nexus *lua_nexus = lua_obj_get_obj(L, __func__, "spbot.nexus");
+    struct lua_nexus *lua_nexus = lua_type_get(L, &lua_nexus_type, 1);
     struct error_info err;
 
     const char *path = luaL_checkstring(L, 2);
@@ -340,11 +338,11 @@
     return 0;
 }
 
-static const struct luaL_Reg lua_nexus_methods[] = {
-    {   "shutdown",     &lua_nexus_shutdown         },
-    {   "load_config",  &lua_nexus_load_config      },
-    {   NULL,           NULL                        }
-};
+
+static struct lua_method lua_nexus_methods[] = LUA_METHODS(
+        LUA_METHOD("shutdown",      lua_nexus_shutdown,     NULL    ),
+        LUA_METHOD("load_config",   lua_nexus_load_config,  NULL    )
+    );
 
 /**
  * Initialize the spbot.nexus type for lua_nexus, and registers an instance bound to the given nexus list at
@@ -353,12 +351,13 @@
 static void lua_nexus_init (lua_State *L, struct nexus *nexus)
 {
     // allocate the global "nexus" object
-    struct lua_nexus *lua_nexus = lua_obj_create_global_type(L, "spbot.nexus", lua_nexus_methods, "nexus", sizeof(*lua_nexus));
+    struct lua_nexus *lua_nexus = lua_type_register_global(L, &lua_nexus_type, lua_nexus_methods, "nexus", sizeof(*lua_nexus));
     
     // initialize it
     lua_nexus->nexus = nexus;
 }
 
+
 /**
  * Global functions
  */
@@ -410,10 +409,15 @@
 
 void lua_objs_init (struct nexus_lua *lua)
 {
-    // init the various bits
-    lua_global_init(lua->st);
+    // register types
+    lua_type_register(lua->st, &lua_module_type, lua_module_methods);
+    
+    // globals
     lua_nexus_init(lua->st, lua->nexus);
     lua_modules_init(lua->st, lua->nexus->modules);
-    lua_module_init(lua->st);
+    
+    // global functions
+    lua_global_init(lua->st);
 }
 
+
--- a/src/lua_type.c	Sun Apr 19 23:53:37 2009 +0300
+++ b/src/lua_type.c	Sun Apr 19 23:56:01 2009 +0300
@@ -2,38 +2,45 @@
 
 #include <lua5.1/lauxlib.h>
 
-void lua_obj_create_type (lua_State *L, const char *name, const struct luaL_Reg methods[])
+void lua_type_register (lua_State *L, const struct lua_type *type, const struct lua_method methods[])
 {
-    luaL_newmetatable(L, name);
+    const struct lua_method *method;
+
+    // create the metatable
+    luaL_newmetatable(L, type->name);
 
     // set the metatable __index to itself
     lua_pushvalue(L, -1);
     lua_setfield(L, -1, "__index");
 
-    // register the methods to the metatable
-    luaL_register(L, NULL, methods);
+    // add the methods to the metatable
+    for (method = methods; method->func && method->info; method++) {
+        lua_pushcfunction(L, method->func);
+        lua_setfield(L, -2, method->name);
+    }
 }
 
-void* lua_obj_create_obj (lua_State *L, const char *name, size_t size)
+void* lua_type_create (lua_State *L, const struct lua_type *type, size_t size)
 {
     // create the new userdata on the stack
     void *ud = lua_newuserdata(L, size);
 
     // get the type and set it
-    luaL_getmetatable(L, name);
+    luaL_getmetatable(L, type->name);
     lua_setmetatable(L, -2);
-    
+
     // ok
     return ud;
 }
 
-void* lua_obj_create_global_type (lua_State *L, const char *type_name, const struct luaL_Reg methods[], const char *global_name, size_t size)
+void* lua_type_register_global (lua_State *L, const struct lua_type *type, const struct lua_method methods[],
+        const char *global_name, size_t size)
 {
     // allocate the global object
     void *obj = lua_newuserdata(L, size);
     
     // create the type metatable
-    lua_obj_create_type(L, type_name, methods);
+    lua_type_register(L, type, methods);
 
     // set the userdata's metatable
     lua_setmetatable(L, -2);
@@ -45,16 +52,13 @@
     return obj;
 }
 
-void* lua_obj_get_obj (lua_State *L, const char *func, const char *name)
+void* lua_type_get (lua_State *L, const struct lua_type *type, int index)
 {
     void *ud;
 
     // validate the userdata arg
-    if ((ud = luaL_checkudata(L, 1, name)) == NULL) {
-        luaL_error(L, "bad type argument to %s: `%s` expected", func, name);
-        
-        // XXX: needs a __noreturn__ attribute
-        return NULL;
+    if ((ud = luaL_checkudata(L, index, type->name)) == NULL) {
+        luaL_error(L, "bad type argument: `%s` expected", type->name); return NULL;
 
     } else {
         // ok
--- a/src/lua_type.h	Sun Apr 19 23:53:37 2009 +0300
+++ b/src/lua_type.h	Sun Apr 19 23:56:01 2009 +0300
@@ -12,23 +12,63 @@
 #include <lua5.1/lauxlib.h>
 
 /**
- * Register a new metatable for a named type, this leaves the metatable on the stack.
+ * A type's method
+ *
+ * XXX: a name field?
  */
-void lua_obj_create_type (lua_State *L, const char *name, const struct luaL_Reg methods[]);
+struct lua_method {
+    /** The name of the method */
+    const char *name;
 
-/**
- * Create a new userdata with the given type metatable name, return the pointer, and keep it on the stack.
- */
-void* lua_obj_create_obj (lua_State *L, const char *name, size_t size);
+    /** The function pointer */
+    lua_CFunction func;
+
+    /** The function definition, optional */
+    const struct lua_func *info;
+};
+
+#define LUA_METHOD(name, func, info) \
+    { (name), (func), (info) }
+
+#define LUA_METHODS(...) \
+    { __VA_ARGS__, { NULL, NULL, NULL } }
 
 /**
- * Create a new metatable for a type, a userdata for that type, and register it as a global
+ * A type
  */
-void* lua_obj_create_global_type (lua_State *L, const char *type_name, const struct luaL_Reg methods[], const char *global_name, size_t size);
+struct lua_type {
+    /** The name of the type */
+    const char *name;
+};
+
+#define LUA_TYPE(name) \
+    { (name) }
 
 /**
- * Get a userdata with the given type metatable name as the first argument for a function.
+ * Register a new metadata table for the given type in the given lua state.
+ *
+ * This leaves the new type (metatable) on the stack.
  */
-void* lua_obj_get_obj (lua_State *L, const char *func, const char *name);
+void lua_type_register (lua_State *L, const struct lua_type *type, const struct lua_method methods[]);
+
+/**
+ * Create a new instance of the given type.
+ *
+ * This leaves the new userdata object on the stack.
+ */
+void* lua_type_create (lua_State *L, const struct lua_type *type, size_t size);
+
+/**
+ * Create a new userdata type, and also create an instance of it, register it as a global, and return it.
+ *
+ * This leaves the new userdata object on the stack.
+ */
+void* lua_type_register_global (lua_State *L, const struct lua_type *type, const struct lua_method methods[],
+        const char *global_name, size_t size);
+
+/**
+ * Get an object of the given type from the given stack position
+ */
+void* lua_type_get (lua_State *L, const struct lua_type *type, int index);
 
 #endif