Skip to content

Commit

Permalink
Support external tuple ops
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Jul 30, 2023
1 parent a6326c2 commit 75cfbb2
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 14 deletions.
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
19 changes: 16 additions & 3 deletions crates/rune/src/runtime/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1255,9 +1255,20 @@ impl Vm {
vm_try!(<()>::from_value(value));
VmResult::Ok(())
}
TargetFallback::Index(lhs, ..) => err(VmErrorKind::UnsupportedTupleIndexGet {
target: vm_try!(lhs.type_info()),
}),
TargetFallback::Index(lhs, index, rhs) => {
if let CallResult::Unsupported(lhs) =
vm_try!(self.call_index_fn(protocol, lhs.clone(), index, (rhs,)))
{
return err(VmErrorKind::UnsupportedTupleIndexGet {
target: vm_try!(lhs.type_info()),
index,
});
}

let value = vm_try!(self.stack.pop());
vm_try!(<()>::from_value(value));
VmResult::Ok(())
}
}
}

Expand Down Expand Up @@ -2187,6 +2198,7 @@ impl Vm {
{
return err(VmErrorKind::UnsupportedTupleIndexGet {
target: vm_try!(value.type_info()),
index,
});
}

Expand Down Expand Up @@ -2226,6 +2238,7 @@ impl Vm {
{
return err(VmErrorKind::UnsupportedTupleIndexGet {
target: vm_try!(value.type_info()),
index,
});
}

Expand Down
9 changes: 5 additions & 4 deletions crates/rune/src/runtime/vm_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,8 @@ impl<T> VmResult<T> {

#[doc(hidden)]
#[inline]
pub fn __rune_macros__unsupported_tuple_index_get(target: TypeInfo) -> Self {
Self::err(VmErrorKind::UnsupportedTupleIndexGet { target })
pub fn __rune_macros__unsupported_tuple_index_get(target: TypeInfo, index: usize) -> Self {
Self::err(VmErrorKind::UnsupportedTupleIndexGet { target, index })
}
}

Expand Down Expand Up @@ -475,6 +475,7 @@ pub(crate) enum VmErrorKind {
},
UnsupportedTupleIndexGet {
target: TypeInfo,
index: usize,
},
UnsupportedTupleIndexSet {
target: TypeInfo,
Expand Down Expand Up @@ -658,9 +659,9 @@ impl fmt::Display for VmErrorKind {
f,
"The index get operation `{target}[{index}]` is not supported",
),
VmErrorKind::UnsupportedTupleIndexGet { target } => write!(
VmErrorKind::UnsupportedTupleIndexGet { target, index } => write!(
f,
"The tuple index get operation is not supported on `{target}`",
"The tuple index get {index} operation is not supported on `{target}`",
),
VmErrorKind::UnsupportedTupleIndexSet { target } => write!(
f,
Expand Down
66 changes: 60 additions & 6 deletions crates/rune/src/tests/external_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ fn assign_ops_struct() -> Result<()> {
}

#[test]
#[ignore = "Currently does not work, but should!"]
fn assign_ops_tuple() -> Result<()> {
macro_rules! test_case {
([$($op:tt)*], $protocol:ident, $derived:tt, $initial:literal, $arg:literal, $expected:literal) => {{
Expand Down Expand Up @@ -153,10 +152,10 @@ fn assign_ops_tuple() -> Result<()> {

let output = vm.clone().call(["type"], (&mut foo,))?;

assert_eq!(foo.0, $expected, "{} != {} (value)", foo.0, $expected);
assert_eq!(foo.1, $expected, "{} != {} (field)", foo.1, $expected);
assert_eq!(foo.2, $expected, "{} != {} (derived)", foo.2, $expected);
assert_eq!(foo.3, $expected, "{} != {} (custom)", foo.3, $expected);
assert_eq!(foo.0, $expected, "{} != {} (value .0)", foo.0, $expected);
assert_eq!(foo.1, $expected, "{} != {} (field .1)", foo.1, $expected);
assert_eq!(foo.2, $expected, "{} != {} (derived .2)", foo.2, $expected);
assert_eq!(foo.3, $expected, "{} != {} (custom .3)", foo.3, $expected);
assert!(matches!(output, Value::Unit));
}
}};
Expand All @@ -176,7 +175,7 @@ fn assign_ops_tuple() -> Result<()> {
}

#[test]
fn binary_ops_struct() -> Result<()> {
fn ordering_struct() -> Result<()> {
macro_rules! test_case {
([$($op:tt)*], $protocol:ident, $initial:literal, $arg:literal, $expected:literal) => {{
#[derive(Debug, Default, Any)]
Expand Down Expand Up @@ -241,6 +240,61 @@ fn binary_ops_struct() -> Result<()> {
test_case!([<=], CMP, 2, 3, true);
test_case!([<=], CMP, 2, 2, true);
test_case!([<=], CMP, 2, 1, false);
Ok(())
}

#[test]
fn eq_struct() -> Result<()> {
macro_rules! test_case {
([$($op:tt)*], $protocol:ident, $initial:literal, $arg:literal, $expected:literal) => {{
#[derive(Debug, Default, Any)]
struct External {
value: i64,
}

impl External {
fn value(&self, value: i64) -> bool {
self.value $($op)* value
}
}

let mut module = Module::new();
module.ty::<External>()?;

module.associated_function(Protocol::$protocol, External::value)?;

let mut context = Context::with_default_modules()?;
context.install(module)?;

let mut sources = Sources::new();
sources.insert(Source::new(
"test",
format!(r#"
pub fn type(number) {{
number {op} {arg}
}}
"#, op = stringify!($($op)*), arg = stringify!($arg)),
));

let unit = prepare(&mut sources)
.with_context(&context)
.build()?;

let unit = Arc::new(unit);

let vm = Vm::new(Arc::new(context.runtime()), unit);

{
let mut foo = External::default();
foo.value = $initial;

let output = vm.clone().call(["type"], (&mut foo,))?;
let a = <bool as FromValue>::from_value(output).into_result()?;

assert_eq!(a, $expected, "{} != {} (value)", foo.value, $expected);
}
}};
}

test_case!([==], EQ, 2, 2, true);
test_case!([==], EQ, 2, 1, false);
Expand Down

0 comments on commit 75cfbb2

Please sign in to comment.