ruchy 4.2.1

A systems scripting language that transpiles to idiomatic Rust with extreme quality engineering
Documentation
    use super::*;
    use std::sync::Arc;

    fn test_eval_literal(lit: &Literal) -> Value {
        match lit {
            Literal::Integer(i, _) => Value::Integer(*i),
            Literal::Float(f) => Value::Float(*f),
            Literal::String(s) => Value::from_string(s.clone()),
            Literal::Bool(b) => Value::Bool(*b),
            Literal::Unit => Value::Nil,
            _ => Value::Nil,
        }
    }

    #[test]
    fn test_wildcard_pattern() {
        let pattern = Pattern::Wildcard;
        let value = Value::Integer(42);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        assert!(result.expect("result should be Some in test").is_empty());
    }

    #[test]
    fn test_identifier_pattern() {
        let pattern = Pattern::Identifier("x".to_string());
        let value = Value::Integer(42);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        let bindings = result.expect("result should be Some in test");
        assert_eq!(bindings.len(), 1);
        assert_eq!(bindings[0].0, "x");
        assert_eq!(bindings[0].1, Value::Integer(42));
    }

    #[test]
    fn test_literal_pattern_match() {
        let pattern = Pattern::Literal(Literal::Integer(42, None));
        let value = Value::Integer(42);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
    }

    #[test]
    fn test_literal_pattern_no_match() {
        let pattern = Pattern::Literal(Literal::Integer(42, None));
        let value = Value::Integer(43);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }

    #[test]
    fn test_tuple_pattern() {
        let patterns = vec![
            Pattern::Identifier("x".to_string()),
            Pattern::Identifier("y".to_string()),
        ];
        let pattern = Pattern::Tuple(patterns);
        let value = Value::Tuple(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        let bindings = result.expect("result should be Some in test");
        assert_eq!(bindings.len(), 2);
        assert_eq!(bindings[0].0, "x");
        assert_eq!(bindings[0].1, Value::Integer(1));
        assert_eq!(bindings[1].0, "y");
        assert_eq!(bindings[1].1, Value::Integer(2));
    }

    #[test]
    fn test_range_pattern_inclusive() {
        let pattern = Pattern::Range {
            start: Box::new(Pattern::Literal(Literal::Integer(1, None))),
            end: Box::new(Pattern::Literal(Literal::Integer(5, None))),
            inclusive: true,
        };

        let value = Value::Integer(3);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());

        let value = Value::Integer(5);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());

        let value = Value::Integer(6);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }

    #[test]
    fn test_or_pattern() {
        let patterns = vec![
            Pattern::Literal(Literal::Integer(1, None)),
            Pattern::Literal(Literal::Integer(2, None)),
            Pattern::Literal(Literal::Integer(3, None)),
        ];
        let pattern = Pattern::Or(patterns);

        let value = Value::Integer(2);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());

        let value = Value::Integer(4);
        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }

    #[test]
    fn test_some_pattern_match() {
        let pattern = Pattern::Some(Box::new(Pattern::Identifier("x".to_string())));
        let value = Value::EnumVariant {
            enum_name: "Option".to_string(),
            variant_name: "Some".to_string(),
            data: Some(vec![Value::Integer(42)]),
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        let bindings = result.expect("result should be Some in test");
        assert_eq!(bindings.len(), 1);
        assert_eq!(bindings[0].0, "x");
        assert_eq!(bindings[0].1, Value::Integer(42));
    }

    #[test]
    fn test_some_pattern_no_match_on_none() {
        let pattern = Pattern::Some(Box::new(Pattern::Identifier("x".to_string())));
        let value = Value::EnumVariant {
            enum_name: "Option".to_string(),
            variant_name: "None".to_string(),
            data: None,
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }

    #[test]
    fn test_none_pattern_match() {
        let pattern = Pattern::None;
        let value = Value::EnumVariant {
            enum_name: "Option".to_string(),
            variant_name: "None".to_string(),
            data: None,
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        let bindings = result.expect("result should be Some in test");
        assert!(bindings.is_empty());
    }

    #[test]
    fn test_none_pattern_no_match_on_some() {
        let pattern = Pattern::None;
        let value = Value::EnumVariant {
            enum_name: "Option".to_string(),
            variant_name: "Some".to_string(),
            data: Some(vec![Value::Integer(42)]),
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }

    #[test]
    fn test_qualified_name_unit_variant_match() {
        let pattern = Pattern::QualifiedName(vec!["Status".to_string(), "Success".to_string()]);
        let value = Value::EnumVariant {
            enum_name: "Status".to_string(),
            variant_name: "Success".to_string(),
            data: None,
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        let bindings = result.expect("result should be Some in test");
        assert!(bindings.is_empty()); // Unit variants have no bindings
    }

    #[test]
    fn test_qualified_name_unit_variant_no_match_wrong_name() {
        let pattern = Pattern::QualifiedName(vec!["Status".to_string(), "Success".to_string()]);
        let value = Value::EnumVariant {
            enum_name: "Status".to_string(),
            variant_name: "Failed".to_string(),
            data: None,
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }

    #[test]
    fn test_qualified_name_no_match_on_tuple_variant() {
        let pattern = Pattern::QualifiedName(vec!["Response".to_string(), "Error".to_string()]);
        let value = Value::EnumVariant {
            enum_name: "Response".to_string(),
            variant_name: "Error".to_string(),
            data: Some(vec![Value::from_string("failed".to_string())]),
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none()); // Should not match - has data
    }

    #[test]
    fn test_tuple_variant_single_element() {
        let pattern = Pattern::TupleVariant {
            path: vec!["Response".to_string(), "Error".to_string()],
            patterns: vec![Pattern::Identifier("msg".to_string())],
        };
        let value = Value::EnumVariant {
            enum_name: "Response".to_string(),
            variant_name: "Error".to_string(),
            data: Some(vec![Value::from_string("failed".to_string())]),
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        let bindings = result.expect("result should be Some in test");
        assert_eq!(bindings.len(), 1);
        assert_eq!(bindings[0].0, "msg");
        assert_eq!(bindings[0].1, Value::from_string("failed".to_string()));
    }

    #[test]
    fn test_tuple_variant_multiple_elements() {
        let pattern = Pattern::TupleVariant {
            path: vec!["Point".to_string(), "Pos".to_string()],
            patterns: vec![
                Pattern::Identifier("x".to_string()),
                Pattern::Identifier("y".to_string()),
            ],
        };
        let value = Value::EnumVariant {
            enum_name: "Point".to_string(),
            variant_name: "Pos".to_string(),
            data: Some(vec![Value::Integer(10), Value::Integer(20)]),
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_some());
        let bindings = result.expect("result should be Some in test");
        assert_eq!(bindings.len(), 2);
        assert_eq!(bindings[0].0, "x");
        assert_eq!(bindings[0].1, Value::Integer(10));
        assert_eq!(bindings[1].0, "y");
        assert_eq!(bindings[1].1, Value::Integer(20));
    }

    #[test]
    fn test_tuple_variant_no_match_wrong_variant_name() {
        let pattern = Pattern::TupleVariant {
            path: vec!["Message".to_string(), "Move".to_string()],
            patterns: vec![Pattern::Identifier("dir".to_string())],
        };
        let value = Value::EnumVariant {
            enum_name: "Message".to_string(),
            variant_name: "Quit".to_string(),
            data: None,
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }

    #[test]
    fn test_tuple_variant_no_match_arity_mismatch() {
        let pattern = Pattern::TupleVariant {
            path: vec!["Point".to_string(), "Pos".to_string()],
            patterns: vec![
                Pattern::Identifier("x".to_string()),
                Pattern::Identifier("y".to_string()),
            ],
        };
        let value = Value::EnumVariant {
            enum_name: "Point".to_string(),
            variant_name: "Pos".to_string(),
            data: Some(vec![Value::Integer(10)]), // Only 1 element, pattern expects 2
        };

        let result = try_pattern_match(&pattern, &value, &test_eval_literal)
            .expect("try_pattern_match should succeed in test");
        assert!(result.is_none());
    }