256 lines
4.3 KiB
Rust
256 lines
4.3 KiB
Rust
use super::harness::*;
|
|
use cagire::forth::Value;
|
|
|
|
fn int(n: i64) -> Value {
|
|
Value::Int(n, None)
|
|
}
|
|
|
|
#[test]
|
|
fn dup() {
|
|
expect_stack("3 dup", &[int(3), int(3)]);
|
|
}
|
|
|
|
#[test]
|
|
fn dup_underflow() {
|
|
expect_error("dup", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn dupn() {
|
|
expect_stack("2 4 dupn", &[int(2), int(2), int(2), int(2)]);
|
|
}
|
|
|
|
#[test]
|
|
fn dupn_one() {
|
|
expect_stack("5 1 dupn", &[int(5)]);
|
|
}
|
|
|
|
#[test]
|
|
fn dupn_zero() {
|
|
expect_stack("5 0 dupn", &[]);
|
|
}
|
|
|
|
#[test]
|
|
fn dupn_underflow() {
|
|
expect_error("3 dupn", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn drop() {
|
|
expect_stack("1 2 drop", &[int(1)]);
|
|
}
|
|
|
|
#[test]
|
|
fn drop_underflow() {
|
|
expect_error("drop", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn swap() {
|
|
expect_stack("1 2 swap", &[int(2), int(1)]);
|
|
}
|
|
|
|
#[test]
|
|
fn swap_underflow() {
|
|
expect_error("1 swap", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn over() {
|
|
expect_stack("1 2 over", &[int(1), int(2), int(1)]);
|
|
}
|
|
|
|
#[test]
|
|
fn over_underflow() {
|
|
expect_error("1 over", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn rot() {
|
|
expect_stack("1 2 3 rot", &[int(2), int(3), int(1)]);
|
|
}
|
|
|
|
#[test]
|
|
fn rot_underflow() {
|
|
expect_error("1 2 rot", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn nip() {
|
|
expect_stack("1 2 nip", &[int(2)]);
|
|
}
|
|
|
|
#[test]
|
|
fn nip_underflow() {
|
|
expect_error("1 nip", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn tuck() {
|
|
expect_stack("1 2 tuck", &[int(2), int(1), int(2)]);
|
|
}
|
|
|
|
#[test]
|
|
fn tuck_underflow() {
|
|
expect_error("1 tuck", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn dup2() {
|
|
expect_stack("1 2 2dup", &[int(1), int(2), int(1), int(2)]);
|
|
}
|
|
|
|
#[test]
|
|
fn dup2_underflow() {
|
|
expect_error("1 2dup", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn drop2() {
|
|
expect_stack("1 2 3 2drop", &[int(1)]);
|
|
}
|
|
|
|
#[test]
|
|
fn drop2_underflow() {
|
|
expect_error("1 2drop", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn swap2() {
|
|
expect_stack("1 2 3 4 2swap", &[int(3), int(4), int(1), int(2)]);
|
|
}
|
|
|
|
#[test]
|
|
fn swap2_underflow() {
|
|
expect_error("1 2 3 2swap", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn over2() {
|
|
expect_stack("1 2 3 4 2over", &[int(1), int(2), int(3), int(4), int(1), int(2)]);
|
|
}
|
|
|
|
#[test]
|
|
fn over2_underflow() {
|
|
expect_error("1 2 3 2over", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn stack_persists() {
|
|
let f = forth();
|
|
let ctx = default_ctx();
|
|
f.evaluate("1 2 3", &ctx).unwrap();
|
|
assert_eq!(f.stack(), vec![int(1), int(2), int(3)]);
|
|
f.evaluate("4 5", &ctx).unwrap();
|
|
assert_eq!(f.stack(), vec![int(1), int(2), int(3), int(4), int(5)]);
|
|
}
|
|
|
|
#[test]
|
|
fn clear_stack() {
|
|
let f = forth();
|
|
f.evaluate("1 2 3", &default_ctx()).unwrap();
|
|
f.clear_stack();
|
|
assert!(f.stack().is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn rev() {
|
|
expect_stack("1 2 3 3 rev", &[int(3), int(2), int(1)]);
|
|
}
|
|
|
|
#[test]
|
|
fn rev_partial() {
|
|
expect_stack("1 2 3 4 2 rev", &[int(1), int(2), int(4), int(3)]);
|
|
}
|
|
|
|
#[test]
|
|
fn rev_one() {
|
|
expect_stack("1 2 3 1 rev", &[int(1), int(2), int(3)]);
|
|
}
|
|
|
|
#[test]
|
|
fn rev_zero() {
|
|
expect_stack("1 2 3 0 rev", &[int(1), int(2), int(3)]);
|
|
}
|
|
|
|
#[test]
|
|
fn rev_underflow() {
|
|
expect_error("1 2 5 rev", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn shuffle_preserves_elements() {
|
|
let f = forth();
|
|
f.evaluate("1 2 3 4 4 shuffle", &default_ctx()).unwrap();
|
|
let mut stack: Vec<i64> = f
|
|
.stack()
|
|
.iter()
|
|
.map(|v| match v {
|
|
Value::Int(n, _) => *n,
|
|
_ => panic!("expected int"),
|
|
})
|
|
.collect();
|
|
stack.sort();
|
|
assert_eq!(stack, vec![1, 2, 3, 4]);
|
|
}
|
|
|
|
#[test]
|
|
fn shuffle_underflow() {
|
|
expect_error("1 2 5 shuffle", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn sort() {
|
|
expect_stack("3 1 4 1 5 5 sort", &[int(1), int(1), int(3), int(4), int(5)]);
|
|
}
|
|
|
|
#[test]
|
|
fn sort_partial() {
|
|
expect_stack("9 3 1 2 3 sort", &[int(9), int(1), int(2), int(3)]);
|
|
}
|
|
|
|
#[test]
|
|
fn sort_underflow() {
|
|
expect_error("1 2 5 sort", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn rsort() {
|
|
expect_stack("1 3 2 3 rsort", &[int(3), int(2), int(1)]);
|
|
}
|
|
|
|
#[test]
|
|
fn sum() {
|
|
expect_stack("1 2 3 4 4 sum", &[int(10)]);
|
|
}
|
|
|
|
#[test]
|
|
fn sum_single() {
|
|
expect_stack("42 1 sum", &[int(42)]);
|
|
}
|
|
|
|
#[test]
|
|
fn sum_zero() {
|
|
expect_stack("1 2 3 0 sum", &[int(1), int(2), int(3), int(0)]);
|
|
}
|
|
|
|
#[test]
|
|
fn sum_underflow() {
|
|
expect_error("1 2 5 sum", "stack underflow");
|
|
}
|
|
|
|
#[test]
|
|
fn prod() {
|
|
expect_stack("2 3 4 3 prod", &[int(24)]);
|
|
}
|
|
|
|
#[test]
|
|
fn prod_single() {
|
|
expect_stack("7 1 prod", &[int(7)]);
|
|
}
|
|
|
|
#[test]
|
|
fn prod_zero_count() {
|
|
expect_stack("1 2 3 0 prod", &[int(1), int(2), int(3), int(1)]);
|
|
}
|