From 61ba76c5a33b7e98051a8f45c3831bf2d08ce2fe Mon Sep 17 00:00:00 2001 From: "John K. Luebs" Date: Fri, 23 Feb 2024 12:14:58 -0600 Subject: [PATCH] Cleanup --- Makefile | 4 +- build.bat | 4 +- luakiwi/luakiwi-int.h | 87 ++++---- luakiwi/luakiwi.cpp | 459 +++++++++++++++++++++--------------------- t.lua | 12 +- 5 files changed, 290 insertions(+), 276 deletions(-) diff --git a/Makefile b/Makefile index e645ed2..c5be3ea 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ SRCDIR := . CC := $(CROSS)gcc CFLAGS := -fPIC -O3 CXXFLAGS := -I$(SRCDIR)/kiwi -fno-rtti -F_LTO := -flto=auto -CXXFLAGS_EXTRA := -std=c++14 -Wall $(F_LTO) +#F_LTO := -flto=auto +CXXFLAGS_EXTRA := -std=c++14 -Wall $(F_LTO) -fstrict-flex-arrays=3 CFLAGS_EXTRA := -pedantic -std=c99 -Wall $(F_LTO) LIBFLAG := -shared LIB_EXT := so diff --git a/build.bat b/build.bat index 4ed97f3..ba8f722 100644 --- a/build.bat +++ b/build.bat @@ -1,2 +1,2 @@ -cl /nologo /O2 /W4 /wd4244 /c /D_CRT_SECURE_NO_DEPRECATE /I "C:\Program Files\luarocks\include" /EHs /I kiwi luakiwi\luakiwi.cpp -link /DLL /out:ckiwi.dll /def:luakiwi.def /LIBPATH:"C:\Program Files\luarocks\lib" luakiwi.obj lua54.lib \ No newline at end of file +cl /nologo /O2 /W4 /wd4200 /c /D_CRT_SECURE_NO_DEPRECATE /I "C:\Program Files\luarocks\include" /EHs /I kiwi luakiwi\luakiwi.cpp +link /DLL /out:ckiwi.dll /def:luakiwi.def /LIBPATH:"C:\Program Files\luarocks\lib" luakiwi.obj lua54.lib diff --git a/luakiwi/luakiwi-int.h b/luakiwi/luakiwi-int.h index 8ca21c4..727fe95 100644 --- a/luakiwi/luakiwi-int.h +++ b/luakiwi/luakiwi-int.h @@ -4,21 +4,24 @@ #include #include +#include #include "luacompat.h" -#define ARR_COUNT(x) ((int)(sizeof(x) / sizeof((x)[0]))) - #if defined(__GNUC__) && !defined(LKIWI_NO_BUILTIN) - #define l_likely(x) (__builtin_expect(((x) != 0), 1)) - #define l_unlikely(x) (__builtin_expect(((x) != 0), 0)) + #define lk_likely(x) (__builtin_expect(((x) != 0), 1)) + #define lk_unlikely(x) (__builtin_expect(((x) != 0), 0)) #else - #define l_likely(x) (x) - #define l_unlikely(x) (x) + #define lk_likely(x) (x) + #define lk_unlikely(x) (x) #endif +namespace { + +using namespace kiwi; + // Lua 5.1 compatibility for missing lua_arith. -static void compat_arith_unm(lua_State* L) { +inline void compat_arith_unm(lua_State* L) { #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 lua_Number n = lua_tonumber(L, -1); if (n != 0 || lua_isnumber(L, -1)) { @@ -35,14 +38,13 @@ static void compat_arith_unm(lua_State* L) { } // This version supports placeholders. -static void setfuncs(lua_State* L, const luaL_Reg* l, int nup) { +inline void setfuncs(lua_State* L, const luaL_Reg* l, int nup) { luaL_checkstack(L, nup, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ if (l->func == NULL) /* place holder? */ lua_pushboolean(L, 0); else { - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ + for (int i = 0; i < nup; i++) /* copy upvalues to the top */ lua_pushvalue(L, -nup); lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ } @@ -51,11 +53,15 @@ static void setfuncs(lua_State* L, const luaL_Reg* l, int nup) { lua_pop(L, nup); /* remove upvalues */ } -#define newlib(L, l) (lua_newtable((L)), setfuncs((L), (l), 0)) +template +constexpr int array_count(T (&)[N]) { + return static_cast(N); +} -namespace { - -using namespace kiwi; +void newlib(lua_State* L, const luaL_Reg* l) { + lua_newtable(L); + setfuncs(L, l, 0); +} enum KiwiErrKind { KiwiErrNone, @@ -80,20 +86,32 @@ struct KiwiExpression { double constant; int term_count; Constraint* owner; - // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html - // Although using one-element arrays this way is discouraged, GCC handles accesses to - // trailing one-element array members analogously to zero-length arrays. - // The only reason avoiding FAM here is to support older MSVC. - // Otherwise this is a non-issue. + +#if !defined(_MSC_VER) || _MSC_VER >= 1900 + KiwiTerm terms[]; + + static constexpr std::size_t sz(int count) { + return sizeof(KiwiExpression) + sizeof(KiwiTerm) * (count > 0 ? count : 0); + } +#else KiwiTerm terms[1]; + + static constexpr std::size_t sz(int count) { + return sizeof(KiwiExpression) + sizeof(KiwiTerm) * (count > 1 ? count - 1 : 0); + } +#endif + + KiwiExpression() = delete; + KiwiExpression(const KiwiExpression&) = delete; + KiwiExpression& operator=(const KiwiExpression&) = delete; + ~KiwiExpression() = delete; }; -// This structure was initially designed for LuaJIT FFI. It works OK for C++ -// though it certainly isn't idiomatic. +// This mechanism was initially designed for LuaJIT FFI. struct KiwiErr { enum KiwiErrKind kind; const char* message; - bool must_free; + bool must_delete; }; struct KiwiSolver { @@ -101,28 +119,27 @@ struct KiwiSolver { Solver solver; }; -const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) { +inline const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) { if (!std::strcmp(ex.what(), base->message)) return base; const auto msg_n = std::strlen(ex.what()) + 1; - auto* mem = static_cast(std::malloc(sizeof(KiwiErr) + msg_n)); + auto* mem = static_cast(::operator new(sizeof(KiwiErr) + msg_n, std::nothrow)); if (!mem) { return base; } - - const auto* err = new (mem) KiwiErr {base->kind, mem + sizeof(KiwiErr), true}; - std::memcpy(const_cast(err->message), ex.what(), msg_n); - return err; + auto* msg = mem + sizeof(KiwiErr); + std::memcpy(msg, ex.what(), msg_n); + return new (mem) KiwiErr {base->kind, msg, true}; } -const constexpr KiwiErr kKiwiErrUnhandledCxxException { - KiwiErrUnknown, - "An unhandled C++ exception occurred."}; - template inline const KiwiErr* wrap_err(F&& f) { + static const constexpr KiwiErr kKiwiErrUnhandledCxxException { + KiwiErrUnknown, + "An unhandled C++ exception occurred."}; + try { f(); } catch (const UnsatisfiableConstraint&) { @@ -198,12 +215,12 @@ inline Constraint* kiwi_constraint_retain(Constraint* c) { return c; } -inline void kiwi_constraint_new( +inline Constraint* kiwi_constraint_new( const KiwiExpression* lhs, const KiwiExpression* rhs, RelationalOperator op, double strength, - Constraint* mem + void* mem ) { if (strength < 0.0) { strength = kiwi::strength::required; @@ -222,7 +239,7 @@ inline void kiwi_constraint_new( terms.emplace_back(*t->var, -t->coefficient); } } - new (mem) Constraint( + return new (mem) Constraint( Expression(std::move(terms), (lhs ? lhs->constant : 0.0) - (rhs ? rhs->constant : 0.0)), static_cast(op), strength diff --git a/luakiwi/luakiwi.cpp b/luakiwi/luakiwi.cpp index 082fece..9fdde07 100644 --- a/luakiwi/luakiwi.cpp +++ b/luakiwi/luakiwi.cpp @@ -5,16 +5,18 @@ #include "luacompat.h" #include "luakiwi-int.h" +namespace { + // Note some of the internal functions do not bother cleaning up the stack, they // are marked with accordingly. enum TypeId { NOTYPE, VAR = 1, TERM, EXPR, CONSTRAINT, SOLVER, ERROR, NUMBER }; -static const int ERR_KIND_TAB = NUMBER + 1; -static const int VAR_SUB_FN = ERR_KIND_TAB + 1; -static const int CONTEXT_TAB_MAX = VAR_SUB_FN + 1; +const int ERR_KIND_TAB = NUMBER + 1; +const int VAR_SUB_FN = ERR_KIND_TAB + 1; +const int CONTEXT_TAB_MAX = VAR_SUB_FN + 1; -static const char* const lkiwi_error_kinds[] = { +constexpr const char* const lkiwi_error_kinds[] = { "KiwiErrNone", "KiwiErrUnsatisfiableConstraint", "KiwiErrUnknownConstraint", @@ -28,12 +30,12 @@ static const char* const lkiwi_error_kinds[] = { "KiwiErrUnknown", }; -static const double STRENGTH_REQUIRED = 1001001000.0; -static const double STRENGTH_STRONG = 1000000.0; -static const double STRENGTH_MEDIUM = 1000.0; -static const double STRENGTH_WEAK = 1.0; +const double STRENGTH_REQUIRED = 1001001000.0; +const double STRENGTH_STRONG = 1000000.0; +const double STRENGTH_MEDIUM = 1000.0; +const double STRENGTH_WEAK = 1.0; -static kiwi::RelationalOperator get_op_opt(lua_State* L, int idx) { +kiwi::RelationalOperator get_op_opt(lua_State* L, int idx) { size_t opn; const char* op = luaL_optlstring(L, idx, "EQ", &opn); @@ -50,12 +52,12 @@ static kiwi::RelationalOperator get_op_opt(lua_State* L, int idx) { return kiwi::OP_EQ; } -static inline void push_type(lua_State* L, int type_id) { +inline void push_type(lua_State* L, int type_id) { lua_rawgeti(L, lua_upvalueindex(1), type_id); } // stack disposition: dirty -static inline int is_udata_obj(lua_State* L, int type_id) { +inline int is_udata_obj(lua_State* L, int type_id) { int result = 0; if (lua_isuserdata(L, 1) && lua_getmetatable(L, 1)) { push_type(L, type_id); @@ -67,7 +69,7 @@ static inline int is_udata_obj(lua_State* L, int type_id) { // get typename, copy the stack string to tidx, helpful when using // with buffers. -static const char* lk_typename(lua_State* L, int idx, int tidx) { +const char* lk_typename(lua_State* L, int idx, int tidx) { const char* ret = 0; if (lua_getmetatable(L, idx)) { lua_getfield(L, -1, "__name"); @@ -80,7 +82,7 @@ static const char* lk_typename(lua_State* L, int idx, int tidx) { } // never returns -static int op_error(lua_State* L, const char* op, int lidx, int ridx) { +int op_error(lua_State* L, const char* op, int lidx, int ridx) { luaL_Buffer buf; size_t len; const char* str; @@ -110,7 +112,7 @@ static int op_error(lua_State* L, const char* op, int lidx, int ridx) { return 0; } -static void check_arg_error(lua_State* L, int idx, int have_mt) { +void check_arg_error(lua_State* L, int idx, int have_mt) { lua_pushstring(L, "__name"); lua_rawget(L, -2); // TODO: simplify this. This is a bit of a hack to deal with missing args. @@ -123,19 +125,19 @@ static void check_arg_error(lua_State* L, int idx, int have_mt) { luaL_typeerror(L, idx < 0 ? top + idx - have_mt - 2 + 1 : idx, lua_tostring(L, -1)); } -static inline void* check_arg(lua_State* L, int idx, int type_id) { +inline void* check_arg(lua_State* L, int idx, int type_id) { void* udp = lua_touserdata(L, idx); int have_mt = lua_getmetatable(L, idx); push_type(L, type_id); - if (l_unlikely(!udp || !have_mt || !lua_rawequal(L, -1, -2))) + if (lk_unlikely(!udp || !have_mt || !lua_rawequal(L, -1, -2))) check_arg_error(L, idx, have_mt); lua_pop(L, 2); return udp; } -static inline void* try_type(lua_State* L, int idx, TypeId type_id) { +inline void* try_type(lua_State* L, int idx, TypeId type_id) { void* p = lua_touserdata(L, idx); if (!p || !lua_getmetatable(L, idx)) return 0; @@ -143,21 +145,21 @@ static inline void* try_type(lua_State* L, int idx, TypeId type_id) { return lua_rawequal(L, -1, -2) ? p : 0; } -static inline Variable* try_var(lua_State* L, int idx) { +inline Variable* try_var(lua_State* L, int idx) { return static_cast(try_type(L, idx, VAR)); } -static inline KiwiTerm* try_term(lua_State* L, int idx) { +inline KiwiTerm* try_term(lua_State* L, int idx) { return static_cast(try_type(L, idx, TERM)); } -static inline KiwiExpression* try_expr(lua_State* L, int idx) { +inline KiwiExpression* try_expr(lua_State* L, int idx) { return static_cast(try_type(L, idx, EXPR)); } // method to test types for expression functions // stack disposition: dirty -static inline void* try_arg(lua_State* L, int idx, TypeId* type_id, double* num) { +inline void* try_arg(lua_State* L, int idx, TypeId* type_id, double* num) { void* p = lua_touserdata(L, idx); if (!p || !lua_getmetatable(L, idx)) { int isnum; @@ -188,38 +190,37 @@ static inline void* try_arg(lua_State* L, int idx, TypeId* type_id, double* num) return 0; } -static inline Variable* get_var(lua_State* L, int idx) { +inline Variable* get_var(lua_State* L, int idx) { return static_cast(check_arg(L, idx, VAR)); } -static inline KiwiTerm* get_term(lua_State* L, int idx) { +inline KiwiTerm* get_term(lua_State* L, int idx) { return static_cast(check_arg(L, idx, TERM)); } -static inline KiwiExpression* get_expr(lua_State* L, int idx) { +inline KiwiExpression* get_expr(lua_State* L, int idx) { return static_cast(check_arg(L, idx, EXPR)); } -static inline KiwiExpression* get_expr_opt(lua_State* L, int idx) { +inline KiwiExpression* get_expr_opt(lua_State* L, int idx) { if (lua_isnoneornil(L, idx)) { return 0; } return static_cast(check_arg(L, idx, EXPR)); } -static inline Constraint* get_constraint(lua_State* L, int idx) { +inline Constraint* get_constraint(lua_State* L, int idx) { return static_cast(check_arg(L, idx, CONSTRAINT)); } -static inline KiwiSolver* get_solver(lua_State* L, int idx) { +inline KiwiSolver* get_solver(lua_State* L, int idx) { return static_cast(check_arg(L, idx, SOLVER)); } // note this expects the 2nd upvalue to have the variable weak table template -static inline Variable* var_new(lua_State* L, Args&&... args) { - auto* p = static_cast(lua_newuserdata(L, sizeof(Variable))); - new (p) Variable(std::forward(args)...); +inline Variable* var_new(lua_State* L, Args&&... args) { + auto* var = new (lua_newuserdata(L, sizeof(Variable))) Variable(std::forward(args)...); push_type(L, VAR); lua_setmetatable(L, -2); @@ -230,46 +231,42 @@ static inline Variable* var_new(lua_State* L, Args&&... args) { lua_rawset(L, lua_upvalueindex(2)); #else lua_pushvalue(L, -1); - lua_rawsetp(L, lua_upvalueindex(2), p); + lua_rawsetp(L, lua_upvalueindex(2), var); #endif - return p; + return var; } -static inline KiwiTerm* term_new(lua_State* L) { - auto* ret = static_cast(lua_newuserdata(L, sizeof(KiwiTerm))); +inline KiwiTerm* term_new(lua_State* L) { + auto* term = static_cast(lua_newuserdata(L, sizeof(KiwiTerm))); push_type(L, TERM); lua_setmetatable(L, -2); - return ret; + return term; } -static inline KiwiExpression* expr_new(lua_State* L, int nterms) { - auto* ret = static_cast(lua_newuserdata( - L, - sizeof(KiwiExpression) + sizeof(KiwiTerm) * (nterms > 1 ? nterms - 1 : 0) - )); - ret->owner = nullptr; +inline KiwiExpression* expr_new(lua_State* L, int nterms) { + auto* expr = static_cast(lua_newuserdata(L, KiwiExpression::sz(nterms))); + expr->owner = nullptr; push_type(L, EXPR); lua_setmetatable(L, -2); - return ret; + return expr; } -static inline Constraint* constraint_new( +inline Constraint* constraint_new( lua_State* L, const KiwiExpression* lhs, const KiwiExpression* rhs, kiwi::RelationalOperator op, double strength ) { - auto* ref = static_cast(lua_newuserdata(L, sizeof(Constraint))); - kiwi_constraint_new(lhs, rhs, op, strength, ref); + auto* c = kiwi_constraint_new(lhs, rhs, op, strength, lua_newuserdata(L, sizeof(Constraint))); push_type(L, CONSTRAINT); lua_setmetatable(L, -2); - return ref; + return c; } // stack disposition: dirty -static KiwiExpression* toexpr(lua_State* L, int idx, KiwiExpression* temp) { +KiwiExpression* toexpr(lua_State* L, int idx, KiwiExpression* temp) { void* ud = lua_touserdata(L, idx); if (!ud) { @@ -302,11 +299,12 @@ static KiwiExpression* toexpr(lua_State* L, int idx, KiwiExpression* temp) { return 0; } -static int relop(lua_State* L, kiwi::RelationalOperator op, const char opdisp[2]) { - KiwiExpression tmpl, tmpr; +int relop(lua_State* L, kiwi::RelationalOperator op, const char opdisp[2]) { + alignas(KiwiExpression) unsigned char tmpl[KiwiExpression::sz(1)]; + alignas(KiwiExpression) unsigned char tmpr[KiwiExpression::sz(1)]; double strength = luaL_optnumber(L, 3, STRENGTH_REQUIRED); - const KiwiExpression* lhs = toexpr(L, 1, &tmpl); - const KiwiExpression* rhs = toexpr(L, 2, &tmpr); + const auto* lhs = toexpr(L, 1, reinterpret_cast(tmpl)); + const auto* rhs = toexpr(L, 2, reinterpret_cast(tmpr)); if (!lhs || !rhs) { op_error(L, opdisp, 1, 2); @@ -316,20 +314,20 @@ static int relop(lua_State* L, kiwi::RelationalOperator op, const char opdisp[2] return 1; } -static int lkiwi_eq(lua_State* L) { +int lkiwi_eq(lua_State* L) { return relop(L, kiwi::OP_EQ, "=="); } -static int lkiwi_le(lua_State* L) { +int lkiwi_le(lua_State* L) { return relop(L, kiwi::OP_LE, "<="); } -static int lkiwi_ge(lua_State* L) { +int lkiwi_ge(lua_State* L) { return relop(L, kiwi::OP_GE, ">="); } -static inline int push_expr_one(lua_State* L, double constant, const KiwiTerm* term) { - KiwiExpression* expr = expr_new(L, 1); +inline int push_expr_one(lua_State* L, double constant, const KiwiTerm* term) { + auto* expr = expr_new(L, 1); expr->constant = constant; expr->term_count = 1; expr->terms[0].coefficient = term->coefficient; @@ -337,9 +335,8 @@ static inline int push_expr_one(lua_State* L, double constant, const KiwiTerm* t return 1; } -static inline int -push_expr_pair(lua_State* L, double constant, const KiwiTerm* ta, const KiwiTerm* tb) { - KiwiExpression* e = expr_new(L, 2); +inline int push_expr_pair(lua_State* L, double constant, const KiwiTerm* ta, const KiwiTerm* tb) { + auto* e = expr_new(L, 2); e->constant = constant; e->term_count = 2; e->terms[0].coefficient = ta->coefficient; @@ -349,9 +346,8 @@ push_expr_pair(lua_State* L, double constant, const KiwiTerm* ta, const KiwiTerm return 1; } -static inline int -push_expr_var_term(lua_State* L, double constant, Variable* var, const KiwiTerm* t) { - KiwiExpression* e = expr_new(L, 2); +inline int push_expr_var_term(lua_State* L, double constant, Variable* var, const KiwiTerm* t) { + auto* e = expr_new(L, 2); e->constant = constant; e->term_count = 2; e->terms[0].coefficient = 1.0; @@ -361,8 +357,8 @@ push_expr_var_term(lua_State* L, double constant, Variable* var, const KiwiTerm* return 1; } -static int push_add_expr_term(lua_State* L, const KiwiExpression* expr, const KiwiTerm* t) { - KiwiExpression* e = expr_new(L, expr->term_count + 1); +int push_add_expr_term(lua_State* L, const KiwiExpression* expr, const KiwiTerm* t) { + auto* e = expr_new(L, expr->term_count + 1); e->constant = expr->constant; e->term_count = expr->term_count + 1; int i = 0; @@ -375,7 +371,7 @@ static int push_add_expr_term(lua_State* L, const KiwiExpression* expr, const Ki return 1; } -static int lkiwi_var_m_add(lua_State* L) { +int lkiwi_var_m_add(lua_State* L) { TypeId type_id_b; double num; void* arg_b = try_arg(L, 2, &type_id_b, &num); @@ -389,7 +385,7 @@ static int lkiwi_var_m_add(lua_State* L) { } } - Variable* var_a = try_var(L, 1); + auto* var_a = try_var(L, 1); if (var_a) { switch (type_id_b) { case VAR: { @@ -413,7 +409,7 @@ static int lkiwi_var_m_add(lua_State* L) { return op_error(L, "+", 1, 2); } -static int lkiwi_var_m_sub(lua_State* L) { +int lkiwi_var_m_sub(lua_State* L) { lua_settop(L, 2); #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 lua_rawgeti(L, lua_upvalueindex(1), VAR_SUB_FN); @@ -426,7 +422,7 @@ static int lkiwi_var_m_sub(lua_State* L) { return 1; } -static int lkiwi_var_m_mul(lua_State* L) { +int lkiwi_var_m_mul(lua_State* L) { int isnum, varidx = 2; double num = lua_tonumberx(L, 1, &isnum); @@ -447,67 +443,67 @@ static int lkiwi_var_m_mul(lua_State* L) { return op_error(L, "*", 1, 2); } -static int lkiwi_var_m_div(lua_State* L) { +int lkiwi_var_m_div(lua_State* L) { auto* var = try_var(L, 1); int isnum; double num = lua_tonumberx(L, 2, &isnum); if (!var || !isnum) { return op_error(L, "/", 1, 2); } - KiwiTerm* term = term_new(L); + auto* term = term_new(L); term->var = kiwi_var_retain(var); term->coefficient = 1.0 / num; return 1; } -static int lkiwi_var_m_unm(lua_State* L) { +int lkiwi_var_m_unm(lua_State* L) { auto* term = term_new(L); term->var = kiwi_var_retain(get_var(L, 1)); term->coefficient = -1.0; return 1; } -static int lkiwi_var_m_eq(lua_State* L) { +int lkiwi_var_m_eq(lua_State* L) { lua_pushboolean(L, get_var(L, 1)->equals(*get_var(L, 2))); return 1; } -static int lkiwi_var_m_tostring(lua_State* L) { +int lkiwi_var_m_tostring(lua_State* L) { auto* var = get_var(L, 1); lua_pushfstring(L, "%s(%f)", var->name().c_str(), var->value()); return 1; } -static int lkiwi_var_m_gc(lua_State* L) { +int lkiwi_var_m_gc(lua_State* L) { get_var(L, 1)->~Variable(); return 0; } -static int lkiwi_var_set_name(lua_State* L) { +int lkiwi_var_set_name(lua_State* L) { auto* var = get_var(L, 1); const char* name = luaL_checkstring(L, 2); var->setName(name); return 0; } -static int lkiwi_var_name(lua_State* L) { +int lkiwi_var_name(lua_State* L) { lua_pushstring(L, get_var(L, 1)->name().c_str()); return 1; } -static int lkiwi_var_set(lua_State* L) { +int lkiwi_var_set(lua_State* L) { auto* var = get_var(L, 1); const double value = luaL_checknumber(L, 2); var->setValue(value); return 0; } -static int lkiwi_var_value(lua_State* L) { +int lkiwi_var_value(lua_State* L) { lua_pushnumber(L, get_var(L, 1)->value()); return 1; } -static int lkiwi_var_toterm(lua_State* L) { +int lkiwi_var_toterm(lua_State* L) { auto* var = get_var(L, 1); double coefficient = luaL_optnumber(L, 2, 1.0); auto* term = term_new(L); @@ -518,12 +514,12 @@ static int lkiwi_var_toterm(lua_State* L) { return 1; } -static int lkiwi_var_toexpr(lua_State* L) { +int lkiwi_var_toexpr(lua_State* L) { const KiwiTerm t {get_var(L, 1), 1.0}; return push_expr_one(L, 0.0, &t); } -static const struct luaL_Reg kiwi_var_m[] = { +constexpr const struct luaL_Reg kiwi_var_m[] = { {"__add", lkiwi_var_m_add}, {"__sub", lkiwi_var_m_sub}, {"__mul", lkiwi_var_m_mul}, @@ -543,13 +539,13 @@ static const struct luaL_Reg kiwi_var_m[] = { {"ge", lkiwi_ge}, {0, 0}}; -static int lkiwi_var_new(lua_State* L) { +int lkiwi_var_new(lua_State* L) { const char* name = luaL_optstring(L, 1, ""); var_new(L, name); return 1; } -static int lkiwi_term_m_mul(lua_State* L) { +int lkiwi_term_m_mul(lua_State* L) { int isnum, termidx = 2; double num = lua_tonumberx(L, 1, &isnum); @@ -570,28 +566,28 @@ static int lkiwi_term_m_mul(lua_State* L) { return op_error(L, "*", 1, 2); } -static int lkiwi_term_m_div(lua_State* L) { +int lkiwi_term_m_div(lua_State* L) { const KiwiTerm* term = try_term(L, 1); int isnum; double num = lua_tonumberx(L, 2, &isnum); if (!term || !isnum) { return op_error(L, "/", 1, 2); } - KiwiTerm* ret = term_new(L); + auto* ret = term_new(L); ret->var = kiwi_var_retain(term->var); ret->coefficient = term->coefficient / num; return 1; } -static int lkiwi_term_m_unm(lua_State* L) { - const KiwiTerm* term = get_term(L, 1); - KiwiTerm* ret = term_new(L); +int lkiwi_term_m_unm(lua_State* L) { + const auto* term = get_term(L, 1); + auto* ret = term_new(L); ret->var = kiwi_var_retain(term->var); ret->coefficient = -term->coefficient; return 1; } -static int lkiwi_term_m_add(lua_State* L) { +int lkiwi_term_m_add(lua_State* L) { TypeId type_id_b; double num; void* arg_b = try_arg(L, 2, &type_id_b, &num); @@ -604,7 +600,7 @@ static int lkiwi_term_m_add(lua_State* L) { } } - const KiwiTerm* term_a = try_term(L, 1); + const auto* term_a = try_term(L, 1); if (term_a) { switch (type_id_b) { case TERM: @@ -624,35 +620,35 @@ static int lkiwi_term_m_add(lua_State* L) { return op_error(L, "+", 1, 2); } -static int lkiwi_term_m_sub(lua_State* L) { +int lkiwi_term_m_sub(lua_State* L) { lua_settop(L, 2); compat_arith_unm(L); lkiwi_term_m_add(L); return 1; } -static int lkiwi_term_toexpr(lua_State* L) { +int lkiwi_term_toexpr(lua_State* L) { return push_expr_one(L, 0.0, get_term(L, 1)); } -static int lkiwi_term_value(lua_State* L) { +int lkiwi_term_value(lua_State* L) { const auto* term = get_term(L, 1); lua_pushnumber(L, term->var->value() * term->coefficient); return 1; } -static int lkiwi_term_m_tostring(lua_State* L) { +int lkiwi_term_m_tostring(lua_State* L) { const auto* term = get_term(L, 1); lua_pushfstring(L, "%f %s", term->coefficient, term->var->name().c_str()); return 1; } -static int lkiwi_term_m_gc(lua_State* L) { +int lkiwi_term_m_gc(lua_State* L) { get_term(L, 1)->var->~Variable(); return 0; } -static int lkiwi_term_m_index(lua_State* L) { +int lkiwi_term_m_index(lua_State* L) { const auto* term = get_term(L, 1); size_t len; const char* k = lua_tolstring(L, 2, &len); @@ -679,7 +675,7 @@ static int lkiwi_term_m_index(lua_State* L) { return 1; } -static const struct luaL_Reg kiwi_term_m[] = { +constexpr const struct luaL_Reg kiwi_term_m[] = { {"__add", lkiwi_term_m_add}, {"__sub", lkiwi_term_m_sub}, {"__mul", lkiwi_term_m_mul}, @@ -695,7 +691,7 @@ static const struct luaL_Reg kiwi_term_m[] = { {"ge", lkiwi_ge}, {0, 0}}; -static int lkiwi_term_new(lua_State* L) { +int lkiwi_term_new(lua_State* L) { auto* var = get_var(L, 1); double coefficient = luaL_optnumber(L, 2, 1.0); auto* term = term_new(L); @@ -704,7 +700,7 @@ static int lkiwi_term_new(lua_State* L) { return 1; } -static int push_expr_constant(lua_State* L, const KiwiExpression* expr, double constant) { +int push_expr_constant(lua_State* L, const KiwiExpression* expr, double constant) { auto* ne = expr_new(L, expr->term_count); for (int i = 0; i < expr->term_count; i++) { ne->terms[i].var = kiwi_var_retain(expr->terms[i].var); @@ -715,7 +711,7 @@ static int push_expr_constant(lua_State* L, const KiwiExpression* expr, double c return 1; } -static int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double coeff) { +int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double coeff) { auto* ne = expr_new(L, expr->term_count); ne->constant = expr->constant * coeff; ne->term_count = expr->term_count; @@ -726,7 +722,7 @@ static int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double return 1; } -static int push_add_expr_expr(lua_State* L, const KiwiExpression* a, const KiwiExpression* b) { +int push_add_expr_expr(lua_State* L, const KiwiExpression* a, const KiwiExpression* b) { int na = a->term_count, nb = b->term_count; auto* ne = expr_new(L, na + nb); @@ -744,7 +740,7 @@ static int push_add_expr_expr(lua_State* L, const KiwiExpression* a, const KiwiE return 1; } -static int lkiwi_expr_m_mul(lua_State* L) { +int lkiwi_expr_m_mul(lua_State* L) { int isnum, expridx = 2; double num = lua_tonumberx(L, 1, &isnum); @@ -761,7 +757,7 @@ static int lkiwi_expr_m_mul(lua_State* L) { return op_error(L, "*", 1, 2); } -static int lkiwi_expr_m_div(lua_State* L) { +int lkiwi_expr_m_div(lua_State* L) { const auto* expr = try_expr(L, 1); int isnum; double num = lua_tonumberx(L, 2, &isnum); @@ -771,12 +767,12 @@ static int lkiwi_expr_m_div(lua_State* L) { return push_mul_expr_coeff(L, expr, 1.0 / num); } -static int lkiwi_expr_m_unm(lua_State* L) { +int lkiwi_expr_m_unm(lua_State* L) { const auto* expr = get_expr(L, 1); return push_mul_expr_coeff(L, expr, -1.0); } -static int lkiwi_expr_m_add(lua_State* L) { +int lkiwi_expr_m_add(lua_State* L) { TypeId type_id_b; double num; void* arg_b = try_arg(L, 2, &type_id_b, &num); @@ -790,7 +786,7 @@ static int lkiwi_expr_m_add(lua_State* L) { } } - const KiwiExpression* expr_a = try_expr(L, 1); + const auto* expr_a = try_expr(L, 1); if (expr_a) { switch (type_id_b) { case EXPR: @@ -810,14 +806,14 @@ static int lkiwi_expr_m_add(lua_State* L) { return op_error(L, "+", 1, 2); } -static int lkiwi_expr_m_sub(lua_State* L) { +int lkiwi_expr_m_sub(lua_State* L) { lua_settop(L, 2); compat_arith_unm(L); lkiwi_expr_m_add(L); return 1; } -static int lkiwi_expr_value(lua_State* L) { +int lkiwi_expr_value(lua_State* L) { const auto* expr = get_expr(L, 1); double sum = expr->constant; for (int i = 0; i < expr->term_count; i++) { @@ -828,7 +824,7 @@ static int lkiwi_expr_value(lua_State* L) { return 1; } -static int lkiwi_expr_terms(lua_State* L) { +int lkiwi_expr_terms(lua_State* L) { const auto* expr = get_expr(L, 1); lua_createtable(L, expr->term_count, 0); for (int i = 0; i < expr->term_count; i++) { @@ -841,12 +837,12 @@ static int lkiwi_expr_terms(lua_State* L) { return 1; } -static int lkiwi_expr_copy(lua_State* L) { - KiwiExpression* expr = get_expr(L, 1); +int lkiwi_expr_copy(lua_State* L) { + auto* expr = get_expr(L, 1); return push_expr_constant(L, expr, expr->constant); } -static int lkiwi_expr_m_tostring(lua_State* L) { +int lkiwi_expr_m_tostring(lua_State* L) { const auto* expr = get_expr(L, 1); luaL_Buffer buf; luaL_buffinit(L, &buf); @@ -865,7 +861,7 @@ static int lkiwi_expr_m_tostring(lua_State* L) { return 1; } -static int lkiwi_expr_m_gc(lua_State* L) { +int lkiwi_expr_m_gc(lua_State* L) { const auto* expr = get_expr(L, 1); if (expr->owner) { expr->owner->~Constraint(); @@ -877,8 +873,8 @@ static int lkiwi_expr_m_gc(lua_State* L) { return 0; } -static int lkiwi_expr_m_index(lua_State* L) { - KiwiExpression* expr = get_expr(L, 1); +int lkiwi_expr_m_index(lua_State* L) { + const auto* expr = get_expr(L, 1); size_t len; const char* k = lua_tolstring(L, 2, &len); if (len == 8 && memcmp("constant", k, len) == 0) { @@ -894,7 +890,7 @@ static int lkiwi_expr_m_index(lua_State* L) { return 1; } -static const struct luaL_Reg kiwi_expr_m[] = { +constexpr const struct luaL_Reg kiwi_expr_m[] = { {"__add", lkiwi_expr_m_add}, {"__sub", lkiwi_expr_m_sub}, {"__mul", lkiwi_expr_m_mul}, @@ -911,28 +907,28 @@ static const struct luaL_Reg kiwi_expr_m[] = { {"ge", lkiwi_ge}, {0, 0}}; -static int lkiwi_expr_new(lua_State* L) { +int lkiwi_expr_new(lua_State* L) { int nterms = lua_gettop(L) - 1; lua_Number constant = luaL_checknumber(L, 1); - KiwiExpression* expr = expr_new(L, nterms); + auto* expr = expr_new(L, nterms); expr->constant = constant; expr->term_count = nterms; for (int i = 0; i < nterms; i++) { - const KiwiTerm* term = get_term(L, i + 2); + const auto* term = get_term(L, i + 2); expr->terms[i].var = kiwi_var_retain(term->var); expr->terms[i].coefficient = term->coefficient; } return 1; } -static int lkiwi_constraint_strength(lua_State* L) { +int lkiwi_constraint_strength(lua_State* L) { lua_pushnumber(L, get_constraint(L, 1)->strength()); return 1; } -static int lkiwi_constraint_op(lua_State* L) { +int lkiwi_constraint_op(lua_State* L) { auto op = get_constraint(L, 1)->op(); const char* opstr = "??"; switch (op) { @@ -950,12 +946,12 @@ static int lkiwi_constraint_op(lua_State* L) { return 1; } -static int lkiwi_constraint_violated(lua_State* L) { +int lkiwi_constraint_violated(lua_State* L) { lua_pushboolean(L, get_constraint(L, 1)->violated()); return 1; } -static int lkiwi_constraint_expression(lua_State* L) { +int lkiwi_constraint_expression(lua_State* L) { auto* c = get_constraint(L, 1); const auto& expr = c->expression(); const auto& terms = expr.terms(); @@ -973,7 +969,7 @@ static int lkiwi_constraint_expression(lua_State* L) { return 1; } -static int lkiwi_constraint_m_tostring(lua_State* L) { +int lkiwi_constraint_m_tostring(lua_State* L) { const auto& c = *get_constraint(L, 1); luaL_Buffer buf; @@ -1027,15 +1023,15 @@ static int lkiwi_constraint_m_tostring(lua_State* L) { return 1; } -static int lkiwi_constraint_m_gc(lua_State* L) { +int lkiwi_constraint_m_gc(lua_State* L) { get_constraint(L, 1)->~Constraint(); return 0; } -static int lkiwi_solver_add_constraint(lua_State* L); -static int lkiwi_solver_remove_constraint(lua_State* L); +int lkiwi_solver_add_constraint(lua_State* L); +int lkiwi_solver_remove_constraint(lua_State* L); -static int lkiwi_constraint_add_to(lua_State* L) { +int lkiwi_constraint_add_to(lua_State* L) { lua_settop(L, 2); lua_rotate(L, 1, 1); lkiwi_solver_add_constraint(L); @@ -1043,7 +1039,7 @@ static int lkiwi_constraint_add_to(lua_State* L) { return 1; } -static int lkiwi_constraint_remove_from(lua_State* L) { +int lkiwi_constraint_remove_from(lua_State* L) { lua_settop(L, 2); lua_rotate(L, 1, 1); lkiwi_solver_remove_constraint(L); @@ -1051,7 +1047,7 @@ static int lkiwi_constraint_remove_from(lua_State* L) { return 1; } -static const struct luaL_Reg kiwi_constraint_m[] = { +constexpr const struct luaL_Reg kiwi_constraint_m[] = { {"__tostring", lkiwi_constraint_m_tostring}, {"__gc", lkiwi_constraint_m_gc}, {"strength", lkiwi_constraint_strength}, @@ -1062,7 +1058,7 @@ static const struct luaL_Reg kiwi_constraint_m[] = { {"remove_from", lkiwi_constraint_remove_from}, {0, 0}}; -static int lkiwi_constraint_new(lua_State* L) { +int lkiwi_constraint_new(lua_State* L) { const auto* lhs = get_expr_opt(L, 1); const auto* rhs = get_expr_opt(L, 2); const auto op = get_op_opt(L, 3); @@ -1072,7 +1068,7 @@ static int lkiwi_constraint_new(lua_State* L) { return 1; } -static int push_pair_constraint( +int push_pair_constraint( lua_State* L, Variable* left, double coeff, @@ -1081,7 +1077,7 @@ static int push_pair_constraint( kiwi::RelationalOperator op, double strength ) { - alignas(KiwiExpression) unsigned char expr_buf[sizeof(KiwiExpression) + sizeof(KiwiTerm)]; + alignas(KiwiExpression) unsigned char expr_buf[KiwiExpression::sz(2)]; auto* expr = reinterpret_cast(&expr_buf); expr->constant = constant; expr->term_count = 2; @@ -1093,7 +1089,7 @@ static int push_pair_constraint( return 1; } -static int lkiwi_constraints_pair_ratio(lua_State* L) { +int lkiwi_constraints_pair_ratio(lua_State* L) { return push_pair_constraint( L, get_var(L, 1), @@ -1105,7 +1101,7 @@ static int lkiwi_constraints_pair_ratio(lua_State* L) { ); } -static int lkiwi_constraints_pair(lua_State* L) { +int lkiwi_constraints_pair(lua_State* L) { return push_pair_constraint( L, get_var(L, 1), @@ -1117,24 +1113,25 @@ static int lkiwi_constraints_pair(lua_State* L) { ); } -static int lkiwi_constraints_single(lua_State* L) { - KiwiExpression expr; - expr.term_count = 1; - expr.terms[0].var = get_var(L, 1); - expr.terms[0].coefficient = 1.0; - expr.constant = luaL_optnumber(L, 2, 0.0); +int lkiwi_constraints_single(lua_State* L) { + alignas(KiwiExpression) unsigned char expr_buf[KiwiExpression::sz(1)]; + auto* expr = reinterpret_cast(&expr_buf); + expr->term_count = 1; + expr->terms[0].var = get_var(L, 1); + expr->terms[0].coefficient = 1.0; + expr->constant = luaL_optnumber(L, 2, 0.0); - constraint_new(L, &expr, 0, get_op_opt(L, 3), luaL_optnumber(L, 4, STRENGTH_REQUIRED)); + constraint_new(L, expr, 0, get_op_opt(L, 3), luaL_optnumber(L, 4, STRENGTH_REQUIRED)); return 1; } -static const struct luaL_Reg lkiwi_constraints[] = { +constexpr const struct luaL_Reg lkiwi_constraints[] = { {"pair_ratio", lkiwi_constraints_pair_ratio}, {"pair", lkiwi_constraints_pair}, {"single", lkiwi_constraints_single}, {0, 0}}; -static void lkiwi_mod_constraints_new(lua_State* L, int ctx_i) { +void lkiwi_mod_constraints_new(lua_State* L, int ctx_i) { luaL_newlibtable(L, lkiwi_constraints); lua_pushvalue(L, ctx_i); setfuncs(L, lkiwi_constraints, 1); @@ -1142,7 +1139,7 @@ static void lkiwi_mod_constraints_new(lua_State* L, int ctx_i) { /* kiwi.Error */ -static void error_new(lua_State* L, const KiwiErr* err, int solver_absi, int item_absi) { +void error_new(lua_State* L, const KiwiErr* err, int solver_absi, int item_absi) { lua_createtable(L, 0, 4); push_type(L, ERROR); lua_setmetatable(L, -2); @@ -1162,12 +1159,12 @@ static void error_new(lua_State* L, const KiwiErr* err, int solver_absi, int ite lua_setfield(L, -2, "item"); } - if (err->must_free) { - free((void*)err); + if (err->must_delete) { + delete const_cast(err); } } -static int lkiwi_error_m_tostring(lua_State* L) { +int lkiwi_error_m_tostring(lua_State* L) { luaL_Buffer buf; luaL_buffinit(L, &buf); @@ -1183,15 +1180,20 @@ static int lkiwi_error_m_tostring(lua_State* L) { luaL_tolstring(L, -1, 0); lua_remove(L, -2); // remove item luaL_addvalue(&buf); - luaL_addchar(&buf, ')'); + luaL_addstring(&buf, ")\n"); + luaL_traceback(L, L, nullptr, 2); + luaL_addvalue(&buf); luaL_pushresult(&buf); + return 1; } -static const struct luaL_Reg lkiwi_error_m[] = {{"__tostring", lkiwi_error_m_tostring}, {0, 0}}; +constexpr const struct luaL_Reg lkiwi_error_m[] = { + {"__tostring", lkiwi_error_m_tostring}, + {0, 0}}; -static int lkiwi_error_mask(lua_State* L) { +int lkiwi_error_mask(lua_State* L) { int invert = lua_toboolean(L, 2); if (lua_type(L, 1) == LUA_TSTRING) { @@ -1201,12 +1203,9 @@ static int lkiwi_error_mask(lua_State* L) { lua_rawgeti(L, lua_upvalueindex(1), ERR_KIND_TAB); unsigned mask = 0; - for (int n = 1;; ++n) { - if (lua_geti(L, 1, n) == LUA_TNIL) { - break; - } + for (int n = 1; lua_geti(L, 1, n) != LUA_TNIL; ++n) { int isnum; - int shift = lua_tointegerx(L, -1, &isnum); + auto shift = lua_tointegerx(L, -1, &isnum); if (!isnum) { lua_rawget(L, -2 /* err_kind table */); shift = lua_tointegerx(L, -1, &isnum); @@ -1221,7 +1220,7 @@ static int lkiwi_error_mask(lua_State* L) { return 1; } -static int lkiwi_solver_handle_err(lua_State* L, const KiwiErr* err, const KiwiSolver* solver) { +int lkiwi_solver_handle_err(lua_State* L, const KiwiErr* err, const KiwiSolver* solver) { /* This assumes solver is at index 1 */ lua_settop(L, 2); if (err) { @@ -1236,91 +1235,88 @@ static int lkiwi_solver_handle_err(lua_State* L, const KiwiErr* err, const KiwiS return 1; } -static int lkiwi_solver_add_constraint(lua_State* L) { +int lkiwi_solver_add_constraint(lua_State* L) { auto* self = get_solver(L, 1); const auto& c = *get_constraint(L, 2); - const KiwiErr* err = kiwi_solver_add_constraint(self->solver, c); + auto* err = kiwi_solver_add_constraint(self->solver, c); return lkiwi_solver_handle_err(L, err, self); } -static int lkiwi_solver_remove_constraint(lua_State* L) { +int lkiwi_solver_remove_constraint(lua_State* L) { auto* self = get_solver(L, 1); const auto& c = *get_constraint(L, 2); - const KiwiErr* err = kiwi_solver_remove_constraint(self->solver, c); + auto* err = kiwi_solver_remove_constraint(self->solver, c); return lkiwi_solver_handle_err(L, err, self); } -static int lkiwi_solver_add_edit_var(lua_State* L) { - KiwiSolver* self = get_solver(L, 1); +int lkiwi_solver_add_edit_var(lua_State* L) { + auto* self = get_solver(L, 1); const auto& var = *get_var(L, 2); double strength = luaL_checknumber(L, 3); - const KiwiErr* err = kiwi_solver_add_edit_var(self->solver, var, strength); + auto* err = kiwi_solver_add_edit_var(self->solver, var, strength); return lkiwi_solver_handle_err(L, err, self); } -static int lkiwi_solver_remove_edit_var(lua_State* L) { - KiwiSolver* self = get_solver(L, 1); +int lkiwi_solver_remove_edit_var(lua_State* L) { + auto* self = get_solver(L, 1); const auto& var = *get_var(L, 2); - const KiwiErr* err = kiwi_solver_remove_edit_var(self->solver, var); + auto* err = kiwi_solver_remove_edit_var(self->solver, var); return lkiwi_solver_handle_err(L, err, self); } -static int lkiwi_solver_suggest_value(lua_State* L) { - KiwiSolver* self = get_solver(L, 1); +int lkiwi_solver_suggest_value(lua_State* L) { + auto* self = get_solver(L, 1); const auto& var = *get_var(L, 2); double value = luaL_checknumber(L, 3); - const KiwiErr* err = kiwi_solver_suggest_value(self->solver, var, value); + auto* err = kiwi_solver_suggest_value(self->solver, var, value); return lkiwi_solver_handle_err(L, err, self); } -static int lkiwi_solver_update_vars(lua_State* L) { +int lkiwi_solver_update_vars(lua_State* L) { get_solver(L, 1)->solver.updateVariables(); return 0; } -static int lkiwi_solver_reset(lua_State* L) { +int lkiwi_solver_reset(lua_State* L) { get_solver(L, 1)->solver.reset(); return 0; } -static int lkiwi_solver_has_constraint(lua_State* L) { +int lkiwi_solver_has_constraint(lua_State* L) { auto* s = get_solver(L, 1); const auto& c = *get_constraint(L, 2); lua_pushboolean(L, s->solver.hasConstraint(c)); return 1; } -static int lkiwi_solver_has_edit_var(lua_State* L) { +int lkiwi_solver_has_edit_var(lua_State* L) { auto* s = get_solver(L, 1); const auto& var = *get_var(L, 2); lua_pushboolean(L, s->solver.hasEditVariable(var)); return 1; } -static int lkiwi_solver_dump(lua_State* L) { +int lkiwi_solver_dump(lua_State* L) { get_solver(L, 1)->solver.dump(); return 0; } -static int lkiwi_solver_dumps(lua_State* L) { - const auto s = get_solver(L, 1)->solver.dumps(); +int lkiwi_solver_dumps(lua_State* L) { + const auto& s = get_solver(L, 1)->solver.dumps(); lua_pushlstring(L, s.data(), s.length()); return 1; } template -static int lkiwi_add_remove_tab(lua_State* L, F&& fn) { - KiwiSolver* solver = get_solver(L, 1); +int lkiwi_add_remove_tab(lua_State* L, F&& fn) { + auto* solver = get_solver(L, 1); int narg = lua_gettop(L); // block this particularly obnoxious case which is always a bug if (lua_type(L, 2) == LUA_TSTRING) { luaL_typeerror(L, 2, "indexable"); } - for (int i = 1;; ++i) { - if (lua_geti(L, 2, i) == LUA_TNIL) { - break; - } + for (int i = 1; lua_geti(L, 2, i) != LUA_TNIL; ++i) { const KiwiErr* err = fn(L, solver); if (err) { error_new(L, err, 1, narg + 1 /* item_absi */); @@ -1339,32 +1335,32 @@ static int lkiwi_add_remove_tab(lua_State* L, F&& fn) { return 1; } -static int lkiwi_solver_add_constraints(lua_State* L) { +int lkiwi_solver_add_constraints(lua_State* L) { return lkiwi_add_remove_tab(L, [](lua_State* L, KiwiSolver* s) { return kiwi_solver_add_constraint(s->solver, *get_constraint(L, -1)); }); } -static int lkiwi_solver_remove_constraints(lua_State* L) { +int lkiwi_solver_remove_constraints(lua_State* L) { return lkiwi_add_remove_tab(L, [](lua_State* L, KiwiSolver* s) { return kiwi_solver_add_constraint(s->solver, *get_constraint(L, -1)); }); } -static int lkiwi_solver_add_edit_vars(lua_State* L) { +int lkiwi_solver_add_edit_vars(lua_State* L) { double strength = luaL_checknumber(L, 3); return lkiwi_add_remove_tab(L, [strength](lua_State* L, KiwiSolver* s) { return kiwi_solver_add_edit_var(s->solver, *get_var(L, -1), strength); }); } -static int lkiwi_solver_remove_edit_vars(lua_State* L) { +int lkiwi_solver_remove_edit_vars(lua_State* L) { return lkiwi_add_remove_tab(L, [](lua_State* L, KiwiSolver* s) { return kiwi_solver_remove_edit_var(s->solver, *get_var(L, -1)); }); } -static int lkiwi_solver_suggest_values(lua_State* L) { +int lkiwi_solver_suggest_values(lua_State* L) { auto* self = get_solver(L, 1); int narg = lua_gettop(L); @@ -1377,10 +1373,7 @@ static int lkiwi_solver_suggest_values(lua_State* L) { luaL_typeerror(L, 3, "indexable"); } - for (int i = 1;; ++i) { - if (lua_geti(L, 2, i) == LUA_TNIL) { - break; - } + for (int i = 1; lua_geti(L, 2, i) != LUA_TNIL; ++i) { auto* var = get_var(L, -1); lua_geti(L, 3, i); @@ -1404,10 +1397,10 @@ static int lkiwi_solver_suggest_values(lua_State* L) { return 2; } -static int lkiwi_solver_set_error_mask(lua_State* L) { - KiwiSolver* solver = get_solver(L, 1); +int lkiwi_solver_set_error_mask(lua_State* L) { + auto* solver = get_solver(L, 1); - unsigned error_mask; + lua_Integer error_mask; if (lua_istable(L, 2)) { lua_settop(L, 3); lua_rotate(L, 1, -1); @@ -1417,21 +1410,21 @@ static int lkiwi_solver_set_error_mask(lua_State* L) { error_mask = luaL_checkinteger(L, 2); } - solver->error_mask = error_mask; + solver->error_mask = static_cast(error_mask); return 0; } -static int lkiwi_solver_m_tostring(lua_State* L) { +int lkiwi_solver_m_tostring(lua_State* L) { lua_pushfstring(L, "kiwi.Solver(%p)", get_solver(L, 1)); return 1; } -static int lkiwi_solver_m_gc(lua_State* L) { +int lkiwi_solver_m_gc(lua_State* L) { get_solver(L, 1)->~KiwiSolver(); return 0; } -static const struct luaL_Reg kiwi_solver_m[] = { +constexpr const struct luaL_Reg kiwi_solver_m[] = { {"add_constraint", lkiwi_solver_add_constraint}, {"add_constraints", lkiwi_solver_add_constraints}, {"remove_constraint", lkiwi_solver_remove_constraint}, @@ -1453,8 +1446,8 @@ static const struct luaL_Reg kiwi_solver_m[] = { {"__gc", lkiwi_solver_m_gc}, {0, 0}}; -static int lkiwi_solver_new_meth(lua_State* L) { - unsigned error_mask; +int lkiwi_solver_new(lua_State* L) { + lua_Integer error_mask; if (lua_istable(L, 1)) { lkiwi_error_mask(L); error_mask = lua_tointeger(L, -1); @@ -1462,19 +1455,17 @@ static int lkiwi_solver_new_meth(lua_State* L) { error_mask = luaL_optinteger(L, 1, 0); } - auto* sp = static_cast(lua_newuserdata(L, sizeof(KiwiSolver))); - new (sp) KiwiSolver {error_mask}; - + new (lua_newuserdata(L, sizeof(KiwiSolver))) KiwiSolver {static_cast(error_mask)}; push_type(L, SOLVER); lua_setmetatable(L, -2); return 1; } -static inline double clamp(double n) { +inline double clamp(double n) { return fmax(0.0, fmin(1000, n)); } -static int lkiwi_strength_create(lua_State* L) { +int lkiwi_strength_create(lua_State* L) { const double a = luaL_checknumber(L, 1); const double b = luaL_checknumber(L, 2); const double c = luaL_checknumber(L, 3); @@ -1485,9 +1476,9 @@ static int lkiwi_strength_create(lua_State* L) { return 1; } -static const struct luaL_Reg lkiwi_strength[] = {{"create", lkiwi_strength_create}, {0, 0}}; +constexpr const struct luaL_Reg lkiwi_strength[] = {{"create", lkiwi_strength_create}, {0, 0}}; -static void lkiwi_mod_strength_new(lua_State* L) { +void lkiwi_mod_strength_new(lua_State* L) { newlib(L, lkiwi_strength); lua_pushnumber(L, STRENGTH_REQUIRED); @@ -1503,27 +1494,27 @@ static void lkiwi_mod_strength_new(lua_State* L) { lua_setfield(L, -2, "WEAK"); } -static int lkiwi_is_var(lua_State* L) { +int lkiwi_is_var(lua_State* L) { return is_udata_obj(L, VAR); } -static int lkiwi_is_term(lua_State* L) { +int lkiwi_is_term(lua_State* L) { return is_udata_obj(L, TERM); } -static int lkiwi_is_expression(lua_State* L) { +int lkiwi_is_expression(lua_State* L) { return is_udata_obj(L, EXPR); } -static int lkiwi_is_constraint(lua_State* L) { +int lkiwi_is_constraint(lua_State* L) { return is_udata_obj(L, CONSTRAINT); } -static int lkiwi_is_solver(lua_State* L) { +int lkiwi_is_solver(lua_State* L) { return is_udata_obj(L, SOLVER); } -static int lkiwi_is_error(lua_State* L) { +int lkiwi_is_error(lua_State* L) { int result = 0; if (lua_getmetatable(L, 1)) { push_type(L, ERROR); @@ -1534,7 +1525,7 @@ static int lkiwi_is_error(lua_State* L) { return 1; } -static const struct luaL_Reg lkiwi[] = { +constexpr const struct luaL_Reg lkiwi[] = { {"Var", 0}, {"is_var", lkiwi_is_var}, {"Term", lkiwi_term_new}, @@ -1543,7 +1534,7 @@ static const struct luaL_Reg lkiwi[] = { {"is_expression", lkiwi_is_expression}, {"Constraint", lkiwi_constraint_new}, {"is_constraint", lkiwi_is_constraint}, - {"Solver", lkiwi_solver_new_meth}, + {"Solver", lkiwi_solver_new}, {"is_solver", lkiwi_is_solver}, {"error_mask", lkiwi_error_mask}, {"is_error", lkiwi_is_error}, @@ -1552,18 +1543,18 @@ static const struct luaL_Reg lkiwi[] = { {"ge", lkiwi_ge}, {0, 0}}; -static int no_member_mt_index(lua_State* L) { +int no_member_mt_index(lua_State* L) { luaL_error(L, "attempt to access non-existent member '%s'", lua_tostring(L, 2)); return 0; } -static void no_member_mt_new(lua_State* L) { +void no_member_mt_new(lua_State* L) { lua_createtable(L, 0, 1); lua_pushcfunction(L, no_member_mt_index); lua_setfield(L, -2, "__index"); } -static void register_type_( +void register_type_n( lua_State* L, const char* name, int context_absi, @@ -1586,11 +1577,19 @@ static void register_type_( lua_rawseti(L, context_absi, type_id); } -#define register_type(L, name, context_absi, ref, m) \ - register_type_(L, name, context_absi, ref, m, ARR_COUNT(m)) +template +constexpr inline void register_type( + lua_State* L, + const char* name, + int context_absi, + int type_id, + const luaL_Reg (&m)[N] +) { + register_type_n(L, name, context_absi, type_id, m, N); +} #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 -static void compat_init(lua_State* L, int context_absi) { +void compat_init(lua_State* L, int context_absi) { static const char var_sub_code[] = "local a,b=...\n" "return a + -b"; @@ -1601,16 +1600,12 @@ static void compat_init(lua_State* L, int context_absi) { lua_rawseti(L, context_absi, VAR_SUB_FN); } #else -static void compat_init(lua_State*, int) {} +void compat_init(lua_State*, int) {} #endif /* Lua 5.1 */ -#ifdef __cplusplus -extern "C" int luaopen_ckiwi(lua_State* L); -#else -extern luaopen_ckiwi(lua_State* L); -#endif +} // namespace -int luaopen_ckiwi(lua_State* L) { +extern "C" int luaopen_ckiwi(lua_State* L) { luaL_checkversion(L); /* context table */ @@ -1627,7 +1622,7 @@ int luaopen_ckiwi(lua_State* L) { register_type(L, "kiwi.Solver", ctx_i, SOLVER, kiwi_solver_m); register_type(L, "kiwi.Error", ctx_i, ERROR, lkiwi_error_m); - lua_createtable(L, 0, ARR_COUNT(lkiwi) + 6); + lua_createtable(L, 0, array_count(lkiwi) + 6); lua_pushvalue(L, ctx_i); setfuncs(L, lkiwi, 1); @@ -1653,8 +1648,8 @@ int luaopen_ckiwi(lua_State* L) { /* ErrKind table */ /* TODO: implement __call metamethod for these */ - lua_createtable(L, ARR_COUNT(lkiwi_error_kinds) + 1, ARR_COUNT(lkiwi_error_kinds)); - for (int i = 0; i < ARR_COUNT(lkiwi_error_kinds); i++) { + lua_createtable(L, array_count(lkiwi_error_kinds) + 1, array_count(lkiwi_error_kinds)); + for (int i = 0; i < array_count(lkiwi_error_kinds); i++) { lua_pushstring(L, lkiwi_error_kinds[i]); lua_pushvalue(L, -1); lua_rawseti(L, -3, i); diff --git a/t.lua b/t.lua index 665c382..dbfe172 100644 --- a/t.lua +++ b/t.lua @@ -8,14 +8,16 @@ do local v3 = kiwi.Var("v3") local v4 = kiwi.Var("v4") local v5 = kiwi.Var("v5") - local c = (3 * v1 + 4 * v2 + 6 * v3):eq(0) + local c1 = (3 * v1 + 4 * v2 + 6 * v3):eq(0) + local c2 = (6 * v4 + 4 * v5 + 2 * v1 + 1.4 * v1 / 0.3):le(1000) - local e = c:expression() - print(e) + local e = c1:expression() + local s = kiwi.Solver() + + s:add_constraints({ c1, c2, c1 }) + print(s:dumps()) end -collectgarbage("collect") -collectgarbage("collect") -- c = (3 * v1 + 4 * v2 + 6 * v3):eq(0) -- local t = c:expression():terms()