From 68e2e03838a475252e519a7a16a9bcb2e3e4dd62 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Mon, 12 Aug 2013 06:59:03 +0200 Subject: Adding LuaBigInt and a few more things. --- Makefile | 1 + includes/BLua.h | 3 +- includes/LuaBigInt.h | 20 +++++ src/BLua.cc | 25 +++++- src/LuaBigInt.cc | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 includes/LuaBigInt.h create mode 100644 src/LuaBigInt.cc 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 - T * recast(int n = 1) { + T * recast(int n = -1) { LuaObjectBase * b; LuaObject * 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 +#include + +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(); + { + LuaBigIntFactory cf(c = new BigInt()); + cf.pushDestruct(L); + } + *c = *a + *b; + r = 1; + break; + case BIGINT_SUB: + b = L.recast(); + { + LuaBigIntFactory cf(c = new BigInt()); + cf.pushDestruct(L); + } + *c = *a - *b; + r = 1; + break; + case BIGINT_MUL: + b = L.recast(); + { + LuaBigIntFactory cf(c = new BigInt()); + cf.pushDestruct(L); + } + *c = *a * *b; + r = 1; + break; + case BIGINT_DIV: + b = L.recast(); + { + LuaBigIntFactory cf(c = new BigInt()); + cf.pushDestruct(L); + } + *c = *a / *b; + r = 1; + break; + case BIGINT_MOD: + b = L.recast(); + { + 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