pluto-src 0.1.1+0.10.4

Sources of Pluto (Lua 5.4 dialect) and logic to build it.
Documentation
#define LUA_LIB
#include "lualib.h"

#include "vendor/Soup/soup/Bigint.hpp"

void pushbigint (lua_State *L, soup::Bigint&& x);

soup::Bigint* checkbigint (lua_State *L, int i) {
  return (soup::Bigint*)luaL_checkudata(L, i, "pluto:bigint");
}

static int bigint_new (lua_State *L) {
  size_t len;
  const char *str = lua_tolstring(L, 1, &len);
  pushbigint(L, soup::Bigint::fromString(str, len));
  return 1;
}

static int bigint_add (lua_State *L) {
  pushbigint(L, *checkbigint(L, 1) + *checkbigint(L, 2));
  return 1;
}

static int bigint_sub (lua_State *L) {
  pushbigint(L, *checkbigint(L, 1) - *checkbigint(L, 2));
  return 1;
}

static int bigint_mul (lua_State *L) {
  pushbigint(L, *checkbigint(L, 1) * *checkbigint(L, 2));
  return 1;
}

static int bigint_div (lua_State *L) {
  auto [q, r] = checkbigint(L, 1)->divide(*checkbigint(L, 2));
  pushbigint(L, std::move(q));
  pushbigint(L, std::move(r));
  return 2;
}

static int bigint_div_mm (lua_State *L) {
  pushbigint(L, *checkbigint(L, 1) / *checkbigint(L, 2));
  return 1;
}

static int bigint_mod (lua_State *L) {
  pushbigint(L, *checkbigint(L, 1) % *checkbigint(L, 2));
  return 1;
}

static int bigint_pow (lua_State *L) {
  pushbigint(L, checkbigint(L, 1)->pow(*checkbigint(L, 2)));
  return 1;
}

static int bigint_tostring (lua_State *L) {
  pluto_pushstring(L, checkbigint(L, 1)->toString());
  return 1;
}

static int bigint_eq (lua_State *L) {
  lua_pushboolean(L, *checkbigint(L, 1) == *checkbigint(L, 2));
  return 1;
}

static int bigint_lt (lua_State *L) {
  lua_pushboolean(L, *checkbigint(L, 1) < *checkbigint(L, 2));
  return 1;
}

static int bigint_le (lua_State *L) {
  lua_pushboolean(L, *checkbigint(L, 1) <= *checkbigint(L, 2));
  return 1;
}

static int bigint_hex (lua_State *L) {
  pluto_pushstring(L, checkbigint(L, 1)->toStringHex());
  return 1;
}

static int bigint_binary (lua_State *L) {
  pluto_pushstring(L, checkbigint(L, 1)->toStringBinary());
  return 1;
}

static int bigint_bitlength (lua_State *L) {
  lua_pushinteger(L, checkbigint(L, 1)->getBitLength());
  return 1;
}

void pushbigint (lua_State *L, soup::Bigint&& x) {
  new (lua_newuserdata(L, sizeof(soup::Bigint))) soup::Bigint(std::move(x));
  if (l_unlikely(luaL_newmetatable(L, "pluto:bigint"))) {
    lua_pushliteral(L, "__gc");
    lua_pushcfunction(L, [](lua_State* L) {
      std::destroy_at<>(checkbigint(L, 1));
      return 0;
    });
    lua_settable(L, -3);
    lua_pushliteral(L, "__add");
    lua_pushcfunction(L, bigint_add);
    lua_settable(L, -3);
    lua_pushliteral(L, "__sub");
    lua_pushcfunction(L, bigint_sub);
    lua_settable(L, -3);
    lua_pushliteral(L, "__mul");
    lua_pushcfunction(L, bigint_mul);
    lua_settable(L, -3);
    lua_pushliteral(L, "__div");
    lua_pushcfunction(L, bigint_div_mm);
    lua_settable(L, -3);
    lua_pushliteral(L, "__mod");
    lua_pushcfunction(L, bigint_mod);
    lua_settable(L, -3);
    lua_pushliteral(L, "__pow");
    lua_pushcfunction(L, bigint_pow);
    lua_settable(L, -3);
    lua_pushliteral(L, "__tostring");
    lua_pushcfunction(L, bigint_tostring);
    lua_settable(L, -3);
    lua_pushliteral(L, "__eq");
    lua_pushcfunction(L, bigint_eq);
    lua_settable(L, -3);
    lua_pushliteral(L, "__lt");
    lua_pushcfunction(L, bigint_lt);
    lua_settable(L, -3);
    lua_pushliteral(L, "__le");
    lua_pushcfunction(L, bigint_le);
    lua_settable(L, -3);
    lua_pushliteral(L, "__index");
    luaL_loadbuffer(L, "return require\"pluto:bigint\"", 28, 0);
    lua_call(L, 0, 1);
    lua_settable(L, -3);
  }
  lua_setmetatable(L, -2);
}

static const luaL_Reg funcs_bigint[] = {
  {"new", bigint_new},
  {"add", bigint_add},
  {"sub", bigint_sub},
  {"mul", bigint_mul},
  {"div", bigint_div},
  {"mod", bigint_mod},
  {"pow", bigint_pow},
  {"tostring", bigint_tostring},
  {"eq", bigint_eq},
  {"lt", bigint_lt},
  {"le", bigint_le},
  {"hex", bigint_hex},
  {"binary", bigint_binary},
  {"bitlength", bigint_bitlength},
  {nullptr, nullptr}
};

PLUTO_NEWLIB(bigint);