From 68e2e03838a475252e519a7a16a9bcb2e3e4dd62 Mon Sep 17 00:00:00 2001
From: "Nicolas \"Pixel\" Noble" <pixel@nobis-crew.org>
Date: Mon, 12 Aug 2013 06:59:03 +0200
Subject: Adding LuaBigInt and a few more things.

---
 src/BLua.cc      |  25 ++++++-
 src/LuaBigInt.cc | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 234 insertions(+), 1 deletion(-)
 create mode 100644 src/LuaBigInt.cc

(limited to 'src')

diff --git a/src/BLua.cc b/src/BLua.cc
index eee663b..886f92e 100644
--- a/src/BLua.cc
+++ b/src/BLua.cc
@@ -838,6 +838,29 @@ bool Balau::Lua::resume(int nargs) throw (GeneralException) {
     }
 }
 
+void Balau::Lua::pcall(int nargs) throw (GeneralException) {
+    int r = lua_pcall(L, nargs, LUA_MULTRET, 0);
+
+    if (r == 0)
+        return;
+
+    pushLuaContext();
+    showerror();
+
+    switch(r) {
+    case LUA_ERRRUN:
+        throw LuaException("Runtime error while running LUA code.");
+    case LUA_ERRMEM:
+        throw LuaException("Memory allocation error while running LUA code.");
+    case LUA_ERRERR:
+        throw LuaException("Error in Error function.");
+    case LUA_ERRSYNTAX:
+        throw LuaException("Syntax error in Lua code.");
+    default:
+        throw LuaException(String("Unknow error while running LUA code (err code: ") + String(r) + ")");
+    }
+}
+
 bool Balau::Lua::resumeC(int & nargs) {
     if (!yielded())
         return false;
@@ -1016,7 +1039,7 @@ Balau::LuaObjectBase * Balau::LuaObjectFactory::getMeInternal(Lua & L, int i) {
 
     if (L.istable(i)) {
         L.push("__obj");
-        L.gettable(i, true);
+        L.gettable(i < 0 ? i - 1 : i, true);
         if (!(o = (LuaObjectBase *) L.touserdata()))
             L.error("Table is not an object.");
         L.pop();
diff --git a/src/LuaBigInt.cc b/src/LuaBigInt.cc
new file mode 100644
index 0000000..67294d9
--- /dev/null
+++ b/src/LuaBigInt.cc
@@ -0,0 +1,210 @@
+#include "LuaBigInt.h"
+
+using namespace Balau;
+
+enum BigInt_functions_t {
+    BIGINT_CONSTRUCTOR,
+};
+
+enum BigInt_methods_t {
+    BIGINT_SET,
+    BIGINT_TOSTRING,
+
+    BIGINT_ADD,
+    BIGINT_SUB,
+    BIGINT_MUL,
+    BIGINT_DIV,
+    BIGINT_MOD,
+};
+
+struct lua_functypes_t BigInt_functions[] = {
+    { BIGINT_CONSTRUCTOR,     NULL,             0, 2, { BLUA_STRING | BLUA_NUMBER, BLUA_NUMBER } },
+    { -1, 0, 0, 0, 0 },
+};
+
+struct lua_functypes_t BigInt_methods[] = {
+    { BIGINT_SET,             "set",            1, 2, { BLUA_STRING | BLUA_NUMBER, BLUA_NUMBER } },
+    { BIGINT_TOSTRING,        "tostring",       0, 1, { BLUA_NUMBER } },
+
+    { BIGINT_ADD,             "add",            1, 1, { BLUA_OBJECT } },
+    { BIGINT_SUB,             "sub",            1, 1, { BLUA_OBJECT } },
+    { BIGINT_MUL,             "mul",            1, 1, { BLUA_OBJECT } },
+    { BIGINT_DIV,             "div",            1, 1, { BLUA_OBJECT } },
+    { BIGINT_MOD,             "mod",            1, 1, { BLUA_OBJECT } },
+
+    { -1, 0, 0, 0, 0 },
+};
+
+struct sLua_BigInt {
+    static int BigInt_proceed_static(Lua & L, int n, int caller);
+    static int BigInt_proceed(Lua & L, int n, BigInt * obj, int caller);
+};
+
+int sLua_BigInt::BigInt_proceed_static(Lua & L, int n, int caller) {
+    int r = 0;
+    String s;
+    int radix = 10;
+
+    switch (caller) {
+    case BIGINT_CONSTRUCTOR:
+        {
+            BigInt * a = new BigInt();
+            if (L.type() == LUA_TSTRING) {
+                s = L.tostring(1);
+                if (n == 2)
+                    radix = L.tonumber(-1);
+                a->set(s, radix);
+            } else {
+                lua_Number f = L.tonumber();
+                a->set(f);
+            }
+            LuaBigIntFactory o(a);
+            o.pushDestruct(L);
+            r = 1;
+            break;
+        }
+    }
+
+    return r;
+}
+
+int sLua_BigInt::BigInt_proceed(Lua & L, int n, BigInt * a, int caller) {
+    int r = 0;
+    BigInt * b, * c, * m;
+    String s;
+    int radix = 10;
+
+    switch (caller) {
+    case BIGINT_SET:
+        if (L.type() == LUA_TSTRING) {
+            s = L.tostring(2);
+            if (n == 3)
+                radix = L.tonumber(-1);
+            a->set(s, radix);
+        } else {
+            lua_Number f = L.tonumber();
+            a->set(f);
+        }
+        r = 0;
+        break;
+    case BIGINT_TOSTRING:
+        if (n == 3)
+            radix = L.tonumber(-1);
+        L.push(a->toString(radix));
+        r = 1;
+        break;
+    case BIGINT_ADD:
+        b = L.recast<BigInt>();
+        {
+            LuaBigIntFactory cf(c = new BigInt());
+            cf.pushDestruct(L);
+        }
+        *c = *a + *b;
+        r = 1;
+        break;
+    case BIGINT_SUB:
+        b = L.recast<BigInt>();
+        {
+            LuaBigIntFactory cf(c = new BigInt());
+            cf.pushDestruct(L);
+        }
+        *c = *a - *b;
+        r = 1;
+        break;
+    case BIGINT_MUL:
+        b = L.recast<BigInt>();
+        {
+            LuaBigIntFactory cf(c = new BigInt());
+            cf.pushDestruct(L);
+        }
+        *c = *a * *b;
+        r = 1;
+        break;
+    case BIGINT_DIV:
+        b = L.recast<BigInt>();
+        {
+            LuaBigIntFactory cf(c = new BigInt());
+            cf.pushDestruct(L);
+        }
+        *c = *a / *b;
+        r = 1;
+        break;
+    case BIGINT_MOD:
+        b = L.recast<BigInt>();
+        {
+            LuaBigIntFactory cf(c = new BigInt());
+            cf.pushDestruct(L);
+        }
+        *c = *a % *b;
+        r = 1;
+        break;
+    }
+
+    return r;
+}
+
+#define METAMETHOD_WRAPPER(op) \
+L.push("__" #op); \
+L.load("" \
+"return function(bigint) return function(a) \n" \
+"    return a:" #op "() \n" \
+"end end\n" \
+""); \
+L.copy(-5); \
+L.pcall(1); \
+L.settable() \
+
+#define METAMETHOD_WRAPPER2(op) \
+L.push("__" #op); \
+L.load("" \
+"return function(bigint) return function(a, b) \n" \
+"    if type(a) ~= 'table' or a.__type ~= bigint then \n" \
+"        a = bigint.new(a) \n" \
+"    end \n" \
+"    if type(b) ~= 'table' or b.__type ~= bigint then \n" \
+"        b = bigint.new(b) \n" \
+"    end \n" \
+"    return a:" #op "(b) \n" \
+"end end\n" \
+""); \
+L.copy(-5); \
+L.pcall(1); \
+L.settable() \
+
+void LuaBigIntFactory::pushStatics(Lua & L) {
+    CHECK_FUNCTIONS(BigInt);
+    CHECK_METHODS(BigInt);
+    PUSH_CLASS(BigInt);
+    PUSH_CONSTRUCTOR(BigInt, BIGINT_CONSTRUCTOR);
+    L.push("BIGINT_METAS");
+    L.newtable();
+    METAMETHOD_WRAPPER2(add);
+    METAMETHOD_WRAPPER2(sub);
+    METAMETHOD_WRAPPER2(div);
+    METAMETHOD_WRAPPER2(mul);
+    METAMETHOD_WRAPPER2(mod);
+    METAMETHOD_WRAPPER(tostring);
+    L.settable(LUA_REGISTRYINDEX);
+    PUSH_CLASS_DONE();
+}
+
+void LuaBigIntFactory::pushObjectAndMembers(Lua & L) {
+    pushObj(L, m_obj, "BigInt");
+
+    L.push("BIGINT_METAS");
+    L.gettable(LUA_REGISTRYINDEX);
+    L.setmetatable();
+
+    PUSH_METHOD(BigInt, BIGINT_SET);
+    PUSH_METHOD(BigInt, BIGINT_TOSTRING);
+
+    PUSH_METHOD(BigInt, BIGINT_ADD);
+    PUSH_METHOD(BigInt, BIGINT_SUB);
+    PUSH_METHOD(BigInt, BIGINT_MUL);
+    PUSH_METHOD(BigInt, BIGINT_DIV);
+    PUSH_METHOD(BigInt, BIGINT_MOD);
+}
+
+void Balau::registerLuaBigInt(Lua & L) {
+    LuaBigIntFactory::pushStatics(L);
+}
-- 
cgit v1.2.3