From 21e881fd6c085e615c438ceb6eb438712f5c5075 Mon Sep 17 00:00:00 2001
From: Benoit Germain <benoit.germain@ubisoft.com>
Date: Wed, 10 Apr 2024 16:21:57 +0200
Subject: C++ migration: wrap lua type values in an enum class for type safety
 and debugging purposes

---
 src/compat.h           | 27 +++++++++++++++++++++++++++
 src/lanes.cpp          | 13 +++++++++----
 src/macros_and_utils.h | 10 ++++++----
 src/tools.cpp          | 30 +++++++++++++++---------------
 4 files changed, 57 insertions(+), 23 deletions(-)

(limited to 'src')

diff --git a/src/compat.h b/src/compat.h
index 8ef1b6c..8d10e78 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -98,3 +98,30 @@ int lua_setiuservalue( lua_State* L, int idx, int n);
 #define LUA_ERRGCMM 666 // doesn't exist in Lua 5.4, we don't care about the actual value
 
 #endif // LUA_VERSION_NUM == 504
+
+// #################################################################################################
+
+// a wrapper over lua types to see them easier in a debugger
+enum class LuaType
+{
+    NONE = LUA_TNONE,
+    NIL = LUA_TNIL,
+    BOOLEAN = LUA_TBOOLEAN,
+    LIGHTUSERDATA = LUA_TLIGHTUSERDATA,
+    NUMBER = LUA_TNUMBER,
+    STRING = LUA_TSTRING,
+    TABLE = LUA_TTABLE,
+    FUNCTION = LUA_TFUNCTION,
+    USERDATA = LUA_TUSERDATA,
+    THREAD = LUA_TTHREAD,
+    CDATA = 10 // LuaJIT CDATA
+};
+
+inline LuaType lua_type_as_enum(lua_State* L, int idx_)
+{
+    return static_cast<LuaType>(lua_type(L, idx_));
+}
+inline char const* lua_typename(lua_State* L, LuaType t_)
+{
+    return lua_typename(L, static_cast<int>(t_));
+}
diff --git a/src/lanes.cpp b/src/lanes.cpp
index 462de0f..1f795cc 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -967,10 +967,10 @@ LUAG_FUNC(require)
 LUAG_FUNC(register)
 {
     char const* name = luaL_checkstring(L, 1);
-    int const mod_type = lua_type(L, 2);
+    LuaType const mod_type{ lua_type_as_enum(L, 2) };
     // ignore extra parameters, just in case
     lua_settop(L, 2);
-    luaL_argcheck(L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type");
+    luaL_argcheck(L, (mod_type == LuaType::TABLE) || (mod_type == LuaType::FUNCTION), 2, "unexpected module type");
     DEBUGSPEW_CODE(Universe* U = universe_get(L));
     STACK_CHECK_START_REL(L, 0); // "name" mod_table
     DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name));
@@ -1226,7 +1226,8 @@ LUAG_FUNC(lane_new)
     STACK_CHECK(L2, 0);
 
     // Lane main function
-    if (lua_type(L, 1) == LUA_TFUNCTION)
+    LuaType const func_type{ lua_type_as_enum(L, 1) };
+    if (func_type == LuaType::FUNCTION)
     {
         DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END));
         DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
@@ -1238,7 +1239,7 @@ LUAG_FUNC(lane_new)
             luaL_error(L, "tried to copy unsupported types"); // doesn't return
         }
     }
-    else if (lua_type(L, 1) == LUA_TSTRING)
+    else if (func_type == LuaType::STRING)
     {
         DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: compile lane body\n" INDENT_END));
         // compile the string
@@ -1247,6 +1248,10 @@ LUAG_FUNC(lane_new)
             luaL_error(L, "error when parsing lane function code"); // doesn't return
         }
     }
+    else
+    {
+        luaL_error(L, "Expected function, got %s", lua_typename(L, func_type)); // doesn't return
+    }
     STACK_CHECK(L, 0);
     STACK_CHECK(L2, 1);
     ASSERT_L(lua_isfunction(L2, 1));
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h
index 99e49f9..e8d5ab5 100644
--- a/src/macros_and_utils.h
+++ b/src/macros_and_utils.h
@@ -182,10 +182,12 @@ template <typename T, auto = []{}>
 struct Unique
 {
     T m_val;
-    Unique() = default;
-    operator T() const { return m_val; }
-    explicit Unique(T b_) : m_val{ b_ } {}
+    constexpr Unique() = default;
+    constexpr operator T() const { return m_val; }
+    constexpr explicit Unique(T b_) : m_val{ b_ } {}
 };
 
+// #################################################################################################
+
 using Source = Unique<lua_State*>;
-using Dest = Unique<lua_State*>;
+using Dest = Unique<lua_State*>;
\ No newline at end of file
diff --git a/src/tools.cpp b/src/tools.cpp
index aa95f04..4a6f2a2 100644
--- a/src/tools.cpp
+++ b/src/tools.cpp
@@ -104,7 +104,7 @@ void luaG_dump( lua_State* L)
 
     for( i = 1; i <= top; ++ i)
     {
-        int type = lua_type( L, i);
+        LuaType type{ lua_type_as_enum(L, i) };
 
         fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type));
 
@@ -1851,8 +1851,8 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
 [[nodiscard]] bool inter_copy_one(Universe* U, Dest L2, int L2_cache_i, Source L, int i, VT vt_, LookupMode mode_, char const* upName_)
 {
     bool ret{ true };
-    int val_type = lua_type( L, i);
-    static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING);
+    LuaType val_type{ lua_type_as_enum(L, i) };
+    static constexpr int pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING);
     STACK_GROW( L2, 1);
     STACK_CHECK_START_REL(L, 0);                                                       // L                          // L2
     STACK_CHECK_START_REL(L2, 0);                                                      // L                          // L2
@@ -1862,7 +1862,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
     DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[static_cast<int>(vt_)]));
 
     // Non-POD can be skipped if its metatable contains { __lanesignore = true }
-    if( ((1 << val_type) & pod_mask) == 0)
+    if( ((1 << static_cast<int>(val_type)) & pod_mask) == 0)
     {
         if( lua_getmetatable( L, i))                                               // ... mt
         {
@@ -1870,7 +1870,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
             if( lua_isboolean( L, -1) && lua_toboolean( L, -1))
             {
                 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END));
-                val_type = LUA_TNIL;
+                val_type = LuaType::NIL;
             }
             lua_pop( L, 2);                                                          // ...
         }
@@ -1882,7 +1882,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
     {
         /* Basic types allowed both as values, and as table keys */
 
-        case LUA_TBOOLEAN:
+        case LuaType::BOOLEAN:
         {
             int const v{ lua_toboolean(L, i) };
             DEBUGSPEW_CODE( fprintf( stderr, "%s\n", v ? "true" : "false"));
@@ -1890,7 +1890,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
         }
         break;
 
-        case LUA_TNUMBER:
+        case LuaType::NUMBER:
         /* LNUM patch support (keeping integer accuracy) */
 #if defined LUA_LNUM || LUA_VERSION_NUM >= 503
         if( lua_isinteger( L, i))
@@ -1909,7 +1909,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
         }
         break;
 
-        case LUA_TSTRING:
+        case LuaType::STRING:
         {
             size_t len;
             char const* s = lua_tolstring( L, i, &len);
@@ -1918,7 +1918,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
         }
         break;
 
-        case LUA_TLIGHTUSERDATA:
+        case LuaType::LIGHTUSERDATA:
         {
             void* p = lua_touserdata( L, i);
             DEBUGSPEW_CODE( fprintf( stderr, "%p\n", p));
@@ -1928,11 +1928,11 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
 
         /* The following types are not allowed as table keys */
 
-        case LUA_TUSERDATA:
+        case LuaType::USERDATA:
         ret = inter_copy_userdata(U, L2, L2_cache_i, L, i, vt_, mode_, upName_);
         break;
 
-        case LUA_TNIL:
+        case LuaType::NIL:
         if (vt_ == VT::KEY)
         {
             ret = false;
@@ -1941,18 +1941,18 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
         lua_pushnil( L2);
         break;
 
-        case LUA_TFUNCTION:
+        case LuaType::FUNCTION:
         ret = inter_copy_function(U, L2, L2_cache_i, L, i, vt_, mode_, upName_);
         break;
 
-        case LUA_TTABLE:
+        case LuaType::TABLE:
         ret = inter_copy_table(U, L2, L2_cache_i, L, i, vt_, mode_, upName_);
         break;
 
         /* The following types cannot be copied */
 
-        case 10: // LuaJIT CDATA
-        case LUA_TTHREAD:
+        case LuaType::CDATA:
+        case LuaType::THREAD:
         ret = false;
         break;
     }
-- 
cgit v1.2.3-55-g6feb