## Coverage Report

#### Created: 2025-09-08 21:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/noah/src/ruchy/src/frontend/parser/actors.rs

    Line
    Count
    Source
    1
    //! Actor system parsing
    2
    3
    use super::{ParserState, *};
    4
    use crate::frontend::ast::{ActorHandler, StructField};
    5
    6
    /// # Errors
    7
    ///
    8
    /// Returns an error if the operation fails
    9
    /// # Errors
    10
    ///
    11
    /// Returns an error if the operation fails
    12
    0
    pub fn parse_actor(state: &mut ParserState) -> Result<Expr> {
    13
    0
        let start_span = state.tokens.advance().expect("checked by parser logic").1; // consume actor
    14
    0
        let name = parse_actor_name(state)?;
    15
    0
        state.tokens.expect(&Token::LeftBrace)?;
    16
    17
    0
        let (state_fields, handlers) = parse_actor_body(state)?;
    18
    0
        state.tokens.expect(&Token::RightBrace)?;
    19
    20
    0
        Ok(Expr::new(
    21
    0
            ExprKind::Actor {
    22
    0
                name,
    23
    0
                state: state_fields,
    24
    0
                handlers,
    25
    0
            },
    26
    0
            start_span,
    27
    0
        ))
    28
    0
    }
    29
    30
    // Helper: Parse actor name (complexity: 2)
    31
    0
    fn parse_actor_name(state: &mut ParserState) -> Result<String> {
    32
    0
        if let Some((Token::Identifier(n), _)) = state.tokens.peek() {
    33
    0
            let name = n.clone();
    34
    0
            state.tokens.advance();
    35
    0
            Ok(name)
    36
        } else {
    37
    0
            bail!("Expected actor name");
    38
        }
    39
    0
    }
    40
    41
    // Helper: Parse actor body (complexity: 4)
    42
    0
    fn parse_actor_body(state: &mut ParserState) -> Result<(Vec<StructField>, Vec<ActorHandler>)> {
    43
    0
        let mut state_fields = Vec::new();
    44
    0
        let mut handlers = Vec::new();
    45
    46
    0
        while !matches!(state.tokens.peek(), Some((Token::RightBrace, _))) {
    47
    0
            if matches!(state.tokens.peek(), Some((Token::State, _))) {
    48
    0
                parse_state_block(state, &mut state_fields)?;
    49
    0
            } else if matches!(state.tokens.peek(), Some((Token::Receive, _))) {
    50
    0
                parse_receive_handler(state, &mut handlers)?;
    51
            } else {
    52
    0
                parse_inline_state_field(state, &mut state_fields)?;
    53
            }
    54
        }
    55
    56
    0
        Ok((state_fields, handlers))
    57
    0
    }
    58
    59
    // Helper: Parse state block (complexity: 5)
    60
    0
    fn parse_state_block(state: &mut ParserState, state_fields: &mut Vec<StructField>) -> Result<()> {
    61
    0
        state.tokens.advance(); // consume 'state'
    62
    0
        state.tokens.expect(&Token::LeftBrace)?;
    63
    64
    0
        while !matches!(state.tokens.peek(), Some((Token::RightBrace, _))) {
    65
    0
            let field_name = parse_field_name(state, "Expected field name in state block")?;
    66
    0
            state.tokens.expect(&Token::Colon)?;
    67
    0
            let ty = utils::parse_type(state)?;
    68
    69
    0
            state_fields.push(StructField {
    70
    0
                name: field_name,
    71
    0
                ty,
    72
    0
                is_pub: false,
    73
    0
            });
    74
    75
    0
            consume_optional_separator(state);
    76
        }
    77
    78
    0
        state.tokens.expect(&Token::RightBrace)?;
    79
    0
        Ok(())
    80
    0
    }
    81
    82
    // Helper: Parse receive handler (complexity: 3)
    83
    0
    fn parse_receive_handler(state: &mut ParserState, handlers: &mut Vec<ActorHandler>) -> Result<()> {
    84
    0
        state.tokens.advance(); // consume 'receive'
    85
    86
    0
        if matches!(state.tokens.peek(), Some((Token::LeftBrace, _))) {
    87
    0
            parse_receive_block(state, handlers)
    88
        } else {
    89
    0
            parse_individual_handler(state, handlers)
    90
        }
    91
    0
    }
    92
    93
    // Helper: Parse receive block with multiple handlers (complexity: 6)
    94
    0
    fn parse_receive_block(state: &mut ParserState, handlers: &mut Vec<ActorHandler>) -> Result<()> {
    95
    0
        state.tokens.advance(); // consume {
    96
    97
    0
        while !matches!(state.tokens.peek(), Some((Token::RightBrace, _))) {
    98
    0
            let message_type = parse_field_name(state, "Expected message type in receive block")?;
    99
    0
            let params = parse_optional_params(state)?;
    100
    0
            state.tokens.expect(&Token::FatArrow)?;
    101
    0
            let body = parse_handler_body(state)?;
    102
    103
    0
            handlers.push(ActorHandler {
    104
    0
                message_type,
    105
    0
                params,
    106
    0
                body,
    107
    0
            });
    108
    109
    0
            if matches!(state.tokens.peek(), Some((Token::Comma, _))) {
    110
    0
                state.tokens.advance();
    111
    0
            }
    112
        }
    113
    114
    0
        state.tokens.expect(&Token::RightBrace)?;
    115
    0
        Ok(())
    116
    0
    }
    117
    118
    // Helper: Parse individual handler (complexity: 4)
    119
    0
    fn parse_individual_handler(state: &mut ParserState, handlers: &mut Vec<ActorHandler>) -> Result<()> {
    120
    0
        let message_type = parse_field_name(state, "Expected message type after receive")?;
    121
    0
        let params = parse_optional_params(state)?;
    122
    123
        // Parse optional return type
    124
    0
        if matches!(state.tokens.peek(), Some((Token::Arrow, _))) {
    125
    0
            state.tokens.advance(); // consume ->
    126
    0
            let _return_type = utils::parse_type(state)?;
    127
    0
        }
    128
    129
    0
        let body = Box::new(collections::parse_block(state)?);
    130
    131
    0
        handlers.push(ActorHandler {
    132
    0
            message_type,
    133
    0
            params,
    134
    0
            body,
    135
    0
        });
    136
    137
    0
        Ok(())
    138
    0
    }
    139
    140
    // Helper: Parse inline state field (complexity: 4)
    141
    0
    fn parse_inline_state_field(state: &mut ParserState, state_fields: &mut Vec<StructField>) -> Result<()> {
    142
    0
        let field_name = parse_field_name(state, "Expected field name")?;
    143
    0
        state.tokens.expect(&Token::Colon)?;
    144
    0
        let ty = utils::parse_type(state)?;
    145
    146
        // Parse optional default value
    147
    0
        if matches!(state.tokens.peek(), Some((Token::Equal, _))) {
    148
    0
            state.tokens.advance(); // consume =
    149
    0
            let _default_value = super::parse_expr_recursive(state)?;
    150
    0
        }
    151
    152
    0
        state_fields.push(StructField {
    153
    0
            name: field_name,
    154
    0
            ty,
    155
    0
            is_pub: false,
    156
    0
        });
    157
    158
    0
        consume_optional_separator(state);
    159
    0
        Ok(())
    160
    0
    }
    161
    162
    // Helper: Parse field name (complexity: 2)
    163
    0
    fn parse_field_name(state: &mut ParserState, error_msg: &str) -> Result<String> {
    164
    0
        if let Some((Token::Identifier(name), _)) = state.tokens.peek() {
    165
    0
            let name = name.clone();
    166
    0
            state.tokens.advance();
    167
    0
            Ok(name)
    168
        } else {
    169
    0
            bail!("{}", error_msg);
    170
        }
    171
    0
    }
    172
    173
    // Helper: Parse optional parameters (complexity: 2)
    174
    0
    fn parse_optional_params(state: &mut ParserState) -> Result<Vec<Param>> {
    175
    0
        if matches!(state.tokens.peek(), Some((Token::LeftParen, _))) {
    176
    0
            utils::parse_params(state)
    177
        } else {
    178
    0
            Ok(Vec::new())
    179
        }
    180
    0
    }
    181
    182
    // Helper: Parse handler body (complexity: 2)
    183
    0
    fn parse_handler_body(state: &mut ParserState) -> Result<Box<Expr>> {
    184
    0
        if matches!(state.tokens.peek(), Some((Token::LeftBrace, _))) {
    185
    0
            Ok(Box::new(collections::parse_block(state)?))
    186
        } else {
    187
    0
            Ok(Box::new(super::parse_expr_recursive(state)?))
    188
        }
    189
    0
    }
    190
    191
    // Helper: Consume optional separator (complexity: 2)
    192
    0
    fn consume_optional_separator(state: &mut ParserState) {
    193
    0
        if matches!(
    194
    0
            state.tokens.peek(),
    195
            Some((Token::Comma | Token::Semicolon, _))
    196
    0
        ) {
    197
    0
            state.tokens.advance();
    198
    0
        }
    199
    0
    }
    200
    201
    #[cfg(test)]
    202
    mod tests {
    203
        use super::*;
    204
    205
        #[test]
    206
        fn test_parse_actor_function_signature() {
    207
            // This test just verifies the function signature compiles and exists
    208
            // Actual functionality testing is done via integration tests due to
    209
            // complex parser infrastructure requirements
    210
    211
            // Verify function exists with correct signature
    212
            // This is a compile-time check - if it compiles, the test passes
    213
            let f: fn(&mut ParserState) -> Result<Expr> = parse_actor;
    214
    215
            // Use the variable to avoid unused warning
    216
            assert!(!format!("{f:p}").is_empty(), "Function exists");
    217
        }
    218
    }