gvars 0.9.0 → 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: 1728504fbc5ee4dcf6e72f18a5f0aff56fa3933f97776d9e57bca20cc8301b45
4
- data.tar.gz: 45fa2513e7c7fc2438dabd33d91505899e7154c8ec4d91fb03008b4f22dbbc9a
3
+ metadata.gz: 3f54223d6addde0cfe225b0894f2da28b43cfa6f679e786baceeee34aedf7238
4
+ data.tar.gz: 3fcc088c1798d3f303825e4ca5167e11b787ffde7f359101426df82b6bde96f2
5
5
  SHA512:
6
- metadata.gz: 0daa5d2870632bd24be477d7e561383bf89ad66ec6efe844717ef2d1e37c9c8219c22bcc9ab644e8c291e408a41c8a5559a684ecf4f70f178a2f5966963f4261
7
- data.tar.gz: 2feac652e6098336616d4dd9f9c893add9ef8745884214297392381bf1182edad60839d8229d53e6fe97d1a2abc3c9a107ce61075ce908f25e7ca037b88fd0b6
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
  //
@@ -20,6 +23,7 @@ static char *get_global_name(VALUE *name) {
20
23
  return namestr;
21
24
  }
22
25
 
26
+
23
27
  static VALUE
24
28
  gvars_f_global_variable_get(VALUE self, VALUE name)
25
29
  {
@@ -41,23 +45,300 @@ gvars_f_global_variables(VALUE self)
41
45
  static VALUE
42
46
  gvars_f_alias_global_variable(VALUE self, VALUE new, VALUE old)
43
47
  {
44
- ID newid = rb_intern(get_global_name(&new));
48
+ ID newid = rb_intern(get_global_name(&new));
45
49
  rb_alias_variable(newid, rb_intern(get_global_name(&old)));
46
50
  return ID2SYM(newid);
47
51
  }
48
52
 
49
- VALUE gvars_module;
53
+ static VALUE
54
+ gvars_enum_length(VALUE self, VALUE args, VALUE eobj)
55
+ {
56
+ return LONG2NUM(RARRAY_LEN(rb_f_global_variables()));
57
+ }
58
+
59
+ static VALUE
60
+ gvars_f_each(VALUE self)
61
+ {
62
+ RETURN_SIZED_ENUMERATOR(self, 0, 0, gvars_enum_length);
63
+
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
+ }
69
+
70
+ return self;
71
+ }
72
+
73
+ static VALUE
74
+ gvars_f_to_h(VALUE self)
75
+ {
76
+ VALUE gvars = gvars_f_global_variables(self);
77
+ VALUE hash = rb_hash_new_capa(RARRAY_LEN(gvars));
78
+
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
+ }
83
+
84
+ return hash;
85
+ }
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
+ }
183
+
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
+ }
50
312
 
51
313
  void
52
314
  Init_gvars(void)
53
315
  {
54
316
  gvars_module = rb_define_module("GVars");
317
+ rb_ivar_set(gvars_module, rb_intern("@vars"), rb_hash_new());
55
318
 
56
319
  // Define module-level functions that can be used as mixins
57
320
  rb_define_module_function(gvars_module, "global_variable_get", gvars_f_global_variable_get, 1);
58
321
  rb_define_module_function(gvars_module, "global_variable_set", gvars_f_global_variable_set, 2);
59
322
  rb_define_module_function(gvars_module, "alias_global_variable", gvars_f_alias_global_variable, 2);
60
323
 
61
- // Don't make mixin, as it exists in Kernel
324
+ // Don't make it an instance method, as it exists in Kernel
62
325
  rb_define_singleton_method(gvars_module, "global_variables", gvars_f_global_variables, 0);
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
+
330
+ // Enumerable methods
331
+ rb_extend_object(gvars_module, rb_mEnumerable);
332
+ rb_define_singleton_method(gvars_module, "each", gvars_f_each, 0);
333
+ rb_define_singleton_method(gvars_module, "to_h", gvars_f_to_h, 0);
334
+
335
+ // Aliases
336
+ VALUE gvars_singleton = rb_singleton_class(gvars_module);
337
+ rb_define_alias(gvars_singleton, "get", "global_variable_get");
338
+ rb_define_alias(gvars_singleton, "[]", "global_variable_get");
339
+ rb_define_alias(gvars_singleton, "set", "global_variable_set");
340
+ rb_define_alias(gvars_singleton, "[]=", "global_variable_set");
341
+ rb_define_alias(gvars_singleton, "alias", "alias_global_variable");
342
+ rb_define_alias(gvars_singleton, "list", "global_variables");
343
+ rb_define_alias(gvars_singleton, "virtual", "define_virtual_method");
63
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.0"
4
+ VERSION = '0.9.7'
5
5
  end
data/lib/gvars.rb CHANGED
@@ -4,12 +4,19 @@ require_relative "gvars/version"
4
4
  require_relative "gvars/gvars"
5
5
 
6
6
  module GVars
7
- class << self
8
- alias get global_variable_get
9
- alias [] global_variable_get
10
- alias set global_variable_set
11
- alias []= global_variable_set
12
- alias alias alias_global_variable
13
- alias list global_variables
7
+ =begin
8
+ # TODO: make this non-eval; unfortunately, it's not easy to fully emulate right now. maybe in the future?
9
+ #
10
+ # NOTE: THIS DOESN'T SUPPORT `$_` or regex vars!
11
+ module_function def global_variable_defined?(key)
12
+ warn "GVArs.global_variable_defined? is currently experimental", category: :experimental, uplevel: 1
13
+ key = Symbol === key ? key : key.to_str.to_sym
14
+
15
+ unless key.match? /\A\$[[:alpha:]_][[:alnum:]_]*\z/
16
+ raise NameError, format("'%s' is not allowed as a global variable name", key)
17
+ end
18
+
19
+ !! eval "defined? #{key}"
14
20
  end
21
+ =end
15
22
  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.0
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