Support #[ruby_name] remapping for classes

This commit is contained in:
Godfrey Chan 2017-09-11 02:01:02 -07:00
parent eeb4d56b08
commit f64727dbea
11 changed files with 174 additions and 96 deletions

View File

@ -1,3 +1,5 @@
#![recursion_limit="1024"]
#[macro_use]
extern crate helix;

View File

@ -9,7 +9,7 @@ case ENV["IMPLEMENTATION"]
when "RUST"
require "duration/native"
ActiveSupport::Duration = ::Duration
ActiveSupport::Duration = ::RustDuration
when "RAILS"
require "active_support/duration"
when "NONE"

View File

@ -14,6 +14,7 @@ const SECONDS_PER_MONTH: i64 = 2629746; // 1/12 of a gregorian year
const SECONDS_PER_YEAR: i64 = 31556952; // length of a gregorian year (365.2425 days)
ruby! {
#[ruby_name="RustDuration"]
class Duration {
struct {
seconds: Option<i32>,

View File

@ -1,7 +1,4 @@
require "helix_runtime"
RubyString = String
require "turbo_blank/native"
class String

View File

@ -2,6 +2,7 @@
extern crate helix;
ruby! {
#[ruby_name = "String"]
reopen class RubyString {
#[ruby_name = "blank?"]
def is_blank(&self) -> bool {

View File

@ -2,7 +2,8 @@
macro_rules! codegen_allocator {
({
type: class,
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
meta: $meta:tt,
struct: (),
methods: $methods:tt
@ -10,24 +11,25 @@ macro_rules! codegen_allocator {
({
type: class,
name: $cls:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
meta: { pub: $pub:tt, reopen: false },
struct: $struct:tt,
methods: [ $($method:tt)* ]
}) => (
impl $cls {
extern "C" fn __mark__(_klass: &$cls) {}
extern "C" fn __free__(_klass: Option<Box<$cls>>) {}
impl $rust_name {
extern "C" fn __mark__(_klass: &$rust_name) {}
extern "C" fn __free__(_klass: Option<Box<$rust_name>>) {}
#[inline]
fn __alloc_with__(rust_self: Option<Box<$cls>>) -> $crate::sys::VALUE {
fn __alloc_with__(rust_self: Option<Box<$rust_name>>) -> $crate::sys::VALUE {
use ::std::mem::transmute;
unsafe {
let instance = $crate::sys::Data_Wrap_Struct(
transmute($cls),
transmute($cls::__mark__ as usize),
transmute($cls::__free__ as usize),
transmute($rust_name),
transmute($rust_name::__mark__ as usize),
transmute($rust_name::__free__ as usize),
transmute(rust_self)
);

View File

@ -29,7 +29,8 @@ macro_rules! codegen {
buffer: [
{
type: class,
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
meta: { pub: $pub:tt, reopen: $reopen:tt },
struct: $struct:tt,
methods: [ $($method:tt)* ]
@ -42,8 +43,9 @@ macro_rules! codegen {
classes: [
$($class)*
{
name: $name,
struct: { codegen_struct! { pub: $pub, name: $name, struct: $struct } },
rust_name: $rust_name,
ruby_name: $ruby_name,
struct: { codegen_struct! { pub: $pub, rust_name: $rust_name, ruby_name: $ruby_name, struct: $struct } },
methods: [ $( codegen_method! { $method } )* ]
}
],
@ -52,7 +54,8 @@ macro_rules! codegen {
codegen_extra_impls!({
type: class,
name: $name,
rust_name: $rust_name,
ruby_name: $ruby_name,
meta: { pub: $pub, reopen: $reopen },
struct: $struct,
methods: [ $($method)* ]
@ -63,7 +66,8 @@ macro_rules! codegen {
type: done,
classes: [ $(
{
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
struct: { $($struct:tt)* },
methods: [ $($method:tt)* ]
}
@ -72,7 +76,7 @@ macro_rules! codegen {
$(
$($struct)*
impl $name {
impl $rust_name {
$($method)*
}
)*
@ -84,7 +88,8 @@ macro_rules! codegen_pub_classes {
{
$({
type: class,
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
meta: { pub: $pub:tt, reopen: $reopen:tt },
struct: $struct:tt,
methods: [ $($method:tt)* ]
@ -93,7 +98,8 @@ macro_rules! codegen_pub_classes {
$(
codegen_pub_classes! {
type: class,
name: $name,
rust_name: $rust_name,
ruby_name: $ruby_name,
pub: $pub
}
)*
@ -101,51 +107,54 @@ macro_rules! codegen_pub_classes {
{
type: class,
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
pub: false
} => {};
{
type: class,
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
pub: true
} => {
pub use self::init_native::$name;
pub use self::init_native::$rust_name;
};
}
#[macro_export]
macro_rules! codegen_struct {
{ pub: false, name: $name:tt, struct: () } => {
codegen_struct! { pub: {}, name: $name, struct: {} }
{ pub: false, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, struct: () } => {
codegen_struct! { pub: {}, rust_name: $rust_name, ruby_name: $ruby_name, struct: {} }
};
{ pub: true, name: $name:tt, struct: () } => {
codegen_struct! { pub: { pub }, name: $name, struct: {} }
{ pub: true, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, struct: () } => {
codegen_struct! { pub: { pub }, rust_name: $rust_name, ruby_name: $ruby_name, struct: {} }
};
{ pub: false, name: $name:tt, struct: { $($rest:tt)* } } => {
codegen_struct! { pub: {}, name: $name, struct: { $($rest)* } }
{ pub: false, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, struct: { $($rest:tt)* } } => {
codegen_struct! { pub: {}, rust_name: $rust_name, ruby_name: $ruby_name, struct: { $($rest)* } }
};
{ pub: true, name: $name:tt, struct: { $($rest:tt)* } } => {
codegen_struct! { pub: { pub }, name: $name, struct: { $($rest)* } }
{ pub: true, rust_name: $rust_name:tt, ruby_name: $ruby_name:tt, struct: { $($rest:tt)* } } => {
codegen_struct! { pub: { pub }, rust_name: $rust_name, ruby_name: $ruby_name, struct: { $($rest)* } }
};
{
pub: { $($pub:tt)* },
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
struct: { $($struct:tt)* }
} => {
#[derive(Clone, Debug)]
#[repr(C)]
$($pub)* struct $name {
$($pub)* struct $rust_name {
helix: $crate::Metadata,
$($struct)*
}
#[allow(non_upper_case_globals)]
static mut $name: usize = 0;
static mut $rust_name: usize = 0;
}
}

View File

@ -2,53 +2,55 @@
macro_rules! codegen_coercions {
({
type: class,
name: $cls:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
meta: { pub: $pub:tt, reopen: $reopen:tt },
struct: (),
methods: $methods:tt
}) => (
impl $crate::UncheckedValue<$cls> for $crate::sys::VALUE {
fn to_checked(self) -> $crate::CheckResult<$cls> {
impl $crate::UncheckedValue<$rust_name> for $crate::sys::VALUE {
fn to_checked(self) -> $crate::CheckResult<$rust_name> {
use $crate::{CheckedValue, sys};
use ::std::ffi::{CStr};
if unsafe { $cls == $crate::as_usize(sys::rb_obj_class(self)) } {
if unsafe { $rust_name == $crate::as_usize(sys::rb_obj_class(self)) } {
Ok(unsafe { CheckedValue::new(self) })
} else {
let val = unsafe { CStr::from_ptr(sys::rb_obj_classname(self)).to_string_lossy() };
Err(format!("No implicit conversion of {} into {}", val, stringify!($cls)))
Err(format!("No implicit conversion of {} into {}", val, stringify!($rust_name)))
}
}
}
impl $crate::ToRust<$cls> for $crate::CheckedValue<$cls> {
fn to_rust(self) -> $cls {
$cls { helix: self.inner }
impl $crate::ToRust<$rust_name> for $crate::CheckedValue<$rust_name> {
fn to_rust(self) -> $rust_name {
$rust_name { helix: self.inner }
}
}
impl_to_ruby!(&'a $cls);
impl_to_ruby!(&'a mut $cls);
impl_to_ruby!(&'a $rust_name);
impl_to_ruby!(&'a mut $rust_name);
);
({
type: class,
name: $cls:tt,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
meta: { pub: $pub:tt, reopen: false },
struct: $struct:tt,
methods: $methods:tt
}) => (
impl_struct_to_rust!(&'a $cls, $cls);
impl_struct_to_rust!(&'a mut $cls, $cls);
impl_struct_to_rust!(&'a $rust_name, $rust_name);
impl_struct_to_rust!(&'a mut $rust_name, $rust_name);
impl $crate::ToRuby for $cls {
impl $crate::ToRuby for $rust_name {
fn to_ruby(self) -> $crate::sys::VALUE {
$cls::__alloc_with__(Some(Box::new(self)))
$rust_name::__alloc_with__(Some(Box::new(self)))
}
}
impl_to_ruby!(&'a $cls);
impl_to_ruby!(&'a mut $cls);
impl_to_ruby!(&'a $rust_name);
impl_to_ruby!(&'a mut $rust_name);
);
}
@ -56,9 +58,9 @@ macro_rules! codegen_coercions {
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_ruby {
($cls:ty) => {
($rust_name:ty) => {
item! {
impl<'a> $crate::ToRuby for $cls {
impl<'a> $crate::ToRuby for $rust_name {
fn to_ruby(self) -> $crate::sys::VALUE {
self.helix
}
@ -69,15 +71,15 @@ macro_rules! impl_to_ruby {
#[macro_export]
macro_rules! impl_struct_to_rust {
($cls:ty, $helix_id:tt) => {
impl<'a> $crate::ToRust<$cls> for $crate::CheckedValue<$cls> {
fn to_rust(self) -> $cls {
($rust_name:ty, $helix_id:tt) => {
impl<'a> $crate::ToRust<$rust_name> for $crate::CheckedValue<$rust_name> {
fn to_rust(self) -> $rust_name {
unsafe { ::std::mem::transmute($crate::sys::Data_Get_Struct_Value(self.inner)) }
}
}
impl<'a> $crate::UncheckedValue<$cls> for $crate::sys::VALUE {
fn to_checked(self) -> $crate::CheckResult<$cls> {
impl<'a> $crate::UncheckedValue<$rust_name> for $crate::sys::VALUE {
fn to_checked(self) -> $crate::CheckResult<$rust_name> {
use $crate::{CheckedValue, sys};
use ::std::ffi::{CStr};

View File

@ -18,41 +18,44 @@ macro_rules! codegen_init {
macro_rules! codegen_class_binding {
{ $class:tt, {
type: class,
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: { $($ruby_name:tt)* },
meta: { pub: $pub:tt, reopen: false },
struct: (),
methods: [ $($method:tt)* ]
} } => ({
use ::std::mem::transmute;
let def = $crate::ClassDefinition::new(cstr!(stringify!($name)));
let def = $crate::ClassDefinition::new(cstr!($($ruby_name)*));
$(
codegen_define_method!(def, $class, $method);
)*
unsafe { $name = transmute(def.class) };
unsafe { $rust_name = transmute(def.class) };
});
{ $class:tt, {
type: class,
name: $name:tt,
rust_name: $rust_name:tt,
ruby_name: { $($ruby_name:tt)* },
meta: { pub: $pub:tt, reopen: true },
struct: (),
methods: [ $($method:tt)* ]
} } => ({
use ::std::mem::transmute;
let def = $crate::ClassDefinition::reopen(cstr!(stringify!($name)));
let def = $crate::ClassDefinition::reopen(cstr!($($ruby_name)*));
$(
codegen_define_method!(def, $class, $method);
)*
unsafe { $name = transmute(def.class) };
unsafe { $rust_name = transmute(def.class) };
});
{ $class:tt, {
type: class,
name: $cls:tt,
rust_name: $rust_name:tt,
ruby_name: { $($ruby_name:tt)* },
meta: { pub: $pub:tt, reopen: $reopen:tt },
struct: { $($struct:tt)* },
methods: [ $($method:tt)* ]
@ -60,16 +63,16 @@ macro_rules! codegen_class_binding {
use ::std::mem::transmute;
extern "C" fn __alloc__(_klass: $crate::sys::VALUE) -> $crate::sys::VALUE {
$cls::__alloc_with__(None)
$rust_name::__alloc_with__(None)
}
let def = $crate::ClassDefinition::wrapped(cstr!(stringify!($cls)), __alloc__);
let def = $crate::ClassDefinition::wrapped(cstr!($($ruby_name)*), __alloc__);
$(
codegen_define_method!(def, $class, $method);
)*
unsafe { $cls = transmute(def.class) }
unsafe { $rust_name = transmute(def.class) }
});
}
@ -78,7 +81,7 @@ macro_rules! codegen_class_binding {
macro_rules! codegen_define_method {
($def:tt, {
type: class,
name: $cls:tt,
rust_name: $cls_rust_name:tt,
$($rest:tt)*
}, {
type: class_method,
@ -135,7 +138,7 @@ macro_rules! codegen_define_method {
)*
handle_exception! {
$cls::$rust_name($($arg),*)
$cls_rust_name::$rust_name($($arg),*)
}
}
@ -148,7 +151,8 @@ macro_rules! codegen_define_method {
($def:tt, {
type: class,
name: $cls:tt,
rust_name: $cls_rust_name:tt,
ruby_name: $cls_ruby_name:tt,
meta: $meta:tt,
struct: $struct:tt,
$($rest:tt)*
@ -194,7 +198,7 @@ macro_rules! codegen_define_method {
#[allow(unused_imports)]
use $crate::{ToRust};
let rust_self = match $crate::UncheckedValue::<codegen_self_pointer_type! { struct: $struct, ownership: { $($ownership)* }, type: $cls }>::to_checked(rb_self) {
let rust_self = match $crate::UncheckedValue::<codegen_self_pointer_type! { struct: $struct, ownership: { $($ownership)* }, type: $cls_rust_name }>::to_checked(rb_self) {
Ok(v) => v,
Err(e) => return Err($crate::ExceptionInfo::with_message(e))
};
@ -226,7 +230,8 @@ macro_rules! codegen_define_method {
($def:tt, {
type: class,
name: $cls:tt,
rust_name: $cls_rust_name:tt,
ruby_name: $cls_ruby_name:tt,
meta: $meta:tt,
struct: $struct:tt,
$($rest:tt)*
@ -239,9 +244,9 @@ macro_rules! codegen_define_method {
ret: { $($ret:tt)* },
body: $body:tt
}) => ({
impl $cls {
impl $cls_rust_name {
pub fn new($($arg : $argty),*) -> $($ret)* {
$cls::$rust_name(unsafe { $crate::sys::Qnil } , $($arg),*)
$cls_rust_name::$rust_name(unsafe { $crate::sys::Qnil } , $($arg),*)
}
}
@ -259,7 +264,7 @@ macro_rules! codegen_define_method {
rb_self
}
fn __checked_initialize__(rb_self: $crate::sys::VALUE, $($arg : $crate::sys::VALUE),*) -> Result<$cls, String> {
fn __checked_initialize__(rb_self: $crate::sys::VALUE, $($arg : $crate::sys::VALUE),*) -> Result<$cls_rust_name, String> {
#[allow(unused_imports)]
use $crate::{ToRust};
@ -271,7 +276,7 @@ macro_rules! codegen_define_method {
let $arg = $crate::ToRust::to_rust($arg);
)*
Ok($cls::initialize(rb_self, $($arg),*))
Ok($cls_rust_name::initialize(rb_self, $($arg),*))
}
let arity = method_arity!($($arg)*);

View File

@ -36,7 +36,8 @@ macro_rules! item {
macro_rules! assert_struct {
(true, {
type: class,
name: $name:ident,
rust_name: $rust_name:ident,
ruby_name: $ruby_name:tt,
meta: $meta:tt,
struct: { $($struct:tt)+ },
methods: $methods:tt
@ -44,7 +45,8 @@ macro_rules! assert_struct {
(false, {
type: class,
name: $name:ident,
rust_name: $rust_name:ident,
ruby_name: $ruby_name:tt,
meta: $meta:tt,
struct: (),
methods: $methods:tt

View File

@ -23,7 +23,8 @@
Class :
{
type: class,
name: «ident»,
rust_name: «ident»,
ruby_name: { string },
meta: «Meta»,
struct: () | { «Field»,* }
methods: [ «Method»,* ]
@ -88,6 +89,7 @@ macro_rules! parse {
state: parse_class,
buffer: $buffer,
stack: {
ruby_name: {},
pub: false,
reopen: false,
$($stack)*
@ -99,8 +101,9 @@ macro_rules! parse {
{
state: parse_class,
buffer: { pub $($rest:tt)* },
buffer: { #[ruby_name = $ruby_name:tt] $($rest:tt)* },
stack: {
ruby_name: {},
pub: false,
reopen: false,
$($stack:tt)*
@ -110,6 +113,29 @@ macro_rules! parse {
state: parse_class,
buffer: { $($rest)* },
stack: {
ruby_name: { $ruby_name },
pub: false,
reopen: false,
$($stack)*
}
}
};
{
state: parse_class,
buffer: { pub $($rest:tt)* },
stack: {
ruby_name: $ruby_name:tt,
pub: false,
reopen: false,
$($stack:tt)*
}
} => {
parse! {
state: parse_class,
buffer: { $($rest)* },
stack: {
ruby_name: $ruby_name,
pub: true,
reopen: false,
$($stack)*
@ -121,6 +147,7 @@ macro_rules! parse {
state: parse_class,
buffer: { reopen $($rest:tt)* },
stack: {
ruby_name: $ruby_name:tt,
pub: $pub:tt,
reopen: false,
$($stack:tt)*
@ -130,6 +157,7 @@ macro_rules! parse {
state: parse_class,
buffer: { $($rest)* },
stack: {
ruby_name: $ruby_name,
pub: $pub,
reopen: true,
$($stack)*
@ -137,12 +165,32 @@ macro_rules! parse {
}
};
{
state: parse_class,
buffer: { class $name:tt $($rest:tt)* },
stack: {
ruby_name: {},
$($stack:tt)*
}
} => {
parse! {
state: parse_class,
buffer: { class $name $($rest)* },
stack: {
ruby_name: { stringify!($name) },
$($stack)*
}
}
};
{
state: parse_class,
buffer: { class $name:tt { $($body:tt)* } $($rest:tt)* },
stack: {
ruby_name: $ruby_name:tt,
pub: $pub:tt,
reopen: $reopen:tt,
$($stack:tt)*
}
} => {
@ -152,7 +200,8 @@ macro_rules! parse {
stack: {
class: {
type: class,
name: $name,
rust_name: $name,
ruby_name: $ruby_name,
meta: { pub: $pub, reopen: $reopen },
struct: uninitialized,
methods: []
@ -171,7 +220,8 @@ macro_rules! parse {
stack: {
class: {
type: class,
name: $name:ident,
rust_name: $rust_name:ident,
ruby_name: $ruby_name:tt,
meta: $meta:tt,
struct: uninitialized,
methods : []
@ -185,7 +235,8 @@ macro_rules! parse {
stack: {
class: {
type: class,
name: $name,
rust_name: $rust_name,
ruby_name: $ruby_name,
meta: $meta,
struct: { $($struct)* },
methods: []
@ -201,7 +252,8 @@ macro_rules! parse {
stack: {
class: {
type: class,
name: $name:ident,
rust_name: $rust_name:ident,
ruby_name: $ruby_name:tt,
meta: $meta:tt,
struct: uninitialized,
methods : []
@ -215,7 +267,8 @@ macro_rules! parse {
stack: {
class: {
type: class,
name: $name,
rust_name: $rust_name,
ruby_name: $ruby_name,
meta: $meta,
struct: (),
methods: []
@ -551,8 +604,8 @@ macro_rules! parse {
stack: {
method: {
type: initializer,
rust_name: $rust_name:tt,
ruby_name: $ruby_name:tt,
rust_name: $rust_method_name:tt,
ruby_name: $ruby_method_name:tt,
self: $self:tt,
args: $args:tt,
ret: uninitialized,
@ -560,7 +613,8 @@ macro_rules! parse {
},
class: {
type: class,
name: $name:ident,
rust_name: $rust_class_name:ident,
ruby_name: $ruby_class_name:tt,
meta: $meta:tt,
struct: $struct:tt,
methods: $methods:tt
@ -574,16 +628,17 @@ macro_rules! parse {
stack: {
method: {
type: initializer,
rust_name: $rust_name,
ruby_name: $ruby_name,
rust_name: $rust_method_name,
ruby_name: $ruby_method_name,
self: $self,
args: $args,
ret: { $name },
ret: { $rust_class_name },
body: $body
},
class: {
type: class,
name: $name,
rust_name: $rust_class_name,
ruby_name: $ruby_class_name,
meta: $meta,
struct: $struct,
methods: $methods
@ -636,7 +691,8 @@ macro_rules! parse {
method: $method:tt,
class: {
type: class,
name: $name:ident,
rust_name: $rust_name:ident,
ruby_name: $ruby_name:tt,
meta: $meta:tt,
struct: $struct:tt,
methods: [ $($methods:tt)* ]
@ -650,7 +706,8 @@ macro_rules! parse {
stack: {
class: {
type: class,
name: $name,
rust_name: $rust_name,
ruby_name: $ruby_name,
meta: $meta,
struct: $struct,
methods: [ $($methods)* $method ]