Skip to content

Commit

Permalink
Add new protocol and native support for Ordering (#591)
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog authored Jul 30, 2023
1 parent ad08e89 commit ceb177f
Show file tree
Hide file tree
Showing 14 changed files with 331 additions and 94 deletions.
8 changes: 8 additions & 0 deletions crates/rune-core/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ impl Protocol {
doc: ["Allows an equality operation to work."],
};

/// Perform an ordered comparison between two values.
pub const CMP: Protocol = Protocol {
name: "cmp",
hash: 0x240f1b75466cd1a3,
repr: Some("if $value < b { }"),
doc: ["Allows for ordering operations to work."],
};

/// The function to implement for the addition operation.
pub const ADD: Protocol = Protocol {
name: "add",
Expand Down
2 changes: 1 addition & 1 deletion crates/rune-macros/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ fn expand_enum_install_with(
module.index_function(#protocol::GET, #index, |this: &Self| {
match this {
#(#matches,)*
_ => return #vm_result::__rune_macros__unsupported_tuple_index_get(<Self as #type_of>::type_info()),
_ => return #vm_result::__rune_macros__unsupported_tuple_index_get(<Self as #type_of>::type_info(), #index),
}
})?;
});
Expand Down
22 changes: 11 additions & 11 deletions crates/rune-macros/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl Context {

/// Parse field attributes.
pub(crate) fn field_attrs(&self, input: &[syn::Attribute]) -> Result<FieldAttrs, ()> {
macro_rules! generate_op {
macro_rules! generate_assign {
($proto:ident, $op:tt) => {
|g| {
let Generate {
Expand Down Expand Up @@ -323,52 +323,52 @@ impl Context {
} else if meta.path == ADD_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_ADD_ASSIGN, +=),
generate: generate_assign!(PROTOCOL_ADD_ASSIGN, +=),
});
} else if meta.path == SUB_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_SUB_ASSIGN, -=),
generate: generate_assign!(PROTOCOL_SUB_ASSIGN, -=),
});
} else if meta.path == DIV_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_DIV_ASSIGN, /=),
generate: generate_assign!(PROTOCOL_DIV_ASSIGN, /=),
});
} else if meta.path == MUL_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_MUL_ASSIGN, *=),
generate: generate_assign!(PROTOCOL_MUL_ASSIGN, *=),
});
} else if meta.path == BIT_AND_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_BIT_AND_ASSIGN, &=),
generate: generate_assign!(PROTOCOL_BIT_AND_ASSIGN, &=),
});
} else if meta.path == BIT_OR_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_BIT_OR_ASSIGN, |=),
generate: generate_assign!(PROTOCOL_BIT_OR_ASSIGN, |=),
});
} else if meta.path == BIT_XOR_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_BIT_XOR_ASSIGN, ^=),
generate: generate_assign!(PROTOCOL_BIT_XOR_ASSIGN, ^=),
});
} else if meta.path == SHL_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_SHL_ASSIGN, <<=),
generate: generate_assign!(PROTOCOL_SHL_ASSIGN, <<=),
});
} else if meta.path == SHR_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_SHR_ASSIGN, >>=),
generate: generate_assign!(PROTOCOL_SHR_ASSIGN, >>=),
});
} else if meta.path == REM_ASSIGN {
attr.protocols.push(FieldProtocol {
custom: self.parse_field_custom(meta.input)?,
generate: generate_op!(PROTOCOL_REM_ASSIGN, %=),
generate: generate_assign!(PROTOCOL_REM_ASSIGN, %=),
});
} else {
return Err(syn::Error::new_spanned(&meta.path, "Unsupported attribute"));
Expand Down
1 change: 0 additions & 1 deletion crates/rune/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,3 @@ pub trait Any: Named + any::Any {
crate::__internal_impl_any!(::std::fmt, crate::no_std::fmt::Error);
crate::__internal_impl_any!(::std::io, crate::no_std::io::Error);
crate::__internal_impl_any!(::std::error, crate::no_std::Error);
crate::__internal_impl_any!(::std::cmp, core::cmp::Ordering);
8 changes: 8 additions & 0 deletions crates/rune/src/compile/named.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::cmp::Ordering;

use crate::no_std::prelude::*;

use crate::module::InstallWith;
Expand Down Expand Up @@ -53,3 +55,9 @@ impl Named for bool {
}

impl InstallWith for bool {}

impl Named for Ordering {
const BASE_NAME: RawStr = RawStr::from_str("Ordering");
}

impl InstallWith for Ordering {}
14 changes: 6 additions & 8 deletions crates/rune/src/modules/cmp.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! The `std::cmp` module.
use core::cmp;
use core::cmp::Ordering;

use crate::runtime::Protocol;
use crate::{ContextError, Module};
Expand All @@ -9,7 +9,7 @@ use crate::{ContextError, Module};
pub fn module() -> Result<Module, ContextError> {
let mut module = Module::with_crate_item("std", ["cmp"]);

let ty = module.ty::<cmp::Ordering>()?.docs([
let ty = module.ty::<Ordering>()?.docs([
"An `Ordering` is the result of a comparison between two values.",
"",
"# Examples",
Expand All @@ -32,21 +32,19 @@ pub fn module() -> Result<Module, ContextError> {

ty.variant_mut(0)?
.make_empty()?
.constructor(|| cmp::Ordering::Less)?
.constructor(|| Ordering::Less)?
.docs(["An ordering where a compared value is less than another."]);

ty.variant_mut(1)?
.make_empty()?
.constructor(|| cmp::Ordering::Equal)?
.constructor(|| Ordering::Equal)?
.docs(["An ordering where a compared value is equal to another."]);

ty.variant_mut(2)?
.make_empty()?
.constructor(|| cmp::Ordering::Greater)?
.constructor(|| Ordering::Greater)?
.docs(["An ordering where a compared value is greater than another."]);

module.associated_function(Protocol::EQ, |lhs: cmp::Ordering, rhs: cmp::Ordering| {
lhs == rhs
})?;
module.associated_function(Protocol::EQ, |lhs: Ordering, rhs: Ordering| lhs == rhs)?;
Ok(module)
}
2 changes: 1 addition & 1 deletion crates/rune/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ mod static_type;
pub use self::static_type::{
StaticType, BOOL_TYPE, BYTES_TYPE, BYTE_TYPE, BYTE_TYPE_HASH, CHAR_TYPE, FLOAT_TYPE,
FLOAT_TYPE_HASH, FORMAT_TYPE, FUNCTION_TYPE, FUTURE_TYPE, GENERATOR_STATE_TYPE, GENERATOR_TYPE,
INTEGER_TYPE, INTEGER_TYPE_HASH, ITERATOR_TYPE, OBJECT_TYPE, OPTION_TYPE, RANGE_TYPE,
INTEGER_TYPE, INTEGER_TYPE_HASH, ITERATOR_TYPE, OBJECT_TYPE, OPTION_TYPE, ORDERING, RANGE_TYPE,
RESULT_TYPE, STREAM_TYPE, STRING_TYPE, TUPLE_TYPE, TYPE, UNIT_TYPE, VEC_TYPE,
};

Expand Down
45 changes: 23 additions & 22 deletions crates/rune/src/runtime/from_value.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::any;
use core::cmp::Ordering;

use crate::no_std::collections::HashMap;
use crate::no_std::prelude::*;
Expand Down Expand Up @@ -252,23 +253,6 @@ impl UnsafeFromValue for &mut Option<Value> {
}
}

impl UnsafeFromValue for &mut Result<Value, Value> {
type Output = *mut Result<Value, Value>;
type Guard = RawMut;

fn from_value(value: Value) -> VmResult<(Self::Output, Self::Guard)> {
let result = vm_try!(value.into_result());
let result = vm_try!(result.into_mut());
VmResult::Ok(Mut::into_raw(result))
}

unsafe fn unsafe_coerce(output: Self::Output) -> Self {
&mut *output
}
}

// String impls

impl FromValue for String {
fn from_value(value: Value) -> VmResult<Self> {
match value {
Expand Down Expand Up @@ -309,6 +293,7 @@ impl FromValue for Box<str> {
///
/// Note that we need to hold onto an instance of the static string to prevent
/// the reference to it from being deallocated (the `StaticString` variant).
#[non_exhaustive]
pub enum StrGuard {
RawRef(RawRef),
StaticString(Arc<StaticString>),
Expand Down Expand Up @@ -408,8 +393,6 @@ impl UnsafeFromValue for &mut String {
}
}

// Result impls

impl<T, E> FromValue for Result<T, E>
where
T: FromValue,
Expand Down Expand Up @@ -438,7 +421,20 @@ impl UnsafeFromValue for &Result<Value, Value> {
}
}

// number impls
impl UnsafeFromValue for &mut Result<Value, Value> {
type Output = *mut Result<Value, Value>;
type Guard = RawMut;

fn from_value(value: Value) -> VmResult<(Self::Output, Self::Guard)> {
let result = vm_try!(value.into_result());
let result = vm_try!(result.into_mut());
VmResult::Ok(Mut::into_raw(result))
}

unsafe fn unsafe_coerce(output: Self::Output) -> Self {
&mut *output
}
}

impl FromValue for () {
fn from_value(value: Value) -> VmResult<Self> {
Expand Down Expand Up @@ -517,8 +513,6 @@ impl FromValue for f32 {
}
}

// map impls

macro_rules! impl_map {
($ty:ty) => {
impl<T> FromValue for $ty
Expand All @@ -542,3 +536,10 @@ macro_rules! impl_map {
}

impl_map!(HashMap<String, T>);

impl FromValue for Ordering {
#[inline]
fn from_value(value: Value) -> VmResult<Self> {
value.into_ordering()
}
}
15 changes: 12 additions & 3 deletions crates/rune/src/runtime/static_type.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::cmp;
use core::cmp::{Eq, Ordering, PartialEq};
use core::hash;

use crate::no_std::collections::HashMap;
Expand Down Expand Up @@ -26,13 +26,13 @@ impl StaticType {
}
}

impl cmp::PartialEq for &'static StaticType {
impl PartialEq for &'static StaticType {
fn eq(&self, other: &Self) -> bool {
self.hash == other.hash
}
}

impl cmp::Eq for &'static StaticType {}
impl Eq for &'static StaticType {}

impl hash::Hash for &'static StaticType {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
Expand Down Expand Up @@ -263,3 +263,12 @@ pub static TYPE: &StaticType = &StaticType {
};

impl_static_type!(rt::Type => TYPE);

/// The specialized type information for type objects.
pub static ORDERING: &StaticType = &StaticType {
name: RawStr::from_str("Ordering"),
// hash for ::std::cmp::Ordering
hash: Hash::new(0x30d24cc3fa13e4b7),
};

impl_static_type!(Ordering => ORDERING);
9 changes: 9 additions & 0 deletions crates/rune/src/runtime/to_value.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::any;
use core::cmp::Ordering;

use crate::no_std::collections::HashMap;
use crate::no_std::prelude::*;
Expand Down Expand Up @@ -247,6 +248,7 @@ number_value_trait!(i128);
number_value_trait!(isize);

impl ToValue for f32 {
#[inline]
fn to_value(self) -> VmResult<Value> {
VmResult::Ok(Value::Float(self as f64))
}
Expand Down Expand Up @@ -274,3 +276,10 @@ macro_rules! impl_map {
}

impl_map!(HashMap<String, T>);

impl ToValue for Ordering {
#[inline]
fn to_value(self) -> VmResult<Value> {
VmResult::Ok(Value::Ordering(self))
}
}
Loading

0 comments on commit ceb177f

Please sign in to comment.