Add ranges.

This commit is contained in:
Stephen Chung
2021-12-15 12:06:17 +08:00
parent 7251f34bce
commit ef14079c61
35 changed files with 1206 additions and 269 deletions

View File

@@ -26,10 +26,12 @@ fn test_bit_fields() -> Result<(), Box<EvalAltResult>> {
9
);
assert_eq!(engine.eval::<INT>("let x = 10; get_bits(x, 1, 3)")?, 5);
assert_eq!(engine.eval::<INT>("let x = 10; x[1..=3]")?, 5);
assert_eq!(
engine.eval::<INT>("let x = 10; set_bits(x, 1, 3, 7); x")?,
14
);
assert_eq!(engine.eval::<INT>("let x = 10; x[1..4] = 7; x")?, 14);
assert_eq!(
engine.eval::<INT>(
"
@@ -45,6 +47,21 @@ fn test_bit_fields() -> Result<(), Box<EvalAltResult>> {
)?,
5
);
assert_eq!(
engine.eval::<INT>(
"
let x = 0b001101101010001;
let count = 0;
for b in bits(x, 2..=11) {
if b { count += 1; }
}
count
"
)?,
5
);
Ok(())
}

View File

@@ -81,57 +81,83 @@ fn test_blobs_parse() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,2,0)"
)?,
engine
.eval::<INT>("let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,2,0)")?,
0
);
assert_eq!(
engine
.eval::<INT>("let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,2,9)")?,
0x0908070605040302
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,2,9)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,2..=11)"
)?,
0x0908070605040302
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_be_int(x,2,10)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,2..11)"
)?,
0x0908070605040302
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_be_int(x,2,10)"
)?,
0x0203040506070809
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,-5,99)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_be_int(x,2..12)"
)?,
0x0203040506070809
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,-5,99)"
)?,
0x0f0e0d0c0b
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,-5,2)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,-5,2)"
)?,
0x0c0b
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,-99,99)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,-99,99)"
)?,
0x0706050403020100
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } write_be(x, 3, 3, -98765432); parse_be_int(x, 3, 3)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } write_be(x, 3, 3, -98765432); parse_be_int(x, 3, 3)"
)?,
0xffffff0000000000_u64 as INT
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } write_le(x, 3, 3, -98765432); parse_le_int(x, 3, 3)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } write_be(x, 3..=5, -98765432); parse_be_int(x, 3..6)"
)?,
0xffffff0000000000_u64 as INT
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } write_le(x, 3, 3, -98765432); parse_le_int(x, 3, 3)"
)?,
0x1cf588
);
@@ -145,57 +171,62 @@ fn test_blobs_parse() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,2,0)"
)?,
engine
.eval::<INT>("let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,2,0)")?,
0
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,2,9)"
)?,
engine
.eval::<INT>("let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,2,9)")?,
0x05040302
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_be_int(x,2,10)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_be_int(x,2,10)"
)?,
0x02030405
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,-5,99)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,-5,99)"
)?,
0x0e0d0c0b
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,-5,2)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,-5,2)"
)?,
0x0c0b
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } parse_le_int(x,-99,99)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } parse_le_int(x,-99,99)"
)?,
0x03020100
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } write_be(x, 3, 3, -98765432); parse_be_int(x, 3, 3)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } write_be(x, 3, 3, -98765432); parse_be_int(x, 3, 3)"
)?,
0xfa1cf500_u32 as INT
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in range(0, 16) { x[n] = n; } write_le(x, 3, 3, -98765432); parse_le_int(x, 3, 3)"
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } write_be(x, 3..=5, -98765432); parse_be_int(x, 3..6)"
)?,
0xfa1cf500_u32 as INT
);
assert_eq!(
engine.eval::<INT>(
"let x = blob(16, 0); for n in 0..16 { x[n] = n; } write_le(x, 3, 3, -98765432); parse_le_int(x, 3, 3)"
)?,
0x1cf588
);

View File

@@ -64,6 +64,28 @@ fn test_for_loop() -> Result<(), Box<EvalAltResult>> {
45
);
assert_eq!(
engine.eval::<INT>(
"
let sum = 0;
for x in 1..10 { sum += x; }
sum
"
)?,
45
);
assert_eq!(
engine.eval::<INT>(
"
let sum = 0;
for x in 1..=10 { sum += x; }
sum
"
)?,
55
);
assert_eq!(
engine.eval::<INT>(
"
@@ -247,18 +269,37 @@ fn test_for_overflow() -> Result<(), Box<EvalAltResult>> {
fn test_for_string() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
let script = r#"
let s = "hello";
let sum = 0;
assert_eq!(
engine.eval::<INT>(
r#"
let s = "hello";
let sum = 0;
for ch in chars(s) {
sum += to_int(ch);
}
for ch in chars(s) {
sum += to_int(ch);
}
sum
"#;
sum
"#
)?,
532
);
assert_eq!(engine.eval::<INT>(script)?, 532);
assert_eq!(
engine.eval::<INT>(
r#"
let s = "hello";
let sum = 0;
for ch in chars(s, 2..=3) {
sum += to_int(ch);
}
sum
"#
)?,
216
);
Ok(())
}

View File

@@ -205,7 +205,7 @@ fn test_module_resolver() -> Result<(), Box<EvalAltResult>> {
r#"
let sum = 0;
for x in range(0, 10) {
for x in 0..10 {
import "hello" as h;
sum += h::answer;
}
@@ -229,7 +229,7 @@ fn test_module_resolver() -> Result<(), Box<EvalAltResult>> {
sum += h::answer;
}
for x in range(0, 10) {
for x in 0..10 {
foo();
}
@@ -249,7 +249,7 @@ fn test_module_resolver() -> Result<(), Box<EvalAltResult>> {
import "hello" as h;
}
for x in range(0, 10) {
for x in 0..10 {
foo();
}
"#,

View File

@@ -4,6 +4,8 @@ use rhai::{Engine, EvalAltResult, INT};
#[test]
fn test_max_operations() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
#[cfg(not(feature = "no_optimize"))]
engine.set_optimization_level(rhai::OptimizationLevel::None);
engine.set_max_operations(500);
engine.on_progress(|count| {
@@ -17,14 +19,14 @@ fn test_max_operations() -> Result<(), Box<EvalAltResult>> {
assert!(matches!(
*engine
.eval::<()>("for x in range(0, 500) {}")
.eval::<()>("for x in 0..500 {}")
.expect_err("should error"),
EvalAltResult::ErrorTooManyOperations(_)
));
engine.set_max_operations(0);
engine.eval::<()>("for x in range(0, 10000) {}")?;
engine.eval::<()>("for x in 0..10000 {}")?;
Ok(())
}
@@ -101,7 +103,7 @@ fn test_max_operations_eval() -> Result<(), Box<EvalAltResult>> {
*engine
.eval::<()>(
r#"
let script = "for x in range(0, 500) {}";
let script = "for x in 0..500 {}";
eval(script);
"#
)
@@ -115,6 +117,8 @@ fn test_max_operations_eval() -> Result<(), Box<EvalAltResult>> {
#[test]
fn test_max_operations_progress() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
#[cfg(not(feature = "no_optimize"))]
engine.set_optimization_level(rhai::OptimizationLevel::None);
engine.set_max_operations(500);
engine.on_progress(|count| {
@@ -127,7 +131,7 @@ fn test_max_operations_progress() -> Result<(), Box<EvalAltResult>> {
assert!(matches!(
*engine
.eval::<()>("for x in range(0, 500) {}")
.eval::<()>("for x in 0..500 {}")
.expect_err("should error"),
EvalAltResult::ErrorTerminated(x, _) if x.as_int()? == 42
));

View File

@@ -784,7 +784,7 @@ fn test_serde_blob() -> Result<(), Box<EvalAltResult>> {
let r = engine.eval::<Dynamic>(
"
let x = blob(10);
for i in range(0, 10) { x[i] = i; }
for i in 0..10 { x[i] = i; }
x
",
)?;

View File

@@ -6,6 +6,33 @@ fn test_switch() -> Result<(), Box<EvalAltResult>> {
let mut scope = Scope::new();
scope.push("x", 42 as INT);
assert_eq!(
engine.eval::<char>("switch 2 { 1 => (), 2 => 'a', 42 => true }")?,
'a'
);
assert_eq!(
engine.eval::<()>("switch 3 { 1 => (), 2 => 'a', 42 => true }")?,
()
);
assert_eq!(
engine.eval::<INT>("switch 3 { 1 => (), 2 => 'a', 42 => true, _ => 123 }")?,
123
);
assert_eq!(
engine.eval_with_scope::<INT>(
&mut scope,
"switch 2 { 1 => (), 2 if x < 40 => 'a', 42 => true, _ => 123 }"
)?,
123
);
assert_eq!(
engine.eval_with_scope::<char>(
&mut scope,
"switch 2 { 1 => (), 2 if x > 40 => 'a', 42 => true, _ => 123 }"
)?,
'a'
);
assert_eq!(
engine.eval_with_scope::<bool>(&mut scope, "switch x { 1 => (), 2 => 'a', 42 => true }")?,
true
@@ -210,3 +237,66 @@ mod test_switch_enum {
Ok(())
}
}
#[test]
fn test_switch_ranges() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
let mut scope = Scope::new();
scope.push("x", 42 as INT);
assert_eq!(
engine.eval_with_scope::<char>(
&mut scope,
"switch x { 10..20 => (), 20..=42 => 'a', 25..45 => 'z', 30..100 => true }"
)?,
'a'
);
assert_eq!(
engine.eval_with_scope::<char>(
&mut scope,
"switch x { 10..20 => (), 20..=42 if x < 40 => 'a', 25..45 => 'z', 30..100 => true }"
)?,
'z'
);
assert_eq!(
engine.eval_with_scope::<char>(
&mut scope,
"switch x { 42 => 'x', 10..20 => (), 20..=42 => 'a', 25..45 => 'z', 30..100 => true, 'w' => true }"
)?,
'x'
);
assert!(matches!(
*engine.compile("switch x { 10..20 => (), 20..=42 => 'a', 25..45 => 'z', 42 => 'x', 30..100 => true }")
.expect_err("should error").0,
ParseErrorType::WrongSwitchIntegerCase
));
assert_eq!(
engine.eval_with_scope::<char>(
&mut scope,
"
switch 5 {
'a' => true,
0..10 if x+2==1+2 => print(40+2),
_ => 'x'
}
"
)?,
'x'
);
assert_eq!(
engine.eval_with_scope::<char>(
&mut scope,
"
switch 5 {
'a' => true,
0..10 if x+2==1+2 => print(40+2),
2..12 => 'z',
_ => 'x'
}
"
)?,
'z'
);
Ok(())
}

View File

@@ -42,7 +42,7 @@ fn test_timestamp() -> Result<(), Box<EvalAltResult>> {
assert!(engine.eval::<bool>(
"
let time1 = timestamp();
for x in range(0, 10000) {}
for x in 0..10000 {}
let time2 = timestamp();
time1 <= time2
"