gvars 0.9.7 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f54223d6addde0cfe225b0894f2da28b43cfa6f679e786baceeee34aedf7238
4
- data.tar.gz: 3fcc088c1798d3f303825e4ca5167e11b787ffde7f359101426df82b6bde96f2
3
+ metadata.gz: 837ffc167909e2abe16ff54fdcd7bfbe4cb6dc0346f1c3e9037b17933f3b89a7
4
+ data.tar.gz: 9e36c6847244b578e63032468c2d94e7fff4f4e05c68cd3a1c126fc257a02b7c
5
5
  SHA512:
6
- metadata.gz: 98c348911582069c49ad6089837708b0479575ab2d176428d4099bb9c107cef7cadc8ce2173853268b4f442abd49385f63c7888ccb611aa9a4a7f5a94af4cdbf
7
- data.tar.gz: 37ef3ebeefa4f341dc70e0fc393147e6b8feadc40a29e3edc4b8f7624e5836354f47c4f6801c53fe9301b871882b9a0ed45e872a6931fa05d80f8bc3db061c6c
6
+ metadata.gz: 7e71e7a19371437156d14f1831045a6229b4fcd055cc82680309266c5ed20781ec030b78e591e38e4a7adb62633ceb98d5284ca69b8e40eb475ee4ea829ee269
7
+ data.tar.gz: f5cba137bad5f8d9db885f468df9bc147f89b7c0106653a409fd8aa5d32767a8fceba372b4a4c778bdf4161ae59c215dd2081cff250aeccfcf4c2c161658c1a9
data/ext/gvars/gvars.c CHANGED
@@ -7,7 +7,7 @@ VALUE gvars_module;
7
7
  //
8
8
  // for checking, it makes that `name` starts with `$`. This isn't really required, as ruby supports
9
9
  // globals that don't start with `$` (but doesn't expose any methods to interact with them)
10
- static char *get_global_name(VALUE *name) {
10
+ static char *get_global_name(VALUE *name, bool raise) {
11
11
  // If `name` is a symbol, get its backing string
12
12
  if (RB_SYMBOL_P(*name)) {
13
13
  *name = rb_sym2str(*name);
@@ -16,7 +16,7 @@ static char *get_global_name(VALUE *name) {
16
16
  char *namestr = StringValueCStr(*name);
17
17
 
18
18
  // Ensure it starts with a dollar sign
19
- if (namestr[0] != '$') {
19
+ if (raise && namestr[0] != '$') {
20
20
  rb_raise(rb_eNameError, "'%s' is not allowed as a global variable name", namestr);
21
21
  }
22
22
 
@@ -27,13 +27,26 @@ static char *get_global_name(VALUE *name) {
27
27
  static VALUE
28
28
  gvars_f_global_variable_get(VALUE self, VALUE name)
29
29
  {
30
- 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));
31
37
  }
32
38
 
33
39
  static VALUE
34
40
  gvars_f_global_variable_set(VALUE self, VALUE name, VALUE value)
35
41
  {
36
- 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);
37
50
  }
38
51
 
39
52
  static VALUE
@@ -45,8 +58,8 @@ gvars_f_global_variables(VALUE self)
45
58
  static VALUE
46
59
  gvars_f_alias_global_variable(VALUE self, VALUE new, VALUE old)
47
60
  {
48
- ID newid = rb_intern(get_global_name(&new));
49
- 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)));
50
63
  return ID2SYM(newid);
51
64
  }
52
65
 
@@ -64,7 +77,7 @@ gvars_f_each(VALUE self)
64
77
  VALUE gvars = gvars_f_global_variables(self);
65
78
  for (long i = 0; i < RARRAY_LEN(gvars); i++) {
66
79
  VALUE key = RARRAY_AREF(gvars, i);
67
- rb_yield(rb_ary_new3(2, key, gvars_f_global_variable_get(self, key)));
80
+ rb_yield(rb_ary_new_from_args(2, key, gvars_f_global_variable_get(self, key)));
68
81
  }
69
82
 
70
83
  return self;
@@ -87,12 +100,13 @@ gvars_f_to_h(VALUE self)
87
100
  struct value_ptr { VALUE *value; };
88
101
  static void value_ptr_mark(void *ptr) { rb_gc_mark(*((struct value_ptr *) ptr)->value); }
89
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); }
90
104
  static const rb_data_type_t value_ptr_data_type = {
91
105
  .wrap_struct_name = "gvars/value_ptr",
92
106
  .function = {
93
107
  .dmark = value_ptr_mark,
94
108
  .dfree = value_ptr_free,
95
- .dsize = NULL // todo: not 0
109
+ .dsize = value_ptr_size,
96
110
  },
97
111
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
98
112
  };
@@ -104,21 +118,21 @@ struct gvars_virtual_var {
104
118
 
105
119
  static void gvars_virtual_var_mark(void *ptr) {
106
120
  struct gvars_virtual_var *gv = ptr;
107
- if (gv->backing != Qundef) rb_gc_mark(gv->backing);
121
+ rb_gc_mark(gv->backing);
108
122
  rb_gc_mark(gv->getter);
109
123
  rb_gc_mark(gv->setter);
110
124
  }
111
125
 
112
- static void gvars_virtual_var_free(void *ptr) {
113
- xfree(ptr);
126
+ static size_t gvars_virtual_var_size(const void *ptr) {
127
+ return sizeof(struct gvars_virtual_var);
114
128
  }
115
129
 
116
130
  static const rb_data_type_t gvars_type = {
117
- .wrap_struct_name = "gvars_var",
131
+ .wrap_struct_name = "gvars/var",
118
132
  .function = {
119
133
  .dmark = gvars_virtual_var_mark,
120
- .dfree = gvars_virtual_var_free,
121
- .dsize = NULL
134
+ .dfree = RUBY_DEFAULT_FREE,
135
+ .dsize = gvars_virtual_var_size,
122
136
  },
123
137
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
124
138
  };
@@ -127,61 +141,39 @@ static const rb_data_type_t gvars_type = {
127
141
  static VALUE gvars_virtual_var_getter(ID id, VALUE *data) {
128
142
  struct gvars_virtual_var *gv;
129
143
  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);
144
+ return rb_proc_call(gv->getter, rb_ary_new());
132
145
  }
133
146
 
134
147
  static void gvars_virtual_var_setter(VALUE val, ID id, VALUE *data) {
135
148
  struct gvars_virtual_var *gv;
136
149
  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);
150
+ rb_proc_call(gv->setter, rb_ary_new_from_args(1, val));
139
151
  }
140
152
 
141
153
  static VALUE gvars_hooked_state_var_getter(ID id, VALUE *data) {
142
154
  struct gvars_virtual_var *gv;
143
155
  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);
156
+ return rb_proc_call(gv->getter, rb_ary_new_from_args(1, gv->backing));
160
157
  }
161
158
 
162
159
  static VALUE gvars_hooked_initial_var_getter(ID id, VALUE *data) {
163
160
  struct gvars_virtual_var *gv;
164
161
  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;
162
+ return gv->backing = rb_proc_call(gv->getter, rb_ary_new_from_args(1, gv->backing));
168
163
  }
169
164
 
170
- static void gvars_hooked_initial_var_setter_noproc(VALUE val, ID id, VALUE *data) {
165
+ static void gvars_hooked_var_setter_noproc(VALUE val, ID id, VALUE *data) {
171
166
  struct gvars_virtual_var *gv;
172
167
  TypedData_Get_Struct(*data, struct gvars_virtual_var, &gvars_type, gv);
173
-
174
168
  gv->backing = val;
175
169
  }
176
170
 
177
- static void gvars_hooked_initial_var_setter_proc(VALUE val, ID id, VALUE *data) {
171
+ static void gvars_hooked_var_setter_proc(VALUE val, ID id, VALUE *data) {
178
172
  struct gvars_virtual_var *gv;
179
173
  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);
174
+ gv->backing = rb_proc_call(gv->setter, rb_ary_new_from_args(2, val, gv->backing));
182
175
  }
183
176
 
184
-
185
177
  static VALUE gvars_virtual_var_alloc(VALUE backing, VALUE getter, VALUE setter) {
186
178
  struct gvars_virtual_var *gv;
187
179
  VALUE gvar_ty = TypedData_Make_Struct(rb_cObject, struct gvars_virtual_var, &gvars_type, gv);
@@ -200,23 +192,7 @@ enum virtual_kind {
200
192
  static void
201
193
  gvars_define_virtual_method(VALUE self, VALUE *name, VALUE backing, VALUE getter, VALUE setter, enum virtual_kind kind, int readonly_special)
202
194
  {
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
-
195
+ char *name_str = get_global_name(name, true);
220
196
  struct value_ptr *vp;
221
197
  VALUE vp_data = TypedData_Make_Struct(rb_cObject, struct value_ptr, &value_ptr_data_type, vp);
222
198
  vp->value = RB_ALLOC(VALUE);
@@ -228,40 +204,51 @@ gvars_define_virtual_method(VALUE self, VALUE *name, VALUE backing, VALUE getter
228
204
  switch (kind) {
229
205
  case GVARS_VIRTUAL_KIND_VIRTUAL:
230
206
  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;
207
+ setter_meth = setter == Qnil ? rb_gvar_readonly_setter : gvars_virtual_var_setter;
237
208
  break;
238
209
 
239
210
  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;
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;
242
215
  break;
243
216
 
244
217
  default:
245
218
  rb_bug("oops");
246
219
  }
247
220
 
248
- if (readonly_special) setter_meth = rb_gvar_readonly_setter;
249
221
 
250
222
  rb_define_hooked_variable(name_str, vp->value, getter_meth, setter_meth);
251
223
 
252
- VALUE hash = rb_iv_get(gvars_module, "@vars");
224
+ VALUE hash = rb_iv_get(gvars_module, "vars");
253
225
  VALUE namesym = rb_str_new_cstr(name_str);
254
226
  rb_hash_aset(hash, namesym, vp_data);
255
227
  }
256
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
+
257
248
  static VALUE
258
249
  gvars_f_define_virtual_method(int argc, VALUE *argv, VALUE self)
259
250
  {
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");
251
+ VALUE name, backing, getter, setter, opts_hash, opts[LENGTH_OF_VIRTUAL_METHOD_KEYWORDS];
265
252
 
266
253
  switch (rb_scan_args(argc, argv, "12:", &name, &getter, &setter, &opts_hash)) {
267
254
  case 1:
@@ -281,22 +268,28 @@ gvars_f_define_virtual_method(int argc, VALUE *argv, VALUE self)
281
268
  rb_bug("oops");
282
269
  }
283
270
 
271
+ getter = convert_to_proc("getter", getter);
272
+ if (!NIL_P(setter)) setter = convert_to_proc("setter", setter);
273
+
284
274
  enum virtual_kind kind = GVARS_VIRTUAL_KIND_VIRTUAL;
285
- rb_get_kwargs(opts_hash, keyword_ids, 0, 3, opts);
275
+ rb_get_kwargs(opts_hash, virtual_method_keyword_ids, 0, LENGTH_OF_VIRTUAL_METHOD_KEYWORDS, opts);
286
276
 
287
- if (opts[0] != Qundef) {
288
- if (opts[1] != Qundef) {
277
+ if (opts[VIRTUAL_METHOD_KEYWORDS_INITIAL] != Qundef) {
278
+ if (opts[VIRTUAL_METHOD_KEYWORDS_STATE] != Qundef) {
289
279
  rb_raise(rb_eArgError, "only one of 'initial' or 'state' may be supplied");
290
280
  }
291
- backing = opts[0];
281
+ backing = opts[VIRTUAL_METHOD_KEYWORDS_INITIAL];
292
282
  kind = GVARS_VIRTUAL_KIND_INITIAL;
293
- } else if (opts[1] != Qundef) {
294
- backing = opts[1];
283
+ } else if (opts[VIRTUAL_METHOD_KEYWORDS_STATE] != Qundef) {
284
+ backing = opts[VIRTUAL_METHOD_KEYWORDS_STATE];
295
285
  kind = GVARS_VIRTUAL_KIND_STATE;
286
+ } else {
287
+ backing = Qnil;
296
288
  }
297
289
 
298
- bool is_readonly = false;
299
- if (opts[2] != Qundef && RTEST(opts[2])) { // sadly no bool expected :-/
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) {
300
293
  if (setter != Qnil) {
301
294
  rb_raise(rb_eArgError, "'readonly: true' may not be supplied when a setter proc is supplied");
302
295
  }
@@ -314,7 +307,11 @@ void
314
307
  Init_gvars(void)
315
308
  {
316
309
  gvars_module = rb_define_module("GVars");
317
- rb_ivar_set(gvars_module, rb_intern("@vars"), rb_hash_new());
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");
318
315
 
319
316
  // Define module-level functions that can be used as mixins
320
317
  rb_define_module_function(gvars_module, "global_variable_get", gvars_f_global_variable_get, 1);
@@ -332,12 +329,13 @@ Init_gvars(void)
332
329
  rb_define_singleton_method(gvars_module, "each", gvars_f_each, 0);
333
330
  rb_define_singleton_method(gvars_module, "to_h", gvars_f_to_h, 0);
334
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
+
335
335
  // Aliases
336
336
  VALUE gvars_singleton = rb_singleton_class(gvars_module);
337
337
  rb_define_alias(gvars_singleton, "get", "global_variable_get");
338
- rb_define_alias(gvars_singleton, "[]", "global_variable_get");
339
338
  rb_define_alias(gvars_singleton, "set", "global_variable_set");
340
- rb_define_alias(gvars_singleton, "[]=", "global_variable_set");
341
339
  rb_define_alias(gvars_singleton, "alias", "alias_global_variable");
342
340
  rb_define_alias(gvars_singleton, "list", "global_variables");
343
341
  rb_define_alias(gvars_singleton, "virtual", "define_virtual_method");
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.7'
4
+ VERSION = '0.9.8'
5
5
  end
data/tmp.rb CHANGED
@@ -1,6 +1,27 @@
1
1
  require 'gvars'
2
2
  p GVars::VERSION
3
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
+
4
25
  100.times do
5
26
  GVars.virtual(:$foo) { p "bar" }
6
27
  # GVars.virtual(:$foo) { p "foo" }
@@ -20,8 +41,26 @@ fail unless 11 == $bar1
20
41
 
21
42
  GVars.virtual(:$bar2, state: 'a') { it.succ!.dup }
22
43
  fail unless ['b', 'c', 'd'] == [$bar2, $bar2, $bar2]
23
- $bar2 = 10
24
- fail unless 11 == $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
25
64
 
26
65
  # GVars.virtual(:$bar, proc{ p "bar" })
27
66
  # GVars.virtual(:$baz, proc{ p "bar" }, proc { p "baz: #{_1}"})
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.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Westerman
@@ -24,7 +24,6 @@ files:
24
24
  - Rakefile
25
25
  - ext/gvars/extconf.rb
26
26
  - ext/gvars/gvars.c
27
- - ext/gvars/gvars.c-old
28
27
  - gb
29
28
  - lib/gvars.rb
30
29
  - lib/gvars/version.rb
@@ -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
- }