1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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);
}
|