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
}