swig-4.0.1-Fix-code-generated-for-Ruby-global-variables.patch 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. From 18a3ef391121d7c4d819448c929721fd1708b40b Mon Sep 17 00:00:00 2001
  2. From: Thomas Reitmayr <treitmayr@devbase.at>
  3. Date: Sun, 27 Oct 2019 21:41:03 +0100
  4. Subject: [PATCH] Fix code generated for Ruby global variables
  5. This commit fixes swig#1653 by creating a Ruby virtual variable
  6. for a C/c++ global variable when SWIG is invoked with the
  7. -globalmodule option.
  8. ---
  9. Doc/Manual/Ruby.html | 18 +++++++
  10. Examples/test-suite/common.mk | 2 +
  11. Examples/test-suite/global_immutable_vars.i | 24 +++++++++
  12. .../test-suite/global_immutable_vars_cpp.i | 24 +++++++++
  13. Examples/test-suite/ruby/Makefile.in | 4 ++
  14. .../ruby/global_immutable_vars_cpp_runme.rb | 47 +++++++++++++++++
  15. .../ruby/global_immutable_vars_runme.rb | 51 +++++++++++++++++++
  16. .../ruby_global_immutable_vars_cpp_runme.rb | 47 +++++++++++++++++
  17. .../ruby/ruby_global_immutable_vars_runme.rb | 51 +++++++++++++++++++
  18. .../test-suite/ruby_global_immutable_vars.i | 25 +++++++++
  19. .../ruby_global_immutable_vars_cpp.i | 23 +++++++++
  20. Source/Modules/ruby.cxx | 36 +++++++++----
  21. 12 files changed, 342 insertions(+), 10 deletions(-)
  22. create mode 100644 Examples/test-suite/global_immutable_vars.i
  23. create mode 100644 Examples/test-suite/global_immutable_vars_cpp.i
  24. create mode 100644 Examples/test-suite/ruby/global_immutable_vars_cpp_runme.rb
  25. create mode 100644 Examples/test-suite/ruby/global_immutable_vars_runme.rb
  26. create mode 100644 Examples/test-suite/ruby/ruby_global_immutable_vars_cpp_runme.rb
  27. create mode 100644 Examples/test-suite/ruby/ruby_global_immutable_vars_runme.rb
  28. create mode 100644 Examples/test-suite/ruby_global_immutable_vars.i
  29. create mode 100644 Examples/test-suite/ruby_global_immutable_vars_cpp.i
  30. diff --git a/Doc/Manual/Ruby.html b/Doc/Manual/Ruby.html
  31. index 3cfd1292ca..6939a8a186 100644
  32. --- a/Doc/Manual/Ruby.html
  33. +++ b/Doc/Manual/Ruby.html
  34. @@ -615,6 +615,24 @@ <H3><a name="Ruby_nn14">34.3.3 Variable Linking</a></H3>
  35. effect until it is explicitly disabled using <tt>%mutable</tt>.
  36. </p>
  37. +<p>Note: When SWIG is invoked with the <tt>-globalmodule</tt> option in
  38. +effect, the C/C++ global variables will be translated into Ruby global
  39. +variables. Type-checking and the optional read-only characteristic are
  40. +available in the same way as described above. However the example would
  41. +then have to be modified and executed in the following way:
  42. +
  43. +<div class="code targetlang">
  44. +<pre>$ <b>irb</b>
  45. +irb(main):001:0&gt; <b>require 'Example'</b>
  46. +true
  47. +irb(main):002:0&gt; <b>$variable1 = 2</b>
  48. +2
  49. +irb(main):003:0&gt; <b>$Variable2 = 4 * 10.3</b>
  50. +41.2
  51. +irb(main):004:0&gt; <b>$Variable2</b>
  52. +41.2</pre>
  53. +</div>
  54. +
  55. <H3><a name="Ruby_nn15">34.3.4 Constants</a></H3>
  56. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
  57. index 5f77928102..008916a561 100644
  58. --- a/Examples/test-suite/common.mk
  59. +++ b/Examples/test-suite/common.mk
  60. @@ -250,6 +250,7 @@ CPP_TEST_CASES += \
  61. funcptr_cpp \
  62. functors \
  63. fvirtual \
  64. + global_immutable_vars_cpp \
  65. global_namespace \
  66. global_ns_arg \
  67. global_scope_types \
  68. @@ -689,6 +690,7 @@ C_TEST_CASES += \
  69. funcptr \
  70. function_typedef \
  71. global_functions \
  72. + global_immutable_vars \
  73. immutable_values \
  74. inctest \
  75. infinity \
  76. diff --git a/Examples/test-suite/global_immutable_vars.i b/Examples/test-suite/global_immutable_vars.i
  77. new file mode 100644
  78. index 0000000000..cd8cb184ba
  79. --- /dev/null
  80. +++ b/Examples/test-suite/global_immutable_vars.i
  81. @@ -0,0 +1,24 @@
  82. +%module global_immutable_vars
  83. +
  84. +// Test immutable and mutable global variables,
  85. +// see http://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIG_readonly_variables
  86. +
  87. +%inline %{
  88. + int default_mutable_var = 40;
  89. +%}
  90. +
  91. +%immutable;
  92. +%feature("immutable", "0") specific_mutable_var;
  93. +
  94. +%inline %{
  95. + int global_immutable_var = 41;
  96. + int specific_mutable_var = 42;
  97. +%}
  98. +
  99. +%mutable;
  100. +%immutable specific_immutable_var;
  101. +%inline %{
  102. + int global_mutable_var = 43;
  103. + int specific_immutable_var = 44;
  104. +%}
  105. +
  106. diff --git a/Examples/test-suite/global_immutable_vars_cpp.i b/Examples/test-suite/global_immutable_vars_cpp.i
  107. new file mode 100644
  108. index 0000000000..66eb8545d2
  109. --- /dev/null
  110. +++ b/Examples/test-suite/global_immutable_vars_cpp.i
  111. @@ -0,0 +1,24 @@
  112. +%module global_immutable_vars_cpp
  113. +
  114. +// Test immutable and mutable global variables,
  115. +// see http://www.swig.org/Doc4.0/SWIGDocumentation.html#SWIG_readonly_variables
  116. +
  117. +%inline %{
  118. + int default_mutable_var = 40;
  119. +%}
  120. +
  121. +%immutable;
  122. +%feature("immutable", "0") specific_mutable_var;
  123. +
  124. +%inline %{
  125. + int global_immutable_var = 41;
  126. + int specific_mutable_var = 42;
  127. +%}
  128. +
  129. +%mutable;
  130. +%immutable specific_immutable_var;
  131. +%inline %{
  132. + int global_mutable_var = 43;
  133. + int specific_immutable_var = 44;
  134. +%}
  135. +
  136. diff --git a/Examples/test-suite/ruby/Makefile.in b/Examples/test-suite/ruby/Makefile.in
  137. index d75cdb0587..2c59029ec0 100644
  138. --- a/Examples/test-suite/ruby/Makefile.in
  139. +++ b/Examples/test-suite/ruby/Makefile.in
  140. @@ -23,6 +23,7 @@ CPP_TEST_CASES = \
  141. li_std_wstring_inherit \
  142. primitive_types \
  143. ruby_alias_method \
  144. + ruby_global_immutable_vars_cpp \
  145. ruby_keywords \
  146. ruby_minherit_shared_ptr \
  147. ruby_naming \
  148. @@ -48,6 +49,7 @@ C_TEST_CASES += \
  149. li_cstring \
  150. ruby_alias_global_function \
  151. ruby_alias_module_function \
  152. + ruby_global_immutable_vars \
  153. ruby_manual_proxy \
  154. include $(srcdir)/../common.mk
  155. @@ -57,6 +59,8 @@ SWIGOPT += -w801 -noautorename -features autodoc=4
  156. # Custom tests - tests with additional commandline options
  157. ruby_alias_global_function.ctest: SWIGOPT += -globalmodule
  158. +ruby_global_immutable_vars.ctest: SWIGOPT += -globalmodule
  159. +ruby_global_immutable_vars_cpp.cpptest: SWIGOPT += -globalmodule
  160. ruby_naming.cpptest: SWIGOPT += -autorename
  161. # Rules for the different types of tests
  162. diff --git a/Examples/test-suite/ruby/global_immutable_vars_cpp_runme.rb b/Examples/test-suite/ruby/global_immutable_vars_cpp_runme.rb
  163. new file mode 100644
  164. index 0000000000..c40896a867
  165. --- /dev/null
  166. +++ b/Examples/test-suite/ruby/global_immutable_vars_cpp_runme.rb
  167. @@ -0,0 +1,47 @@
  168. +#!/usr/bin/env ruby
  169. +#
  170. +# C++ version of global_immutable_vars_runme.rb
  171. +#
  172. +
  173. +require 'swig_assert'
  174. +
  175. +require 'global_immutable_vars_cpp'
  176. +
  177. +# first check if all variables can be read
  178. +swig_assert_each_line( <<EOF )
  179. +Global_immutable_vars_cpp::default_mutable_var == 40
  180. +Global_immutable_vars_cpp::global_immutable_var == 41
  181. +Global_immutable_vars_cpp::specific_mutable_var == 42
  182. +Global_immutable_vars_cpp::global_mutable_var == 43
  183. +Global_immutable_vars_cpp::specific_immutable_var == 44
  184. +EOF
  185. +
  186. +# check that all mutable variables can be modified
  187. +swig_assert_each_line( <<EOF )
  188. +Global_immutable_vars_cpp::default_mutable_var = 80
  189. +Global_immutable_vars_cpp::default_mutable_var == 80
  190. +Global_immutable_vars_cpp::specific_mutable_var = 82
  191. +Global_immutable_vars_cpp::specific_mutable_var == 82
  192. +Global_immutable_vars_cpp::global_mutable_var = 83
  193. +Global_immutable_vars_cpp::global_mutable_var == 83
  194. +EOF
  195. +
  196. +# now check that immutable variables cannot be modified
  197. +had_exception = false
  198. +begin
  199. + Global_immutable_vars_cpp::global_immutable_var = 81
  200. +rescue NoMethodError => e
  201. + had_exception = true
  202. +end
  203. +swig_assert(had_exception, nil,
  204. + "Global_immutable_vars_cpp::global_immutable_var is writable (expected to be immutable)")
  205. +
  206. +had_exception = false
  207. +begin
  208. + Global_immutable_vars_cpp::specific_immutable_var = 81
  209. +rescue NoMethodError => e
  210. + had_exception = true
  211. +end
  212. +swig_assert(had_exception, nil,
  213. + "Global_immutable_vars_cpp::specific_immutable_var is writable (expected to be immutable)")
  214. +
  215. diff --git a/Examples/test-suite/ruby/global_immutable_vars_runme.rb b/Examples/test-suite/ruby/global_immutable_vars_runme.rb
  216. new file mode 100644
  217. index 0000000000..af55cfeb34
  218. --- /dev/null
  219. +++ b/Examples/test-suite/ruby/global_immutable_vars_runme.rb
  220. @@ -0,0 +1,51 @@
  221. +#!/usr/bin/env ruby
  222. +#
  223. +# Here the proper generation of mutable and immutable variables is tested
  224. +# in the target language.
  225. +# Immutable variables do not have "<var>=" methods generated by SWIG,
  226. +# therefore trying to assign these variables shall throw a NoMethodError
  227. +# exception.
  228. +#
  229. +
  230. +require 'swig_assert'
  231. +
  232. +require 'global_immutable_vars'
  233. +
  234. +# first check if all variables can be read
  235. +swig_assert_each_line( <<EOF )
  236. +Global_immutable_vars::default_mutable_var == 40
  237. +Global_immutable_vars::global_immutable_var == 41
  238. +Global_immutable_vars::specific_mutable_var == 42
  239. +Global_immutable_vars::global_mutable_var == 43
  240. +Global_immutable_vars::specific_immutable_var == 44
  241. +EOF
  242. +
  243. +# check that all mutable variables can be modified
  244. +swig_assert_each_line( <<EOF )
  245. +Global_immutable_vars::default_mutable_var = 80
  246. +Global_immutable_vars::default_mutable_var == 80
  247. +Global_immutable_vars::specific_mutable_var = 82
  248. +Global_immutable_vars::specific_mutable_var == 82
  249. +Global_immutable_vars::global_mutable_var = 83
  250. +Global_immutable_vars::global_mutable_var == 83
  251. +EOF
  252. +
  253. +# now check that immutable variables cannot be modified
  254. +had_exception = false
  255. +begin
  256. + Global_immutable_vars::global_immutable_var = 81
  257. +rescue NoMethodError => e
  258. + had_exception = true
  259. +end
  260. +swig_assert(had_exception, nil,
  261. + "Global_immutable_vars::global_immutable_var is writable (expected to be immutable)")
  262. +
  263. +had_exception = false
  264. +begin
  265. + Global_immutable_vars::specific_immutable_var = 81
  266. +rescue NoMethodError => e
  267. + had_exception = true
  268. +end
  269. +swig_assert(had_exception, nil,
  270. + "Global_immutable_vars::specific_immutable_var is writable (expected to be immutable)")
  271. +
  272. diff --git a/Examples/test-suite/ruby/ruby_global_immutable_vars_cpp_runme.rb b/Examples/test-suite/ruby/ruby_global_immutable_vars_cpp_runme.rb
  273. new file mode 100644
  274. index 0000000000..8453254eb3
  275. --- /dev/null
  276. +++ b/Examples/test-suite/ruby/ruby_global_immutable_vars_cpp_runme.rb
  277. @@ -0,0 +1,47 @@
  278. +#!/usr/bin/env ruby
  279. +#
  280. +# C++ version of ruby_global_immutable_vars_runme.rb.
  281. +#
  282. +
  283. +require 'swig_assert'
  284. +
  285. +require 'ruby_global_immutable_vars_cpp'
  286. +
  287. +# first check if all variables can be read
  288. +swig_assert_each_line( <<EOF )
  289. +$default_mutable_var == 40
  290. +$global_immutable_var == 41
  291. +$specific_mutable_var == 42
  292. +$global_mutable_var == 43
  293. +$specific_immutable_var == 44
  294. +EOF
  295. +
  296. +# check that all mutable variables can be modified
  297. +swig_assert_each_line( <<EOF )
  298. +$default_mutable_var = 80
  299. +$default_mutable_var == 80
  300. +$specific_mutable_var = 82
  301. +$specific_mutable_var == 82
  302. +$global_mutable_var = 83
  303. +$global_mutable_var == 83
  304. +EOF
  305. +
  306. +# now check that immutable variables cannot be modified
  307. +had_exception = false
  308. +begin
  309. + $global_immutable_var = 81
  310. +rescue NameError => e
  311. + had_exception = true
  312. +end
  313. +swig_assert(had_exception, nil,
  314. + "$global_immutable_var is writable (expected to be immutable)")
  315. +
  316. +had_exception = false
  317. +begin
  318. + $specific_immutable_var = 81
  319. +rescue NameError => e
  320. + had_exception = true
  321. +end
  322. +swig_assert(had_exception, nil,
  323. + "$specific_immutable_var is writable (expected to be immutable)")
  324. +
  325. diff --git a/Examples/test-suite/ruby/ruby_global_immutable_vars_runme.rb b/Examples/test-suite/ruby/ruby_global_immutable_vars_runme.rb
  326. new file mode 100644
  327. index 0000000000..fda1ccf0f0
  328. --- /dev/null
  329. +++ b/Examples/test-suite/ruby/ruby_global_immutable_vars_runme.rb
  330. @@ -0,0 +1,51 @@
  331. +#!/usr/bin/env ruby
  332. +#
  333. +# This test program is similar to global_immutable_vars_runme.rb
  334. +# with the difference that the global variables to check are also
  335. +# Ruby global variables (SWIG Ruby option "-globalmodule").
  336. +#
  337. +# Immutable global variables shall throw a NameError exception.
  338. +#
  339. +
  340. +require 'swig_assert'
  341. +
  342. +require 'ruby_global_immutable_vars'
  343. +
  344. +# first check if all variables can be read
  345. +swig_assert_each_line( <<EOF )
  346. +$default_mutable_var == 40
  347. +$global_immutable_var == 41
  348. +$specific_mutable_var == 42
  349. +$global_mutable_var == 43
  350. +$specific_immutable_var == 44
  351. +EOF
  352. +
  353. +# check that all mutable variables can be modified
  354. +swig_assert_each_line( <<EOF )
  355. +$default_mutable_var = 80
  356. +$default_mutable_var == 80
  357. +$specific_mutable_var = 82
  358. +$specific_mutable_var == 82
  359. +$global_mutable_var = 83
  360. +$global_mutable_var == 83
  361. +EOF
  362. +
  363. +# now check that immutable variables cannot be modified
  364. +had_exception = false
  365. +begin
  366. + $global_immutable_var = 81
  367. +rescue NameError => e
  368. + had_exception = true
  369. +end
  370. +swig_assert(had_exception, nil,
  371. + "$global_immutable_var is writable (expected to be immutable)")
  372. +
  373. +had_exception = false
  374. +begin
  375. + $specific_immutable_var = 81
  376. +rescue NameError => e
  377. + had_exception = true
  378. +end
  379. +swig_assert(had_exception, nil,
  380. + "$specific_immutable_var is writable (expected to be immutable)")
  381. +
  382. diff --git a/Examples/test-suite/ruby_global_immutable_vars.i b/Examples/test-suite/ruby_global_immutable_vars.i
  383. new file mode 100644
  384. index 0000000000..dc49cd9467
  385. --- /dev/null
  386. +++ b/Examples/test-suite/ruby_global_immutable_vars.i
  387. @@ -0,0 +1,25 @@
  388. +%module ruby_global_immutable_vars
  389. +
  390. +// This copy of global_immutable_vars.i shall be compiled with the
  391. +// SWIG Ruby option "-globalmodule" in order to check the code path
  392. +// for registering global methods (in contrast to module methods).
  393. +
  394. +%inline %{
  395. + int default_mutable_var = 40;
  396. +%}
  397. +
  398. +%immutable;
  399. +%feature("immutable", "0") specific_mutable_var;
  400. +
  401. +%inline %{
  402. + int global_immutable_var = 41;
  403. + int specific_mutable_var = 42;
  404. +%}
  405. +
  406. +%mutable;
  407. +%immutable specific_immutable_var;
  408. +%inline %{
  409. + int global_mutable_var = 43;
  410. + int specific_immutable_var = 44;
  411. +%}
  412. +
  413. diff --git a/Examples/test-suite/ruby_global_immutable_vars_cpp.i b/Examples/test-suite/ruby_global_immutable_vars_cpp.i
  414. new file mode 100644
  415. index 0000000000..cf3145e801
  416. --- /dev/null
  417. +++ b/Examples/test-suite/ruby_global_immutable_vars_cpp.i
  418. @@ -0,0 +1,23 @@
  419. +%module ruby_global_immutable_vars_cpp
  420. +
  421. +// C++ version of ruby_global_immutable_vars.i
  422. +
  423. +%inline %{
  424. + int default_mutable_var = 40;
  425. +%}
  426. +
  427. +%immutable;
  428. +%feature("immutable", "0") specific_mutable_var;
  429. +
  430. +%inline %{
  431. + int global_immutable_var = 41;
  432. + int specific_mutable_var = 42;
  433. +%}
  434. +
  435. +%mutable;
  436. +%immutable specific_immutable_var;
  437. +%inline %{
  438. + int global_mutable_var = 43;
  439. + int specific_immutable_var = 44;
  440. +%}
  441. +
  442. diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx
  443. index 6a1e16d5da..c8f582679b 100644
  444. --- a/Source/Modules/ruby.cxx
  445. +++ b/Source/Modules/ruby.cxx
  446. @@ -2192,6 +2192,11 @@ class RUBY:public Language {
  447. String *getfname, *setfname;
  448. Wrapper *getf, *setf;
  449. + // Determine whether virtual global variables shall be used
  450. + // which have different getter and setter signatures,
  451. + // see https://docs.ruby-lang.org/en/2.6.0/extension_rdoc.html#label-Global+Variables+Shared+Between+C+and+Ruby
  452. + const bool use_virtual_var = (current == NO_CPP && useGlobalModule);
  453. +
  454. getf = NewWrapper();
  455. setf = NewWrapper();
  456. @@ -2201,7 +2206,7 @@ class RUBY:public Language {
  457. getfname = Swig_name_wrapper(getname);
  458. Setattr(n, "wrap:name", getfname);
  459. Printv(getf->def, "SWIGINTERN VALUE\n", getfname, "(", NIL);
  460. - Printf(getf->def, "VALUE self");
  461. + Printf(getf->def, (use_virtual_var) ? "ID id" : "VALUE self");
  462. Printf(getf->def, ") {");
  463. Wrapper_add_local(getf, "_val", "VALUE _val");
  464. @@ -2235,8 +2240,12 @@ class RUBY:public Language {
  465. String *setname = Swig_name_set(NSPACE_TODO, iname);
  466. setfname = Swig_name_wrapper(setname);
  467. Setattr(n, "wrap:name", setfname);
  468. - Printv(setf->def, "SWIGINTERN VALUE\n", setfname, "(VALUE self, ", NIL);
  469. - Printf(setf->def, "VALUE _val) {");
  470. + Printf(setf->def, "SWIGINTERN ");
  471. + if (use_virtual_var) {
  472. + Printv(setf->def, "void\n", setfname, "(VALUE _val, ID id) {", NIL);
  473. + } else {
  474. + Printv(setf->def, "VALUE\n", setfname, "(VALUE self, VALUE _val) {", NIL);
  475. + }
  476. tm = Swig_typemap_lookup("varin", n, name, 0);
  477. if (tm) {
  478. Replaceall(tm, "$input", "_val");
  479. @@ -2247,9 +2256,14 @@ class RUBY:public Language {
  480. } else {
  481. Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s\n", SwigType_str(t, 0));
  482. }
  483. - Printv(setf->code, tab4, "return _val;\n", NIL);
  484. - Printf(setf->code, "fail:\n");
  485. - Printv(setf->code, tab4, "return Qnil;\n", NIL);
  486. + if (use_virtual_var) {
  487. + Printf(setf->code, "fail:\n");
  488. + Printv(setf->code, tab4, "return;\n", NIL);
  489. + } else {
  490. + Printv(setf->code, tab4, "return _val;\n", NIL);
  491. + Printf(setf->code, "fail:\n");
  492. + Printv(setf->code, tab4, "return Qnil;\n", NIL);
  493. + }
  494. Printf(setf->code, "}\n");
  495. Wrapper_print(setf, f_wrappers);
  496. Delete(setname);
  497. @@ -2259,7 +2273,7 @@ class RUBY:public Language {
  498. if (CPlusPlus) {
  499. Insert(getfname, 0, "VALUEFUNC(");
  500. Append(getfname, ")");
  501. - Insert(setfname, 0, "VALUEFUNC(");
  502. + Insert(setfname, 0, (use_virtual_var) ? "(void (*)(ANYARGS))(" : "VALUEFUNC(");
  503. Append(setfname, ")");
  504. }
  505. @@ -2283,9 +2297,11 @@ class RUBY:public Language {
  506. Printv(s, tab4, "rb_define_singleton_method(", modvar, ", \"", iname, "=\", ", setfname, ", 1);\n", NIL);
  507. }
  508. } else {
  509. - Printv(s, tab4, "rb_define_global_method(\"", iname, "\", ", getfname, ", 0);\n", NIL);
  510. - if (!GetFlag(n, "feature:immutable")) {
  511. - Printv(s, tab4, "rb_define_global_method(\"", iname, "=\", ", setfname, ", 1);\n", NIL);
  512. + Printv(s, tab4, "rb_define_virtual_variable(\"$", iname, "\", ", getfname, ", ", NIL);
  513. + if (GetFlag(n, "feature:immutable")) {
  514. + Printv(s, tab4, "0);\n", NIL);
  515. + } else {
  516. + Printv(s, tab4, setfname, ");\n", NIL);
  517. }
  518. }
  519. Printv(f_init, s, NIL);