From 3811d822121805a36f6c3ebd56d33b309834ee64 Mon Sep 17 00:00:00 2001 From: "John K. Luebs" Date: Thu, 22 Feb 2024 16:02:31 -0600 Subject: [PATCH] skin this cat --- Makefile | 4 +- kiwi.lua | 1 - luakiwi/.clang-format | 88 ++++++++ luakiwi/kiwibridge.cpp | 331 +++++++++++++++++++++++++++++ {ckiwi => luakiwi}/luacompat.h | 0 {ckiwi => luakiwi}/luakiwi-int.h | 0 {ckiwi => luakiwi}/luakiwi.cpp | 352 +++++++++++++++---------------- 7 files changed, 595 insertions(+), 181 deletions(-) create mode 100644 luakiwi/.clang-format create mode 100644 luakiwi/kiwibridge.cpp rename {ckiwi => luakiwi}/luacompat.h (100%) rename {ckiwi => luakiwi}/luakiwi-int.h (100%) rename {ckiwi => luakiwi}/luakiwi.cpp (82%) diff --git a/Makefile b/Makefile index 04add60..5e6329d 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ endif OBJS := ckiwi.o luakiwi.o -VPATH = $(SRCDIR)/ckiwi +VPATH = $(SRCDIR)/ckiwi $(SRCDIR)/luakiwi all: ckiwi.$(LIB_EXT) @@ -45,7 +45,7 @@ ckiwi.$(LIB_EXT): $(OBJS) $(CXX) $(CXXFLAGS) $(CFLAGS) $(CFLAGS_EXTRA) -I$(SRCDIR)/kiwi $(LIBFLAG) -o $@ $^ ckiwi.o: ckiwi.h -luakiwi.o: ckiwi.h luakiwi-int.h luacompat.h +luakiwi.o: ckiwi.h kiwibridge.cpp luakiwi-int.h luacompat.h %.o: %.c $(CC) -I$(LUA_INCDIR) $(CFLAGS) $(CFLAGS_EXTRA) -c -o $@ $< diff --git a/kiwi.lua b/kiwi.lua index b30b41a..50e894e 100644 --- a/kiwi.lua +++ b/kiwi.lua @@ -78,7 +78,6 @@ KiwiConstraintRef kiwi_constraint_new( double strength ); void kiwi_constraint_del(KiwiConstraintRef constraint); -KiwiConstraintRef kiwi_constraint_clone(KiwiConstraintRef constraint); double kiwi_constraint_strength(KiwiConstraintRef constraint); enum KiwiRelOp kiwi_constraint_op(KiwiConstraintRef constraint); diff --git a/luakiwi/.clang-format b/luakiwi/.clang-format new file mode 100644 index 0000000..f9132f8 --- /dev/null +++ b/luakiwi/.clang-format @@ -0,0 +1,88 @@ +AccessModifierOffset: -2 +AlignAfterOpenBracket: BlockIndent # New in v14. For earlier clang-format versions, use AlwaysBreak instead. +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: false +AlignTrailingComments: false +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BreakAfterAttributes: Always +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +BreakInheritanceList: AfterColon +BreakStringLiterals: false +ColumnLimit: 98 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +FixNamespaceComments: true +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentCaseLabels: true +IndentPPDirectives: BeforeHash +IndentWidth: 3 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +PointerAlignment: Left +ReferenceAlignment: Left # New in v13. int &name ==> int& name +ReflowComments: false +SeparateDefinitionBlocks: Always # New in v14. +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never diff --git a/luakiwi/kiwibridge.cpp b/luakiwi/kiwibridge.cpp new file mode 100644 index 0000000..cbf0d61 --- /dev/null +++ b/luakiwi/kiwibridge.cpp @@ -0,0 +1,331 @@ +#include + +#include +#include + +namespace { + +using namespace kiwi; + +enum KiwiErrKind { + KiwiErrNone, + KiwiErrUnsatisfiableConstraint = 1, + KiwiErrUnknownConstraint, + KiwiErrDuplicateConstraint, + KiwiErrUnknownEditVariable, + KiwiErrDuplicateEditVariable, + KiwiErrBadRequiredStrength, + KiwiErrInternalSolverError, + KiwiErrAlloc, + KiwiErrNullObject, + KiwiErrUnknown, +}; + +enum KiwiRelOp { KIWI_OP_LE, KIWI_OP_GE, KIWI_OP_EQ }; + +typedef struct KiwiVarRefType* KiwiVarRef; +typedef struct KiwiConstraintRefType* KiwiConstraintRef; + +struct KiwiTerm { + Variable* var; + double coefficient; +}; + +struct KiwiExpression { + double constant; + int term_count; + Constraint* owner; + KiwiTerm terms[1]; // LuaJIT: struct KiwiTerm terms_[?]; +}; + +struct KiwiErr { + enum KiwiErrKind kind; + const char* message; + bool must_free; +}; + +struct KiwiSolver { + unsigned error_mask; + Solver solver; +}; + +template +inline R make_cref(Args&&... args) { + static_assert( + sizeof(R) >= sizeof(T), // NOLINT(bugprone-sizeof-expression) + "to_cref: R too small for T" + ); + static_assert(alignof(R) >= alignof(T), "to_cref: R alignment too small for T"); + + R cref; + new (&cref) T(std::forward(args)...); + return cref; +} + +template +inline decltype(auto) make_var_cref(Args&&... args) { + return make_cref(std::forward(args)...); +} + +template +inline decltype(auto) make_constraint_cref(Args&&... args) { + return make_cref(std::forward(args)...); +} + +template +class SharedRef { + private: + R& cref_; + + public: + explicit SharedRef(R& cref) : cref_(cref) {} + + static_assert( + sizeof(R) >= sizeof(T), // NOLINT(bugprone-sizeof-expression) + "SharedRef CS too small for T" + ); + + R clone() const { + return make_cref(cref()); + } + + void release() { + if (cref_) { + ptr()->~T(); + cref_ = nullptr; + } + } + + T* ptr() { + T* p; + void* s = &cref_; + std::memcpy(&p, &s, sizeof p); // NOLINT(bugprone-sizeof-expression) + return p; + } + + const T* const_ptr() const { + const T* p; + const void* s = &cref_; + std::memcpy(&p, &s, sizeof p); // NOLINT(bugprone-sizeof-expression) + return p; + } + + const T& cref() const { + return *const_ptr(); + } + + T* operator&() const { + return ptr(); + } + + T* operator->() { + return ptr(); + } + + const T* operator->() const { + return const_ptr(); + } + + operator const T&() const { + return cref(); + } + + explicit operator bool() const { + return cref_; + } +}; + +using ConstraintRef = SharedRef; +using VariableRef = SharedRef; +using ConstVariableRef = const SharedRef; + +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)); + 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; +} + +const constexpr KiwiErr kKiwiErrUnhandledCxxException { + KiwiErrUnknown, + "An unhandled C++ exception occurred."}; + +const constexpr KiwiErr kKiwiErrNullObjectArg0 { + KiwiErrNullObject, + "null object passed as argument #0 (self)"}; + +const constexpr KiwiErr kKiwiErrNullObjectArg1 { + KiwiErrNullObject, + "null object passed as argument #1"}; + +template +inline const KiwiErr* wrap_err(F&& f) { + try { + f(); + } catch (const UnsatisfiableConstraint& ex) { + static const constexpr KiwiErr err { + KiwiErrUnsatisfiableConstraint, + "The constraint cannot be satisfied."}; + return &err; + } catch (const UnknownConstraint& ex) { + static const constexpr KiwiErr err { + KiwiErrUnknownConstraint, + "The constraint has not been added to the solver."}; + return &err; + + } catch (const DuplicateConstraint& ex) { + static const constexpr KiwiErr err { + KiwiErrDuplicateConstraint, + "The constraint has already been added to the solver."}; + return &err; + + } catch (const UnknownEditVariable& ex) { + static const constexpr KiwiErr err { + KiwiErrUnknownEditVariable, + "The edit variable has not been added to the solver."}; + return &err; + + } catch (const DuplicateEditVariable& ex) { + static const constexpr KiwiErr err { + KiwiErrDuplicateEditVariable, + "The edit variable has already been added to the solver."}; + return &err; + + } catch (const BadRequiredStrength& ex) { + static const constexpr KiwiErr err { + KiwiErrBadRequiredStrength, + "A required strength cannot be used in this context."}; + return &err; + + } catch (const InternalSolverError& ex) { + static const constexpr KiwiErr base { + KiwiErrInternalSolverError, + "An internal solver error occurred."}; + return new_error(&base, ex); + } catch (std::bad_alloc&) { + static const constexpr KiwiErr err {KiwiErrAlloc, "A memory allocation failed."}; + return &err; + } catch (const std::exception& ex) { + return new_error(&kKiwiErrUnhandledCxxException, ex); + } catch (...) { + return &kKiwiErrUnhandledCxxException; + } + return nullptr; +} + +template +inline const KiwiErr* wrap_err(P ptr, F&& f) { + if (!ptr) { + return &kKiwiErrNullObjectArg0; + } + return wrap_err([&]() { f(ptr); }); +} + +template +inline const KiwiErr* wrap_err(P ptr, R& ref, F&& f) { + if (!ptr) { + return &kKiwiErrNullObjectArg0; + } + return wrap_err([&]() { f(ptr, ref); }); +} + +// inline void kiwi_var_del(KiwiVarRef var) { VariableRef(var).release(); } + +inline Variable* kiwi_var_retain(Variable* var) { + alignas(Variable) unsigned char buf[sizeof(Variable)]; + new (buf) Variable(*var); + return var; +} + +inline Constraint* kiwi_constraint_retain(Constraint* c) { + alignas(Constraint) unsigned char buf[sizeof(Constraint)]; + new (buf) Constraint(*c); + return c; +} + +inline void kiwi_constraint_new( + const KiwiExpression* lhs, + const KiwiExpression* rhs, + enum KiwiRelOp op, + double strength, + Constraint* mem +) { + if (strength < 0.0) { + strength = kiwi::strength::required; + } + + std::vector terms; + terms.reserve((lhs ? lhs->term_count : 0) + (rhs ? rhs->term_count : 0)); + + if (lhs) { + // FIXME FIXME: this should cause a copy! + for (auto* t = lhs->terms; t != lhs->terms + lhs->term_count; ++t) { + terms.emplace_back(*t->var, t->coefficient); + } + } + if (rhs) { + for (auto* t = rhs->terms; t != rhs->terms + rhs->term_count; ++t) { + terms.emplace_back(*t->var, -t->coefficient); + } + } + new (mem) Constraint( + Expression(std::move(terms), (lhs ? lhs->constant : 0.0) - (rhs ? rhs->constant : 0.0)), + static_cast(op), + strength + ); +} + +int kiwi_constraint_expression(const Constraint* c, KiwiExpression* out, int out_size) { + const auto& expr = c->expression(); + const auto& terms = expr.terms(); + const int n_terms = terms.size(); + if (!out || out_size < n_terms) + return n_terms; + + // FIXME FIXME FIXME: dangling pointer + auto* p = out->terms; + for (const auto& t : terms) { + Variable* v = const_cast(&t.variable()); + *p = KiwiTerm {v, t.coefficient()}; + ++p; + } + out->term_count = p - out->terms; + out->constant = expr.constant(); + + return n_terms; +} + +inline const KiwiErr* kiwi_solver_add_constraint(KiwiSolver* s, const Constraint& constraint) { + return wrap_err(s, constraint, [](auto* s, const auto& c) { s->solver.addConstraint(c); }); +} + +inline const KiwiErr* kiwi_solver_remove_constraint(KiwiSolver* s, const Constraint& constraint) { + return wrap_err(s, constraint, [](auto* s, const auto& c) { s->solver.removeConstraint(c); }); +} + +inline const KiwiErr* +kiwi_solver_add_edit_var(KiwiSolver* s, const Variable& var, double strength) { + return wrap_err(s, var, [strength](auto* s, const auto& v) { + s->solver.addEditVariable(v, strength); + }); +} + +inline const KiwiErr* kiwi_solver_remove_edit_var(KiwiSolver* s, const Variable& var) { + return wrap_err(s, var, [](auto* s, const auto& v) { s->solver.removeEditVariable(v); }); +} + +inline const KiwiErr* +kiwi_solver_suggest_value(KiwiSolver* s, const Variable& var, double value) { + return wrap_err(s, var, [value](auto* s, const auto& v) { s->solver.suggestValue(v, value); }); +} + +} // namespace diff --git a/ckiwi/luacompat.h b/luakiwi/luacompat.h similarity index 100% rename from ckiwi/luacompat.h rename to luakiwi/luacompat.h diff --git a/ckiwi/luakiwi-int.h b/luakiwi/luakiwi-int.h similarity index 100% rename from ckiwi/luakiwi-int.h rename to luakiwi/luakiwi-int.h diff --git a/ckiwi/luakiwi.cpp b/luakiwi/luakiwi.cpp similarity index 82% rename from ckiwi/luakiwi.cpp rename to luakiwi/luakiwi.cpp index 513be00..d1c5d13 100644 --- a/ckiwi/luakiwi.cpp +++ b/luakiwi/luakiwi.cpp @@ -2,7 +2,7 @@ #include #include -#include "ckiwi.h" +#include "kiwibridge.cpp" #include "luacompat.h" #include "luakiwi-int.h" @@ -144,17 +144,16 @@ static inline void* try_type(lua_State* L, int idx, enum TypeId type_id) { return lua_rawequal(L, -1, -2) ? p : 0; } -static inline KiwiVarRef try_var(lua_State* L, int idx) { - void* p = try_type(L, idx, VAR); - return p ? *(KiwiVarRef*)p : 0; +static 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) { - return (KiwiTerm*)try_type(L, idx, TERM); + return static_cast(try_type(L, idx, TERM)); } static inline KiwiExpression* try_expr(lua_State* L, int idx) { - return (KiwiExpression*)try_type(L, idx, EXPR); + return static_cast(try_type(L, idx, EXPR)); } // method to test types for expression functions @@ -190,51 +189,52 @@ static inline void* try_arg(lua_State* L, int idx, enum TypeId* type_id, double* return 0; } -static inline KiwiVarRef get_var(lua_State* L, int idx) { - return *((KiwiVarRef*)check_arg(L, idx, VAR)); +static 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) { - return (KiwiTerm*)check_arg(L, idx, TERM); + return static_cast(check_arg(L, idx, TERM)); } static inline KiwiExpression* get_expr(lua_State* L, int idx) { - return (KiwiExpression*)check_arg(L, idx, EXPR); + return static_cast(check_arg(L, idx, EXPR)); } static inline KiwiExpression* get_expr_opt(lua_State* L, int idx) { if (lua_isnoneornil(L, idx)) { return 0; } - return (KiwiExpression*)check_arg(L, idx, EXPR); + return static_cast(check_arg(L, idx, EXPR)); } -static inline KiwiConstraintRef get_constraint(lua_State* L, int idx) { - return *((KiwiConstraintRef*)check_arg(L, idx, CONSTRAINT)); +static 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) { - return *(KiwiSolver**)check_arg(L, idx, SOLVER); + return static_cast(check_arg(L, idx, SOLVER)); } // note this expects the 2nd upvalue to have the variable weak table -static inline KiwiVarRef var_new(lua_State* L, KiwiVarRef var) { - KiwiVarRef* varp = (KiwiVarRef*)lua_newuserdata(L, sizeof(KiwiVarRef)); - *varp = var; +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)...); push_type(L, VAR); lua_setmetatable(L, -2); #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 // a true compatibility shim has performance implications here - lua_pushlightuserdata(L, var); + lua_pushlightuserdata(L, p); lua_pushvalue(L, -2); lua_rawset(L, lua_upvalueindex(2)); #else lua_pushvalue(L, -1); - lua_rawsetp(L, lua_upvalueindex(2), var); + lua_rawsetp(L, lua_upvalueindex(2), p); #endif - return var; + return p; } static inline KiwiTerm* term_new(lua_State* L) { @@ -254,19 +254,19 @@ static inline KiwiExpression* expr_new(lua_State* L, int nterms) { return ret; } -static inline KiwiConstraintRef constraint_new( +static inline Constraint* constraint_new( lua_State* L, const KiwiExpression* lhs, const KiwiExpression* rhs, enum KiwiRelOp op, double strength ) { - KiwiConstraintRef* ref = (KiwiConstraintRef*)lua_newuserdata(L, sizeof(KiwiConstraintRef)); - *ref = kiwi_constraint_new(lhs, rhs, op, strength); + auto* ref = static_cast(lua_newuserdata(L, sizeof(Constraint))); + kiwi_constraint_new(lhs, rhs, op, strength, ref); push_type(L, CONSTRAINT); lua_setmetatable(L, -2); - return *ref; + return ref; } // stack disposition: dirty @@ -291,7 +291,7 @@ static KiwiExpression* toexpr(lua_State* L, int idx, KiwiExpression* temp) { temp->term_count = 1; push_type(L, VAR); if (lua_rawequal(L, -1, -3)) { - temp->terms[0].var = *(KiwiVarRef*)ud; + temp->terms[0].var = static_cast(ud); temp->terms[0].coefficient = 1.0; return temp; } @@ -334,7 +334,7 @@ static inline int push_expr_one(lua_State* L, double constant, const KiwiTerm* t expr->constant = constant; expr->term_count = 1; expr->terms[0].coefficient = term->coefficient; - expr->terms[0].var = kiwi_var_clone(term->var); + expr->terms[0].var = kiwi_var_retain(term->var); return 1; } @@ -344,21 +344,21 @@ push_expr_pair(lua_State* L, double constant, const KiwiTerm* ta, const KiwiTerm e->constant = constant; e->term_count = 2; e->terms[0].coefficient = ta->coefficient; - e->terms[0].var = kiwi_var_clone(ta->var); + e->terms[0].var = kiwi_var_retain(ta->var); e->terms[1].coefficient = tb->coefficient; - e->terms[1].var = kiwi_var_clone(tb->var); + e->terms[1].var = kiwi_var_retain(tb->var); return 1; } static inline int -push_expr_var_term(lua_State* L, double constant, KiwiVarRef var, const KiwiTerm* t) { +push_expr_var_term(lua_State* L, double constant, Variable* var, const KiwiTerm* t) { KiwiExpression* e = expr_new(L, 2); e->constant = constant; e->term_count = 2; e->terms[0].coefficient = 1.0; - e->terms[0].var = kiwi_var_clone(var); + e->terms[0].var = kiwi_var_retain(var); e->terms[1].coefficient = t->coefficient; - e->terms[1].var = kiwi_var_clone(t->var); + e->terms[1].var = kiwi_var_retain(t->var); return 1; } @@ -369,42 +369,42 @@ static int push_add_expr_term(lua_State* L, const KiwiExpression* expr, const Ki int i = 0; for (; i < expr->term_count; ++i) { e->terms[i].coefficient = expr->terms[i].coefficient; - e->terms[i].var = kiwi_var_clone(expr->terms[i].var); + e->terms[i].var = kiwi_var_retain(expr->terms[i].var); } e->terms[i].coefficient = t->coefficient; - e->terms[i].var = kiwi_var_clone(t->var); + e->terms[i].var = kiwi_var_retain(t->var); return 1; } static int lkiwi_var_m_add(lua_State* L) { enum TypeId type_id_b; double num; - const void* arg_b = try_arg(L, 2, &type_id_b, &num); + void* arg_b = try_arg(L, 2, &type_id_b, &num); if (type_id_b == VAR) { int isnum_a; num = lua_tonumberx(L, 1, &isnum_a); if (isnum_a) { - const KiwiTerm t = {*(KiwiVarRef*)arg_b, 1.0}; + const KiwiTerm t {static_cast(arg_b), 1.0}; return push_expr_one(L, num, &t); } } - KiwiVarRef var_a = try_var(L, 1); + Variable* var_a = try_var(L, 1); if (var_a) { switch (type_id_b) { case VAR: { - const KiwiTerm ta = {var_a, 1.0}, tb = {*(KiwiVarRef*)arg_b, 1.0}; + const KiwiTerm ta {var_a, 1.0}, tb {static_cast(arg_b), 1.0}; return push_expr_pair(L, 0.0, &ta, &tb); } case TERM: - return push_expr_var_term(L, 0.0, var_a, (const KiwiTerm*)arg_b); + return push_expr_var_term(L, 0.0, var_a, (static_cast(arg_b))); case EXPR: { - const KiwiTerm t = {var_a, 1.0}; - return push_add_expr_term(L, (const KiwiExpression*)arg_b, &t); + const KiwiTerm t {var_a, 1.0}; + return push_add_expr_term(L, static_cast(arg_b), &t); } case NUMBER: { - const KiwiTerm t = {var_a, 1.0}; + const KiwiTerm t {var_a, 1.0}; return push_expr_one(L, num, &t); } default: @@ -437,10 +437,10 @@ static int lkiwi_var_m_mul(lua_State* L) { } if (isnum) { - KiwiVarRef var = try_var(L, varidx); + auto* var = try_var(L, varidx); if (var) { - KiwiTerm* term = term_new(L); - term->var = kiwi_var_clone(var); + auto* term = term_new(L); + term->var = kiwi_var_retain(var); term->coefficient = num; return 1; } @@ -449,82 +449,78 @@ static int lkiwi_var_m_mul(lua_State* L) { } static int lkiwi_var_m_div(lua_State* L) { - KiwiVarRef var = try_var(L, 1); + 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); - term->var = kiwi_var_clone(var); + term->var = kiwi_var_retain(var); term->coefficient = 1.0 / num; return 1; } static int lkiwi_var_m_unm(lua_State* L) { - KiwiVarRef var = get_var(L, 1); - KiwiTerm* term = term_new(L); - term->var = kiwi_var_clone(var); + 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) { - lua_pushboolean(L, get_var(L, 1) == get_var(L, 2)); + lua_pushboolean(L, get_var(L, 1)->equals(*get_var(L, 2))); return 1; } static int lkiwi_var_m_tostring(lua_State* L) { - KiwiVarRef var = get_var(L, 1); - lua_pushfstring(L, "%s(%f)", kiwi_var_name(var), kiwi_var_value(var)); + 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) { - KiwiVarRef var = get_var(L, 1); - kiwi_var_del(var); + get_var(L, 1)->~Variable(); return 0; } static int lkiwi_var_set_name(lua_State* L) { - KiwiVarRef var = get_var(L, 1); + auto* var = get_var(L, 1); const char* name = luaL_checkstring(L, 2); - kiwi_var_set_name(var, name); + var->setName(name); return 0; } static int lkiwi_var_name(lua_State* L) { - KiwiVarRef var = get_var(L, 1); - lua_pushstring(L, kiwi_var_name(var)); + lua_pushstring(L, get_var(L, 1)->name().c_str()); return 1; } static int lkiwi_var_set(lua_State* L) { - KiwiVarRef var = get_var(L, 1); + auto* var = get_var(L, 1); const double value = luaL_checknumber(L, 2); - kiwi_var_set_value(var, value); + var->setValue(value); return 0; } static int lkiwi_var_value(lua_State* L) { - KiwiVarRef var = get_var(L, 1); - lua_pushnumber(L, kiwi_var_value(var)); + lua_pushnumber(L, get_var(L, 1)->value()); return 1; } static int lkiwi_var_toterm(lua_State* L) { - KiwiVarRef var = get_var(L, 1); + auto* var = get_var(L, 1); double coefficient = luaL_optnumber(L, 2, 1.0); + auto* term = term_new(L); - KiwiTerm* term = term_new(L); - term->var = kiwi_var_clone(var); + term->var = kiwi_var_retain(var); term->coefficient = coefficient; return 1; } static int lkiwi_var_toexpr(lua_State* L) { - const KiwiTerm t = {get_var(L, 1), 1.0}; + const KiwiTerm t {get_var(L, 1), 1.0}; return push_expr_one(L, 0.0, &t); } @@ -550,7 +546,7 @@ static const struct luaL_Reg kiwi_var_m[] = { static int lkiwi_var_new(lua_State* L) { const char* name = luaL_optstring(L, 1, ""); - var_new(L, kiwi_var_new(name)); + var_new(L, name); return 1; } @@ -564,10 +560,10 @@ static int lkiwi_term_m_mul(lua_State* L) { } if (isnum) { - const KiwiTerm* term = try_term(L, termidx); + const auto* term = try_term(L, termidx); if (term) { - KiwiTerm* ret = term_new(L); - ret->var = kiwi_var_clone(term->var); + auto* ret = term_new(L); + ret->var = kiwi_var_retain(term->var); ret->coefficient = term->coefficient * num; return 1; } @@ -583,7 +579,7 @@ static int lkiwi_term_m_div(lua_State* L) { return op_error(L, "/", 1, 2); } KiwiTerm* ret = term_new(L); - ret->var = kiwi_var_clone(term->var); + ret->var = kiwi_var_retain(term->var); ret->coefficient = term->coefficient / num; return 1; } @@ -591,7 +587,7 @@ static int lkiwi_term_m_div(lua_State* L) { static int lkiwi_term_m_unm(lua_State* L) { const KiwiTerm* term = get_term(L, 1); KiwiTerm* ret = term_new(L); - ret->var = kiwi_var_clone(term->var); + ret->var = kiwi_var_retain(term->var); ret->coefficient = -term->coefficient; return 1; } @@ -599,7 +595,7 @@ static int lkiwi_term_m_unm(lua_State* L) { static int lkiwi_term_m_add(lua_State* L) { enum TypeId type_id_b; double num; - const void* arg_b = try_arg(L, 2, &type_id_b, &num); + void* arg_b = try_arg(L, 2, &type_id_b, &num); if (type_id_b == TERM) { int isnum_a; @@ -613,13 +609,13 @@ static int lkiwi_term_m_add(lua_State* L) { if (term_a) { switch (type_id_b) { case TERM: - return push_expr_pair(L, 0.0, term_a, (const KiwiTerm*)arg_b); + return push_expr_pair(L, 0.0, term_a, static_cast(arg_b)); case VAR: { - const KiwiTerm term_b = {*(KiwiVarRef*)arg_b, 1.0}; + const KiwiTerm term_b {static_cast(arg_b), 1.0}; return push_expr_pair(L, 0.0, term_a, &term_b); } case EXPR: - return push_add_expr_term(L, (const KiwiExpression*)arg_b, term_a); + return push_add_expr_term(L, static_cast(arg_b), term_a); case NUMBER: return push_expr_one(L, num, term_a); default: @@ -641,25 +637,24 @@ static int lkiwi_term_toexpr(lua_State* L) { } static int lkiwi_term_value(lua_State* L) { - KiwiTerm* term = get_term(L, 1); - lua_pushnumber(L, kiwi_var_value(term->var) * term->coefficient); + 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) { - KiwiTerm* term = get_term(L, 1); - lua_pushfstring(L, "%f %s", term->coefficient, kiwi_var_name(term->var)); + 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) { - KiwiTerm* term = get_term(L, 1); - kiwi_var_del(term->var); + get_term(L, 1)->var->~Variable(); return 0; } static int lkiwi_term_m_index(lua_State* L) { - KiwiTerm* term = get_term(L, 1); + const auto* term = get_term(L, 1); size_t len; const char* k = lua_tolstring(L, 2, &len); if (len == 3 && memcmp("var", k, len) == 0) { @@ -670,7 +665,7 @@ static int lkiwi_term_m_index(lua_State* L) { lua_rawgetp(L, lua_upvalueindex(2), term->var); #endif if (lua_isnil(L, -1)) - var_new(L, kiwi_var_clone(term->var)); + var_new(L, *term->var); return 1; } else if (len == 11 && memcmp("coefficient", k, len) == 0) { lua_pushnumber(L, term->coefficient); @@ -702,18 +697,18 @@ static const struct luaL_Reg kiwi_term_m[] = { {0, 0}}; static int lkiwi_term_new(lua_State* L) { - KiwiVarRef var = get_var(L, 1); + auto* var = get_var(L, 1); double coefficient = luaL_optnumber(L, 2, 1.0); - KiwiTerm* term = term_new(L); - term->var = kiwi_var_clone(var); + auto* term = term_new(L); + term->var = kiwi_var_retain(var); term->coefficient = coefficient; return 1; } static int push_expr_constant(lua_State* L, const KiwiExpression* expr, double constant) { - KiwiExpression* ne = expr_new(L, expr->term_count); + auto* ne = expr_new(L, expr->term_count); for (int i = 0; i < expr->term_count; i++) { - ne->terms[i].var = kiwi_var_clone(expr->terms[i].var); + ne->terms[i].var = kiwi_var_retain(expr->terms[i].var); ne->terms[i].coefficient = expr->terms[i].coefficient; } ne->constant = constant; @@ -722,11 +717,11 @@ static int push_expr_constant(lua_State* L, const KiwiExpression* expr, double c } static int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double coeff) { - KiwiExpression* ne = expr_new(L, expr->term_count); + auto* ne = expr_new(L, expr->term_count); ne->constant = expr->constant * coeff; ne->term_count = expr->term_count; for (int i = 0; i < expr->term_count; i++) { - ne->terms[i].var = kiwi_var_clone(expr->terms[i].var); + ne->terms[i].var = kiwi_var_retain(expr->terms[i].var); ne->terms[i].coefficient = expr->terms[i].coefficient * coeff; } return 1; @@ -735,16 +730,16 @@ static int push_mul_expr_coeff(lua_State* L, const KiwiExpression* expr, double static int push_add_expr_expr(lua_State* L, const KiwiExpression* a, const KiwiExpression* b) { int na = a->term_count, nb = b->term_count; - KiwiExpression* ne = expr_new(L, na + nb); + auto* ne = expr_new(L, na + nb); ne->constant = a->constant + b->constant; ne->term_count = na + nb; for (int i = 0; i < na; i++) { - ne->terms[i].var = kiwi_var_clone(a->terms[i].var); + ne->terms[i].var = kiwi_var_retain(a->terms[i].var); ne->terms[i].coefficient = a->terms[i].coefficient; } for (int i = 0; i < nb; i++) { - ne->terms[i + na].var = kiwi_var_clone(b->terms[i].var); + ne->terms[i + na].var = kiwi_var_retain(b->terms[i].var); ne->terms[i + na].coefficient = b->terms[i].coefficient; } return 1; @@ -760,7 +755,7 @@ static int lkiwi_expr_m_mul(lua_State* L) { } if (isnum) { - const KiwiExpression* expr = try_expr(L, expridx); + const auto* expr = try_expr(L, expridx); if (expr) return push_mul_expr_coeff(L, expr, num); } @@ -768,7 +763,7 @@ static int lkiwi_expr_m_mul(lua_State* L) { } static int lkiwi_expr_m_div(lua_State* L) { - const KiwiExpression* expr = try_expr(L, 1); + const auto* expr = try_expr(L, 1); int isnum; double num = lua_tonumberx(L, 2, &isnum); if (!expr || !isnum) { @@ -778,20 +773,20 @@ static int lkiwi_expr_m_div(lua_State* L) { } static int lkiwi_expr_m_unm(lua_State* L) { - const KiwiExpression* expr = get_expr(L, 1); + 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) { enum TypeId type_id_b; double num; - const void* arg_b = try_arg(L, 2, &type_id_b, &num); + void* arg_b = try_arg(L, 2, &type_id_b, &num); if (type_id_b == EXPR) { int isnum_a; num = lua_tonumberx(L, 1, &isnum_a); if (isnum_a) { - const KiwiExpression* expr_b = (const KiwiExpression*)arg_b; + auto* expr_b = static_cast(arg_b); return push_expr_constant(L, expr_b, num + expr_b->constant); } } @@ -800,11 +795,11 @@ static int lkiwi_expr_m_add(lua_State* L) { if (expr_a) { switch (type_id_b) { case EXPR: - return push_add_expr_expr(L, expr_a, (const KiwiExpression*)arg_b); + return push_add_expr_expr(L, expr_a, static_cast(arg_b)); case TERM: - return push_add_expr_term(L, expr_a, (const KiwiTerm*)arg_b); + return push_add_expr_term(L, expr_a, static_cast(arg_b)); case VAR: { - const KiwiTerm term_b = {*(KiwiVarRef*)arg_b, 1.0}; + const KiwiTerm term_b {static_cast(arg_b), 1.0}; return push_add_expr_term(L, expr_a, &term_b); } case NUMBER: @@ -824,23 +819,23 @@ static int lkiwi_expr_m_sub(lua_State* L) { } static int lkiwi_expr_value(lua_State* L) { - KiwiExpression* expr = get_expr(L, 1); + const auto* expr = get_expr(L, 1); double sum = expr->constant; for (int i = 0; i < expr->term_count; i++) { - const KiwiTerm* t = &expr->terms[i]; - sum += kiwi_var_value(t->var) * t->coefficient; + const auto* t = &expr->terms[i]; + sum += t->var->value() * t->coefficient; } lua_pushnumber(L, sum); return 1; } static int lkiwi_expr_terms(lua_State* L) { - KiwiExpression* expr = get_expr(L, 1); + const auto* expr = get_expr(L, 1); lua_createtable(L, expr->term_count, 0); for (int i = 0; i < expr->term_count; i++) { - KiwiTerm* t = &expr->terms[i]; - KiwiTerm* new_term = term_new(L); - new_term->var = kiwi_var_clone(t->var); + const auto* t = &expr->terms[i]; + auto* new_term = term_new(L); + new_term->var = kiwi_var_retain(t->var); new_term->coefficient = t->coefficient; lua_rawseti(L, -2, i + 1); } @@ -858,7 +853,7 @@ static void push_expr_string(lua_State* L, KiwiExpression* expr) { for (int i = 0; i < expr->term_count; i++) { KiwiTerm* t = &expr->terms[i]; - lua_pushfstring(L, "%f %s", t->coefficient, kiwi_var_name(t->var)); + lua_pushfstring(L, "%f %s", t->coefficient, t->var->name().c_str()); luaL_addvalue(&buf); luaL_addstring(&buf, " + "); } @@ -874,9 +869,9 @@ static int lkiwi_expr_m_tostring(lua_State* L) { } static int lkiwi_expr_m_gc(lua_State* L) { - KiwiExpression* expr = get_expr(L, 1); - for (int i = 0; i < expr->term_count; i++) { - kiwi_var_del(expr->terms[i].var); + const auto* expr = get_expr(L, 1); + for (auto* t = expr->terms; t != expr->terms + expr->term_count; ++t) { + t->var->~Variable(); } return 0; } @@ -925,45 +920,42 @@ static int lkiwi_expr_new(lua_State* L) { for (int i = 0; i < nterms; i++) { const KiwiTerm* term = get_term(L, i + 2); - expr->terms[i].var = kiwi_var_clone(term->var); + 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) { - KiwiConstraintRef c = get_constraint(L, 1); - lua_pushnumber(L, kiwi_constraint_strength(c)); + lua_pushnumber(L, get_constraint(L, 1)->strength()); return 1; } static int lkiwi_constraint_op(lua_State* L) { - KiwiConstraintRef c = get_constraint(L, 1); - enum KiwiRelOp op = kiwi_constraint_op(c); + auto op = get_constraint(L, 1)->op(); const char* opstr = "??"; switch (op) { - case KIWI_OP_EQ: - opstr = "EQ"; - break; - case KIWI_OP_LE: + case kiwi::OP_LE: opstr = "LE"; break; - case KIWI_OP_GE: + case kiwi::OP_GE: opstr = "GE"; break; + case kiwi::OP_EQ: + opstr = "EQ"; + break; } lua_pushlstring(L, opstr, 2); return 1; } static int lkiwi_constraint_violated(lua_State* L) { - KiwiConstraintRef c = get_constraint(L, 1); - lua_pushboolean(L, kiwi_constraint_violated(c)); + lua_pushboolean(L, get_constraint(L, 1)->violated()); return 1; } static int lkiwi_constraint_expression(lua_State* L) { - KiwiConstraintRef c = get_constraint(L, 1); + auto* c = get_constraint(L, 1); const static int SZ = 7; KiwiExpression* expr = expr_new(L, SZ); int n = kiwi_constraint_expression(c, expr, SZ); @@ -977,41 +969,46 @@ static int lkiwi_constraint_expression(lua_State* L) { } static int lkiwi_constraint_m_tostring(lua_State* L) { - KiwiConstraintRef c = get_constraint(L, 1); + const auto& c = *get_constraint(L, 1); - const static int SZ = 16; - KiwiExpression* expr = - (KiwiExpression*)stalloc(sizeof(KiwiExpression) + sizeof(KiwiTerm) * (SZ - 1)); - int n = kiwi_constraint_expression(c, expr, SZ); + const constexpr static int SZ = 16; + + alignas(KiwiExpression + ) unsigned char expr_buf[sizeof(KiwiExpression) + sizeof(KiwiTerm) * (SZ - 1)]; + auto* expr = reinterpret_cast(&expr_buf); + + int n = kiwi_constraint_expression(&c, expr, SZ); if (l_unlikely(n > SZ)) { - expr = (KiwiExpression*)malloc(sizeof(KiwiExpression) + sizeof(KiwiTerm) * (n - 1)); + expr = + static_cast(malloc(sizeof(KiwiExpression) + sizeof(KiwiTerm) * (n - 1)) + ); if (!expr) { luaL_error(L, "out of memory"); } - kiwi_constraint_expression(c, expr, n); + kiwi_constraint_expression(&c, expr, n); } luaL_Buffer buf; luaL_buffinit(L, &buf); const char* oppart = " ?? 0 | "; - switch (kiwi_constraint_op(c)) { - case KIWI_OP_EQ: - oppart = " == 0 | "; - break; - case KIWI_OP_LE: + switch (c.op()) { + case kiwi::OP_LE: oppart = " <= 0 | "; break; - case KIWI_OP_GE: + case kiwi::OP_GE: oppart = " >= 0 | "; break; + case kiwi::OP_EQ: + oppart = " == 0 | "; + break; } push_expr_string(L, expr); luaL_addvalue(&buf); luaL_addlstring(&buf, oppart, 8); const char* strength_name = 0; - const double strength = kiwi_constraint_strength(c); + const double strength = c.strength(); if (strength == STRENGTH_REQUIRED) { strength_name = "required"; @@ -1035,8 +1032,7 @@ static int lkiwi_constraint_m_tostring(lua_State* L) { } static int lkiwi_constraint_m_gc(lua_State* L) { - KiwiConstraintRef c = get_constraint(L, 1); - kiwi_constraint_del(c); + get_constraint(L, 1)->~Constraint(); return 0; } @@ -1082,14 +1078,15 @@ static int lkiwi_constraint_new(lua_State* L) { static int push_pair_constraint( lua_State* L, - KiwiVarRef left, + Variable* left, double coeff, - KiwiVarRef right, + Variable* right, double constant, enum KiwiRelOp op, double strength ) { - KiwiExpression* expr = (KiwiExpression*)stalloc(sizeof(KiwiExpression) + sizeof(KiwiTerm)); + alignas(KiwiExpression) unsigned char expr_buf[sizeof(KiwiExpression) + sizeof(KiwiTerm)]; + auto* expr = reinterpret_cast(&expr_buf); expr->constant = constant; expr->term_count = 2; expr->terms[0].var = left; @@ -1233,8 +1230,7 @@ static int lkiwi_solver_handle_err(lua_State* L, const KiwiErr* err, const KiwiS lua_settop(L, 2); if (err) { error_new(L, err, 1, 2); - unsigned error_mask; - memcpy(&error_mask, solver, sizeof(error_mask)); + unsigned error_mask = solver->error_mask; if (error_mask & (1 << err->kind)) { return 2; } else { @@ -1245,22 +1241,22 @@ static int lkiwi_solver_handle_err(lua_State* L, const KiwiErr* err, const KiwiS } static int lkiwi_solver_add_constraint(lua_State* L) { - KiwiSolver* solver = get_solver(L, 1); - KiwiConstraintRef c = get_constraint(L, 2); + auto* solver = get_solver(L, 1); + const auto& c = *get_constraint(L, 2); const KiwiErr* err = kiwi_solver_add_constraint(solver, c); return lkiwi_solver_handle_err(L, err, solver); } static int lkiwi_solver_remove_constraint(lua_State* L) { - KiwiSolver* solver = get_solver(L, 1); - KiwiConstraintRef c = get_constraint(L, 2); + auto* solver = get_solver(L, 1); + const auto& c = *get_constraint(L, 2); const KiwiErr* err = kiwi_solver_remove_constraint(solver, c); return lkiwi_solver_handle_err(L, err, solver); } static int lkiwi_solver_add_edit_var(lua_State* L) { KiwiSolver* solver = get_solver(L, 1); - KiwiVarRef var = get_var(L, 2); + const auto& var = *get_var(L, 2); double strength = luaL_checknumber(L, 3); const KiwiErr* err = kiwi_solver_add_edit_var(solver, var, strength); return lkiwi_solver_handle_err(L, err, solver); @@ -1268,46 +1264,51 @@ static int lkiwi_solver_add_edit_var(lua_State* L) { static int lkiwi_solver_remove_edit_var(lua_State* L) { KiwiSolver* solver = get_solver(L, 1); - KiwiVarRef var = get_var(L, 2); + const auto& var = *get_var(L, 2); const KiwiErr* err = kiwi_solver_remove_edit_var(solver, var); return lkiwi_solver_handle_err(L, err, solver); } static int lkiwi_solver_suggest_value(lua_State* L) { KiwiSolver* solver = get_solver(L, 1); - KiwiVarRef var = get_var(L, 2); + const auto& var = *get_var(L, 2); double value = luaL_checknumber(L, 3); const KiwiErr* err = kiwi_solver_suggest_value(solver, var, value); return lkiwi_solver_handle_err(L, err, solver); } static int lkiwi_solver_update_vars(lua_State* L) { - kiwi_solver_update_vars(get_solver(L, 1)); + get_solver(L, 1)->solver.updateVariables(); return 0; } static int lkiwi_solver_reset(lua_State* L) { - kiwi_solver_reset(get_solver(L, 1)); + get_solver(L, 1)->solver.reset(); return 0; } static int lkiwi_solver_has_constraint(lua_State* L) { - lua_pushboolean(L, kiwi_solver_has_constraint(get_solver(L, 1), get_constraint(L, 2))); + 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) { - lua_pushboolean(L, kiwi_solver_has_edit_var(get_solver(L, 1), get_var(L, 2))); + 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) { - kiwi_solver_dump(get_solver(L, 1)); + get_solver(L, 1)->solver.dump(); return 0; } static int lkiwi_solver_dumps(lua_State* L) { - lua_pushstring(L, kiwi_solver_dumps(get_solver(L, 1))); + const auto s = get_solver(L, 1)->solver.dumps(); + lua_pushlstring(L, s.data(), s.length()); return 1; } @@ -1328,8 +1329,7 @@ static int lkiwi_add_remove_tab(lua_State* L, add_remove_fn_t fn, void* d) { const KiwiErr* err = fn(L, solver, d); if (err) { error_new(L, err, 1, narg + 1 /* item_absi */); - unsigned error_mask; - memcpy(&error_mask, solver, sizeof(error_mask)); + unsigned error_mask = solver->error_mask; if (error_mask & (1 << err->kind)) { lua_replace(L, 3); lua_settop(L, 3); @@ -1345,8 +1345,7 @@ static int lkiwi_add_remove_tab(lua_State* L, add_remove_fn_t fn, void* d) { } static const KiwiErr* add_constraint_fn(lua_State* L, KiwiSolver* s, void* d) { - KiwiConstraintRef c = get_constraint(L, -1); - return kiwi_solver_add_constraint(s, c); + return kiwi_solver_add_constraint(s, *get_constraint(L, -1)); } static int lkiwi_solver_add_constraints(lua_State* L) { @@ -1354,8 +1353,7 @@ static int lkiwi_solver_add_constraints(lua_State* L) { } static const KiwiErr* remove_constraint_fn(lua_State* L, KiwiSolver* s, void* d) { - KiwiConstraintRef c = get_constraint(L, -1); - return kiwi_solver_remove_constraint(s, c); + return kiwi_solver_remove_constraint(s, *get_constraint(L, -1)); } static int lkiwi_solver_remove_constraints(lua_State* L) { @@ -1363,8 +1361,7 @@ static int lkiwi_solver_remove_constraints(lua_State* L) { } static const KiwiErr* add_edit_var_fn(lua_State* L, KiwiSolver* s, void* d) { - KiwiVarRef v = get_var(L, -1); - return kiwi_solver_add_edit_var(s, v, *(double*)d); + return kiwi_solver_add_edit_var(s, *get_var(L, -1), *(double*)d); } static int lkiwi_solver_add_edit_vars(lua_State* L) { @@ -1373,8 +1370,7 @@ static int lkiwi_solver_add_edit_vars(lua_State* L) { } static const KiwiErr* remove_edit_var_fn(lua_State* L, KiwiSolver* s, void* d) { - KiwiVarRef v = get_var(L, -1); - return kiwi_solver_remove_edit_var(s, v); + return kiwi_solver_remove_edit_var(s, *get_var(L, -1)); } static int lkiwi_solver_remove_edit_vars(lua_State* L) { @@ -1398,15 +1394,15 @@ static int lkiwi_solver_suggest_values(lua_State* L) { if (lua_geti(L, 2, i) == LUA_TNIL) { break; } - KiwiVarRef var = get_var(L, -1); + auto* var = get_var(L, -1); + lua_geti(L, 3, i); double value = luaL_checknumber(L, -1); - const KiwiErr* err = kiwi_solver_suggest_value(solver, var, value); + const KiwiErr* err = kiwi_solver_suggest_value(solver, *var, value); if (err) { error_new(L, err, 1, narg + 1 /* item_absi */); - unsigned error_mask; - memcpy(&error_mask, solver, sizeof(error_mask)); + unsigned error_mask = solver->error_mask; if (error_mask & (1 << err->kind)) { lua_replace(L, 4); lua_settop(L, 4); @@ -1434,7 +1430,7 @@ static int lkiwi_solver_set_error_mask(lua_State* L) { error_mask = luaL_checkinteger(L, 2); } - memcpy(solver, &error_mask, sizeof(error_mask)); + solver->error_mask = error_mask; return 0; } @@ -1444,7 +1440,7 @@ static int lkiwi_solver_tostring(lua_State* L) { } static int lkiwi_solver_del(lua_State* L) { - kiwi_solver_del(get_solver(L, 1)); + get_solver(L, 1)->~KiwiSolver(); return 0; } @@ -1479,8 +1475,8 @@ static int lkiwi_solver_new_meth(lua_State* L) { error_mask = luaL_optinteger(L, 1, 0); } - KiwiSolver** sp = (KiwiSolver**)lua_newuserdata(L, sizeof(KiwiSolver*)); - *sp = kiwi_solver_new(error_mask); + KiwiSolver* sp = static_cast(lua_newuserdata(L, sizeof(KiwiSolver))); + new (sp) KiwiSolver {error_mask}; push_type(L, SOLVER); lua_setmetatable(L, -2);