49ad76e7c3
This commit refactors the test suite by removing the monolithic `integration_test.rs` file. The tests have been categorized and moved into dedicated modules within the `tests/` directory: - `tests/parser.rs`: Contains tests for parsing various literal values. - `tests/destructuring.rs`: Houses tests related to destructuring syntax. - `tests/closures.rs`: Includes tests for closure behavior and related optimizations. - `tests/optimizer.rs`: Contains tests specifically targeting optimizer logic and regressions. - `tests/records.rs`: Holds tests for record syntax and associated optimizations. - `tests/rtl.rs`: Contains tests for runtime library operators and functions. - `tests/pipeline.rs`: Tests for pipeline functionality. - `tests/macros.rs`: Tests for macro expansion and related issues. - `tests/error_recovery.rs`: Includes tests for compiler error handling and recovery mechanisms. - `tests/examples.rs`: Verifies the execution of example scripts. This reorganization improves test discoverability and maintainability. The `lib.rs` file has also been updated to reflect these changes by removing the reference to the old `integration_test` module. The `type_checker.rs` file has had some tests removed, as they are now covered by the more specific tests in `tests/error_recovery.rs`.
140 lines
4.1 KiB
Rust
140 lines
4.1 KiB
Rust
use myc::ast::environment::Environment;
|
|
use myc::ast::types::Value;
|
|
|
|
#[test]
|
|
fn test_dynamic_call_destructuring_underflow() {
|
|
let env = Environment::new();
|
|
let source = "(do
|
|
(def call-dynamic (fn [f data] (f data)))
|
|
(def data [10 [20 30]])
|
|
(def x (fn [[a [b c]]] (+ a (+ b c))))
|
|
(call-dynamic x data))";
|
|
|
|
let result = env.run_script(source);
|
|
if let Err(e) = &result {
|
|
panic!("Failed: {}", e);
|
|
}
|
|
assert_eq!(format!("{}", result.unwrap()), "60");
|
|
}
|
|
|
|
#[test]
|
|
fn test_nested_destructuring_optimization() {
|
|
let env = Environment::new();
|
|
|
|
let source_tuple = "((fn [[x y]] (+ x y)) [10 20])";
|
|
assert_eq!(format!("{}", env.run_script(source_tuple).unwrap()), "30");
|
|
let dump_tuple = env.dump_ast(source_tuple).unwrap();
|
|
assert!(
|
|
dump_tuple.contains("Constant: 30"),
|
|
"Nested tuple should be folded to 30. Dump:\n{}",
|
|
dump_tuple
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_def_destructuring() {
|
|
let env = Environment::new();
|
|
|
|
// 1. Global destructuring
|
|
let source_global = "(do (def [a b] [1 2]) (+ a b))";
|
|
assert_eq!(format!("{}", env.run_script(source_global).unwrap()), "3");
|
|
|
|
// 2. Local nested destructuring inside a function
|
|
let source_local =
|
|
"((fn [x] (do (def [a [[b c] d]] x) (+ a (+ b (+ c d))))) [1 [[2 3] 4]])";
|
|
assert_eq!(format!("{}", env.run_script(source_local).unwrap()), "10");
|
|
|
|
// 3. Verify destructuring result manually
|
|
let source_check = "(do (def [x y] [7 8]) [x y])";
|
|
let res = env.run_script(source_check).unwrap();
|
|
if let Value::Tuple(vals) = res {
|
|
assert_eq!(vals.len(), 2);
|
|
assert_eq!(format!("{}", vals[0]), "7");
|
|
assert_eq!(format!("{}", vals[1]), "8");
|
|
} else {
|
|
panic!("Expected tuple from [x y], got {:?}", res);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_assign_destructuring() {
|
|
// 1. Simple assignment destructuring
|
|
{
|
|
let env = Environment::new();
|
|
let source_simple = "(do (def a 0) (def b 0) (assign [a b] [10 20]) (+ a b))";
|
|
assert_eq!(format!("{}", env.run_script(source_simple).unwrap()), "30");
|
|
}
|
|
|
|
// 2. Nested assignment destructuring
|
|
{
|
|
let env = Environment::new();
|
|
let source_nested =
|
|
"(do (def a 0) (def b 0) (def c 0) (assign [a [b c]] [1 [2 3]]) (+ a (+ b c)))";
|
|
assert_eq!(format!("{}", env.run_script(source_nested).unwrap()), "6");
|
|
}
|
|
|
|
// 3. Assignment value check
|
|
{
|
|
let env = Environment::new();
|
|
let source_return = "(do (def a 0) (def b 0) (assign [a b] [5 6]) [a b])";
|
|
let res = env.run_script(source_return).unwrap();
|
|
if let Value::Tuple(vals) = res {
|
|
assert_eq!(vals.len(), 2);
|
|
assert_eq!(format!("{}", vals[0]), "5");
|
|
assert_eq!(format!("{}", vals[1]), "6");
|
|
} else {
|
|
panic!("Expected tuple from [a b], got {:?}", res);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_multi_level_destructuring() {
|
|
let env = Environment::new();
|
|
let source = "(do
|
|
(def process_data (fn [conf]
|
|
(do
|
|
(def [str s] conf)
|
|
(def [f ss] s)
|
|
[\"Symbol:\" str \"field:\" f \"id:\" ss]
|
|
)
|
|
)
|
|
)
|
|
(process_data [\"btc\" [:close \"cls\"]]))";
|
|
|
|
let res = env.run_script(source).unwrap();
|
|
assert_eq!(
|
|
format!("{}", res),
|
|
"[\"Symbol:\" \"btc\" \"field:\" :close \"id:\" \"cls\"]"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_captured_slot_destructuring() {
|
|
let env = Environment::new();
|
|
// A closure capturing both slots from a destructuring def must work correctly.
|
|
let source = r#"
|
|
(do
|
|
(def [x y] [10 20])
|
|
(def get-sum (fn [] (+ x y)))
|
|
(get-sum))
|
|
"#;
|
|
assert_eq!(format!("{}", env.run_script(source).unwrap()), "30");
|
|
}
|
|
|
|
#[test]
|
|
fn test_destructuring_capture_mutation() {
|
|
let env = Environment::new();
|
|
// A closure mutating a slot bound via destructuring must see the updated value.
|
|
let source = r#"
|
|
(do
|
|
(def [a b] [1 2])
|
|
(def inc! (fn [] (assign a (+ a b))))
|
|
(inc!)
|
|
(inc!)
|
|
a)
|
|
"#;
|
|
// 1+2=3, 3+2=5
|
|
assert_eq!(format!("{}", env.run_script(source).unwrap()), "5");
|
|
}
|