mirror of https://github.com/tildeio/helix
Refactor codegen into more pieces
This commit is contained in:
parent
4ebf9e9da5
commit
ea51eeb654
|
@ -0,0 +1,39 @@
|
|||
#[macro_export]
|
||||
macro_rules! codegen_allocator {
|
||||
({
|
||||
type: class,
|
||||
name: $name:tt,
|
||||
meta: $meta:tt,
|
||||
struct: (),
|
||||
methods: $methods:tt
|
||||
}) => ();
|
||||
|
||||
({
|
||||
type: class,
|
||||
name: $cls: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>>) {}
|
||||
|
||||
#[inline]
|
||||
fn __alloc_with__(rust_self: Option<Box<$cls>>) -> $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_self)
|
||||
);
|
||||
|
||||
instance
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,11 +1,19 @@
|
|||
#[macro_export]
|
||||
macro_rules! codegen {
|
||||
{ [ $($ast:tt)* ] } => {
|
||||
codegen! {
|
||||
type: top,
|
||||
classes: [],
|
||||
buffer: [ $($ast)* ]
|
||||
mod init_native {
|
||||
codegen! {
|
||||
type: top,
|
||||
classes: [],
|
||||
buffer: [ $($ast)* ]
|
||||
}
|
||||
|
||||
codegen_init! { [ $($ast)* ] }
|
||||
}
|
||||
|
||||
codegen_pub_classes!($($ast)*);
|
||||
|
||||
pub use self::init_native::Init_native;
|
||||
};
|
||||
|
||||
{
|
||||
|
@ -47,6 +55,14 @@ macro_rules! codegen {
|
|||
],
|
||||
buffer: [ $($rest)* ]
|
||||
}
|
||||
|
||||
codegen_extra_impls!({
|
||||
type: class,
|
||||
name: $name,
|
||||
meta: { pub: $pub, reopen: $reopen },
|
||||
struct: $struct,
|
||||
methods: [ $($method)* ]
|
||||
});
|
||||
};
|
||||
|
||||
{
|
||||
|
@ -69,6 +85,41 @@ macro_rules! codegen {
|
|||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! codegen_pub_classes {
|
||||
{
|
||||
$({
|
||||
type: class,
|
||||
name: $name:tt,
|
||||
meta: { pub: $pub:tt, reopen: $reopen:tt },
|
||||
struct: $struct:tt,
|
||||
methods: [ $($method:tt)* ]
|
||||
})*
|
||||
} => {
|
||||
$(
|
||||
codegen_pub_classes! {
|
||||
type: class,
|
||||
name: $name,
|
||||
pub: $pub
|
||||
}
|
||||
)*
|
||||
};
|
||||
|
||||
{
|
||||
type: class,
|
||||
name: $name:tt,
|
||||
pub: false
|
||||
} => {};
|
||||
|
||||
{
|
||||
type: class,
|
||||
name: $name:tt,
|
||||
pub: true
|
||||
} => {
|
||||
pub use self::init_native::$name;
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! codegen_struct {
|
||||
{ pub: false, name: $name:tt, struct: () } => {
|
||||
|
@ -151,3 +202,11 @@ macro_rules! codegen_method {
|
|||
pub fn $name($($ownership)* $self, $($args)*) -> $($ret)* $body
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! codegen_extra_impls {
|
||||
($class:tt) => (
|
||||
codegen_allocator!($class);
|
||||
codegen_coercions!($class);
|
||||
)
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#[macro_export]
|
||||
macro_rules! codegen_coercions {
|
||||
({
|
||||
type: class,
|
||||
name: $cls: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> {
|
||||
use $crate::{CheckedValue, sys};
|
||||
use ::std::ffi::{CStr};
|
||||
|
||||
if unsafe { $cls == ::std::mem::transmute(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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::ToRust<$cls> for $crate::CheckedValue<$cls> {
|
||||
fn to_rust(self) -> $cls {
|
||||
$cls { helix: self.inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_ruby!(&'a $cls);
|
||||
impl_to_ruby!(&'a mut $cls);
|
||||
);
|
||||
|
||||
({
|
||||
type: class,
|
||||
name: $cls: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 $crate::ToRuby for $cls {
|
||||
fn to_ruby(self) -> $crate::sys::VALUE {
|
||||
$cls::__alloc_with__(Some(Box::new(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_ruby!(&'a $cls);
|
||||
impl_to_ruby!(&'a mut $cls);
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_to_ruby {
|
||||
($cls:ty) => {
|
||||
item! {
|
||||
impl<'a> $crate::ToRuby for $cls {
|
||||
fn to_ruby(self) -> $crate::sys::VALUE {
|
||||
self.helix
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
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> {
|
||||
use $crate::{CheckedValue, sys};
|
||||
use ::std::ffi::{CStr};
|
||||
|
||||
if unsafe { $helix_id == ::std::mem::transmute(sys::rb_obj_class(self)) } {
|
||||
if unsafe { $crate::sys::Data_Get_Struct_Value(self) == ::std::ptr::null_mut() } {
|
||||
Err(format!("Uninitialized {}", $crate::inspect(unsafe { sys::rb_obj_class(self) })))
|
||||
} else {
|
||||
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, $crate::inspect(unsafe { sys::rb_obj_class(self) })))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@ macro_rules! codegen_init {
|
|||
pub extern "C" fn Init_native() {
|
||||
$crate::sys::check_version();
|
||||
|
||||
|
||||
$(
|
||||
codegen_class_coercions!($class);
|
||||
codegen_class_binding!($class, $class);
|
||||
)*
|
||||
}
|
||||
|
@ -59,31 +59,8 @@ macro_rules! codegen_class_binding {
|
|||
} } => ({
|
||||
use ::std::mem::transmute;
|
||||
|
||||
extern "C" fn __mark__(_klass: &$cls) {}
|
||||
extern "C" fn __free__(_klass: Option<Box<$cls>>) {}
|
||||
|
||||
extern "C" fn __alloc__(_klass: $crate::sys::VALUE) -> $crate::sys::VALUE {
|
||||
__alloc_with__(None)
|
||||
}
|
||||
|
||||
impl $cls {
|
||||
fn __alloc_with__(rust_self: Option<Box<$cls>>) -> $crate::sys::VALUE {
|
||||
__alloc_with__(rust_self)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn __alloc_with__(rust_self: Option<Box<$cls>>) -> $crate::sys::VALUE {
|
||||
unsafe {
|
||||
let instance = $crate::sys::Data_Wrap_Struct(
|
||||
transmute($cls),
|
||||
transmute(__mark__ as usize),
|
||||
transmute(__free__ as usize),
|
||||
transmute(rust_self)
|
||||
);
|
||||
|
||||
instance
|
||||
}
|
||||
$cls::__alloc_with__(None)
|
||||
}
|
||||
|
||||
let def = $crate::ClassDefinition::wrapped(cstr!(stringify!($cls)), __alloc__);
|
||||
|
@ -301,60 +278,6 @@ macro_rules! codegen_define_method {
|
|||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! codegen_class_coercions {
|
||||
({
|
||||
type: class,
|
||||
name: $cls: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> {
|
||||
use $crate::{CheckedValue, sys};
|
||||
use ::std::ffi::{CStr};
|
||||
|
||||
if unsafe { $cls == ::std::mem::transmute(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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::ToRust<$cls> for $crate::CheckedValue<$cls> {
|
||||
fn to_rust(self) -> $cls {
|
||||
$cls { helix: self.inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_ruby!(&'a $cls);
|
||||
impl_to_ruby!(&'a mut $cls);
|
||||
);
|
||||
|
||||
({
|
||||
type: class,
|
||||
name: $cls: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 $crate::ToRuby for $cls {
|
||||
fn to_ruby(self) -> $crate::sys::VALUE {
|
||||
$cls::__alloc_with__(Some(Box::new(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl_to_ruby!(&'a $cls);
|
||||
impl_to_ruby!(&'a mut $cls);
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! codegen_self_pointer_type {
|
||||
|
@ -375,49 +298,6 @@ macro_rules! codegen_self_pointer_type {
|
|||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! impl_to_ruby {
|
||||
($cls:ty) => {
|
||||
item! {
|
||||
impl<'a> $crate::ToRuby for $cls {
|
||||
fn to_ruby(self) -> $crate::sys::VALUE {
|
||||
self.helix
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
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> {
|
||||
use $crate::{CheckedValue, sys};
|
||||
use ::std::ffi::{CStr};
|
||||
|
||||
if unsafe { $helix_id == ::std::mem::transmute(sys::rb_obj_class(self)) } {
|
||||
if unsafe { $crate::sys::Data_Get_Struct_Value(self) == ::std::ptr::null_mut() } {
|
||||
Err(format!("Uninitialized {}", $crate::inspect(unsafe { sys::rb_obj_class(self) })))
|
||||
} else {
|
||||
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, $crate::inspect(unsafe { sys::rb_obj_class(self) })))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! method_arity {
|
||||
( $($arg:tt)* ) => {
|
||||
|
|
|
@ -76,7 +76,6 @@ macro_rules! parse {
|
|||
stack: { ast: $ast:tt }
|
||||
} => {
|
||||
codegen! { $ast }
|
||||
codegen_init! { $ast }
|
||||
};
|
||||
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue