gvars 0.9.5 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/gvars/extconf.rb +1 -1
- data/ext/gvars/gvars.c +254 -25
- data/gb +9 -0
- data/lib/gvars/version.rb +1 -1
- data/tmp.rb +73 -0
- metadata +3 -2
- data/ext/gvars/gvars.c-old +0 -147
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 837ffc167909e2abe16ff54fdcd7bfbe4cb6dc0346f1c3e9037b17933f3b89a7
|
|
4
|
+
data.tar.gz: 9e36c6847244b578e63032468c2d94e7fff4f4e05c68cd3a1c126fc257a02b7c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7e71e7a19371437156d14f1831045a6229b4fcd055cc82680309266c5ed20781ec030b78e591e38e4a7adb62633ceb98d5284ca69b8e40eb475ee4ea829ee269
|
|
7
|
+
data.tar.gz: f5cba137bad5f8d9db885f468df9bc147f89b7c0106653a409fd8aa5d32767a8fceba372b4a4c778bdf4161ae59c215dd2081cff250aeccfcf4c2c161658c1a9
|
data/ext/gvars/extconf.rb
CHANGED
data/ext/gvars/gvars.c
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#include "ruby.h"
|
|
2
|
+
#define dbg(...) (fprintf(stderr, "%s:%s:%d: ", __FILE__, __FUNCTION__, __LINE__), fprintf(stderr,__VA_ARGS__),fprintf(stderr,"\n"),fflush(stderr))
|
|
3
|
+
|
|
4
|
+
VALUE gvars_module;
|
|
2
5
|
|
|
3
6
|
// Converts `name` to a global variable name, ensures it's valid, and returns it.
|
|
4
7
|
//
|
|
5
8
|
// for checking, it makes that `name` starts with `$`. This isn't really required, as ruby supports
|
|
6
9
|
// globals that don't start with `$` (but doesn't expose any methods to interact with them)
|
|
7
|
-
static char *get_global_name(VALUE *name) {
|
|
10
|
+
static char *get_global_name(VALUE *name, bool raise) {
|
|
8
11
|
// If `name` is a symbol, get its backing string
|
|
9
12
|
if (RB_SYMBOL_P(*name)) {
|
|
10
13
|
*name = rb_sym2str(*name);
|
|
@@ -13,7 +16,7 @@ static char *get_global_name(VALUE *name) {
|
|
|
13
16
|
char *namestr = StringValueCStr(*name);
|
|
14
17
|
|
|
15
18
|
// Ensure it starts with a dollar sign
|
|
16
|
-
if (namestr[0] != '$') {
|
|
19
|
+
if (raise && namestr[0] != '$') {
|
|
17
20
|
rb_raise(rb_eNameError, "'%s' is not allowed as a global variable name", namestr);
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -24,13 +27,26 @@ static char *get_global_name(VALUE *name) {
|
|
|
24
27
|
static VALUE
|
|
25
28
|
gvars_f_global_variable_get(VALUE self, VALUE name)
|
|
26
29
|
{
|
|
27
|
-
return rb_gv_get(get_global_name(&name));
|
|
30
|
+
return rb_gv_get(get_global_name(&name, true));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static VALUE
|
|
34
|
+
gvars_f_global_variable_aref(VALUE self, VALUE name)
|
|
35
|
+
{
|
|
36
|
+
return rb_gv_get(get_global_name(&name, false));
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
static VALUE
|
|
31
40
|
gvars_f_global_variable_set(VALUE self, VALUE name, VALUE value)
|
|
32
41
|
{
|
|
33
|
-
return rb_gv_set(get_global_name(&name), value);
|
|
42
|
+
return rb_gv_set(get_global_name(&name, true), value);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
static VALUE
|
|
47
|
+
gvars_f_global_variable_aset(VALUE self, VALUE name, VALUE value)
|
|
48
|
+
{
|
|
49
|
+
return rb_gv_set(get_global_name(&name, false), value);
|
|
34
50
|
}
|
|
35
51
|
|
|
36
52
|
static VALUE
|
|
@@ -42,52 +58,260 @@ gvars_f_global_variables(VALUE self)
|
|
|
42
58
|
static VALUE
|
|
43
59
|
gvars_f_alias_global_variable(VALUE self, VALUE new, VALUE old)
|
|
44
60
|
{
|
|
45
|
-
|
|
46
|
-
rb_alias_variable(newid, rb_intern(get_global_name(&old)));
|
|
61
|
+
ID newid = rb_intern(get_global_name(&new, true));
|
|
62
|
+
rb_alias_variable(newid, rb_intern(get_global_name(&old, true)));
|
|
47
63
|
return ID2SYM(newid);
|
|
48
64
|
}
|
|
49
65
|
|
|
50
66
|
static VALUE
|
|
51
67
|
gvars_enum_length(VALUE self, VALUE args, VALUE eobj)
|
|
52
68
|
{
|
|
53
|
-
|
|
69
|
+
return LONG2NUM(RARRAY_LEN(rb_f_global_variables()));
|
|
54
70
|
}
|
|
55
71
|
|
|
56
72
|
static VALUE
|
|
57
73
|
gvars_f_each(VALUE self)
|
|
58
74
|
{
|
|
59
|
-
|
|
75
|
+
RETURN_SIZED_ENUMERATOR(self, 0, 0, gvars_enum_length);
|
|
60
76
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
VALUE gvars = gvars_f_global_variables(self);
|
|
78
|
+
for (long i = 0; i < RARRAY_LEN(gvars); i++) {
|
|
79
|
+
VALUE key = RARRAY_AREF(gvars, i);
|
|
80
|
+
rb_yield(rb_ary_new_from_args(2, key, gvars_f_global_variable_get(self, key)));
|
|
81
|
+
}
|
|
66
82
|
|
|
67
|
-
|
|
83
|
+
return self;
|
|
68
84
|
}
|
|
69
85
|
|
|
70
86
|
static VALUE
|
|
71
87
|
gvars_f_to_h(VALUE self)
|
|
72
88
|
{
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
VALUE gvars = gvars_f_global_variables(self);
|
|
90
|
+
VALUE hash = rb_hash_new_capa(RARRAY_LEN(gvars));
|
|
75
91
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
92
|
+
for (long i = 0; i < RARRAY_LEN(gvars); i++) {
|
|
93
|
+
VALUE key = RARRAY_AREF(gvars, i);
|
|
94
|
+
rb_hash_aset(hash, key, gvars_f_global_variable_get(self, key));
|
|
95
|
+
}
|
|
80
96
|
|
|
81
|
-
|
|
97
|
+
return hash;
|
|
82
98
|
}
|
|
83
99
|
|
|
100
|
+
struct value_ptr { VALUE *value; };
|
|
101
|
+
static void value_ptr_mark(void *ptr) { rb_gc_mark(*((struct value_ptr *) ptr)->value); }
|
|
102
|
+
static void value_ptr_free(void *ptr) { ruby_xfree(((struct value_ptr *) ptr)->value); }
|
|
103
|
+
static size_t value_ptr_size(const void *ptr) { return sizeof(struct value_ptr); }
|
|
104
|
+
static const rb_data_type_t value_ptr_data_type = {
|
|
105
|
+
.wrap_struct_name = "gvars/value_ptr",
|
|
106
|
+
.function = {
|
|
107
|
+
.dmark = value_ptr_mark,
|
|
108
|
+
.dfree = value_ptr_free,
|
|
109
|
+
.dsize = value_ptr_size,
|
|
110
|
+
},
|
|
111
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
112
|
+
};
|
|
84
113
|
|
|
85
|
-
|
|
114
|
+
|
|
115
|
+
struct gvars_virtual_var {
|
|
116
|
+
VALUE backing, getter, setter;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
static void gvars_virtual_var_mark(void *ptr) {
|
|
120
|
+
struct gvars_virtual_var *gv = ptr;
|
|
121
|
+
rb_gc_mark(gv->backing);
|
|
122
|
+
rb_gc_mark(gv->getter);
|
|
123
|
+
rb_gc_mark(gv->setter);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static size_t gvars_virtual_var_size(const void *ptr) {
|
|
127
|
+
return sizeof(struct gvars_virtual_var);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
static const rb_data_type_t gvars_type = {
|
|
131
|
+
.wrap_struct_name = "gvars/var",
|
|
132
|
+
.function = {
|
|
133
|
+
.dmark = gvars_virtual_var_mark,
|
|
134
|
+
.dfree = RUBY_DEFAULT_FREE,
|
|
135
|
+
.dsize = gvars_virtual_var_size,
|
|
136
|
+
},
|
|
137
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
static VALUE gvars_virtual_var_getter(ID id, VALUE *data) {
|
|
142
|
+
struct gvars_virtual_var *gv;
|
|
143
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
144
|
+
return rb_proc_call(gv->getter, rb_ary_new());
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
static void gvars_virtual_var_setter(VALUE val, ID id, VALUE *data) {
|
|
148
|
+
struct gvars_virtual_var *gv;
|
|
149
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
150
|
+
rb_proc_call(gv->setter, rb_ary_new_from_args(1, val));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
static VALUE gvars_hooked_state_var_getter(ID id, VALUE *data) {
|
|
154
|
+
struct gvars_virtual_var *gv;
|
|
155
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
156
|
+
return rb_proc_call(gv->getter, rb_ary_new_from_args(1, gv->backing));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static VALUE gvars_hooked_initial_var_getter(ID id, VALUE *data) {
|
|
160
|
+
struct gvars_virtual_var *gv;
|
|
161
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
162
|
+
return gv->backing = rb_proc_call(gv->getter, rb_ary_new_from_args(1, gv->backing));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static void gvars_hooked_var_setter_noproc(VALUE val, ID id, VALUE *data) {
|
|
166
|
+
struct gvars_virtual_var *gv;
|
|
167
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
168
|
+
gv->backing = val;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
static void gvars_hooked_var_setter_proc(VALUE val, ID id, VALUE *data) {
|
|
172
|
+
struct gvars_virtual_var *gv;
|
|
173
|
+
TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
|
|
174
|
+
gv->backing = rb_proc_call(gv->setter, rb_ary_new_from_args(2, val, gv->backing));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
static VALUE gvars_virtual_var_alloc(VALUE backing, VALUE getter, VALUE setter) {
|
|
178
|
+
struct gvars_virtual_var *gv;
|
|
179
|
+
VALUE gvar_ty = TypedData_Make_Struct(rb_cObject, struct gvars_virtual_var, &gvars_type, gv);
|
|
180
|
+
gv->backing = backing;
|
|
181
|
+
gv->getter = getter;
|
|
182
|
+
gv->setter = setter;
|
|
183
|
+
return gvar_ty;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
enum virtual_kind {
|
|
187
|
+
GVARS_VIRTUAL_KIND_VIRTUAL,
|
|
188
|
+
GVARS_VIRTUAL_KIND_INITIAL,
|
|
189
|
+
GVARS_VIRTUAL_KIND_STATE,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
static void
|
|
193
|
+
gvars_define_virtual_method(VALUE self, VALUE *name, VALUE backing, VALUE getter, VALUE setter, enum virtual_kind kind, int readonly_special)
|
|
194
|
+
{
|
|
195
|
+
char *name_str = get_global_name(name, true);
|
|
196
|
+
struct value_ptr *vp;
|
|
197
|
+
VALUE vp_data = TypedData_Make_Struct(rb_cObject, struct value_ptr, &value_ptr_data_type, vp);
|
|
198
|
+
vp->value = RB_ALLOC(VALUE);
|
|
199
|
+
*vp->value = gvars_virtual_var_alloc(backing, getter, setter);
|
|
200
|
+
|
|
201
|
+
rb_gvar_getter_t *getter_meth;
|
|
202
|
+
rb_gvar_setter_t *setter_meth;
|
|
203
|
+
|
|
204
|
+
switch (kind) {
|
|
205
|
+
case GVARS_VIRTUAL_KIND_VIRTUAL:
|
|
206
|
+
getter_meth = gvars_virtual_var_getter;
|
|
207
|
+
setter_meth = setter == Qnil ? rb_gvar_readonly_setter : gvars_virtual_var_setter;
|
|
208
|
+
break;
|
|
209
|
+
|
|
210
|
+
case GVARS_VIRTUAL_KIND_STATE:
|
|
211
|
+
case GVARS_VIRTUAL_KIND_INITIAL:
|
|
212
|
+
getter_meth = kind == GVARS_VIRTUAL_KIND_INITIAL ? gvars_hooked_initial_var_getter : gvars_hooked_state_var_getter;
|
|
213
|
+
if (readonly_special) setter_meth = rb_gvar_readonly_setter;
|
|
214
|
+
else setter_meth = setter == Qnil ? gvars_hooked_var_setter_noproc : gvars_hooked_var_setter_proc;
|
|
215
|
+
break;
|
|
216
|
+
|
|
217
|
+
default:
|
|
218
|
+
rb_bug("oops");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
rb_define_hooked_variable(name_str, vp->value, getter_meth, setter_meth);
|
|
223
|
+
|
|
224
|
+
VALUE hash = rb_iv_get(gvars_module, "vars");
|
|
225
|
+
VALUE namesym = rb_str_new_cstr(name_str);
|
|
226
|
+
rb_hash_aset(hash, namesym, vp_data);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
enum virtual_method_keywords {
|
|
230
|
+
VIRTUAL_METHOD_KEYWORDS_INITIAL,
|
|
231
|
+
VIRTUAL_METHOD_KEYWORDS_STATE,
|
|
232
|
+
VIRTUAL_METHOD_KEYWORDS_READONLY,
|
|
233
|
+
LENGTH_OF_VIRTUAL_METHOD_KEYWORDS,
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
static ID virtual_method_keyword_ids[LENGTH_OF_VIRTUAL_METHOD_KEYWORDS];
|
|
237
|
+
|
|
238
|
+
static VALUE convert_to_proc(const char *name, VALUE input) {
|
|
239
|
+
VALUE proc = rb_convert_type(input, T_DATA, "Proc", "to_proc");
|
|
240
|
+
|
|
241
|
+
if (NIL_P(proc) || !rb_obj_is_proc(proc)) {
|
|
242
|
+
rb_raise(rb_eTypeError, "wrong %s type %s (expected Proc)", name, rb_obj_classname(proc));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return proc;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static VALUE
|
|
249
|
+
gvars_f_define_virtual_method(int argc, VALUE *argv, VALUE self)
|
|
250
|
+
{
|
|
251
|
+
VALUE name, backing, getter, setter, opts_hash, opts[LENGTH_OF_VIRTUAL_METHOD_KEYWORDS];
|
|
252
|
+
|
|
253
|
+
switch (rb_scan_args(argc, argv, "12:", &name, &getter, &setter, &opts_hash)) {
|
|
254
|
+
case 1:
|
|
255
|
+
getter = (rb_need_block(), rb_block_proc());
|
|
256
|
+
setter = Qnil;
|
|
257
|
+
break;
|
|
258
|
+
|
|
259
|
+
case 2:
|
|
260
|
+
setter = Qnil;
|
|
261
|
+
|
|
262
|
+
case 3:
|
|
263
|
+
if (rb_block_given_p()) {
|
|
264
|
+
rb_warn("given block not used");
|
|
265
|
+
}
|
|
266
|
+
break;
|
|
267
|
+
default:
|
|
268
|
+
rb_bug("oops");
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
getter = convert_to_proc("getter", getter);
|
|
272
|
+
if (!NIL_P(setter)) setter = convert_to_proc("setter", setter);
|
|
273
|
+
|
|
274
|
+
enum virtual_kind kind = GVARS_VIRTUAL_KIND_VIRTUAL;
|
|
275
|
+
rb_get_kwargs(opts_hash, virtual_method_keyword_ids, 0, LENGTH_OF_VIRTUAL_METHOD_KEYWORDS, opts);
|
|
276
|
+
|
|
277
|
+
if (opts[VIRTUAL_METHOD_KEYWORDS_INITIAL] != Qundef) {
|
|
278
|
+
if (opts[VIRTUAL_METHOD_KEYWORDS_STATE] != Qundef) {
|
|
279
|
+
rb_raise(rb_eArgError, "only one of 'initial' or 'state' may be supplied");
|
|
280
|
+
}
|
|
281
|
+
backing = opts[VIRTUAL_METHOD_KEYWORDS_INITIAL];
|
|
282
|
+
kind = GVARS_VIRTUAL_KIND_INITIAL;
|
|
283
|
+
} else if (opts[VIRTUAL_METHOD_KEYWORDS_STATE] != Qundef) {
|
|
284
|
+
backing = opts[VIRTUAL_METHOD_KEYWORDS_STATE];
|
|
285
|
+
kind = GVARS_VIRTUAL_KIND_STATE;
|
|
286
|
+
} else {
|
|
287
|
+
backing = Qnil;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// sadly no bool expected :-/
|
|
291
|
+
bool is_readonly = opts[VIRTUAL_METHOD_KEYWORDS_READONLY] != Qundef && RTEST(opts[VIRTUAL_METHOD_KEYWORDS_READONLY]);
|
|
292
|
+
if (is_readonly) {
|
|
293
|
+
if (setter != Qnil) {
|
|
294
|
+
rb_raise(rb_eArgError, "'readonly: true' may not be supplied when a setter proc is supplied");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
setter = Qnil;
|
|
298
|
+
is_readonly = true;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
gvars_define_virtual_method(self, &name, backing, getter, setter, kind, is_readonly);
|
|
302
|
+
|
|
303
|
+
return name; //TODO: ID2SYM(id)
|
|
304
|
+
}
|
|
86
305
|
|
|
87
306
|
void
|
|
88
307
|
Init_gvars(void)
|
|
89
308
|
{
|
|
90
309
|
gvars_module = rb_define_module("GVars");
|
|
310
|
+
rb_ivar_set(gvars_module, rb_intern("vars"), rb_hash_new());
|
|
311
|
+
|
|
312
|
+
virtual_method_keyword_ids[VIRTUAL_METHOD_KEYWORDS_INITIAL] = rb_intern("initial");
|
|
313
|
+
virtual_method_keyword_ids[VIRTUAL_METHOD_KEYWORDS_STATE] = rb_intern("state");
|
|
314
|
+
virtual_method_keyword_ids[VIRTUAL_METHOD_KEYWORDS_READONLY] = rb_intern("readonly");
|
|
91
315
|
|
|
92
316
|
// Define module-level functions that can be used as mixins
|
|
93
317
|
rb_define_module_function(gvars_module, "global_variable_get", gvars_f_global_variable_get, 1);
|
|
@@ -97,17 +321,22 @@ Init_gvars(void)
|
|
|
97
321
|
// Don't make it an instance method, as it exists in Kernel
|
|
98
322
|
rb_define_singleton_method(gvars_module, "global_variables", gvars_f_global_variables, 0);
|
|
99
323
|
|
|
324
|
+
// Don't make it an instance method, cause we don't want it included
|
|
325
|
+
rb_define_singleton_method(gvars_module, "define_virtual_method", gvars_f_define_virtual_method, -1);
|
|
326
|
+
|
|
100
327
|
// Enumerable methods
|
|
101
|
-
|
|
328
|
+
rb_extend_object(gvars_module, rb_mEnumerable);
|
|
102
329
|
rb_define_singleton_method(gvars_module, "each", gvars_f_each, 0);
|
|
103
330
|
rb_define_singleton_method(gvars_module, "to_h", gvars_f_to_h, 0);
|
|
104
331
|
|
|
332
|
+
rb_define_singleton_method(gvars_module, "[]", gvars_f_global_variable_aref, 1);
|
|
333
|
+
rb_define_singleton_method(gvars_module, "[]=", gvars_f_global_variable_aset, 2);
|
|
334
|
+
|
|
105
335
|
// Aliases
|
|
106
336
|
VALUE gvars_singleton = rb_singleton_class(gvars_module);
|
|
107
337
|
rb_define_alias(gvars_singleton, "get", "global_variable_get");
|
|
108
|
-
rb_define_alias(gvars_singleton, "[]", "global_variable_get");
|
|
109
338
|
rb_define_alias(gvars_singleton, "set", "global_variable_set");
|
|
110
|
-
rb_define_alias(gvars_singleton, "[]=", "global_variable_set");
|
|
111
339
|
rb_define_alias(gvars_singleton, "alias", "alias_global_variable");
|
|
112
340
|
rb_define_alias(gvars_singleton, "list", "global_variables");
|
|
341
|
+
rb_define_alias(gvars_singleton, "virtual", "define_virtual_method");
|
|
113
342
|
}
|
data/gb
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
version = nil
|
|
4
|
+
File.open File.join __dir__, 'lib', 'gvars', 'version.rb' do |f|
|
|
5
|
+
f.read =~ /VERSION = '(.*)'/ and (version = $1; break)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
fail "cant find version" unless version
|
|
9
|
+
system('gem build gvars') && system("gem install ./gvars-#{version}.gem")
|
data/lib/gvars/version.rb
CHANGED
data/tmp.rb
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'gvars'
|
|
2
|
+
p GVars::VERSION
|
|
3
|
+
|
|
4
|
+
require 'optparse'
|
|
5
|
+
OptParse.new do |op|
|
|
6
|
+
op.on '--timeout=X', 'the timeout'
|
|
7
|
+
op.parse %w[--timeout 34.5], into: GVars
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
p $timeout
|
|
11
|
+
|
|
12
|
+
__END__
|
|
13
|
+
h = {}
|
|
14
|
+
GVars.virtual(:$-e, &h.method(:[]).curry(1).<<(:$-e))
|
|
15
|
+
# GVars.virtual(:$-e,) { $-W.to_s }
|
|
16
|
+
# $-v = false
|
|
17
|
+
# p $-e
|
|
18
|
+
# $-v = true
|
|
19
|
+
# p $-e
|
|
20
|
+
# $-v = nil
|
|
21
|
+
p $-e
|
|
22
|
+
|
|
23
|
+
exit
|
|
24
|
+
|
|
25
|
+
100.times do
|
|
26
|
+
GVars.virtual(:$foo) { p "bar" }
|
|
27
|
+
# GVars.virtual(:$foo) { p "foo" }
|
|
28
|
+
# $foo
|
|
29
|
+
# p($foo)
|
|
30
|
+
# p GVars.instance_variable_get(:@vars)
|
|
31
|
+
GC.start
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
GVars.virtual(:$foo1) { "hello" }; fail unless 'hello' == $foo1
|
|
35
|
+
GVars.virtual(:$foo2, proc{ "hello" }); fail unless 'hello' == $foo2
|
|
36
|
+
GVars.virtual(:$foo3, proc{ "hello" }, proc { it + 1 }); fail unless ['hello', 3, 'hello'] == [$foo3, $foo3 = 3, $foo3]
|
|
37
|
+
|
|
38
|
+
GVars.virtual(:$bar1, initial: 0) { it + 1 }; fail unless [1, 2, 3] == [$bar1, $bar1, $bar1]
|
|
39
|
+
$bar1 = 10
|
|
40
|
+
fail unless 11 == $bar1
|
|
41
|
+
|
|
42
|
+
GVars.virtual(:$bar2, state: 'a') { it.succ!.dup }
|
|
43
|
+
fail unless ['b', 'c', 'd'] == [$bar2, $bar2, $bar2]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
GVars.virtual(:$lol) { @x = 3 }
|
|
47
|
+
class Thing
|
|
48
|
+
def doit
|
|
49
|
+
$lol
|
|
50
|
+
p @x
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
Thing.new.doit
|
|
54
|
+
p @x
|
|
55
|
+
trace_var :$bar, proc {|v| puts "$_ is now '#{v}'" }
|
|
56
|
+
$bar = 2
|
|
57
|
+
$bar = 3
|
|
58
|
+
trace_var :$_, proc {|v| puts "$_ is now '#{v}'" }
|
|
59
|
+
$_ = "hello"
|
|
60
|
+
$_ = ' there'
|
|
61
|
+
|
|
62
|
+
# $bar2 = 10
|
|
63
|
+
# fail unless 11 == $bar2
|
|
64
|
+
|
|
65
|
+
# GVars.virtual(:$bar, proc{ p "bar" })
|
|
66
|
+
# GVars.virtual(:$baz, proc{ p "bar" }, proc { p "baz: #{_1}"})
|
|
67
|
+
|
|
68
|
+
# 100.times do
|
|
69
|
+
# $foo
|
|
70
|
+
# $bar
|
|
71
|
+
# $baz
|
|
72
|
+
# GC.start
|
|
73
|
+
# end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gvars
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sam Westerman
|
|
@@ -24,10 +24,11 @@ files:
|
|
|
24
24
|
- Rakefile
|
|
25
25
|
- ext/gvars/extconf.rb
|
|
26
26
|
- ext/gvars/gvars.c
|
|
27
|
-
-
|
|
27
|
+
- gb
|
|
28
28
|
- lib/gvars.rb
|
|
29
29
|
- lib/gvars/version.rb
|
|
30
30
|
- sig/gvars.rbs
|
|
31
|
+
- tmp.rb
|
|
31
32
|
homepage: https://github.com/sampersand/gvars
|
|
32
33
|
licenses:
|
|
33
34
|
- MIT
|
data/ext/gvars/gvars.c-old
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#include "ruby.h"
|
|
2
|
-
|
|
3
|
-
// Converts `name` to a global variable name, ensures it's valid, and returns it.
|
|
4
|
-
//
|
|
5
|
-
// for checking, it makes that `name` starts with `$`. This isn't really required, as ruby supports
|
|
6
|
-
// globals that don't start with `$` (but doesn't expose any methods to interact with them)
|
|
7
|
-
static char *get_global_name(VALUE *name) {
|
|
8
|
-
// printf("spot1\n");
|
|
9
|
-
if (RB_SYMBOL_P(*name)) *name = rb_sym2str(*name);
|
|
10
|
-
// printf("spot2\n");
|
|
11
|
-
char *namestr = StringValueCStr(*name);
|
|
12
|
-
// printf("spot3\n");
|
|
13
|
-
|
|
14
|
-
if (namestr[0] != '$') {
|
|
15
|
-
rb_raise(rb_eNameError, "'%s' is not allowed as a global variable name", namestr);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return namestr;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static VALUE
|
|
22
|
-
gvars_f_get(VALUE self, VALUE name)
|
|
23
|
-
{
|
|
24
|
-
// extern VALUE rb_gvars_get(ID);
|
|
25
|
-
return rb_gvars_get(rb_intern(get_global_name(&name)));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static VALUE
|
|
29
|
-
gvars_f_set(VALUE self, VALUE name, VALUE value)
|
|
30
|
-
{
|
|
31
|
-
return rb_gv_set(get_global_name(&name), value);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
static VALUE
|
|
35
|
-
gvars_f_defined_p(VALUE self, VALUE name)
|
|
36
|
-
{
|
|
37
|
-
extern VALUE rb_gvar_defined(ID);
|
|
38
|
-
return rb_gvar_defined(rb_check_id(&name));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static VALUE
|
|
42
|
-
gvars_list(VALUE self)
|
|
43
|
-
{
|
|
44
|
-
return rb_f_global_variables();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
static VALUE
|
|
48
|
-
gvars_f_alias(VALUE self, VALUE new, VALUE old)
|
|
49
|
-
{
|
|
50
|
-
ID newid = rb_intern(get_global_name(&new));
|
|
51
|
-
rb_alias_variable(newid, rb_intern(get_global_name(&old)));
|
|
52
|
-
return ID2SYM(newid);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
struct hooked_var {
|
|
56
|
-
VALUE getter, setter;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
static VALUE hooked_var_getter(ID id, VALUE *data) {
|
|
60
|
-
struct hooked_var *bv = (struct hooked_var *)data;
|
|
61
|
-
return rb_proc_call_kw(bv->getter, rb_ary_new3(1, rb_id2str(id)), RB_NO_KEYWORDS);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
static void hooked_var_setter(VALUE val, ID id, VALUE *data) {
|
|
65
|
-
struct hooked_var *bv = (struct hooked_var *)data;
|
|
66
|
-
rb_proc_call_kw(bv->setter, rb_ary_new3(2, rb_id2str(id), val), RB_NO_KEYWORDS);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
static VALUE
|
|
70
|
-
gvars_define_virtual_global(int argc, VALUE *argv, VALUE self)
|
|
71
|
-
{
|
|
72
|
-
VALUE name, getter, setter;
|
|
73
|
-
|
|
74
|
-
switch (rb_scan_args(argc, argv, "12", &name, &getter, &setter)) {
|
|
75
|
-
case 1:
|
|
76
|
-
getter = (rb_need_block(), rb_block_proc());
|
|
77
|
-
setter = Qnil;
|
|
78
|
-
break;
|
|
79
|
-
|
|
80
|
-
case 2:
|
|
81
|
-
setter = Qnil;
|
|
82
|
-
|
|
83
|
-
case 3:
|
|
84
|
-
if (rb_block_given_p()) {
|
|
85
|
-
rb_warn("given block not used");
|
|
86
|
-
}
|
|
87
|
-
break;
|
|
88
|
-
default:
|
|
89
|
-
rb_bug("oops");
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
char *name_str = get_global_name(&name);
|
|
93
|
-
|
|
94
|
-
VALUE getter_proc, setter_proc;
|
|
95
|
-
|
|
96
|
-
getter_proc = rb_convert_type(getter, T_DATA, "Proc", "to_proc");
|
|
97
|
-
if (NIL_P(getter_proc) || !rb_obj_is_proc(getter_proc)) {
|
|
98
|
-
rb_raise(rb_eTypeError, "wrong getter type %s (expected Proc)", rb_obj_classname(getter_proc));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (NIL_P(setter)) {
|
|
102
|
-
setter_proc = Qnil;
|
|
103
|
-
} else {
|
|
104
|
-
setter_proc = rb_convert_type(setter, T_DATA, "Proc", "to_proc");
|
|
105
|
-
if (NIL_P(setter_proc) || !rb_obj_is_proc(setter_proc)) {
|
|
106
|
-
rb_raise(rb_eTypeError, "wrong setter type %s (expected Proc)", rb_obj_classname(setter_proc));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// todo: not just leak memory here lol
|
|
111
|
-
struct hooked_var *hv = (struct hooked_var *)malloc(sizeof(struct hooked_var));
|
|
112
|
-
hv->getter = getter_proc;
|
|
113
|
-
hv->setter = setter_proc;
|
|
114
|
-
|
|
115
|
-
rb_define_hooked_variable(name_str, (VALUE *)hv, hooked_var_getter, setter_proc == Qnil ? rb_gvar_readonly_setter : hooked_var_setter);
|
|
116
|
-
extern void rb_gvar_ractor_local(const char *);
|
|
117
|
-
rb_gvar_ractor_local(name_str);
|
|
118
|
-
return name; //TODO: ID2SYM(id)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
VALUE gvars_module;
|
|
122
|
-
|
|
123
|
-
void
|
|
124
|
-
Init_gvars(void)
|
|
125
|
-
{
|
|
126
|
-
gvars_module = rb_define_module("GVars");
|
|
127
|
-
|
|
128
|
-
// Define module-level functions that can be used as mixins
|
|
129
|
-
rb_define_module_function(gvars_module, "global_variable_get", gvars_f_get, 1);
|
|
130
|
-
rb_define_module_function(gvars_module, "global_variable_set", gvars_f_set, 2);
|
|
131
|
-
// rb_define_module_function(gvars_module, "global_variable_defined?", gvars_f_defined_p, 1);
|
|
132
|
-
rb_define_module_function(gvars_module, "alias_global_variable", gvars_f_alias, 2);
|
|
133
|
-
|
|
134
|
-
// Don't make mixin, as it exists in Kernel
|
|
135
|
-
rb_define_singleton_method(gvars_module, "global_variables", gvars_list, 0);
|
|
136
|
-
|
|
137
|
-
// aliases at top-level
|
|
138
|
-
rb_define_alias(rb_singleton_class(gvars_module), "get", "global_variable_get");
|
|
139
|
-
rb_define_alias(rb_singleton_class(gvars_module), "set", "global_variable_set");
|
|
140
|
-
// rb_define_alias(rb_singleton_class(gvars_module), "defined?", "global_variable_defined?");
|
|
141
|
-
rb_define_alias(rb_singleton_class(gvars_module), "alias", "alias_global_variable");
|
|
142
|
-
rb_define_alias(rb_singleton_class(gvars_module), "list", "global_variables");
|
|
143
|
-
rb_define_alias(rb_singleton_class(gvars_module), "[]", "global_variable_get");
|
|
144
|
-
rb_define_alias(rb_singleton_class(gvars_module), "[]=", "global_variable_set");
|
|
145
|
-
|
|
146
|
-
// rb_define_singleton_method(gvars_module, "virtual", gvars_define_virtual_global, -1);
|
|
147
|
-
}
|