From 088a636192eee64d1850d1a834c47e861748fa3a Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Fri, 1 Jun 2018 16:11:53 +0900 Subject: [PATCH] allow private constructor. also add docopt example You can do this by setting: ``` def initialize(helix, ...) { } ``` Right now this only works on the constructor and only unexported is supported. --- Cargo.toml | 3 +- Rakefile | 4 +- crates/libcruby-sys/src/lib.rs | 6 +- examples/docopt/.gitignore | 3 + examples/docopt/Cargo.toml | 14 +++ examples/docopt/Gemfile | 6 ++ examples/docopt/Rakefile | 20 ++++ examples/docopt/lib/docopt.rb | 2 + examples/docopt/spec/docopt_spec.rb | 95 +++++++++++++++++++ examples/docopt/spec/spec_helper.rb | 5 + examples/docopt/src/lib.rs | 52 ++++++++++ examples/game_of_life/src/lib.rs | 2 + ruby/ext/helix_runtime/native/helix_runtime.c | 4 + ruby/ext/helix_runtime/native/helix_runtime.h | 2 + src/class_definition.rs | 6 ++ src/macros/codegen.rs | 3 + src/macros/init.rs | 26 +++++ src/macros/parser.rs | 51 ++++++++++ 18 files changed, 299 insertions(+), 5 deletions(-) create mode 100644 examples/docopt/.gitignore create mode 100644 examples/docopt/Cargo.toml create mode 100644 examples/docopt/Gemfile create mode 100755 examples/docopt/Rakefile create mode 100644 examples/docopt/lib/docopt.rb create mode 100644 examples/docopt/spec/docopt_spec.rb create mode 100644 examples/docopt/spec/spec_helper.rb create mode 100644 examples/docopt/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 0991b7d..c8a57bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,8 +20,7 @@ travis-ci = { repository = "tildeio/helix", branch = "master" } appveyor = { repository = "tildeio/helix", branch = "master", service = "github" } [workspace] - -members = ["examples/calculator", "examples/console", "examples/game_of_life", "examples/geometry", "examples/duration", "examples/membership", "examples/text_transform", "examples/turbo_blank", "examples/json_builder"] +members = ["examples/calculator", "examples/console", "examples/docopt", "examples/game_of_life", "examples/geometry", "examples/duration", "examples/membership", "examples/text_transform", "examples/turbo_blank", "examples/json_builder"] [dependencies] libc = "0.2.0" diff --git a/Rakefile b/Rakefile index 38a595e..c1dd089 100644 --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,7 @@ task :test do sh "bundle exec rake" end - examples = ENV["EXAMPLES"] || "duration calculator console game_of_life geometry membership text_transform turbo_blank json_builder" + examples = ENV["EXAMPLES"] || "duration calculator console docopt game_of_life geometry membership text_transform turbo_blank json_builder" sh "bash ./examples/runner default #{examples}" end @@ -15,7 +15,7 @@ task :install do sh "bundle" end - examples = ENV["EXAMPLES"] || "duration calculator console game_of_life geometry membership text_transform turbo_blank json_builder" + examples = ENV["EXAMPLES"] || "duration calculator console docopt game_of_life geometry membership text_transform turbo_blank json_builder" sh "bash ./examples/runner install #{examples}" end diff --git a/crates/libcruby-sys/src/lib.rs b/crates/libcruby-sys/src/lib.rs index 77e3c9a..ab9f071 100644 --- a/crates/libcruby-sys/src/lib.rs +++ b/crates/libcruby-sys/src/lib.rs @@ -167,6 +167,9 @@ extern "C" { #[link_name = "HELIX_OBJ_FROZEN"] pub fn OBJ_FROZEN(v: VALUE) -> bool; + #[link_name = "HELIX_CLASS_OF"] + pub fn CLASS_OF(v: VALUE) -> VALUE; + #[link_name = "HELIX_T_OBJECT"] pub static T_OBJECT: isize; @@ -210,9 +213,10 @@ extern "C" { pub fn rb_define_module_under(namespace: VALUE, name: c_string) -> VALUE; pub fn rb_define_class(name: c_string, superclass: VALUE) -> VALUE; pub fn rb_define_class_under(namespace: VALUE, name: c_string, superclass: VALUE) -> VALUE; - pub fn rb_define_alloc_func(klass: VALUE, func: extern "C" fn(klass: VALUE) -> VALUE); + pub fn rb_define_alloc_func(class: VALUE, func: extern "C" fn(class: VALUE) -> VALUE); pub fn rb_define_method(class: VALUE, name: c_string, func: c_func, arity: isize); pub fn rb_define_singleton_method(class: VALUE, name: c_string, func: c_func, arity: isize); + pub fn rb_undef_method(class: VALUE, name: c_string); pub fn rb_enc_get_index(obj: VALUE) -> isize; pub fn rb_utf8_encindex() -> isize; pub fn rb_sprintf(specifier: c_string, ...) -> VALUE; diff --git a/examples/docopt/.gitignore b/examples/docopt/.gitignore new file mode 100644 index 0000000..4268bc7 --- /dev/null +++ b/examples/docopt/.gitignore @@ -0,0 +1,3 @@ +target +*.bundle +*.gem diff --git a/examples/docopt/Cargo.toml b/examples/docopt/Cargo.toml new file mode 100644 index 0000000..d222861 --- /dev/null +++ b/examples/docopt/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "docopt" +version = "0.1.0" +authors = ["Godhuda "] + +[lib] + +crate-type = ["cdylib"] + +[dependencies.helix] +path = "../.." + +[dependencies] +docopt = "*" diff --git a/examples/docopt/Gemfile b/examples/docopt/Gemfile new file mode 100644 index 0000000..f0e95fa --- /dev/null +++ b/examples/docopt/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +gem 'helix_runtime', path: '../../ruby' +gem 'rake', '~> 10.0' +gem 'rspec', '~> 3.4' +gem 'colorize' diff --git a/examples/docopt/Rakefile b/examples/docopt/Rakefile new file mode 100755 index 0000000..a91d4ca --- /dev/null +++ b/examples/docopt/Rakefile @@ -0,0 +1,20 @@ +require 'bundler/setup' +require 'helix_runtime/build_task' +require 'rspec/core/rake_task' +require_relative '../shared.rb' + +# For Windows +$stdout.sync = true + +HelixRuntime::BuildTask.new do |t| + t.build_root = File.expand_path("../..", __dir__) + t.helix_lib_dir = File.expand_path("../../ruby/windows_build", __dir__) + t.pre_build = HelixRuntime::Tests.pre_build +end + +RSpec::Core::RakeTask.new(:spec) do |t| + t.verbose = false +end + +task :spec => :build +task :default => :spec diff --git a/examples/docopt/lib/docopt.rb b/examples/docopt/lib/docopt.rb new file mode 100644 index 0000000..852359e --- /dev/null +++ b/examples/docopt/lib/docopt.rb @@ -0,0 +1,2 @@ +require 'helix_runtime' +require 'docopt/native' diff --git a/examples/docopt/spec/docopt_spec.rb b/examples/docopt/spec/docopt_spec.rb new file mode 100644 index 0000000..1abcb22 --- /dev/null +++ b/examples/docopt/spec/docopt_spec.rb @@ -0,0 +1,95 @@ +require "spec_helper" +USAGE = <... + naval_fate ship move [--speed=] [--acc=] + naval_fate ship shoot + naval_fate mine (set|remove) [--moored | --drifting] + naval_fate (-h | --help) + naval_fate --version + naval_fate (-o | --option) + + Options: + -h --help Show this screen. + --version Show version. + --speed= Speed in knots [default: 10]. + --acc= Speed in knots per second. + --moored Moored (anchored) mine. + --drifting Drifting mine. + -o --option Test long and short option. +USAGE + +describe "Docopt" do + it "can not be constructed" do + expect { Docopt.new }.to raise_error(NoMethodError) + end + + it "should parse and return bools" do + argv = "naval_fate --help".split + + options = Docopt.parse(USAGE, argv) + expect(options["--help"]).to be true + end + + it "should parse strings" do + x = "1" + y = "2" + argv = "naval_fate ship shoot #{x} #{y}".split + + options = Docopt.parse(USAGE, argv) + expect(options["ship"]).to eq(true) + expect(options["shoot"]).to eq(true) + expect(options[""]).to eq(x) + expect(options[""]).to eq(y) + end + + it "should set short and long options are when provided" do + argv = "naval_fate -o".split + options = Docopt.parse(USAGE, argv) + expect(options["--option"]).to eq(true) + argv = "naval_fate --option".split + options = Docopt.parse(USAGE, argv) + expect(options["--option"]).to eq(true) + end + + it "should parse an array of strings" do + names = %w(enterprise mission) + argv = "naval_fate ship new #{names.join(" ")}".split + + options = Docopt.parse(USAGE, argv) + expect(options["ship"]).to eq(true) + expect(options[""]).to eq(names) + end + + it "should use default values" do + argv = "naval_fate ship foo move 0 0".split + + options = Docopt.parse(USAGE, argv) + expect(options["--speed"]).to eq("10") + end + + it "should return nil for unused options" do + argv = "naval_fate ship foo move 0 0".split + + options = Docopt.parse(USAGE, argv) + expect(options["--acc"]).to be_nil + end + + it "should handle complex cases" do + name = "enterprise" + x = "1" + y = "2" + speed = "10" + argv = "naval_fate ship #{name} move #{x} #{y} --speed=#{speed}".split + + options = Docopt.parse(USAGE, argv) + expect(options["ship"]).to eq(true) + expect(options["move"]).to eq(true) + expect(options[""]).to eq([name]) + expect(options[""]).to eq(x) + expect(options[""]).to eq(y) + expect(options["--speed"]).to eq(speed) + end +end diff --git a/examples/docopt/spec/spec_helper.rb b/examples/docopt/spec/spec_helper.rb new file mode 100644 index 0000000..ddc15eb --- /dev/null +++ b/examples/docopt/spec/spec_helper.rb @@ -0,0 +1,5 @@ +$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) +require 'docopt' + +RSpec.configure do |config| +end diff --git a/examples/docopt/src/lib.rs b/examples/docopt/src/lib.rs new file mode 100644 index 0000000..0cdbab9 --- /dev/null +++ b/examples/docopt/src/lib.rs @@ -0,0 +1,52 @@ +#![recursion_limit="1024"] + +#[macro_use] +extern crate helix; +extern crate docopt; + +use docopt::ArgvMap; +use helix::{ToRuby, ToRubyResult}; + +ruby! { + class Docopt { + struct { + options: ArgvMap, + } + + #[ruby_visibility=unexported] + def initialize(helix, options: ArgvMap) { + Docopt { helix, options } + } + + def parse(usage: String, argv: Vec) -> Result { + let result = docopt::Docopt::new(usage) + .and_then(|d| d.help(false).argv(argv.into_iter()).parse()); + + match result { + Ok(args) => Ok(Docopt::new(args)), + Err(error) => match error { + docopt::Error::WithProgramUsage(e, msg) => { + Err(format!("{}\n\n{}\n", e, msg)) + }, + e => { + Err(format!("{}", e)) + } + } + } + } + + #[ruby_name="[]"] + def get(&self, key: String) -> ToRubyResult { + match self.options.map.find(&key) { + None => ().to_ruby(), + Some(value) => match *value { + docopt::Value::Counted(uint) => uint.to_ruby(), + docopt::Value::Plain(None) => ().to_ruby(), + ref plain @ docopt::Value::Plain(Some(_)) => plain.as_str().to_ruby(), + ref switch @ docopt::Value::Switch(_) => switch.as_bool().to_ruby(), + ref list @ docopt::Value::List(_) => list.as_vec().to_ruby() + }, + } + } + } +} diff --git a/examples/game_of_life/src/lib.rs b/examples/game_of_life/src/lib.rs index 84ccc25..0bb3bd7 100644 --- a/examples/game_of_life/src/lib.rs +++ b/examples/game_of_life/src/lib.rs @@ -1,3 +1,5 @@ +#![recursion_limit="1024"] + #[macro_use] extern crate helix; extern crate rand; diff --git a/ruby/ext/helix_runtime/native/helix_runtime.c b/ruby/ext/helix_runtime/native/helix_runtime.c index dd2763e..48050aa 100644 --- a/ruby/ext/helix_runtime/native/helix_runtime.c +++ b/ruby/ext/helix_runtime/native/helix_runtime.c @@ -73,6 +73,10 @@ bool HELIX_rb_str_ascii_only_p(VALUE str) { return rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT; } +VALUE HELIX_CLASS_OF(VALUE v) { + return CLASS_OF(v); +} + VALUE HELIX_Data_Wrap_Struct(VALUE klass, HELIX_RUBY_DATA_FUNC mark, HELIX_RUBY_DATA_FUNC free, void* data) { return Data_Wrap_Struct(klass, mark, free, data); } diff --git a/ruby/ext/helix_runtime/native/helix_runtime.h b/ruby/ext/helix_runtime/native/helix_runtime.h index fb32100..39efddf 100644 --- a/ruby/ext/helix_runtime/native/helix_runtime.h +++ b/ruby/ext/helix_runtime/native/helix_runtime.h @@ -72,6 +72,8 @@ HELIX_EXTERN VALUE HELIX_rb_utf8_str_new(const char* str, long len); HELIX_EXTERN bool HELIX_rb_str_valid_encoding_p(VALUE str); HELIX_EXTERN bool HELIX_rb_str_ascii_only_p(VALUE str); +HELIX_EXTERN VALUE HELIX_CLASS_OF(VALUE v); + // typedef VALUE (*HELIX_rb_alloc_func_t)(VALUE); // void HELIX_rb_define_alloc_func(VALUE klass, HELIX_rb_alloc_func_t func); diff --git a/src/class_definition.rs b/src/class_definition.rs index a2d269b..b95f969 100644 --- a/src/class_definition.rs +++ b/src/class_definition.rs @@ -70,4 +70,10 @@ impl ClassDefinition { } } } + + pub fn undefine_class_method(&self, name: c_string) { + unsafe { + sys::rb_undef_method(sys::CLASS_OF(self.class.0), name); + } + } } diff --git a/src/macros/codegen.rs b/src/macros/codegen.rs index 8882993..c4a9dc9 100644 --- a/src/macros/codegen.rs +++ b/src/macros/codegen.rs @@ -165,6 +165,7 @@ macro_rules! codegen_method { type: initializer, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, self: { ownership: {}, name: $self:tt @@ -182,6 +183,7 @@ macro_rules! codegen_method { type: class_method, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, self: (), args: [ $($args:tt)* ], ret: { $($ret:tt)* }, @@ -196,6 +198,7 @@ macro_rules! codegen_method { type: instance_method, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, self: { ownership: { $($ownership:tt)* }, name: $self:tt diff --git a/src/macros/init.rs b/src/macros/init.rs index b991668..09a1d14 100644 --- a/src/macros/init.rs +++ b/src/macros/init.rs @@ -86,6 +86,7 @@ macro_rules! codegen_define_method { type: class_method, rust_name: $rust_name:tt, ruby_name: { $($ruby_name:tt)* }, + ruby_visibility: $ruby_visibility:tt, self: (), args: [ $($arg:tt : $argty:ty),* ], ret: { $($ret:tt)* }, @@ -141,6 +142,7 @@ macro_rules! codegen_define_method { type: instance_method, rust_name: $rust_name:tt, ruby_name: { $($ruby_name:tt)* }, + ruby_visibility: $ruby_visibility:tt, self: { ownership: { $($ownership:tt)* }, name: $self:tt }, args: [ $($arg:tt : $argty:ty),* ], ret: { $($ret:tt)* }, @@ -189,6 +191,29 @@ macro_rules! codegen_define_method { $def.define_method($crate::MethodDefinition::instance(name, method, arity)) }); + ($def:tt, { + type: class, + rust_name: $cls_rust_name:tt, + $($rest:tt)* + }, { + type: initializer, + rust_name: $rust_name:tt, + ruby_name: $ruby_name:tt, + ruby_visibility: unexported, + self: $self:tt, + args: [ $($arg:tt : $argty:ty),* ], + ret: { $($ret:tt)* }, + body: $body:tt + }) => ({ + impl $cls_rust_name { + pub fn new($($arg : $argty),*) -> $($ret)* { + $cls_rust_name::$rust_name(unsafe { $crate::sys::Qnil } , $($arg),*) + } + } + + $def.undefine_class_method(cstr!("new")) + }); + ($def:tt, { type: class, rust_name: $cls_rust_name:tt, @@ -200,6 +225,7 @@ macro_rules! codegen_define_method { type: initializer, rust_name: $rust_name:tt, ruby_name: { $($ruby_name:tt)* }, + ruby_visibility: $ruby_visibility:tt, self: { ownership: {}, name: $self:tt }, args: [ $($arg:tt : $argty:ty),* ], ret: { $($ret:tt)* }, diff --git a/src/macros/parser.rs b/src/macros/parser.rs index cd69127..b71832e 100644 --- a/src/macros/parser.rs +++ b/src/macros/parser.rs @@ -294,6 +294,7 @@ macro_rules! parse { stack: { rust_name: uninitialized, ruby_name: uninitialized, + ruby_visibility: public, $($stack)* } } @@ -301,6 +302,28 @@ macro_rules! parse { // STATE: parse_method_attributes + { + state: parse_method_attributes, + buffer: { #[ruby_visibility = $ruby_visibility:tt] $($rest:tt)* }, + stack: { + rust_name: uninitialized, + ruby_name: $ruby_name:tt, + ruby_visibility: public, + $($stack:tt)* + } + } => { + parse! { + state: parse_method_attributes, + buffer: { $($rest)* }, + stack: { + rust_name: uninitialized, + ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, + $($stack)* + } + } + }; + { state: parse_method_attributes, buffer: { #[ruby_name = $ruby_name:tt] $($rest:tt)* }, @@ -383,6 +406,7 @@ macro_rules! parse { stack: { rust_name: initialize, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class: $class:tt, $($stack:tt)* } @@ -394,6 +418,7 @@ macro_rules! parse { state: parse_arguments_initialize, buffer: { $($args)* }, stack: { + ruby_visibility: $ruby_visibility, class_body: { $($rest)* }, class: $class, $($stack)* @@ -407,6 +432,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, $($stack:tt)* } } => { @@ -416,6 +442,7 @@ macro_rules! parse { stack: { rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, class_body: { $($rest)* }, $($stack)* } @@ -428,6 +455,7 @@ macro_rules! parse { state: parse_arguments_initialize, buffer: { $helix_arg:tt, $($args:tt)+ }, stack: { + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -442,6 +470,7 @@ macro_rules! parse { type: initializer, rust_name: initialize, ruby_name: { "initialize" }, + ruby_visibility: $ruby_visibility, self: { ownership: { }, name: $helix_arg @@ -459,6 +488,7 @@ macro_rules! parse { state: parse_arguments_initialize, buffer: { $helix_arg:tt }, stack: { + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -473,6 +503,7 @@ macro_rules! parse { type: initializer, rust_name: initialize, ruby_name: { "initialize" }, + ruby_visibility: $ruby_visibility, self: { ownership: { }, name: $helix_arg @@ -494,6 +525,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -508,6 +540,7 @@ macro_rules! parse { type: instance_method, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: { ownership: { &mut }, name: $self_arg @@ -527,6 +560,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -541,6 +575,7 @@ macro_rules! parse { type: instance_method, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: { ownership: { &mut }, name: $self_arg @@ -560,6 +595,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -574,6 +610,7 @@ macro_rules! parse { type: instance_method, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: { ownership: { & }, name: $self_arg @@ -593,6 +630,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -607,6 +645,7 @@ macro_rules! parse { type: instance_method, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: { ownership: { & }, name: $self_arg @@ -626,6 +665,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -640,6 +680,7 @@ macro_rules! parse { type: instance_method, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: { ownership: { }, name: $self_arg @@ -659,6 +700,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -673,6 +715,7 @@ macro_rules! parse { type: instance_method, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: { ownership: { }, name: $self_arg @@ -692,6 +735,7 @@ macro_rules! parse { stack: { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -704,6 +748,7 @@ macro_rules! parse { type: class_method, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: (), args: [ $($args)* ], ret: uninitialized, @@ -724,6 +769,7 @@ macro_rules! parse { type: $type:tt, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, self: $self:tt, args: $args:tt, ret: uninitialized, @@ -742,6 +788,7 @@ macro_rules! parse { type: $type, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: $self, args: $args, ret: { $ret }, @@ -760,6 +807,7 @@ macro_rules! parse { type: initializer, rust_name: $rust_method_name:tt, ruby_name: $ruby_method_name:tt, + ruby_visibility: $ruby_visibility:tt, self: $self:tt, args: $args:tt, ret: uninitialized, @@ -784,6 +832,7 @@ macro_rules! parse { type: initializer, rust_name: $rust_method_name, ruby_name: $ruby_method_name, + ruby_visibility: $ruby_visibility, self: $self, args: $args, ret: { $rust_class_name }, @@ -810,6 +859,7 @@ macro_rules! parse { type: $type:tt, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, self: $self:tt, args: $args:tt, ret: uninitialized, @@ -826,6 +876,7 @@ macro_rules! parse { type: $type, rust_name: $rust_name, ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, self: $self, args: $args, ret: { () },