summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-08-12 06:59:03 +0200
committerNicolas "Pixel" Noble <pixel@nobis-crew.org>2013-08-12 06:59:03 +0200
commit68e2e03838a475252e519a7a16a9bcb2e3e4dd62 (patch)
treec3f059fc59c4221fda81f006a578b5b4fe7643bb
parent0d528cd7be88272ac9ce33641ab80a7fd0600f0a (diff)
Adding LuaBigInt and a few more things.
-rw-r--r--Makefile1
-rw-r--r--includes/BLua.h3
-rw-r--r--includes/LuaBigInt.h20
-rw-r--r--src/BLua.cc25
-rw-r--r--src/LuaBigInt.cc210
5 files changed, 257 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index c155c10..9dcb920 100644
--- a/Makefile
+++ b/Makefile
@@ -65,6 +65,7 @@ HttpServer.cc \
SimpleMustache.cc \
\
BLua.cc \
+LuaBigInt.cc \
LuaHandle.cc \
LuaTask.cc \
\
diff --git a/includes/BLua.h b/includes/BLua.h
index 1bcf763..1312051 100644
--- a/includes/BLua.h
+++ b/includes/BLua.h
@@ -123,6 +123,7 @@ class Lua {
void call(const char * funcName, int tableIdx = LUA_GLOBALSINDEX, int nArgs = 0);
void call(int nArgs = 0) { resume(nArgs); }
+ void pcall(int nArgs = 0) throw (GeneralException);
void push() { checkstack(); lua_pushnil(L); }
void push(lua_Number n) { checkstack(); lua_pushnumber(L, n); }
@@ -191,7 +192,7 @@ class Lua {
void weaken();
template<class T>
- T * recast(int n = 1) {
+ T * recast(int n = -1) {
LuaObjectBase * b;
LuaObject<T> * r;
diff --git a/includes/LuaBigInt.h b/includes/LuaBigInt.h
new file mode 100644
index 0000000..260c2e9
--- /dev/null
+++ b/includes/LuaBigInt.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <BLua.h>
+#include <BigInt.h>
+
+namespace Balau {
+
+class LuaBigIntFactory : public LuaObjectFactory {
+ public:
+ LuaBigIntFactory(BigInt * b) : m_obj(b) { }
+ static void pushStatics(Lua & L);
+ protected:
+ void pushObjectAndMembers(Lua & L);
+ private:
+ BigInt * m_obj;
+};
+
+void registerLuaBigInt(Lua &);
+
+};
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);
+}