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`.
124 lines
3.2 KiB
Rust
124 lines
3.2 KiB
Rust
use myc::ast::environment::Environment;
|
|
|
|
#[test]
|
|
fn test_record_basics() {
|
|
let env = Environment::new();
|
|
let source = r#"
|
|
((fn [user] [(.name user) (.age user)])
|
|
{:name "Alice" :age 30})
|
|
"#;
|
|
let res = env.run_script(source).unwrap();
|
|
assert_eq!(format!("{}", res), "[\"Alice\" 30]");
|
|
}
|
|
|
|
#[test]
|
|
fn test_record_optimized_access() {
|
|
let env = Environment::new();
|
|
let source_eval = "(.price {:id 1 :price 99.5})";
|
|
|
|
let res = env.run_script(source_eval).unwrap();
|
|
assert_eq!(format!("{}", res), "99.5");
|
|
|
|
// Verify optimization to GET_FIELD when the record contains non-constants
|
|
let source_ast = "(fn [id] (.price {:id id :price 99.5}))";
|
|
let dump = env.dump_ast(source_ast).unwrap();
|
|
assert!(
|
|
dump.contains("GetField: .price"),
|
|
"Should be optimized to GetField. Dump:\n{}",
|
|
dump
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_first_class_field_accessor() {
|
|
let env = Environment::new();
|
|
let source = r#"
|
|
(do
|
|
(def get-name .name)
|
|
(get-name {:name "Alice"}))
|
|
"#;
|
|
let res = env.run_script(source).unwrap();
|
|
assert_eq!(format!("{}", res), "\"Alice\"");
|
|
}
|
|
|
|
#[test]
|
|
fn test_record_constant_folding() {
|
|
let env = Environment::new();
|
|
// Optimizer should fold (.x {:x 10}) into 10
|
|
let source = "(.x {:x 10 :y 20})";
|
|
let dump = env.dump_ast(source).unwrap();
|
|
assert!(
|
|
dump.contains("Constant: 10"),
|
|
"Should evaluate GetField at compile time."
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_record_literal_constant_folding() {
|
|
let env = Environment::new();
|
|
let source = " {:a 1 :b 2} ";
|
|
let dump = env.dump_ast(source).unwrap();
|
|
|
|
assert!(
|
|
dump.contains("Constant: {:a 1, :b 2}"),
|
|
"Should transform a pure record literal into a constant value."
|
|
);
|
|
assert!(
|
|
!dump.contains("Record {"),
|
|
"Should not leave a runtime Record node in the AST."
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_record_inlining_in_while_loop() {
|
|
let env_ast = Environment::new();
|
|
let source = r#"
|
|
(do
|
|
(def loop-config {:start 0 :limit 10})
|
|
(def loop-idx 0)
|
|
(while (< loop-idx (.limit loop-config))
|
|
(assign loop-idx (+ loop-idx 1)))
|
|
loop-idx
|
|
)
|
|
"#;
|
|
let dump = env_ast.dump_ast(source).unwrap();
|
|
|
|
assert!(
|
|
dump.contains("Constant: 10") || dump.contains("GetField: .limit"),
|
|
"The limit should be resolved to a constant 10 or kept as GetField."
|
|
);
|
|
|
|
let env_run = Environment::new();
|
|
let res = env_run.run_script(source).unwrap();
|
|
assert_eq!(format!("{}", res), "10");
|
|
}
|
|
|
|
#[test]
|
|
fn test_record_errors() {
|
|
let env = Environment::new();
|
|
|
|
// 1. Missing field
|
|
let res_missing = env.run_script("(.missing {:a 1})");
|
|
assert!(res_missing.is_err());
|
|
assert!(res_missing.unwrap_err().contains("Invalid arguments"));
|
|
|
|
// 2. Not a record
|
|
let res_not_rec = env.run_script("(.name 123)");
|
|
assert!(res_not_rec.is_err());
|
|
assert!(res_not_rec.unwrap_err().contains("Invalid arguments"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_record_layout_interning() {
|
|
let env = Environment::new();
|
|
let source = r#"
|
|
(do
|
|
(def r1 {:a 1 :b 2})
|
|
(def r2 {:a 10 :b 20})
|
|
(= r1 r2))
|
|
"#;
|
|
let res = env.run_script(source).unwrap();
|
|
assert_eq!(format!("{}", res), "false");
|
|
}
|
|
|