From a8e1f37362487fb6107a064af1edbee50dd0eacf Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Fri, 15 Jun 2018 20:48:29 -0700 Subject: [PATCH] Allow arbitrary attributes for methods --- .appveyor.yml | 2 +- .travis.yml | 2 +- Cargo.toml | 2 +- Rakefile | 4 +-- examples/unit/.gitignore | 4 +++ examples/unit/Cargo.toml | 11 ++++++++ examples/unit/Gemfile | 4 +++ examples/unit/Rakefile | 14 ++++++++++ examples/unit/lib/unit.rb | 7 +++++ examples/unit/src/lib.rs | 14 ++++++++++ src/macros/codegen.rs | 6 ++++ src/macros/init.rs | 4 +++ src/macros/parser.rs | 59 +++++++++++++++++++++++++++++++++++++-- 13 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 examples/unit/.gitignore create mode 100644 examples/unit/Cargo.toml create mode 100644 examples/unit/Gemfile create mode 100644 examples/unit/Rakefile create mode 100644 examples/unit/lib/unit.rb create mode 100644 examples/unit/src/lib.rs diff --git a/.appveyor.yml b/.appveyor.yml index d985879..432d9dd 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -4,7 +4,7 @@ cache: environment: # can't run game_of_life since termion doesn't support windows https://github.com/redox-os/termion/issues/103 - EXAMPLES: duration calculator console geometry membership text_transform turbo_blank json_builder + EXAMPLES: unit calculator console duration docopt geometry json_builder membership text_transform turbo_blank VERBOSE: true RUST_BACKTRACE: 1 matrix: diff --git a/.travis.yml b/.travis.yml index 35eafc5..be23342 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ cache: env: global: - - EXAMPLES="duration calculator console game_of_life geometry membership text_transform turbo_blank json_builder" + - EXAMPLES="unit calculator console duration docopt game_of_life geometry json_builder membership text_transform turbo_blank" - VERBOSE=true - RUST_BACKTRACE=1 - RUST_VERSION=stable diff --git a/Cargo.toml b/Cargo.toml index c8a57bb..be19331 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ travis-ci = { repository = "tildeio/helix", branch = "master" } appveyor = { repository = "tildeio/helix", branch = "master", service = "github" } [workspace] -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"] +members = ["examples/calculator", "examples/console", "examples/docopt", "examples/duration", "examples/game_of_life", "examples/geometry", "examples/json_builder", "examples/membership", "examples/text_transform", "examples/turbo_blank", "examples/unit"] [dependencies] libc = "0.2.0" diff --git a/Rakefile b/Rakefile index c1dd089..60cf947 100644 --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,7 @@ task :test do sh "bundle exec rake" end - examples = ENV["EXAMPLES"] || "duration calculator console docopt game_of_life geometry membership text_transform turbo_blank json_builder" + examples = ENV["EXAMPLES"] || "unit calculator console docopt duration game_of_life geometry json_builder membership text_transform turbo_blank" sh "bash ./examples/runner default #{examples}" end @@ -15,7 +15,7 @@ task :install do sh "bundle" end - examples = ENV["EXAMPLES"] || "duration calculator console docopt game_of_life geometry membership text_transform turbo_blank json_builder" + examples = ENV["EXAMPLES"] || "unit calculator console docopt duration game_of_life geometry json_builder membership text_transform turbo_blank" sh "bash ./examples/runner install #{examples}" end diff --git a/examples/unit/.gitignore b/examples/unit/.gitignore new file mode 100644 index 0000000..d20cbfe --- /dev/null +++ b/examples/unit/.gitignore @@ -0,0 +1,4 @@ +target +tmp +*.bundle +*.so diff --git a/examples/unit/Cargo.toml b/examples/unit/Cargo.toml new file mode 100644 index 0000000..fba011d --- /dev/null +++ b/examples/unit/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "unit" +version = "0.1.0" +authors = ["Godfrey Chan "] + +[lib] + +crate-type = ["cdylib"] + +[dependencies.helix] +path = "../.." diff --git a/examples/unit/Gemfile b/examples/unit/Gemfile new file mode 100644 index 0000000..91b3aee --- /dev/null +++ b/examples/unit/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem 'helix_runtime', path: '../../ruby' +gem 'rake', '~> 10.0' diff --git a/examples/unit/Rakefile b/examples/unit/Rakefile new file mode 100644 index 0000000..0f501c8 --- /dev/null +++ b/examples/unit/Rakefile @@ -0,0 +1,14 @@ +require 'bundler/setup' +require 'helix_runtime/build_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 + +task :default => :build diff --git a/examples/unit/lib/unit.rb b/examples/unit/lib/unit.rb new file mode 100644 index 0000000..708e61a --- /dev/null +++ b/examples/unit/lib/unit.rb @@ -0,0 +1,7 @@ +require "helix_runtime" + +begin + require "unit/native" +rescue LoadError + warn "Unable to load unit/native. Please run `rake build`" +end diff --git a/examples/unit/src/lib.rs b/examples/unit/src/lib.rs new file mode 100644 index 0000000..c60f315 --- /dev/null +++ b/examples/unit/src/lib.rs @@ -0,0 +1,14 @@ +#[macro_use] +extern crate helix; + +ruby! { + class Attributes { + #[doc(hidden)] + #[ruby_name="foo"] + #[inline] + #[cfg(not(foo="bar"))] + def bar() { + println!("Hello from bar!"); + } + } +} diff --git a/src/macros/codegen.rs b/src/macros/codegen.rs index c4a9dc9..275de54 100644 --- a/src/macros/codegen.rs +++ b/src/macros/codegen.rs @@ -166,6 +166,7 @@ macro_rules! codegen_method { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: { $($attributes:tt)* }, self: { ownership: {}, name: $self:tt @@ -175,6 +176,7 @@ macro_rules! codegen_method { body: $body:block } } => { + $($attributes)* pub fn $rust_name($self : $crate::Metadata, $($arg : $argty),*) -> $($ret)* $body }; @@ -184,12 +186,14 @@ macro_rules! codegen_method { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: { $($attributes:tt)* }, self: (), args: [ $($args:tt)* ], ret: { $($ret:tt)* }, body: $body:block } } => { + $($attributes)* pub fn $rust_name($($args)*) -> $($ret)* $body }; @@ -199,6 +203,7 @@ macro_rules! codegen_method { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: { $($attributes:tt)* }, self: { ownership: { $($ownership:tt)* }, name: $self:tt @@ -208,6 +213,7 @@ macro_rules! codegen_method { body: $body:block } } => { + $($attributes)* pub fn $rust_name($($ownership)* $self, $($args)*) -> $($ret)* $body }; } diff --git a/src/macros/init.rs b/src/macros/init.rs index 09a1d14..fabffa0 100644 --- a/src/macros/init.rs +++ b/src/macros/init.rs @@ -87,6 +87,7 @@ macro_rules! codegen_define_method { rust_name: $rust_name:tt, ruby_name: { $($ruby_name:tt)* }, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, self: (), args: [ $($arg:tt : $argty:ty),* ], ret: { $($ret:tt)* }, @@ -143,6 +144,7 @@ macro_rules! codegen_define_method { rust_name: $rust_name:tt, ruby_name: { $($ruby_name:tt)* }, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, self: { ownership: { $($ownership:tt)* }, name: $self:tt }, args: [ $($arg:tt : $argty:ty),* ], ret: { $($ret:tt)* }, @@ -200,6 +202,7 @@ macro_rules! codegen_define_method { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: unexported, + attributes: $attributes:tt, self: $self:tt, args: [ $($arg:tt : $argty:ty),* ], ret: { $($ret:tt)* }, @@ -226,6 +229,7 @@ macro_rules! codegen_define_method { rust_name: $rust_name:tt, ruby_name: { $($ruby_name:tt)* }, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes: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 0aeac3a..604cb0c 100644 --- a/src/macros/parser.rs +++ b/src/macros/parser.rs @@ -295,6 +295,7 @@ macro_rules! parse { rust_name: uninitialized, ruby_name: uninitialized, ruby_visibility: public, + attributes: {}, $($stack)* } } @@ -302,6 +303,26 @@ macro_rules! parse { // STATE: parse_method_attributes + { + state: parse_method_attributes, + buffer: { #[ruby_name = $ruby_name:tt] $($rest:tt)* }, + stack: { + rust_name: uninitialized, + ruby_name: uninitialized, + $($stack:tt)* + } + } => { + parse! { + state: parse_method_attributes, + buffer: { $($rest)* }, + stack: { + rust_name: uninitialized, + ruby_name: { $ruby_name }, + $($stack)* + } + } + }; + { state: parse_method_attributes, buffer: { #[ruby_visibility = $ruby_visibility:tt] $($rest:tt)* }, @@ -326,10 +347,12 @@ macro_rules! parse { { state: parse_method_attributes, - buffer: { #[ruby_name = $ruby_name:tt] $($rest:tt)* }, + buffer: { #[$($attribute:tt)*] $($rest:tt)* }, stack: { rust_name: uninitialized, - ruby_name: uninitialized, + ruby_name: $ruby_name:tt, + ruby_visibility: $ruby_visibility:tt, + attributes: { $($attributes:tt)* }, $($stack:tt)* } } => { @@ -338,7 +361,9 @@ macro_rules! parse { buffer: { $($rest)* }, stack: { rust_name: uninitialized, - ruby_name: { $ruby_name }, + ruby_name: $ruby_name, + ruby_visibility: $ruby_visibility, + attributes: { $($attributes)* #[$($attribute)*] }, $($stack)* } } @@ -407,6 +432,7 @@ macro_rules! parse { rust_name: initialize, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class: $class:tt, $($stack:tt)* } @@ -419,6 +445,7 @@ macro_rules! parse { buffer: { $($args)* }, stack: { ruby_visibility: $ruby_visibility, + attributes: $attributes, class_body: { $($rest)* }, class: $class, $($stack)* @@ -433,6 +460,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, $($stack:tt)* } } => { @@ -443,6 +471,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, class_body: { $($rest)* }, $($stack)* } @@ -456,6 +485,7 @@ macro_rules! parse { buffer: { $helix_arg:tt, $($args:tt)+ }, stack: { ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -471,6 +501,7 @@ macro_rules! parse { rust_name: initialize, ruby_name: { "initialize" }, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { }, name: $helix_arg @@ -489,6 +520,7 @@ macro_rules! parse { buffer: { $helix_arg:tt }, stack: { ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -504,6 +536,7 @@ macro_rules! parse { rust_name: initialize, ruby_name: { "initialize" }, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { }, name: $helix_arg @@ -526,6 +559,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -541,6 +575,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { &mut }, name: $self_arg @@ -561,6 +596,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -576,6 +612,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { &mut }, name: $self_arg @@ -596,6 +633,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -611,6 +649,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { & }, name: $self_arg @@ -631,6 +670,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -646,6 +686,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { & }, name: $self_arg @@ -666,6 +707,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -681,6 +723,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { }, name: $self_arg @@ -701,6 +744,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -716,6 +760,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: { ownership: { }, name: $self_arg @@ -736,6 +781,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, class_body: $class_body:tt, $($stack:tt)* } @@ -749,6 +795,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: (), args: [ $($args)* ], ret: uninitialized, @@ -770,6 +817,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, self: $self:tt, args: $args:tt, ret: uninitialized, @@ -789,6 +837,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: $self, args: $args, ret: { $ret }, @@ -808,6 +857,7 @@ macro_rules! parse { rust_name: $rust_method_name:tt, ruby_name: $ruby_method_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, self: $self:tt, args: $args:tt, ret: uninitialized, @@ -833,6 +883,7 @@ macro_rules! parse { rust_name: $rust_method_name, ruby_name: $ruby_method_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: $self, args: $args, ret: { $rust_class_name }, @@ -860,6 +911,7 @@ macro_rules! parse { rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, ruby_visibility: $ruby_visibility:tt, + attributes: $attributes:tt, self: $self:tt, args: $args:tt, ret: uninitialized, @@ -877,6 +929,7 @@ macro_rules! parse { rust_name: $rust_name, ruby_name: $ruby_name, ruby_visibility: $ruby_visibility, + attributes: $attributes, self: $self, args: $args, ret: { () },