#include "point.h" #include extern "C" Janet geom_point_get(void *p, Janet key); extern "C" void geom_point_tostring(void *p, JanetBuffer *buffer) { std::stringstream stream; stream << "<2geom/point " << *static_cast(p) << ">"; janet_buffer_push_cstring(buffer, stream.str().c_str()); } const JanetAbstractType geom_point_type = { "2geom/point", NULL, NULL, geom_point_get, NULL, NULL, NULL, geom_point_tostring }; Janet janet_wrap_point(Geom::Point const &x) { Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point)); *box = (Geom::Point)x; return janet_wrap_abstract(box); } Geom::Point janet_unwrap_point(Janet x) { if (janet_checktype(x, JANET_ABSTRACT)) { void *abst = janet_unwrap_abstract(x); if (janet_abstract_type(abst) == &geom_point_type) return *(Geom::Point *)abst; } janet_panic("not a point"); return Geom::Point(); } extern "C" Janet cfun_geom_point_new(int32_t argc, Janet *argv) { janet_fixarity(argc, 2); double x = janet_getnumber(argv, 0); double y = janet_getnumber(argv, 1); return janet_wrap_point(Geom::Point(x, y)); } const JanetReg it_cfuns[] = { { "point", cfun_geom_point_new, "(geom/point x y)\n\nCreate a Point from x/y coordinate values." }, {NULL, NULL, NULL} }; #define OPMETHOD(name, oper) \ static Janet cfun_geom_point_##name(int32_t argc, Janet *argv) { \ janet_arity(argc, 2, -1); \ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point)); \ *box = janet_unwrap_point(argv[0]); \ for (int i = 1; i < argc; i++) \ *box oper##= janet_unwrap_point(argv[i]); \ return janet_wrap_abstract(box); \ } \ \ static Janet cfun_geom_point_##name##_mut(int32_t argc, Janet *argv) { \ janet_arity(argc, 2, -1); \ Geom::Point *box = (Geom::Point *)janet_abstract(&geom_point_type, sizeof(Geom::Point)); \ for (int i = 1; i < argc; i++) \ *box oper##= janet_unwrap_point(argv[i]); \ return janet_wrap_abstract(box); \ } OPMETHOD(add, +) OPMETHOD(sub, -) static JanetMethod geom_point_methods[] = { {"+", cfun_geom_point_add}, {"-", cfun_geom_point_sub}, {NULL, NULL} }; extern "C" Janet geom_point_get(void *p, Janet key) { Geom::Point *box = (Geom::Point *)p; if (!janet_checktype(key, JANET_KEYWORD)) janet_panicf("expected keyword, got %v", key); uint8_t const *keystr = janet_unwrap_keyword(key); if (janet_string_equal(keystr, janet_cstring("x"))) { return janet_wrap_number(box->x()); } else if (janet_string_equal(keystr, janet_cstring("y"))) { return janet_wrap_number(box->y()); } else { return janet_getmethod(keystr, geom_point_methods); } } extern "C" void janet_lib_geom_point(JanetTable *env) { janet_cfuns(env, NULL, it_cfuns); janet_register_abstract_type(&geom_point_type); }