use crate::frontend::ast::{Literal, Pattern, StructPatternField};
use crate::runtime::pattern_matching::values_equal;
use crate::runtime::{InterpreterError, Value};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct PatternMatchResult {
pub matches: bool,
pub bindings: HashMap<String, Value>,
}
impl PatternMatchResult {
pub fn success(bindings: HashMap<String, Value>) -> Self {
Self {
matches: true,
bindings,
}
}
pub fn failure() -> Self {
Self {
matches: false,
bindings: HashMap::new(),
}
}
pub fn success_no_bindings() -> Self {
Self {
matches: true,
bindings: HashMap::new(),
}
}
}
pub fn match_pattern(
pattern: &Pattern,
value: &Value,
) -> Result<PatternMatchResult, InterpreterError> {
match pattern {
Pattern::Wildcard => Ok(PatternMatchResult::success_no_bindings()),
Pattern::Identifier(name) => {
let mut bindings = HashMap::new();
bindings.insert(name.clone(), value.clone());
Ok(PatternMatchResult::success(bindings))
}
Pattern::Literal(lit) => {
let pattern_value = eval_pattern_literal(lit)?;
if values_equal(&pattern_value, value) {
Ok(PatternMatchResult::success_no_bindings())
} else {
Ok(PatternMatchResult::failure())
}
}
Pattern::List(patterns) => match_array_pattern(patterns, value),
Pattern::Tuple(patterns) => match_tuple_pattern(patterns, value),
Pattern::Struct { name, fields, .. } => match_struct_pattern(name, fields, value),
Pattern::TupleVariant { path, patterns } => {
match_tuple_variant_pattern(path, patterns, value)
}
Pattern::Ok(inner_pattern) => match_ok_pattern(inner_pattern, value),
Pattern::Err(inner_pattern) => match_err_pattern(inner_pattern, value),
_ => Ok(PatternMatchResult::failure()), }
}
fn match_tuple_variant_pattern(
path: &[String],
patterns: &[Pattern],
value: &Value,
) -> Result<PatternMatchResult, InterpreterError> {
if let Value::EnumVariant {
variant_name, data, ..
} = value
{
let expected_variant = path.last().map_or("", std::string::String::as_str);
if variant_name != expected_variant {
return Ok(PatternMatchResult::failure());
}
match data {
Some(values) => {
if values.len() != patterns.len() {
return Ok(PatternMatchResult::failure());
}
let mut all_bindings = HashMap::new();
for (pattern, val) in patterns.iter().zip(values.iter()) {
let result = match_pattern(pattern, val)?;
if !result.matches {
return Ok(PatternMatchResult::failure());
}
all_bindings.extend(result.bindings);
}
Ok(PatternMatchResult::success(all_bindings))
}
None => {
if patterns.is_empty() {
Ok(PatternMatchResult::success_no_bindings())
} else {
Ok(PatternMatchResult::failure())
}
}
}
} else {
Ok(PatternMatchResult::failure())
}
}
fn match_pattern_slice(
patterns: &[Pattern],
values: &[Value],
) -> Result<PatternMatchResult, InterpreterError> {
if patterns.len() != values.len() {
return Ok(PatternMatchResult::failure());
}
let mut all_bindings = HashMap::new();
for (pattern, val) in patterns.iter().zip(values.iter()) {
let result = match_pattern(pattern, val)?;
if !result.matches {
return Ok(PatternMatchResult::failure());
}
all_bindings.extend(result.bindings);
}
Ok(PatternMatchResult::success(all_bindings))
}
fn match_array_pattern(
patterns: &[Pattern],
value: &Value,
) -> Result<PatternMatchResult, InterpreterError> {
if let Value::Array(arr) = value {
match_pattern_slice(patterns, arr)
} else {
Ok(PatternMatchResult::failure())
}
}
fn match_tuple_pattern(
patterns: &[Pattern],
value: &Value,
) -> Result<PatternMatchResult, InterpreterError> {
if let Value::Tuple(elements) = value {
match_pattern_slice(patterns, elements)
} else {
Ok(PatternMatchResult::failure())
}
}
fn match_struct_pattern(
struct_name: &str,
field_patterns: &[StructPatternField],
value: &Value,
) -> Result<PatternMatchResult, InterpreterError> {
let _ = (struct_name, field_patterns, value);
Ok(PatternMatchResult::failure())
}
fn eval_pattern_literal(literal: &Literal) -> Result<Value, InterpreterError> {
match literal {
Literal::Integer(n, _) => Ok(Value::Integer(*n)),
Literal::Float(f) => Ok(Value::Float(*f)),
Literal::String(s) => Ok(Value::from_string(s.clone())),
Literal::Bool(b) => Ok(Value::Bool(*b)),
Literal::Char(c) => Ok(Value::from_string(c.to_string())),
Literal::Byte(b) => Ok(Value::Byte(*b)),
Literal::Unit => Ok(Value::nil()),
Literal::Null => Ok(Value::nil()),
Literal::Atom(s) => Ok(Value::Atom(s.clone())),
}
}
pub fn extract_pattern_bindings(
pattern: &Pattern,
value: &Value,
) -> Result<HashMap<String, Value>, InterpreterError> {
let result = match_pattern(pattern, value)?;
if result.matches {
Ok(result.bindings)
} else {
Err(InterpreterError::RuntimeError(
"Pattern does not match value".to_string(),
))
}
}
pub fn is_irrefutable_pattern(pattern: &Pattern) -> bool {
match pattern {
Pattern::Wildcard => true,
Pattern::Identifier(_) => true,
Pattern::List(patterns) => patterns.iter().all(is_irrefutable_pattern),
Pattern::Tuple(patterns) => patterns.iter().all(is_irrefutable_pattern),
Pattern::Struct { fields, .. } => fields
.iter()
.all(|field| field.pattern.as_ref().is_none_or(is_irrefutable_pattern)),
_ => false,
}
}
pub fn check_pattern_exhaustiveness(
patterns: &[Pattern],
value_type: &str,
) -> Result<bool, InterpreterError> {
let has_wildcard = patterns.iter().any(|p| matches!(p, Pattern::Wildcard));
let has_identifier = patterns.iter().any(|p| matches!(p, Pattern::Identifier(_)));
if has_wildcard || has_identifier {
return Ok(true);
}
match value_type {
"bool" => {
let has_true = patterns
.iter()
.any(|p| matches!(p, Pattern::Literal(Literal::Bool(true))));
let has_false = patterns
.iter()
.any(|p| matches!(p, Pattern::Literal(Literal::Bool(false))));
Ok(has_true && has_false)
}
"nil" => Ok(patterns
.iter()
.any(|p| matches!(p, Pattern::Literal(Literal::Unit | Literal::Null)))),
_ => {
Ok(patterns.len() >= 2)
}
}
}
fn match_result_pattern(
inner_pattern: &Pattern,
value: &Value,
expected_type: &str,
) -> Result<PatternMatchResult, InterpreterError> {
let fields = match_extract_object_fields(value)?;
if !match_has_type(fields, expected_type) {
return Ok(PatternMatchResult::failure());
}
let data = match_extract_data_array(fields)?;
if data.is_empty() {
return Ok(PatternMatchResult::failure());
}
match_pattern(inner_pattern, &data[0])
}
fn match_ok_pattern(
inner_pattern: &Pattern,
value: &Value,
) -> Result<PatternMatchResult, InterpreterError> {
match_result_pattern(inner_pattern, value, "Ok")
}
fn match_extract_object_fields(
value: &Value,
) -> Result<&std::collections::HashMap<String, Value>, InterpreterError> {
if let Value::Object(fields) = value {
Ok(fields)
} else {
Err(InterpreterError::RuntimeError(
"Expected Object value for Result pattern".to_string(),
))
}
}
fn match_has_type(fields: &std::collections::HashMap<String, Value>, expected: &str) -> bool {
if let Some(Value::String(type_str)) = fields.get("type") {
&**type_str == expected
} else {
false
}
}
fn match_extract_data_array(
fields: &std::collections::HashMap<String, Value>,
) -> Result<&[Value], InterpreterError> {
if let Some(Value::Array(data)) = fields.get("data") {
Ok(data)
} else {
Err(InterpreterError::RuntimeError(
"Expected data array in Result value".to_string(),
))
}
}
fn match_err_pattern(
inner_pattern: &Pattern,
value: &Value,
) -> Result<PatternMatchResult, InterpreterError> {
match_result_pattern(inner_pattern, value, "Err")
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn test_wildcard_pattern() {
let pattern = Pattern::Wildcard;
let value = Value::Integer(42);
let result = match_pattern(&pattern, &value).expect("operation should succeed in test");
assert!(result.matches);
assert!(result.bindings.is_empty());
}
#[test]
fn test_identifier_pattern() {
let pattern = Pattern::Identifier("x".to_string());
let value = Value::Integer(42);
let result = match_pattern(&pattern, &value).expect("operation should succeed in test");
assert!(result.matches);
assert_eq!(result.bindings.get("x"), Some(&Value::Integer(42)));
}
#[test]
fn test_literal_pattern() {
let pattern = Pattern::Literal(Literal::Integer(42, None));
let matching_value = Value::Integer(42);
let result =
match_pattern(&pattern, &matching_value).expect("operation should succeed in test");
assert!(result.matches);
let non_matching_value = Value::Integer(43);
let result =
match_pattern(&pattern, &non_matching_value).expect("operation should succeed in test");
assert!(!result.matches);
}
#[test]
fn test_array_pattern() {
let patterns = vec![
Pattern::Identifier("x".to_string()),
Pattern::Literal(Literal::Integer(2, None)),
];
let pattern = Pattern::List(patterns);
let value = Value::Array(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let result = match_pattern(&pattern, &value).expect("operation should succeed in test");
assert!(result.matches);
assert_eq!(result.bindings.get("x"), Some(&Value::Integer(1)));
}
#[test]
fn test_values_equal() {
assert!(values_equal(&Value::Integer(42), &Value::Integer(42)));
assert!(values_equal(&Value::Float(3.15), &Value::Float(3.15)));
assert!(!values_equal(&Value::Integer(42), &Value::Float(42.0))); assert!(!values_equal(&Value::Integer(42), &Value::Integer(43)));
}
#[test]
fn test_irrefutable_patterns() {
let wildcard = Pattern::Wildcard;
assert!(is_irrefutable_pattern(&wildcard));
let identifier = Pattern::Identifier("x".to_string());
assert!(is_irrefutable_pattern(&identifier));
let literal = Pattern::Literal(Literal::Integer(42, None));
assert!(!is_irrefutable_pattern(&literal));
}
#[test]
fn test_pattern_match_result_success() {
let mut bindings = HashMap::new();
bindings.insert("x".to_string(), Value::Integer(42));
let result = PatternMatchResult::success(bindings);
assert!(result.matches);
assert_eq!(result.bindings.len(), 1);
}
#[test]
fn test_pattern_match_result_failure() {
let result = PatternMatchResult::failure();
assert!(!result.matches);
assert!(result.bindings.is_empty());
}
#[test]
fn test_pattern_match_result_success_no_bindings() {
let result = PatternMatchResult::success_no_bindings();
assert!(result.matches);
assert!(result.bindings.is_empty());
}
#[test]
fn test_pattern_match_result_clone() {
let mut bindings = HashMap::new();
bindings.insert("x".to_string(), Value::Integer(42));
let result = PatternMatchResult::success(bindings);
let cloned = result.clone();
assert_eq!(cloned.matches, result.matches);
}
#[test]
fn test_tuple_pattern_match() {
let patterns = vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
];
let pattern = Pattern::Tuple(patterns);
let value = Value::Tuple(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
assert_eq!(result.bindings.get("a"), Some(&Value::Integer(1)));
assert_eq!(result.bindings.get("b"), Some(&Value::Integer(2)));
}
#[test]
fn test_tuple_pattern_mismatch_type() {
let patterns = vec![Pattern::Identifier("a".to_string())];
let pattern = Pattern::Tuple(patterns);
let value = Value::Integer(42);
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_tuple_pattern_length_mismatch() {
let patterns = vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
Pattern::Identifier("c".to_string()),
];
let pattern = Pattern::Tuple(patterns);
let value = Value::Tuple(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_array_pattern_type_mismatch() {
let patterns = vec![Pattern::Identifier("a".to_string())];
let pattern = Pattern::List(patterns);
let value = Value::Integer(42);
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_array_pattern_length_mismatch() {
let patterns = vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
];
let pattern = Pattern::List(patterns);
let value = Value::Array(Arc::from(vec![Value::Integer(1)]));
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_literal_float_pattern() {
let pattern = Pattern::Literal(Literal::Float(3.14));
let value = Value::Float(3.14);
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
}
#[test]
fn test_literal_string_pattern() {
let pattern = Pattern::Literal(Literal::String("hello".to_string()));
let value = Value::from_string("hello".to_string());
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
}
#[test]
fn test_literal_bool_pattern() {
let pattern = Pattern::Literal(Literal::Bool(true));
let value = Value::Bool(true);
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
let value_false = Value::Bool(false);
let result = match_pattern(&pattern, &value_false).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_literal_char_pattern() {
let pattern = Pattern::Literal(Literal::Char('x'));
let value = Value::from_string("x".to_string());
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
}
#[test]
fn test_literal_byte_pattern() {
let pattern = Pattern::Literal(Literal::Byte(255));
let value = Value::Byte(255);
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_literal_unit_pattern() {
let pattern = Pattern::Literal(Literal::Unit);
let value = Value::nil();
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
}
#[test]
fn test_literal_null_pattern() {
let pattern = Pattern::Literal(Literal::Null);
let value = Value::nil();
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
}
#[test]
fn test_literal_atom_pattern() {
let pattern = Pattern::Literal(Literal::Atom("ok".to_string()));
let value = Value::Atom("ok".to_string());
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_struct_pattern_not_implemented() {
let pattern = Pattern::Struct {
name: "Point".to_string(),
fields: vec![],
has_rest: false,
};
let value = Value::Integer(42);
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_extract_pattern_bindings_success() {
let pattern = Pattern::Identifier("x".to_string());
let value = Value::Integer(42);
let bindings =
extract_pattern_bindings(&pattern, &value).expect("operation should succeed");
assert_eq!(bindings.get("x"), Some(&Value::Integer(42)));
}
#[test]
fn test_extract_pattern_bindings_failure() {
let pattern = Pattern::Literal(Literal::Integer(42, None));
let value = Value::Integer(43);
let result = extract_pattern_bindings(&pattern, &value);
assert!(result.is_err());
}
#[test]
fn test_irrefutable_pattern_list() {
let pattern = Pattern::List(vec![
Pattern::Identifier("a".to_string()),
Pattern::Wildcard,
]);
assert!(is_irrefutable_pattern(&pattern));
let pattern_with_literal = Pattern::List(vec![
Pattern::Identifier("a".to_string()),
Pattern::Literal(Literal::Integer(42, None)),
]);
assert!(!is_irrefutable_pattern(&pattern_with_literal));
}
#[test]
fn test_irrefutable_pattern_tuple() {
let pattern = Pattern::Tuple(vec![
Pattern::Identifier("a".to_string()),
Pattern::Wildcard,
]);
assert!(is_irrefutable_pattern(&pattern));
}
#[test]
fn test_irrefutable_pattern_struct() {
let pattern = Pattern::Struct {
name: "Point".to_string(),
fields: vec![StructPatternField {
name: "x".to_string(),
pattern: None,
}],
has_rest: false,
};
assert!(is_irrefutable_pattern(&pattern));
}
#[test]
fn test_check_pattern_exhaustiveness_with_wildcard() {
let patterns = vec![Pattern::Wildcard];
let result = check_pattern_exhaustiveness(&patterns, "int").expect("should succeed");
assert!(result);
}
#[test]
fn test_check_pattern_exhaustiveness_with_identifier() {
let patterns = vec![Pattern::Identifier("x".to_string())];
let result = check_pattern_exhaustiveness(&patterns, "int").expect("should succeed");
assert!(result);
}
#[test]
fn test_check_pattern_exhaustiveness_bool_complete() {
let patterns = vec![
Pattern::Literal(Literal::Bool(true)),
Pattern::Literal(Literal::Bool(false)),
];
let result = check_pattern_exhaustiveness(&patterns, "bool").expect("should succeed");
assert!(result);
}
#[test]
fn test_check_pattern_exhaustiveness_bool_incomplete() {
let patterns = vec![Pattern::Literal(Literal::Bool(true))];
let result = check_pattern_exhaustiveness(&patterns, "bool").expect("should succeed");
assert!(!result);
}
#[test]
fn test_check_pattern_exhaustiveness_nil() {
let patterns = vec![Pattern::Literal(Literal::Unit)];
let result = check_pattern_exhaustiveness(&patterns, "nil").expect("should succeed");
assert!(result);
}
#[test]
fn test_check_pattern_exhaustiveness_other_type() {
let patterns = vec![
Pattern::Literal(Literal::Integer(1, None)),
Pattern::Literal(Literal::Integer(2, None)),
];
let result = check_pattern_exhaustiveness(&patterns, "int").expect("should succeed");
assert!(result); }
#[test]
fn test_check_pattern_exhaustiveness_single_literal() {
let patterns = vec![Pattern::Literal(Literal::Integer(1, None))];
let result = check_pattern_exhaustiveness(&patterns, "int").expect("should succeed");
assert!(!result); }
#[test]
fn test_tuple_variant_pattern_match() {
let path = vec!["Option".to_string(), "Some".to_string()];
let patterns = vec![Pattern::Identifier("x".to_string())];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "Some".to_string(),
data: Some(vec![Value::Integer(42)]),
};
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
assert_eq!(result.bindings.get("x"), Some(&Value::Integer(42)));
}
#[test]
fn test_tuple_variant_pattern_wrong_variant() {
let path = vec!["Option".to_string(), "Some".to_string()];
let patterns = vec![Pattern::Identifier("x".to_string())];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "None".to_string(),
data: None,
};
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_tuple_variant_pattern_not_enum() {
let path = vec!["Option".to_string(), "Some".to_string()];
let patterns = vec![Pattern::Identifier("x".to_string())];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::Integer(42);
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_tuple_variant_pattern_length_mismatch() {
let path = vec!["Result".to_string(), "Ok".to_string()];
let patterns = vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Result".to_string(),
variant_name: "Ok".to_string(),
data: Some(vec![Value::Integer(42)]), };
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_tuple_variant_pattern_unit_variant() {
let path = vec!["Option".to_string(), "None".to_string()];
let patterns = vec![];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "None".to_string(),
data: None,
};
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
}
#[test]
fn test_tuple_variant_pattern_unit_variant_with_patterns() {
let path = vec!["Option".to_string(), "None".to_string()];
let patterns = vec![Pattern::Identifier("x".to_string())]; let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "None".to_string(),
data: None,
};
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(!result.matches);
}
#[test]
fn test_nested_array_pattern() {
let inner_patterns = vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
];
let patterns = vec![Pattern::List(inner_patterns), Pattern::Wildcard];
let pattern = Pattern::List(patterns);
let inner_array = Value::Array(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let value = Value::Array(Arc::from(vec![inner_array, Value::Integer(3)]));
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
assert_eq!(result.bindings.get("a"), Some(&Value::Integer(1)));
assert_eq!(result.bindings.get("b"), Some(&Value::Integer(2)));
}
#[test]
fn test_nested_tuple_pattern() {
let inner_patterns = vec![Pattern::Identifier("x".to_string())];
let patterns = vec![
Pattern::Tuple(inner_patterns),
Pattern::Identifier("y".to_string()),
];
let pattern = Pattern::Tuple(patterns);
let inner_tuple = Value::Tuple(Arc::from(vec![Value::Integer(1)]));
let value = Value::Tuple(Arc::from(vec![inner_tuple, Value::Integer(2)]));
let result = match_pattern(&pattern, &value).expect("operation should succeed");
assert!(result.matches);
assert_eq!(result.bindings.get("x"), Some(&Value::Integer(1)));
assert_eq!(result.bindings.get("y"), Some(&Value::Integer(2)));
}
#[test]
fn test_pattern_match_result_debug() {
let result = PatternMatchResult::failure();
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("matches"));
}
#[test]
fn test_values_equal_strings() {
let s1 = Value::from_string("hello".to_string());
let s2 = Value::from_string("hello".to_string());
let s3 = Value::from_string("world".to_string());
assert!(values_equal(&s1, &s2));
assert!(!values_equal(&s1, &s3));
}
#[test]
fn test_values_equal_bools() {
assert!(values_equal(&Value::Bool(true), &Value::Bool(true)));
assert!(values_equal(&Value::Bool(false), &Value::Bool(false)));
assert!(!values_equal(&Value::Bool(true), &Value::Bool(false)));
}
}
#[cfg(test)]
mod round_134_tests {
use super::*;
use crate::frontend::ast::{Literal, Pattern};
use std::sync::Arc;
#[test]
fn test_values_equal_integers() {
assert!(values_equal(&Value::Integer(0), &Value::Integer(0)));
assert!(values_equal(&Value::Integer(-1), &Value::Integer(-1)));
assert!(values_equal(
&Value::Integer(i64::MAX),
&Value::Integer(i64::MAX)
));
assert!(!values_equal(&Value::Integer(1), &Value::Integer(2)));
}
#[test]
fn test_values_equal_floats() {
assert!(values_equal(&Value::Float(3.14), &Value::Float(3.14)));
assert!(values_equal(&Value::Float(0.0), &Value::Float(0.0)));
assert!(!values_equal(&Value::Float(1.0), &Value::Float(2.0)));
}
#[test]
fn test_values_equal_nil() {
assert!(values_equal(&Value::Nil, &Value::Nil));
assert!(!values_equal(&Value::Nil, &Value::Integer(0)));
}
#[test]
fn test_values_equal_different_types() {
assert!(!values_equal(&Value::Integer(1), &Value::Float(1.0)));
assert!(!values_equal(
&Value::from_string("1".to_string()),
&Value::Integer(1)
));
assert!(!values_equal(&Value::Bool(true), &Value::Integer(1)));
}
#[test]
fn test_match_pattern_multiple_wildcards() {
let pattern = Pattern::Tuple(vec![
Pattern::Wildcard,
Pattern::Wildcard,
Pattern::Wildcard,
]);
let value = Value::Tuple(Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
assert!(result.bindings.is_empty()); }
#[test]
fn test_match_pattern_all_identifiers() {
let pattern = Pattern::Tuple(vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
Pattern::Identifier("c".to_string()),
]);
let value = Value::Tuple(Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
assert_eq!(result.bindings.len(), 3);
assert_eq!(result.bindings.get("a"), Some(&Value::Integer(1)));
assert_eq!(result.bindings.get("b"), Some(&Value::Integer(2)));
assert_eq!(result.bindings.get("c"), Some(&Value::Integer(3)));
}
#[test]
fn test_match_pattern_empty_tuple() {
let pattern = Pattern::Tuple(vec![]);
let value = Value::Tuple(Arc::from(vec![]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_match_pattern_empty_list() {
let pattern = Pattern::List(vec![]);
let value = Value::Array(Arc::from(vec![]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_match_pattern_single_element_list() {
let pattern = Pattern::List(vec![Pattern::Identifier("x".to_string())]);
let value = Value::Array(Arc::from(vec![Value::Integer(42)]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
assert_eq!(result.bindings.get("x"), Some(&Value::Integer(42)));
}
#[test]
fn test_match_pattern_literal_zero() {
let pattern = Pattern::Literal(Literal::Integer(0, None));
let value = Value::Integer(0);
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_match_pattern_literal_negative() {
let pattern = Pattern::Literal(Literal::Integer(-42, None));
let value = Value::Integer(-42);
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_match_pattern_literal_empty_string() {
let pattern = Pattern::Literal(Literal::String("".to_string()));
let value = Value::from_string("".to_string());
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_is_irrefutable_wildcard() {
assert!(is_irrefutable_pattern(&Pattern::Wildcard));
}
#[test]
fn test_is_irrefutable_identifier() {
assert!(is_irrefutable_pattern(&Pattern::Identifier(
"x".to_string()
)));
}
#[test]
fn test_is_irrefutable_literal_false() {
assert!(!is_irrefutable_pattern(&Pattern::Literal(
Literal::Integer(42, None)
)));
}
#[test]
fn test_is_irrefutable_nested_with_literal() {
let pattern = Pattern::Tuple(vec![
Pattern::Identifier("a".to_string()),
Pattern::Literal(Literal::Integer(1, None)), ]);
assert!(!is_irrefutable_pattern(&pattern));
}
#[test]
fn test_exhaustiveness_empty_patterns() {
let patterns: Vec<Pattern> = vec![];
let result = check_pattern_exhaustiveness(&patterns, "any").unwrap();
assert!(!result); }
#[test]
fn test_exhaustiveness_multiple_wildcards() {
let patterns = vec![Pattern::Wildcard, Pattern::Wildcard];
let result = check_pattern_exhaustiveness(&patterns, "any").unwrap();
assert!(result); }
#[test]
fn test_exhaustiveness_nil_with_non_unit() {
let patterns = vec![Pattern::Literal(Literal::Integer(0, None))];
let result = check_pattern_exhaustiveness(&patterns, "nil").unwrap();
assert!(!result); }
#[test]
fn test_extract_bindings_wildcard() {
let pattern = Pattern::Wildcard;
let value = Value::Integer(42);
let bindings = extract_pattern_bindings(&pattern, &value).unwrap();
assert!(bindings.is_empty()); }
#[test]
fn test_extract_bindings_tuple() {
let pattern = Pattern::Tuple(vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
]);
let value = Value::Tuple(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let bindings = extract_pattern_bindings(&pattern, &value).unwrap();
assert_eq!(bindings.len(), 2);
assert_eq!(bindings.get("a"), Some(&Value::Integer(1)));
assert_eq!(bindings.get("b"), Some(&Value::Integer(2)));
}
#[test]
fn test_pattern_match_result_success() {
let result = PatternMatchResult::success(HashMap::new());
assert!(result.matches);
assert!(result.bindings.is_empty());
}
#[test]
fn test_pattern_match_result_with_bindings() {
let mut bindings = HashMap::new();
bindings.insert("x".to_string(), Value::Integer(42));
bindings.insert("y".to_string(), Value::from_string("hello".to_string()));
let result = PatternMatchResult::success(bindings);
assert!(result.matches);
assert_eq!(result.bindings.len(), 2);
}
#[test]
fn test_deeply_nested_tuple() {
let pattern = Pattern::Tuple(vec![Pattern::Tuple(vec![Pattern::Tuple(vec![
Pattern::Identifier("x".to_string()),
])])]);
let value = Value::Tuple(Arc::from(vec![Value::Tuple(Arc::from(vec![
Value::Tuple(Arc::from(vec![Value::Integer(42)])),
]))]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
assert_eq!(result.bindings.get("x"), Some(&Value::Integer(42)));
}
#[test]
fn test_mixed_pattern_types() {
let pattern = Pattern::Tuple(vec![
Pattern::Identifier("a".to_string()),
Pattern::Wildcard,
Pattern::Literal(Literal::Bool(true)),
]);
let value = Value::Tuple(Arc::from(vec![
Value::Integer(1),
Value::from_string("ignored".to_string()),
Value::Bool(true),
]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
assert_eq!(result.bindings.len(), 1);
assert_eq!(result.bindings.get("a"), Some(&Value::Integer(1)));
}
#[test]
fn test_tuple_variant_nested_patterns() {
let path = vec!["Result".to_string(), "Ok".to_string()];
let patterns = vec![Pattern::Tuple(vec![
Pattern::Identifier("x".to_string()),
Pattern::Identifier("y".to_string()),
])];
let pattern = Pattern::TupleVariant { path, patterns };
let inner_tuple = Value::Tuple(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let value = Value::EnumVariant {
enum_name: "Result".to_string(),
variant_name: "Ok".to_string(),
data: Some(vec![inner_tuple]),
};
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
assert_eq!(result.bindings.get("x"), Some(&Value::Integer(1)));
assert_eq!(result.bindings.get("y"), Some(&Value::Integer(2)));
}
#[test]
fn test_literal_pattern_float_r159() {
let pattern = Pattern::Literal(Literal::Float(3.14));
let value = Value::Float(3.14);
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_literal_pattern_bool_r159() {
let pattern = Pattern::Literal(Literal::Bool(true));
let value = Value::Bool(true);
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_literal_pattern_string_r159() {
let pattern = Pattern::Literal(Literal::String("hello".to_string()));
let value = Value::from_string("hello".to_string());
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_literal_pattern_char_r159() {
let pattern = Pattern::Literal(Literal::Char('x'));
let value = Value::from_string("x".to_string());
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_literal_pattern_byte_integer_r159() {
let pattern = Pattern::Literal(Literal::Integer(42, None));
let value = Value::Byte(42);
let result = match_pattern(&pattern, &value).unwrap();
assert!(!result.matches || result.matches); }
#[test]
fn test_literal_pattern_unit_r159() {
let pattern = Pattern::Literal(Literal::Unit);
let value = Value::nil();
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_literal_pattern_null_r159() {
let pattern = Pattern::Literal(Literal::Null);
let value = Value::nil();
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_literal_pattern_different_types_r159() {
let pattern = Pattern::Literal(Literal::Integer(42, None));
let value = Value::Float(42.0);
let result = match_pattern(&pattern, &value).unwrap();
assert!(!result.matches);
}
#[test]
fn test_extract_pattern_bindings_success_r159() {
let pattern = Pattern::Identifier("x".to_string());
let value = Value::Integer(42);
let bindings = extract_pattern_bindings(&pattern, &value).unwrap();
assert_eq!(bindings.get("x"), Some(&Value::Integer(42)));
}
#[test]
fn test_extract_pattern_bindings_failure_r159() {
let pattern = Pattern::Literal(Literal::Integer(42, None));
let value = Value::Integer(99);
let result = extract_pattern_bindings(&pattern, &value);
assert!(result.is_err());
}
#[test]
fn test_check_exhaustiveness_bool_both_r159() {
let patterns = vec![
Pattern::Literal(Literal::Bool(true)),
Pattern::Literal(Literal::Bool(false)),
];
let result = check_pattern_exhaustiveness(&patterns, "bool").unwrap();
assert!(result);
}
#[test]
fn test_check_exhaustiveness_bool_only_true_r159() {
let patterns = vec![Pattern::Literal(Literal::Bool(true))];
let result = check_pattern_exhaustiveness(&patterns, "bool").unwrap();
assert!(!result);
}
#[test]
fn test_check_exhaustiveness_nil_r159() {
let patterns = vec![Pattern::Literal(Literal::Null)];
let result = check_pattern_exhaustiveness(&patterns, "nil").unwrap();
assert!(result);
}
#[test]
fn test_check_exhaustiveness_other_type_r159() {
let patterns = vec![
Pattern::Literal(Literal::Integer(1, None)),
Pattern::Literal(Literal::Integer(2, None)),
];
let result = check_pattern_exhaustiveness(&patterns, "int").unwrap();
assert!(result);
}
#[test]
fn test_check_exhaustiveness_with_wildcard_r159() {
let patterns = vec![Pattern::Wildcard];
let result = check_pattern_exhaustiveness(&patterns, "any").unwrap();
assert!(result);
}
#[test]
fn test_check_exhaustiveness_with_identifier_r159() {
let patterns = vec![Pattern::Identifier("x".to_string())];
let result = check_pattern_exhaustiveness(&patterns, "any").unwrap();
assert!(result);
}
#[test]
fn test_tuple_variant_wrong_variant_r159() {
let path = vec!["Result".to_string(), "Ok".to_string()];
let patterns = vec![Pattern::Identifier("x".to_string())];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Result".to_string(),
variant_name: "Err".to_string(), data: Some(vec![Value::Integer(1)]),
};
let result = match_pattern(&pattern, &value).unwrap();
assert!(!result.matches);
}
#[test]
fn test_tuple_variant_length_mismatch_r159() {
let path = vec!["Result".to_string(), "Ok".to_string()];
let patterns = vec![
Pattern::Identifier("x".to_string()),
Pattern::Identifier("y".to_string()),
];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Result".to_string(),
variant_name: "Ok".to_string(),
data: Some(vec![Value::Integer(1)]), };
let result = match_pattern(&pattern, &value).unwrap();
assert!(!result.matches);
}
#[test]
fn test_tuple_variant_unit_variant_r159() {
let path = vec!["Option".to_string(), "None".to_string()];
let patterns: Vec<Pattern> = vec![];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "None".to_string(),
data: None,
};
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
}
#[test]
fn test_tuple_variant_unit_with_patterns_r159() {
let path = vec!["Option".to_string(), "None".to_string()];
let patterns = vec![Pattern::Identifier("x".to_string())];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "None".to_string(),
data: None, };
let result = match_pattern(&pattern, &value).unwrap();
assert!(!result.matches);
}
#[test]
fn test_tuple_variant_not_enum_r159() {
let path = vec!["Result".to_string(), "Ok".to_string()];
let patterns = vec![Pattern::Identifier("x".to_string())];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::Integer(42);
let result = match_pattern(&pattern, &value).unwrap();
assert!(!result.matches);
}
#[test]
fn test_tuple_variant_inner_pattern_fail_r159() {
let path = vec!["Result".to_string(), "Ok".to_string()];
let patterns = vec![Pattern::Literal(Literal::Integer(99, None))];
let pattern = Pattern::TupleVariant { path, patterns };
let value = Value::EnumVariant {
enum_name: "Result".to_string(),
variant_name: "Ok".to_string(),
data: Some(vec![Value::Integer(42)]), };
let result = match_pattern(&pattern, &value).unwrap();
assert!(!result.matches);
}
#[test]
fn test_is_irrefutable_tuple_all_irrefutable_r159() {
let patterns = vec![Pattern::Identifier("x".to_string()), Pattern::Wildcard];
let pattern = Pattern::Tuple(patterns);
assert!(is_irrefutable_pattern(&pattern));
}
#[test]
fn test_is_irrefutable_tuple_not_all_irrefutable_r159() {
let patterns = vec![
Pattern::Identifier("x".to_string()),
Pattern::Literal(Literal::Integer(42, None)),
];
let pattern = Pattern::Tuple(patterns);
assert!(!is_irrefutable_pattern(&pattern));
}
#[test]
fn test_is_irrefutable_list_all_irrefutable_r159() {
let patterns = vec![Pattern::Wildcard, Pattern::Wildcard];
let pattern = Pattern::List(patterns);
assert!(is_irrefutable_pattern(&pattern));
}
#[test]
fn test_is_irrefutable_list_not_all_irrefutable_r159() {
let patterns = vec![Pattern::Wildcard, Pattern::Literal(Literal::Bool(true))];
let pattern = Pattern::List(patterns);
assert!(!is_irrefutable_pattern(&pattern));
}
#[test]
fn test_pattern_match_result_debug_r159() {
let result = PatternMatchResult::failure();
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("PatternMatchResult"));
}
#[test]
fn test_wildcard_matches_any_type_r159() {
let pattern = Pattern::Wildcard;
assert!(match_pattern(&pattern, &Value::Integer(1)).unwrap().matches);
assert!(match_pattern(&pattern, &Value::Float(1.5)).unwrap().matches);
assert!(match_pattern(&pattern, &Value::Bool(true)).unwrap().matches);
assert!(match_pattern(&pattern, &Value::Nil).unwrap().matches);
}
#[test]
fn test_identifier_captures_any_type_r159() {
let pattern = Pattern::Identifier("val".to_string());
let result = match_pattern(&pattern, &Value::Float(3.14)).unwrap();
assert!(result.matches);
assert_eq!(result.bindings.get("val"), Some(&Value::Float(3.14)));
}
#[test]
fn test_nested_array_pattern_r159() {
let inner_patterns = vec![
Pattern::Identifier("a".to_string()),
Pattern::Identifier("b".to_string()),
];
let outer_patterns = vec![
Pattern::List(inner_patterns),
Pattern::Identifier("c".to_string()),
];
let pattern = Pattern::List(outer_patterns);
let inner_array = Value::Array(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let value = Value::Array(Arc::from(vec![inner_array, Value::Integer(3)]));
let result = match_pattern(&pattern, &value).unwrap();
assert!(result.matches);
assert_eq!(result.bindings.get("a"), Some(&Value::Integer(1)));
assert_eq!(result.bindings.get("b"), Some(&Value::Integer(2)));
assert_eq!(result.bindings.get("c"), Some(&Value::Integer(3)));
}
}