gvars 0.9.5 → 0.9.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a3f32ce689ea5b4077c4736674afc353494fafd71bec8dc0e108cc95c33424a
4
- data.tar.gz: 237e9f7383637a345dde01342598ec24b01c8e4f8e953f33cde03fc164cb1ba8
3
+ metadata.gz: 3f54223d6addde0cfe225b0894f2da28b43cfa6f679e786baceeee34aedf7238
4
+ data.tar.gz: 3fcc088c1798d3f303825e4ca5167e11b787ffde7f359101426df82b6bde96f2
5
5
  SHA512:
6
- metadata.gz: 54094ee144a422dca37c6ae607d1250829b987c33f92b38f7fb6c2b5ef6aa291a8249bb170db0330c0eac2020178ae6fb4579ee95e82f3f810561f978dc8f1d5
7
- data.tar.gz: 7052348eee6adec41144417564e472575b943f03b4a9edfcf3d2a1e9e715dcde50eb3f56393c8423c42319629ba0a4a97ef0846f4b38b841fb0b063d72f0b280
6
+ metadata.gz: 98c348911582069c49ad6089837708b0479575ab2d176428d4099bb9c107cef7cadc8ce2173853268b4f442abd49385f63c7888ccb611aa9a4a7f5a94af4cdbf
7
+ data.tar.gz: 37ef3ebeefa4f341dc70e0fc393147e6b8feadc40a29e3edc4b8f7624e5836354f47c4f6801c53fe9301b871882b9a0ed45e872a6931fa05d80f8bc3db061c6c
data/ext/gvars/extconf.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'mkmf'
2
2
 
3
- # $CFLAGS << ' -g -fsanitize=undefined'
3
+ $CFLAGS << ' -g -fsanitize=undefined'
4
4
 
5
5
  create_makefile 'gvars/gvars'
data/ext/gvars/gvars.c CHANGED
@@ -1,4 +1,7 @@
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
  //
@@ -42,7 +45,7 @@ gvars_f_global_variables(VALUE self)
42
45
  static VALUE
43
46
  gvars_f_alias_global_variable(VALUE self, VALUE new, VALUE old)
44
47
  {
45
- ID newid = rb_intern(get_global_name(&new));
48
+ ID newid = rb_intern(get_global_name(&new));
46
49
  rb_alias_variable(newid, rb_intern(get_global_name(&old)));
47
50
  return ID2SYM(newid);
48
51
  }
@@ -50,44 +53,268 @@ gvars_f_alias_global_variable(VALUE self, VALUE new, VALUE old)
50
53
  static VALUE
51
54
  gvars_enum_length(VALUE self, VALUE args, VALUE eobj)
52
55
  {
53
- return LONG2NUM(RARRAY_LEN(rb_f_global_variables()));
56
+ return LONG2NUM(RARRAY_LEN(rb_f_global_variables()));
54
57
  }
55
58
 
56
59
  static VALUE
57
60
  gvars_f_each(VALUE self)
58
61
  {
59
- RETURN_SIZED_ENUMERATOR(self, 0, 0, gvars_enum_length);
62
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, gvars_enum_length);
60
63
 
61
- VALUE gvars = gvars_f_global_variables(self);
62
- for (long i = 0; i < RARRAY_LEN(gvars); i++) {
63
- VALUE key = RARRAY_AREF(gvars, i);
64
- rb_yield(rb_ary_new3(2, key, gvars_f_global_variable_get(self, key)));
65
- }
64
+ VALUE gvars = gvars_f_global_variables(self);
65
+ for (long i = 0; i < RARRAY_LEN(gvars); i++) {
66
+ VALUE key = RARRAY_AREF(gvars, i);
67
+ rb_yield(rb_ary_new3(2, key, gvars_f_global_variable_get(self, key)));
68
+ }
66
69
 
67
- return self;
70
+ return self;
68
71
  }
69
72
 
70
73
  static VALUE
71
74
  gvars_f_to_h(VALUE self)
72
75
  {
73
- VALUE gvars = gvars_f_global_variables(self);
74
- VALUE hash = rb_hash_new_capa(RARRAY_LEN(gvars));
76
+ VALUE gvars = gvars_f_global_variables(self);
77
+ VALUE hash = rb_hash_new_capa(RARRAY_LEN(gvars));
75
78
 
76
- for (long i = 0; i < RARRAY_LEN(gvars); i++) {
77
- VALUE key = RARRAY_AREF(gvars, i);
78
- rb_hash_aset(hash, key, gvars_f_global_variable_get(self, key));
79
- }
79
+ for (long i = 0; i < RARRAY_LEN(gvars); i++) {
80
+ VALUE key = RARRAY_AREF(gvars, i);
81
+ rb_hash_aset(hash, key, gvars_f_global_variable_get(self, key));
82
+ }
80
83
 
81
- return hash;
84
+ return hash;
82
85
  }
83
86
 
87
+ struct value_ptr { VALUE *value; };
88
+ static void value_ptr_mark(void *ptr) { rb_gc_mark(*((struct value_ptr *) ptr)->value); }
89
+ static void value_ptr_free(void *ptr) { ruby_xfree(((struct value_ptr *) ptr)->value); }
90
+ static const rb_data_type_t value_ptr_data_type = {
91
+ .wrap_struct_name = "gvars/value_ptr",
92
+ .function = {
93
+ .dmark = value_ptr_mark,
94
+ .dfree = value_ptr_free,
95
+ .dsize = NULL // todo: not 0
96
+ },
97
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
98
+ };
99
+
100
+
101
+ struct gvars_virtual_var {
102
+ VALUE backing, getter, setter;
103
+ };
104
+
105
+ static void gvars_virtual_var_mark(void *ptr) {
106
+ struct gvars_virtual_var *gv = ptr;
107
+ if (gv->backing != Qundef) rb_gc_mark(gv->backing);
108
+ rb_gc_mark(gv->getter);
109
+ rb_gc_mark(gv->setter);
110
+ }
111
+
112
+ static void gvars_virtual_var_free(void *ptr) {
113
+ xfree(ptr);
114
+ }
115
+
116
+ static const rb_data_type_t gvars_type = {
117
+ .wrap_struct_name = "gvars_var",
118
+ .function = {
119
+ .dmark = gvars_virtual_var_mark,
120
+ .dfree = gvars_virtual_var_free,
121
+ .dsize = NULL
122
+ },
123
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
124
+ };
125
+
126
+
127
+ static VALUE gvars_virtual_var_getter(ID id, VALUE *data) {
128
+ struct gvars_virtual_var *gv;
129
+ TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
130
+
131
+ return rb_proc_call_kw(gv->getter, rb_ary_new(), RB_NO_KEYWORDS);
132
+ }
133
+
134
+ static void gvars_virtual_var_setter(VALUE val, ID id, VALUE *data) {
135
+ struct gvars_virtual_var *gv;
136
+ TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
137
+
138
+ rb_proc_call_kw(gv->setter, rb_ary_new3(1, val), RB_NO_KEYWORDS);
139
+ }
140
+
141
+ static VALUE gvars_hooked_state_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
+
145
+ return rb_proc_call_kw(gv->getter, rb_ary_new3(1, gv->backing), RB_NO_KEYWORDS);
146
+ }
147
+
148
+ static void gvars_hooked_state_var_setter_noproc(VALUE val, ID id, VALUE *data) {
149
+ struct gvars_virtual_var *gv;
150
+ TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
151
+
152
+ gv->backing = val;
153
+ }
154
+
155
+ static void gvars_hooked_state_var_setter_proc(VALUE val, ID id, VALUE *data) {
156
+ struct gvars_virtual_var *gv;
157
+ TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
158
+
159
+ gv->backing = rb_proc_call_kw(gv->setter, rb_ary_new3(2, val, gv->backing), RB_NO_KEYWORDS);
160
+ }
161
+
162
+ static VALUE gvars_hooked_initial_var_getter(ID id, VALUE *data) {
163
+ struct gvars_virtual_var *gv;
164
+ TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
165
+
166
+ gv->backing = rb_proc_call_kw(gv->getter, rb_ary_new3(1, gv->backing), RB_NO_KEYWORDS);
167
+ return gv->backing;
168
+ }
169
+
170
+ static void gvars_hooked_initial_var_setter_noproc(VALUE val, ID id, VALUE *data) {
171
+ struct gvars_virtual_var *gv;
172
+ TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
173
+
174
+ gv->backing = val;
175
+ }
176
+
177
+ static void gvars_hooked_initial_var_setter_proc(VALUE val, ID id, VALUE *data) {
178
+ struct gvars_virtual_var *gv;
179
+ TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
180
+
181
+ gv->backing = rb_proc_call_kw(gv->setter, rb_ary_new3(2, val, gv->backing), RB_NO_KEYWORDS);
182
+ }
84
183
 
85
- VALUE gvars_module;
184
+
185
+ static VALUE gvars_virtual_var_alloc(VALUE backing, VALUE getter, VALUE setter) {
186
+ struct gvars_virtual_var *gv;
187
+ VALUE gvar_ty = TypedData_Make_Struct(rb_cObject, struct gvars_virtual_var, &gvars_type, gv);
188
+ gv->backing = backing;
189
+ gv->getter = getter;
190
+ gv->setter = setter;
191
+ return gvar_ty;
192
+ }
193
+
194
+ enum virtual_kind {
195
+ GVARS_VIRTUAL_KIND_VIRTUAL,
196
+ GVARS_VIRTUAL_KIND_INITIAL,
197
+ GVARS_VIRTUAL_KIND_STATE,
198
+ };
199
+
200
+ static void
201
+ gvars_define_virtual_method(VALUE self, VALUE *name, VALUE backing, VALUE getter, VALUE setter, enum virtual_kind kind, int readonly_special)
202
+ {
203
+ char *name_str = get_global_name(name);
204
+ VALUE getter_proc, setter_proc;
205
+
206
+ getter_proc = rb_convert_type(getter, T_DATA, "Proc", "to_proc");
207
+ if (NIL_P(getter_proc) || !rb_obj_is_proc(getter_proc)) {
208
+ rb_raise(rb_eTypeError, "wrong getter type %s (expected Proc)", rb_obj_classname(getter_proc));
209
+ }
210
+
211
+ if (NIL_P(setter)) {
212
+ setter_proc = Qnil;
213
+ } else {
214
+ setter_proc = rb_convert_type(setter, T_DATA, "Proc", "to_proc");
215
+ if (NIL_P(setter_proc) || !rb_obj_is_proc(setter_proc)) {
216
+ rb_raise(rb_eTypeError, "wrong setter type %s (expected Proc)", rb_obj_classname(setter_proc));
217
+ }
218
+ }
219
+
220
+ struct value_ptr *vp;
221
+ VALUE vp_data = TypedData_Make_Struct(rb_cObject, struct value_ptr, &value_ptr_data_type, vp);
222
+ vp->value = RB_ALLOC(VALUE);
223
+ *vp->value = gvars_virtual_var_alloc(backing, getter, setter);
224
+
225
+ rb_gvar_getter_t *getter_meth;
226
+ rb_gvar_setter_t *setter_meth;
227
+
228
+ switch (kind) {
229
+ case GVARS_VIRTUAL_KIND_VIRTUAL:
230
+ getter_meth = gvars_virtual_var_getter;
231
+ setter_meth = setter_proc == Qnil ? rb_gvar_readonly_setter : gvars_virtual_var_setter;
232
+ break;
233
+
234
+ case GVARS_VIRTUAL_KIND_INITIAL:
235
+ getter_meth = gvars_hooked_initial_var_getter;
236
+ setter_meth = setter_proc == Qnil ? gvars_hooked_initial_var_setter_noproc : gvars_hooked_initial_var_setter_proc;
237
+ break;
238
+
239
+ case GVARS_VIRTUAL_KIND_STATE:
240
+ getter_meth = gvars_hooked_state_var_getter;
241
+ setter_meth = setter_proc == Qnil ? gvars_hooked_state_var_setter_noproc : gvars_hooked_state_var_setter_proc;
242
+ break;
243
+
244
+ default:
245
+ rb_bug("oops");
246
+ }
247
+
248
+ if (readonly_special) setter_meth = rb_gvar_readonly_setter;
249
+
250
+ rb_define_hooked_variable(name_str, vp->value, getter_meth, setter_meth);
251
+
252
+ VALUE hash = rb_iv_get(gvars_module, "@vars");
253
+ VALUE namesym = rb_str_new_cstr(name_str);
254
+ rb_hash_aset(hash, namesym, vp_data);
255
+ }
256
+
257
+ static VALUE
258
+ gvars_f_define_virtual_method(int argc, VALUE *argv, VALUE self)
259
+ {
260
+ VALUE name, backing = Qundef, getter, setter, opts_hash, opts[3];
261
+ ID keyword_ids[3];
262
+ keyword_ids[0] = rb_intern("initial");
263
+ keyword_ids[1] = rb_intern("state");
264
+ keyword_ids[2] = rb_intern("readonly");
265
+
266
+ switch (rb_scan_args(argc, argv, "12:", &name, &getter, &setter, &opts_hash)) {
267
+ case 1:
268
+ getter = (rb_need_block(), rb_block_proc());
269
+ setter = Qnil;
270
+ break;
271
+
272
+ case 2:
273
+ setter = Qnil;
274
+
275
+ case 3:
276
+ if (rb_block_given_p()) {
277
+ rb_warn("given block not used");
278
+ }
279
+ break;
280
+ default:
281
+ rb_bug("oops");
282
+ }
283
+
284
+ enum virtual_kind kind = GVARS_VIRTUAL_KIND_VIRTUAL;
285
+ rb_get_kwargs(opts_hash, keyword_ids, 0, 3, opts);
286
+
287
+ if (opts[0] != Qundef) {
288
+ if (opts[1] != Qundef) {
289
+ rb_raise(rb_eArgError, "only one of 'initial' or 'state' may be supplied");
290
+ }
291
+ backing = opts[0];
292
+ kind = GVARS_VIRTUAL_KIND_INITIAL;
293
+ } else if (opts[1] != Qundef) {
294
+ backing = opts[1];
295
+ kind = GVARS_VIRTUAL_KIND_STATE;
296
+ }
297
+
298
+ bool is_readonly = false;
299
+ if (opts[2] != Qundef && RTEST(opts[2])) { // sadly no bool expected :-/
300
+ if (setter != Qnil) {
301
+ rb_raise(rb_eArgError, "'readonly: true' may not be supplied when a setter proc is supplied");
302
+ }
303
+
304
+ setter = Qnil;
305
+ is_readonly = true;
306
+ }
307
+
308
+ gvars_define_virtual_method(self, &name, backing, getter, setter, kind, is_readonly);
309
+
310
+ return name; //TODO: ID2SYM(id)
311
+ }
86
312
 
87
313
  void
88
314
  Init_gvars(void)
89
315
  {
90
316
  gvars_module = rb_define_module("GVars");
317
+ rb_ivar_set(gvars_module, rb_intern("@vars"), rb_hash_new());
91
318
 
92
319
  // Define module-level functions that can be used as mixins
93
320
  rb_define_module_function(gvars_module, "global_variable_get", gvars_f_global_variable_get, 1);
@@ -97,8 +324,11 @@ Init_gvars(void)
97
324
  // Don't make it an instance method, as it exists in Kernel
98
325
  rb_define_singleton_method(gvars_module, "global_variables", gvars_f_global_variables, 0);
99
326
 
327
+ // Don't make it an instance method, cause we don't want it included
328
+ rb_define_singleton_method(gvars_module, "define_virtual_method", gvars_f_define_virtual_method, -1);
329
+
100
330
  // Enumerable methods
101
- rb_extend_object(gvars_module, rb_mEnumerable);
331
+ rb_extend_object(gvars_module, rb_mEnumerable);
102
332
  rb_define_singleton_method(gvars_module, "each", gvars_f_each, 0);
103
333
  rb_define_singleton_method(gvars_module, "to_h", gvars_f_to_h, 0);
104
334
 
@@ -110,4 +340,5 @@ Init_gvars(void)
110
340
  rb_define_alias(gvars_singleton, "[]=", "global_variable_set");
111
341
  rb_define_alias(gvars_singleton, "alias", "alias_global_variable");
112
342
  rb_define_alias(gvars_singleton, "list", "global_variables");
343
+ rb_define_alias(gvars_singleton, "virtual", "define_virtual_method");
113
344
  }
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GVars
4
- VERSION = '0.9.5'
4
+ VERSION = '0.9.7'
5
5
  end
data/tmp.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'gvars'
2
+ p GVars::VERSION
3
+
4
+ 100.times do
5
+ GVars.virtual(:$foo) { p "bar" }
6
+ # GVars.virtual(:$foo) { p "foo" }
7
+ # $foo
8
+ # p($foo)
9
+ # p GVars.instance_variable_get(:@vars)
10
+ GC.start
11
+ end
12
+
13
+ GVars.virtual(:$foo1) { "hello" }; fail unless 'hello' == $foo1
14
+ GVars.virtual(:$foo2, proc{ "hello" }); fail unless 'hello' == $foo2
15
+ GVars.virtual(:$foo3, proc{ "hello" }, proc { it + 1 }); fail unless ['hello', 3, 'hello'] == [$foo3, $foo3 = 3, $foo3]
16
+
17
+ GVars.virtual(:$bar1, initial: 0) { it + 1 }; fail unless [1, 2, 3] == [$bar1, $bar1, $bar1]
18
+ $bar1 = 10
19
+ fail unless 11 == $bar1
20
+
21
+ GVars.virtual(:$bar2, state: 'a') { it.succ!.dup }
22
+ fail unless ['b', 'c', 'd'] == [$bar2, $bar2, $bar2]
23
+ $bar2 = 10
24
+ fail unless 11 == $bar2
25
+
26
+ # GVars.virtual(:$bar, proc{ p "bar" })
27
+ # GVars.virtual(:$baz, proc{ p "bar" }, proc { p "baz: #{_1}"})
28
+
29
+ # 100.times do
30
+ # $foo
31
+ # $bar
32
+ # $baz
33
+ # GC.start
34
+ # 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.5
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Westerman
@@ -25,9 +25,11 @@ files:
25
25
  - ext/gvars/extconf.rb
26
26
  - ext/gvars/gvars.c
27
27
  - ext/gvars/gvars.c-old
28
+ - gb
28
29
  - lib/gvars.rb
29
30
  - lib/gvars/version.rb
30
31
  - sig/gvars.rbs
32
+ - tmp.rb
31
33
  homepage: https://github.com/sampersand/gvars
32
34
  licenses:
33
35
  - MIT