Skip to content

Commit 64078cf

Browse files
committed
Implement partial comparison
1 parent e1ddb7e commit 64078cf

File tree

16 files changed

+488
-73
lines changed

16 files changed

+488
-73
lines changed

crates/rune/src/modules/collections/vec_deque.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub(super) fn setup(m: &mut Module) -> Result<(), ContextError> {
5757
m.associated_function(Protocol::STRING_DEBUG, VecDeque::string_debug)?;
5858
m.associated_function(Protocol::PARTIAL_EQ, VecDeque::partial_eq)?;
5959
m.associated_function(Protocol::EQ, VecDeque::eq)?;
60+
m.associated_function(Protocol::PARTIAL_CMP, VecDeque::partial_cmp)?;
6061
m.associated_function(Protocol::CMP, VecDeque::cmp)?;
6162
Ok(())
6263
}
@@ -548,11 +549,31 @@ impl VecDeque {
548549
VmResult::Ok(true)
549550
}
550551

552+
fn partial_cmp(this: &VecDeque, other: &VecDeque) -> VmResult<Option<Ordering>> {
553+
let mut b = other.inner.iter();
554+
555+
for a in this.inner.iter() {
556+
let Some(b) = b.next() else {
557+
return VmResult::Ok(Some(Ordering::Greater));
558+
};
559+
560+
match vm_try!(Value::partial_cmp(a, b)) {
561+
Some(Ordering::Equal) => (),
562+
other => return VmResult::Ok(other),
563+
}
564+
}
565+
566+
if b.next().is_some() {
567+
return VmResult::Ok(Some(Ordering::Less));
568+
};
569+
570+
VmResult::Ok(Some(Ordering::Equal))
571+
}
572+
551573
fn cmp(this: &VecDeque, other: &VecDeque) -> VmResult<Ordering> {
552-
let mut a = this.inner.iter();
553574
let mut b = other.inner.iter();
554575

555-
while let Some(a) = a.next() {
576+
for a in this.inner.iter() {
556577
let Some(b) = b.next() else {
557578
return VmResult::Ok(Ordering::Greater);
558579
};

crates/rune/src/modules/object.rs

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,40 @@
11
//! The `std::object` module.
22
3+
use core::cmp::Ordering;
4+
35
use crate::no_std::prelude::*;
46

57
use crate as rune;
6-
use crate::runtime::{Iterator, Object, Protocol, Value};
8+
use crate::runtime::{
9+
EnvProtocolCaller, FromValue, Iterator, Object, Protocol, Ref, Value, VmResult,
10+
};
711
use crate::{ContextError, Module};
812

913
/// Construct the `std::object` module.
1014
pub fn module() -> Result<Module, ContextError> {
11-
let mut module = Module::with_crate_item("std", ["object"]);
12-
13-
module.ty::<Object>()?;
14-
15-
module.function_meta(Object::new__meta)?;
16-
module.function_meta(Object::with_capacity__meta)?;
17-
module.function_meta(Object::len__meta)?;
18-
module.function_meta(Object::is_empty__meta)?;
19-
module.function_meta(Object::insert__meta)?;
20-
module.function_meta(remove)?;
21-
module.function_meta(Object::clear__meta)?;
22-
module.function_meta(contains_key)?;
23-
module.function_meta(get)?;
24-
25-
module.function_meta(Object::rune_iter__meta)?;
26-
module.associated_function(Protocol::INTO_ITER, Object::rune_iter)?;
27-
module.function_meta(keys)?;
28-
module.function_meta(values)?;
29-
Ok(module)
15+
let mut m = Module::with_crate_item("std", ["object"]);
16+
17+
m.ty::<Object>()?;
18+
19+
m.function_meta(Object::new__meta)?;
20+
m.function_meta(Object::with_capacity__meta)?;
21+
m.function_meta(Object::len__meta)?;
22+
m.function_meta(Object::is_empty__meta)?;
23+
m.function_meta(Object::insert__meta)?;
24+
m.function_meta(remove)?;
25+
m.function_meta(Object::clear__meta)?;
26+
m.function_meta(contains_key)?;
27+
m.function_meta(get)?;
28+
29+
m.function_meta(Object::rune_iter__meta)?;
30+
m.function_meta(keys)?;
31+
m.function_meta(values)?;
32+
m.associated_function(Protocol::INTO_ITER, Object::rune_iter)?;
33+
m.associated_function(Protocol::PARTIAL_EQ, partial_eq)?;
34+
m.associated_function(Protocol::EQ, eq)?;
35+
m.associated_function(Protocol::PARTIAL_CMP, partial_cmp)?;
36+
m.associated_function(Protocol::CMP, cmp)?;
37+
Ok(m)
3038
}
3139

3240
/// Returns `true` if the map contains a value for the specified key.
@@ -117,3 +125,41 @@ fn values(object: &Object) -> Iterator {
117125
let iter = object.values().cloned().collect::<Vec<_>>().into_iter();
118126
Iterator::from_double_ended("std::object::Values", iter)
119127
}
128+
129+
fn partial_eq(this: &Object, other: Value) -> VmResult<bool> {
130+
let mut other = vm_try!(other.into_iter());
131+
132+
for (k1, v1) in this.iter() {
133+
let Some(value) = vm_try!(other.next()) else {
134+
return VmResult::Ok(false);
135+
};
136+
137+
let (k2, v2) = vm_try!(<(Ref<String>, Value)>::from_value(value));
138+
139+
if k1 != &*k2 {
140+
return VmResult::Ok(false);
141+
}
142+
143+
if !vm_try!(Value::partial_eq(v1, &v2)) {
144+
return VmResult::Ok(false);
145+
}
146+
}
147+
148+
if vm_try!(other.next()).is_some() {
149+
return VmResult::Ok(false);
150+
}
151+
152+
VmResult::Ok(true)
153+
}
154+
155+
fn eq(this: &Object, other: &Object) -> VmResult<bool> {
156+
Object::eq_with(this, other, &mut EnvProtocolCaller)
157+
}
158+
159+
fn partial_cmp(this: &Object, other: &Object) -> VmResult<Option<Ordering>> {
160+
Object::partial_cmp_with(this, other, &mut EnvProtocolCaller)
161+
}
162+
163+
fn cmp(this: &Object, other: &Object) -> VmResult<Ordering> {
164+
Object::cmp_with(this, other, &mut EnvProtocolCaller)
165+
}

crates/rune/src/modules/vec.rs

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! The `std::vec` module.
22
3-
use core::cmp;
3+
use core::cmp::Ordering;
44

55
use crate as rune;
66
use crate::no_std::prelude::*;
77
use crate::runtime::{
8-
FromValue, Function, Iterator, Protocol, Ref, Value, Vec, VmErrorKind, VmResult,
8+
EnvProtocolCaller, FromValue, Function, Iterator, Protocol, Ref, Value, Vec, VmErrorKind,
9+
VmResult,
910
};
1011
use crate::{ContextError, Module};
1112

@@ -50,6 +51,8 @@ pub fn module() -> Result<Module, ContextError> {
5051
m.associated_function(Protocol::INDEX_SET, Vec::set)?;
5152
m.associated_function(Protocol::PARTIAL_EQ, partial_eq)?;
5253
m.associated_function(Protocol::EQ, eq)?;
54+
m.associated_function(Protocol::PARTIAL_CMP, partial_cmp)?;
55+
m.associated_function(Protocol::CMP, cmp)?;
5356
Ok(m)
5457
}
5558

@@ -242,14 +245,14 @@ fn get(this: &Vec, index: Value) -> VmResult<Option<Value>> {
242245
fn sort_by(vec: &mut Vec, comparator: &Function) -> VmResult<()> {
243246
let mut error = None;
244247

245-
vec.sort_by(|a, b| match comparator.call::<_, cmp::Ordering>((a, b)) {
248+
vec.sort_by(|a, b| match comparator.call::<_, Ordering>((a, b)) {
246249
VmResult::Ok(ordering) => ordering,
247250
VmResult::Err(e) => {
248251
if error.is_none() {
249252
error = Some(e);
250253
}
251254

252-
cmp::Ordering::Equal
255+
Ordering::Equal
253256
}
254257
});
255258

@@ -544,22 +547,14 @@ fn partial_eq(this: &Vec, other: Value) -> VmResult<bool> {
544547
VmResult::Ok(true)
545548
}
546549

547-
fn eq(this: &Vec, other: Value) -> VmResult<bool> {
548-
let mut other = vm_try!(other.into_iter());
549-
550-
for a in this.as_slice() {
551-
let Some(b) = vm_try!(other.next()) else {
552-
return VmResult::Ok(false);
553-
};
554-
555-
if !vm_try!(Value::eq(a, &b)) {
556-
return VmResult::Ok(false);
557-
}
558-
}
550+
fn eq(this: &Vec, other: &Vec) -> VmResult<bool> {
551+
Vec::eq_with(this, other, &mut EnvProtocolCaller)
552+
}
559553

560-
if vm_try!(other.next()).is_some() {
561-
return VmResult::Ok(false);
562-
}
554+
fn partial_cmp(this: &Vec, other: &Vec) -> VmResult<Option<Ordering>> {
555+
Vec::partial_cmp_with(this, other, &mut EnvProtocolCaller)
556+
}
563557

564-
VmResult::Ok(true)
558+
fn cmp(this: &Vec, other: &Vec) -> VmResult<Ordering> {
559+
Vec::cmp_with(this, other, &mut EnvProtocolCaller)
565560
}

crates/rune/src/runtime/object.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,36 @@ impl Object {
334334
VmResult::Ok(true)
335335
}
336336

337+
pub(crate) fn partial_cmp_with(
338+
a: &Self,
339+
b: &Self,
340+
caller: &mut impl ProtocolCaller,
341+
) -> VmResult<Option<Ordering>> {
342+
let mut b = b.inner.iter();
343+
344+
for (k1, v1) in a.inner.iter() {
345+
let Some((k2, v2)) = b.next() else {
346+
return VmResult::Ok(Some(Ordering::Greater));
347+
};
348+
349+
match k1.partial_cmp(k2) {
350+
Some(Ordering::Equal) => (),
351+
other => return VmResult::Ok(other),
352+
}
353+
354+
match Value::partial_cmp_with(v1, v2, caller) {
355+
VmResult::Ok(Some(Ordering::Equal)) => (),
356+
other => return other,
357+
}
358+
}
359+
360+
if b.next().is_some() {
361+
return VmResult::Ok(Some(Ordering::Less));
362+
}
363+
364+
VmResult::Ok(Some(Ordering::Equal))
365+
}
366+
337367
pub(crate) fn cmp_with(
338368
a: &Self,
339369
b: &Self,

crates/rune/src/runtime/range.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,19 @@ impl Range {
9595
Value::eq_with(&a.end, &b.end, caller)
9696
}
9797

98+
pub(crate) fn partial_cmp_with(
99+
a: &Self,
100+
b: &Self,
101+
caller: &mut impl ProtocolCaller,
102+
) -> VmResult<Option<Ordering>> {
103+
match vm_try!(Value::partial_cmp_with(&a.start, &b.start, caller)) {
104+
Some(Ordering::Equal) => (),
105+
other => return VmResult::Ok(other),
106+
}
107+
108+
Value::partial_cmp_with(&a.end, &b.end, caller)
109+
}
110+
98111
pub(crate) fn cmp_with(
99112
a: &Self,
100113
b: &Self,

crates/rune/src/runtime/range_from.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,27 @@ impl RangeFrom {
7070
b: &Self,
7171
caller: &mut impl ProtocolCaller,
7272
) -> VmResult<bool> {
73-
VmResult::Ok(vm_try!(Value::partial_eq_with(&a.start, &b.start, caller)))
73+
Value::partial_eq_with(&a.start, &b.start, caller)
7474
}
7575

7676
pub(crate) fn eq_with(a: &Self, b: &Self, caller: &mut impl ProtocolCaller) -> VmResult<bool> {
77-
VmResult::Ok(vm_try!(Value::eq_with(&a.start, &b.start, caller)))
77+
Value::eq_with(&a.start, &b.start, caller)
78+
}
79+
80+
pub(crate) fn partial_cmp_with(
81+
a: &Self,
82+
b: &Self,
83+
caller: &mut impl ProtocolCaller,
84+
) -> VmResult<Option<Ordering>> {
85+
Value::partial_cmp_with(&a.start, &b.start, caller)
7886
}
7987

8088
pub(crate) fn cmp_with(
8189
a: &Self,
8290
b: &Self,
8391
caller: &mut impl ProtocolCaller,
8492
) -> VmResult<Ordering> {
85-
VmResult::Ok(vm_try!(Value::cmp_with(&a.start, &b.start, caller)))
93+
Value::cmp_with(&a.start, &b.start, caller)
8694
}
8795

8896
/// Test if the range contains the given integer.

crates/rune/src/runtime/range_full.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ impl RangeFull {
3838
VmResult::Ok(true)
3939
}
4040

41+
pub(crate) fn partial_cmp_with(
42+
_: &Self,
43+
_: &Self,
44+
_: &mut impl ProtocolCaller,
45+
) -> VmResult<Option<Ordering>> {
46+
VmResult::Ok(Some(Ordering::Equal))
47+
}
48+
4149
pub(crate) fn cmp_with(_: &Self, _: &Self, _: &mut impl ProtocolCaller) -> VmResult<Ordering> {
4250
VmResult::Ok(Ordering::Equal)
4351
}

crates/rune/src/runtime/range_inclusive.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,19 @@ impl RangeInclusive {
9595
Value::eq_with(&a.end, &b.end, caller)
9696
}
9797

98+
pub(crate) fn partial_cmp_with(
99+
a: &Self,
100+
b: &Self,
101+
caller: &mut impl ProtocolCaller,
102+
) -> VmResult<Option<Ordering>> {
103+
match vm_try!(Value::partial_cmp_with(&a.start, &b.start, caller)) {
104+
Some(Ordering::Equal) => (),
105+
other => return VmResult::Ok(other),
106+
}
107+
108+
Value::partial_cmp_with(&a.end, &b.end, caller)
109+
}
110+
98111
pub(crate) fn cmp_with(
99112
a: &Self,
100113
b: &Self,

crates/rune/src/runtime/range_to.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ impl RangeTo {
4242
Value::eq_with(&a.end, &b.end, caller)
4343
}
4444

45+
pub(crate) fn partial_cmp_with(
46+
a: &Self,
47+
b: &Self,
48+
caller: &mut impl ProtocolCaller,
49+
) -> VmResult<Option<Ordering>> {
50+
Value::partial_cmp_with(&a.end, &b.end, caller)
51+
}
52+
4553
pub(crate) fn cmp_with(
4654
a: &Self,
4755
b: &Self,

crates/rune/src/runtime/range_to_inclusive.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ impl RangeToInclusive {
4242
Value::eq_with(&a.end, &b.end, caller)
4343
}
4444

45+
pub(crate) fn partial_cmp_with(
46+
a: &Self,
47+
b: &Self,
48+
caller: &mut impl ProtocolCaller,
49+
) -> VmResult<Option<Ordering>> {
50+
Value::partial_cmp_with(&a.end, &b.end, caller)
51+
}
52+
4553
pub(crate) fn cmp_with(
4654
a: &Self,
4755
b: &Self,

0 commit comments

Comments
 (0)