diff options
Diffstat (limited to 'src/point.cpp')
| -rw-r--r-- | src/point.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/point.cpp b/src/point.cpp new file mode 100644 index 0000000..70a4888 --- /dev/null +++ b/src/point.cpp @@ -0,0 +1,106 @@ +#include "point.h" + +#include <sstream> + +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<Geom::Point *>(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); +} |
