Skip to main content

ternlang_core/
parser.rs

1use crate::lexer::Token;
2use crate::ast::*;
3use logos::{Logos, Lexer};
4
5pub struct Parser<'a> {
6    lex: Lexer<'a, Token>,
7}
8
9#[derive(Debug)]
10pub enum ParseError {
11    UnexpectedToken(String),
12    ExpectedToken(String, String),
13    InvalidTrit(String),
14    NonExhaustiveMatch(String),
15}
16
17impl std::fmt::Display for ParseError {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        match self {
20            Self::UnexpectedToken(tok) =>
21                write!(f, "[PARSE-001] Unexpected token '{tok}' — the lexer hit something it didn't expect. Check your syntax."),
22            Self::ExpectedToken(expected, found) =>
23                write!(f, "[PARSE-002] Expected {expected} but found '{found}'. The grammar demands it."),
24            Self::InvalidTrit(val) =>
25                write!(f, "[PARSE-003] '{val}' is not a valid trit. Trits are -1, 0, or +1. No in-betweens."),
26            Self::NonExhaustiveMatch(msg) =>
27                write!(f, "[PARSE-004] Non-exhaustive match: {msg}. Ternary has three states — cover all three or the compiler won't let you through."),
28        }
29    }
30}
31
32impl<'a> Parser<'a> {
33    pub fn new(input: &'a str) -> Self {
34        Self { lex: Token::lexer(input) }
35    }
36
37    pub fn parse_program(&mut self) -> Result<Program, ParseError> {
38        let mut imports = Vec::new();
39        let mut structs = Vec::new();
40        let mut agents = Vec::new();
41        let mut functions = Vec::new();
42        while self.peek_token().is_ok() {
43            match self.peek_token()? {
44                Token::Use => {
45                    if let Stmt::Use { path } = self.parse_stmt()? {
46                        imports.push(path);
47                    }
48                }
49                Token::Struct => structs.push(self.parse_struct_def()?),
50                Token::Agent  => agents.push(self.parse_agent_def()?),
51                _             => functions.push(self.parse_function()?),
52            }
53        }
54        Ok(Program { imports, structs, agents, functions })
55    }
56
57    fn parse_agent_def(&mut self) -> Result<AgentDef, ParseError> {
58        self.expect(Token::Agent)?;
59        let name = match self.next_token()? {
60            Token::Ident(n) => n,
61            t => return Err(ParseError::ExpectedToken("agent name".into(), format!("{:?}", t))),
62        };
63        self.expect(Token::LBrace)?;
64        let mut methods = Vec::new();
65        while self.peek_token()? != Token::RBrace {
66            methods.push(self.parse_function()?);
67        }
68        self.expect(Token::RBrace)?;
69        Ok(AgentDef { name, methods })
70    }
71
72    fn parse_struct_def(&mut self) -> Result<StructDef, ParseError> {
73        self.expect(Token::Struct)?;
74        let name = match self.next_token()? {
75            Token::Ident(n) => n,
76            t => return Err(ParseError::ExpectedToken("struct name".into(), format!("{:?}", t))),
77        };
78        self.expect(Token::LBrace)?;
79        let mut fields = Vec::new();
80        while self.peek_token()? != Token::RBrace {
81            let field_name = match self.next_token()? {
82                Token::Ident(n) => n,
83                t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
84            };
85            self.expect(Token::Colon)?;
86            let field_type = self.parse_type()?;
87            fields.push((field_name, field_type));
88            if let Ok(Token::Comma) = self.peek_token() { self.next_token()?; }
89        }
90        self.expect(Token::RBrace)?;
91        Ok(StructDef { name, fields })
92    }
93
94    pub fn parse_function(&mut self) -> Result<Function, ParseError> {
95        self.expect(Token::Fn)?;
96        let name = match self.next_token()? {
97            Token::Ident(n) => n,
98            t => return Err(ParseError::ExpectedToken("function name".into(), format!("{:?}", t))),
99        };
100
101        self.expect(Token::LParen)?;
102        let mut params = Vec::new();
103        if self.peek_token()? != Token::RParen {
104            loop {
105                let p_name = match self.next_token()? {
106                    Token::Ident(n) => n,
107                    t => return Err(ParseError::ExpectedToken("parameter name".into(), format!("{:?}", t))),
108                };
109                self.expect(Token::Colon)?;
110                let p_type = self.parse_type()?;
111                params.push((p_name, p_type));
112                if self.peek_token()? == Token::Comma { self.next_token()?; } else { break; }
113            }
114        }
115        self.expect(Token::RParen)?;
116        self.expect(Token::Arrow)?;
117        let return_type = self.parse_type()?;
118        let body = match self.parse_block()? {
119            Stmt::Block(stmts) => stmts,
120            _ => unreachable!(),
121        };
122        Ok(Function { name, params, return_type, body })
123    }
124
125    fn next_token(&mut self) -> Result<Token, ParseError> {
126        self.lex.next()
127            .map(|res| res.map_err(|_| ParseError::UnexpectedToken("Invalid token".into())))
128            .transpose()?
129            .ok_or(ParseError::UnexpectedToken("EOF".into()))
130    }
131
132    fn peek_token(&mut self) -> Result<Token, ParseError> {
133        let mut cloned = self.lex.clone();
134        cloned.next()
135            .map(|res| res.map_err(|_| ParseError::UnexpectedToken("Invalid token".into())))
136            .transpose()?
137            .ok_or(ParseError::UnexpectedToken("EOF".into()))
138    }
139
140    pub fn parse_expr(&mut self) -> Result<Expr, ParseError> {
141        self.parse_binary_expr(0)
142    }
143
144    fn parse_binary_expr(&mut self, min_prec: i8) -> Result<Expr, ParseError> {
145        let mut lhs = self.parse_unary_expr()?;
146        loop {
147            let Ok(op_token) = self.peek_token() else { break };
148            let prec = self.get_precedence(&op_token);
149            if prec < min_prec { break; }
150            self.next_token()?;
151            let rhs = self.parse_binary_expr(prec + 1)?;
152            lhs = Expr::BinaryOp {
153                op: self.token_to_binop(op_token),
154                lhs: Box::new(lhs),
155                rhs: Box::new(rhs),
156            };
157        }
158        Ok(lhs)
159    }
160
161    fn get_precedence(&self, token: &Token) -> i8 {
162        match token {
163            Token::Or                      => 0,
164            Token::And                     => 1,
165            Token::Equal | Token::NotEqual => 2,
166            Token::LAngle | Token::RAngle  => 2, // Comparisons
167            Token::Plus  | Token::Minus    => 3,
168            Token::Star                    => 4,
169            _ => -1,
170        }
171    }
172
173    fn token_to_binop(&self, token: Token) -> BinOp {
174        match token {
175            Token::Plus     => BinOp::Add,
176            Token::Minus    => BinOp::Sub,
177            Token::Star     => BinOp::Mul,
178            Token::Equal    => BinOp::Equal,
179            Token::NotEqual => BinOp::NotEqual,
180            Token::And      => BinOp::And,
181            Token::Or       => BinOp::Or,
182            Token::LAngle   => BinOp::Less,
183            Token::RAngle   => BinOp::Greater,
184            _ => unreachable!(),
185        }
186    }
187
188    /// Parse unary prefix expressions, then wrap with postfix (field access, indexing, `?`).
189    fn parse_unary_expr(&mut self) -> Result<Expr, ParseError> {
190        let mut expr = self.parse_primary_expr()?;
191        loop {
192            match self.peek_token()? {
193                Token::Dot => {
194                    self.next_token()?; // consume `.`
195                    let field = match self.next_token()? {
196                        Token::Ident(n) => n,
197                        t => return Err(ParseError::ExpectedToken("field name".into(), format!("{:?}", t))),
198                    };
199                    expr = Expr::FieldAccess { object: Box::new(expr), field };
200                }
201                Token::LBracket => {
202                    self.next_token()?; // consume `[`
203                    let row = self.parse_expr()?;
204                    self.expect(Token::Comma)?;
205                    let col = self.parse_expr()?;
206                    self.expect(Token::RBracket)?;
207                    expr = Expr::Index { object: Box::new(expr), row: Box::new(row), col: Box::new(col) };
208                }
209                Token::UncertainBranch => {
210                    // Postfix `?` — ternary error propagation.
211                    // Disambiguate from `if cond ? { }`: if the token after `?` is `{`, this
212                    // `?` belongs to the enclosing if/while statement — don't consume it.
213                    let mut lookahead = self.lex.clone();
214                    lookahead.next(); // skip `?`
215                    let after_q = lookahead.next();
216                    let is_uncertain_branch = matches!(after_q, Some(Ok(Token::LBrace)));
217                    if !is_uncertain_branch {
218                        self.next_token()?; // consume `?`
219                        expr = Expr::Propagate { expr: Box::new(expr) };
220                    } else {
221                        break;
222                    }
223                }
224                _ => break,
225            }
226        }
227        Ok(expr)
228    }
229
230    fn parse_primary_expr(&mut self) -> Result<Expr, ParseError> {
231        let token = self.next_token()?;
232        match token {
233            // spawn AgentName           — local agent
234            // spawn remote "addr" Name  — remote agent (Phase 5.1)
235            Token::Spawn => {
236                let node_addr = if let Ok(Token::Remote) = self.peek_token() {
237                    self.next_token()?; // consume `remote`
238                    match self.next_token()? {
239                        Token::StringLit(addr) => Some(addr),
240                        t => return Err(ParseError::ExpectedToken("node address string".into(), format!("{:?}", t))),
241                    }
242                } else {
243                    None
244                };
245                let agent_name = match self.next_token()? {
246                    Token::Ident(n) => n,
247                    t => return Err(ParseError::ExpectedToken("agent name".into(), format!("{:?}", t))),
248                };
249                Ok(Expr::Spawn { agent_name, node_addr })
250            }
251            // await <agentref_expr> — receive from agent mailbox
252            Token::Await => {
253                let target = self.parse_unary_expr()?;
254                Ok(Expr::Await { target: Box::new(target) })
255            }
256            Token::NodeId => Ok(Expr::NodeId),
257            Token::Minus => {
258                let expr = self.parse_unary_expr()?;
259                Ok(Expr::UnaryOp { op: UnOp::Neg, expr: Box::new(expr) })
260            }
261            Token::TritLiteral => {
262                let slice = self.lex.slice();
263                let val = slice.parse::<i8>()
264                    .map_err(|_| ParseError::InvalidTrit(slice.to_string()))?;
265                Ok(Expr::TritLiteral(val))
266            }
267            // Semantic trit keywords: affirm=+1, tend=0, reject=-1
268            Token::Affirm => Ok(Expr::TritLiteral(1)),
269            Token::Tend   => Ok(Expr::TritLiteral(0)),
270            Token::Reject => Ok(Expr::TritLiteral(-1)),
271            Token::Int(val) => Ok(Expr::IntLiteral(val)),
272            Token::StringLit(s) => Ok(Expr::StringLiteral(s)),
273            Token::Ident(name) => {
274                // cast(expr) built-in: returns Cast node
275                if name == "cast" {
276                    if let Ok(Token::LParen) = self.peek_token() {
277                        self.next_token()?;
278                        let inner = self.parse_expr()?;
279                        self.expect(Token::RParen)?;
280                        // Type is resolved by context (the let binding ty)
281                        // Emit with placeholder Trit — semantic pass refines this
282                        return Ok(Expr::Cast { expr: Box::new(inner), ty: Type::Trit });
283                    }
284                }
285
286                if let Ok(Token::LParen) = self.peek_token() {
287                    // Function call
288                    self.next_token()?;
289                    let mut args = Vec::new();
290                    if self.peek_token()? != Token::RParen {
291                        loop {
292                            args.push(self.parse_expr()?);
293                            if self.peek_token()? == Token::Comma {
294                                self.next_token()?;
295                            } else {
296                                break;
297                            }
298                        }
299                    }
300                    self.expect(Token::RParen)?;
301                    Ok(Expr::Call { callee: name, args })
302                } else {
303                    Ok(Expr::Ident(name))
304                }
305            }
306            Token::LParen => {
307                let expr = self.parse_expr()?;
308                self.expect(Token::RParen)?;
309                Ok(expr)
310            }
311            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
312        }
313    }
314
315    pub fn parse_stmt(&mut self) -> Result<Stmt, ParseError> {
316        let token = self.peek_token()?;
317        match token {
318            Token::At => {
319                self.next_token()?;
320                let dir = match self.next_token()? {
321                    Token::SparseSkip  => "sparseskip".to_string(),
322                    Token::Ident(n)    => n,
323                    t => return Err(ParseError::ExpectedToken("directive".into(), format!("{:?}", t))),
324                };
325                let stmt = self.parse_stmt()?;
326                Ok(Stmt::Decorated { directive: dir, stmt: Box::new(stmt) })
327            }
328
329            Token::Use => {
330                self.next_token()?;
331                let mut path = Vec::new();
332                loop {
333                    // Accept both identifiers and reserved type keywords as path segments
334                    let segment = match self.next_token()? {
335                        Token::Ident(n)   => n,
336                        Token::TritType   => "trit".to_string(),
337                        Token::TritTensor => "trittensor".to_string(),
338                        t => return Err(ParseError::ExpectedToken("module path segment".into(), format!("{:?}", t))),
339                    };
340                    path.push(segment);
341                    if let Ok(Token::DoubleColon) = self.peek_token() {
342                        self.next_token()?;
343                    } else {
344                        break;
345                    }
346                }
347                self.expect(Token::Semicolon)?;
348                Ok(Stmt::Use { path })
349            }
350
351            Token::Let => {
352                self.next_token()?;
353                // optional mut
354                let _mutable = if let Ok(Token::Mut) = self.peek_token() {
355                    self.next_token()?; true
356                } else { false };
357
358                let name = match self.next_token()? {
359                    Token::Ident(n) => n,
360                    t => return Err(ParseError::ExpectedToken("identifier".into(), format!("{:?}", t))),
361                };
362                self.expect(Token::Colon)?;
363                let ty = self.parse_type()?;
364                let value = if let Ok(Token::Assign) = self.peek_token() {
365                    self.next_token()?;
366                    self.parse_expr()?
367                } else {
368                    Expr::TritLiteral(0)
369                };
370                self.expect(Token::Semicolon)?;
371                Ok(Stmt::Let { name, ty, value })
372            }
373
374            Token::If => {
375                self.next_token()?;
376                let condition = self.parse_expr()?;
377                if let Ok(Token::UncertainBranch) = self.peek_token() {
378                    self.next_token()?;
379                    let on_pos  = Box::new(self.parse_block()?);
380                    self.expect(Token::Else)?;
381                    let on_zero = Box::new(self.parse_block()?);
382                    self.expect(Token::Else)?;
383                    let on_neg  = Box::new(self.parse_block()?);
384                    Ok(Stmt::IfTernary { condition, on_pos, on_zero, on_neg })
385                } else {
386                    // Binary if: if cond { A } else { B }
387                    // Maps to IfTernary(cond, A, B, B)
388                    let then_branch = Box::new(self.parse_block()?);
389                    let else_branch = if let Ok(Token::Else) = self.peek_token() {
390                        self.next_token()?;
391                        Box::new(self.parse_block()?)
392                    } else {
393                        Box::new(Stmt::Block(vec![]))
394                    };
395                    Ok(Stmt::IfTernary {
396                        condition,
397                        on_pos: then_branch,
398                        on_zero: else_branch.clone(),
399                        on_neg: else_branch,
400                    })
401                }
402            }
403
404            Token::Match => {
405                self.next_token()?;
406                let condition = self.parse_expr()?;
407                self.expect(Token::LBrace)?;
408                let mut arms = Vec::new();
409                while self.peek_token()? != Token::RBrace {
410                    let val = match self.next_token()? {
411                        Token::TritLiteral => {
412                            let slice = self.lex.slice();
413                            slice.parse::<i8>().map_err(|_| ParseError::InvalidTrit(slice.to_string()))?
414                        }
415                        Token::Affirm => 1,
416                        Token::Tend   => 0,
417                        Token::Reject => -1,
418                        t => return Err(ParseError::ExpectedToken("trit pattern (1, 0, -1, or affirm, tend, reject)".into(), format!("{:?}", t))),
419                    };
420                    self.expect(Token::FatArrow)?;
421                    let stmt = self.parse_stmt()?;
422                    arms.push((val, stmt));
423                }
424                self.expect(Token::RBrace)?;
425
426                // Enforce exhaustiveness: must have arms for -1, 0, and +1
427                let has_pos  = arms.iter().any(|(v, _)| *v ==  1);
428                let has_zero = arms.iter().any(|(v, _)| *v ==  0);
429                let has_neg  = arms.iter().any(|(v, _)| *v == -1);
430                if !has_pos || !has_zero || !has_neg {
431                    let missing: Vec<&str> = [
432                        if !has_pos  { Some("1 (truth)")    } else { None },
433                        if !has_zero { Some("0 (hold)")     } else { None },
434                        if !has_neg  { Some("-1 (conflict)") } else { None },
435                    ].iter().filter_map(|x| *x).collect();
436                    return Err(ParseError::NonExhaustiveMatch(
437                        format!("match missing arms: {}", missing.join(", "))
438                    ));
439                }
440
441                Ok(Stmt::Match { condition, arms })
442            }
443
444            // for <var> in <expr> { body }
445            Token::For => {
446                self.next_token()?;
447                let var = match self.next_token()? {
448                    Token::Ident(n) => n,
449                    t => return Err(ParseError::ExpectedToken("loop variable".into(), format!("{:?}", t))),
450                };
451                self.expect(Token::In)?;
452                let iter = self.parse_expr()?;
453                let body = Box::new(self.parse_block()?);
454                Ok(Stmt::ForIn { var, iter, body })
455            }
456
457            // while <condition> [?] { on_pos } [else { on_zero } else { on_neg }]
458            Token::While => {
459                self.next_token()?;
460                let condition = self.parse_expr()?;
461                if let Ok(Token::UncertainBranch) = self.peek_token() {
462                    self.next_token()?;
463                    let on_pos  = Box::new(self.parse_block()?);
464                    self.expect(Token::Else)?;
465                    let on_zero = Box::new(self.parse_block()?);
466                    self.expect(Token::Else)?;
467                    let on_neg  = Box::new(self.parse_block()?);
468                    Ok(Stmt::WhileTernary { condition, on_pos, on_zero, on_neg })
469                } else {
470                    // Binary while: while cond { body }
471                    // Maps to WhileTernary(cond, body, Break, Break)
472                    let body = Box::new(self.parse_block()?);
473                    Ok(Stmt::WhileTernary {
474                        condition,
475                        on_pos: body,
476                        on_zero: Box::new(Stmt::Break),
477                        on_neg: Box::new(Stmt::Break),
478                    })
479                }
480            }
481
482            // loop { body }
483            Token::Loop => {
484                self.next_token()?;
485                let body = Box::new(self.parse_block()?);
486                Ok(Stmt::Loop { body })
487            }
488
489            // send <target_expr> <message_expr>;
490            Token::Send => {
491                self.next_token()?;
492                let target = self.parse_expr()?;
493                let message = self.parse_expr()?;
494                self.expect(Token::Semicolon)?;
495                Ok(Stmt::Send { target, message })
496            }
497
498            Token::Break => {
499                self.next_token()?;
500                self.expect(Token::Semicolon)?;
501                Ok(Stmt::Break)
502            }
503
504            Token::Continue => {
505                self.next_token()?;
506                self.expect(Token::Semicolon)?;
507                Ok(Stmt::Continue)
508            }
509
510            Token::Return => {
511                self.next_token()?;
512                let expr = self.parse_expr()?;
513                self.expect(Token::Semicolon)?;
514                Ok(Stmt::Return(expr))
515            }
516
517            Token::LBrace => self.parse_block(),
518
519            _ => {
520                // Could be: expr; OR assignment: ident.field = value; OR ident[row, col] = value;
521                let expr = self.parse_expr()?;
522
523                // Check for assignment
524                if let Ok(Token::Assign) = self.peek_token() {
525                    match expr {
526                        Expr::FieldAccess { object, field } => {
527                            if let Expr::Ident(obj_name) = *object {
528                                self.next_token()?; // consume `=`
529                                let value = self.parse_expr()?;
530                                self.expect(Token::Semicolon)?;
531                                return Ok(Stmt::FieldSet { object: obj_name, field, value });
532                            }
533                        }
534                        Expr::Index { object, row, col } => {
535                            if let Expr::Ident(obj_name) = *object {
536                                self.next_token()?; // consume `=`
537                                let value = self.parse_expr()?;
538                                self.expect(Token::Semicolon)?;
539                                return Ok(Stmt::IndexSet { object: obj_name, row: *row, col: *col, value });
540                            }
541                        }
542                        _ => {}
543                    }
544                    return Err(ParseError::UnexpectedToken("invalid assignment target".into()));
545                }
546
547                self.expect(Token::Semicolon)?;
548                Ok(Stmt::Expr(expr))
549            }
550        }
551    }
552
553    fn parse_block(&mut self) -> Result<Stmt, ParseError> {
554        self.expect(Token::LBrace)?;
555        let mut stmts = Vec::new();
556        while self.peek_token()? != Token::RBrace {
557            stmts.push(self.parse_stmt()?);
558        }
559        self.expect(Token::RBrace)?;
560        Ok(Stmt::Block(stmts))
561    }
562
563    fn parse_type(&mut self) -> Result<Type, ParseError> {
564        let token = self.next_token()?;
565        match token {
566            Token::TritType   => Ok(Type::Trit),
567            Token::AgentRef   => Ok(Type::AgentRef),
568            Token::TritTensor => {
569                self.expect(Token::LAngle)?;
570                let mut dims = Vec::new();
571                loop {
572                    let d = match self.next_token()? {
573                        Token::Int(v) => v as usize,
574                        // TritLiteral matches "0" and "1" — accept them as dims
575                        Token::TritLiteral => {
576                            let s = self.lex.slice();
577                            s.parse::<i8>().unwrap_or(0).max(0) as usize
578                        }
579                        t => return Err(ParseError::ExpectedToken("dimension".into(), format!("{:?}", t))),
580                    };
581                    dims.push(d);
582                    if self.peek_token()? == Token::Ident("x".to_string()) {
583                        self.next_token()?;
584                    } else {
585                        break;
586                    }
587                }
588                self.expect(Token::RAngle)?;
589                Ok(Type::TritTensor { dims })
590            }
591            Token::Ident(ref name) => match name.as_str() {
592                "int"    => Ok(Type::Int),
593                "float"  => Ok(Type::Float),
594                "bool"   => Ok(Type::Bool),
595                "string" => Ok(Type::String),
596                // Named struct type
597                _        => Ok(Type::Named(name.clone())),
598            },
599            _ => Err(ParseError::UnexpectedToken(format!("{:?}", token))),
600        }
601    }
602
603    fn expect(&mut self, expected: Token) -> Result<(), ParseError> {
604        let token = self.next_token()?;
605        if token == expected {
606            Ok(())
607        } else {
608            Err(ParseError::ExpectedToken(format!("{:?}", expected), format!("{:?}", token)))
609        }
610    }
611}
612
613#[cfg(test)]
614mod tests {
615    use super::*;
616
617    #[test]
618    fn test_parse_function() {
619        let input = "fn invert(signal: trit) -> trit { return -signal; }";
620        let mut parser = Parser::new(input);
621        let func = parser.parse_function().unwrap();
622        assert_eq!(func.name, "invert");
623        assert_eq!(func.params[0].1, Type::Trit);
624        assert_eq!(func.return_type, Type::Trit);
625    }
626
627    #[test]
628    fn test_parse_match() {
629        let input = "match x { 1 => return 1; 0 => return 0; -1 => return -1; }";
630        let mut parser = Parser::new(input);
631        let stmt = parser.parse_stmt().unwrap();
632        if let Stmt::Match { arms, .. } = stmt {
633            assert_eq!(arms.len(), 3);
634            assert_eq!(arms[0].0, 1);
635            assert_eq!(arms[1].0, 0);
636            assert_eq!(arms[2].0, -1);
637        } else {
638            panic!("Expected Match");
639        }
640    }
641
642    #[test]
643    fn test_match_exhaustiveness_enforced() {
644        // Missing hold (0) arm — must fail
645        let input = "match x { 1 => return 1; -1 => return -1; }";
646        let mut parser = Parser::new(input);
647        let result = parser.parse_stmt();
648        assert!(matches!(result, Err(ParseError::NonExhaustiveMatch(_))),
649            "expected NonExhaustiveMatch error");
650    }
651
652    #[test]
653    fn test_parse_for_loop() {
654        let input = "for item in weights { return item; }";
655        let mut parser = Parser::new(input);
656        let stmt = parser.parse_stmt().unwrap();
657        assert!(matches!(stmt, Stmt::ForIn { .. }));
658    }
659
660    #[test]
661    fn test_parse_loop_break() {
662        let input = "loop { break; }";
663        let mut parser = Parser::new(input);
664        let stmt = parser.parse_stmt().unwrap();
665        assert!(matches!(stmt, Stmt::Loop { .. }));
666    }
667
668    #[test]
669    fn test_parse_use() {
670        let input = "use std::trit;";
671        let mut parser = Parser::new(input);
672        let stmt = parser.parse_stmt().unwrap();
673        if let Stmt::Use { path } = stmt {
674            assert_eq!(path, vec!["std", "trit"]);
675        } else {
676            panic!("Expected Use");
677        }
678    }
679
680    #[test]
681    fn test_parse_mut_let() {
682        let input = "let mut signal: trit = 1;";
683        let mut parser = Parser::new(input);
684        let stmt = parser.parse_stmt().unwrap();
685        assert!(matches!(stmt, Stmt::Let { .. }));
686    }
687
688    #[test]
689    fn test_parse_struct_def() {
690        let input = "struct Signal { value: trit, weight: trit }";
691        let mut parser = Parser::new(input);
692        let s = parser.parse_struct_def().unwrap();
693        assert_eq!(s.name, "Signal");
694        assert_eq!(s.fields.len(), 2);
695        assert_eq!(s.fields[0], ("value".to_string(), Type::Trit));
696        assert_eq!(s.fields[1], ("weight".to_string(), Type::Trit));
697    }
698
699    #[test]
700    fn test_parse_field_access() {
701        let input = "let v: trit = sig.value;";
702        let mut parser = Parser::new(input);
703        let stmt = parser.parse_stmt().unwrap();
704        if let Stmt::Let { value: Expr::FieldAccess { field, .. }, .. } = stmt {
705            assert_eq!(field, "value");
706        } else {
707            panic!("Expected FieldAccess in let binding");
708        }
709    }
710
711    #[test]
712    fn test_parse_field_set() {
713        let input = "sig.value = 1;";
714        let mut parser = Parser::new(input);
715        let stmt = parser.parse_stmt().unwrap();
716        assert!(matches!(stmt, Stmt::FieldSet { .. }));
717    }
718
719    #[test]
720    fn test_parse_cast() {
721        let input = "let t: trit = cast(flag);";
722        let mut parser = Parser::new(input);
723        let stmt = parser.parse_stmt().unwrap();
724        if let Stmt::Let { value: Expr::Cast { .. }, .. } = stmt {
725            // ok
726        } else {
727            panic!("Expected Cast in let binding");
728        }
729    }
730
731    #[test]
732    fn test_parse_named_type() {
733        let input = "let s: Signal;";
734        let mut parser = Parser::new(input);
735        let stmt = parser.parse_stmt().unwrap();
736        if let Stmt::Let { ty: Type::Named(name), .. } = stmt {
737            assert_eq!(name, "Signal");
738        } else {
739            panic!("Expected Named type");
740        }
741    }
742
743    #[test]
744    fn test_parse_agent_def() {
745        let input = r#"
746            agent Voter {
747                fn handle(msg: trit) -> trit {
748                    match msg {
749                         1 => { return  1; }
750                         0 => { return  0; }
751                        -1 => { return -1; }
752                    }
753                }
754            }
755        "#;
756        let mut parser = Parser::new(input);
757        let agent = parser.parse_agent_def().unwrap();
758        assert_eq!(agent.name, "Voter");
759        assert_eq!(agent.methods.len(), 1);
760        assert_eq!(agent.methods[0].name, "handle");
761    }
762
763    #[test]
764    fn test_parse_spawn() {
765        let input = "let v: agentref = spawn Voter;";
766        let mut parser = Parser::new(input);
767        let stmt = parser.parse_stmt().unwrap();
768        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
769            assert_eq!(agent_name, "Voter");
770            assert_eq!(node_addr, None);
771        } else {
772            panic!("Expected spawn in let binding");
773        }
774    }
775
776    #[test]
777    fn test_parse_spawn_remote() {
778        let input = r#"let v: agentref = spawn remote "10.0.0.1:7373" Voter;"#;
779        let mut parser = Parser::new(input);
780        let stmt = parser.parse_stmt().unwrap();
781        if let Stmt::Let { ty: Type::AgentRef, value: Expr::Spawn { agent_name, node_addr }, .. } = stmt {
782            assert_eq!(agent_name, "Voter");
783            assert_eq!(node_addr, Some("10.0.0.1:7373".to_string()));
784        } else {
785            panic!("Expected remote spawn in let binding");
786        }
787    }
788
789    #[test]
790    fn test_parse_send() {
791        let input = "send v 1;";
792        let mut parser = Parser::new(input);
793        let stmt = parser.parse_stmt().unwrap();
794        assert!(matches!(stmt, Stmt::Send { .. }));
795    }
796
797    #[test]
798    fn test_parse_await() {
799        let input = "let reply: trit = await v;";
800        let mut parser = Parser::new(input);
801        let stmt = parser.parse_stmt().unwrap();
802        if let Stmt::Let { value: Expr::Await { .. }, .. } = stmt {
803            // ok
804        } else {
805            panic!("Expected await in let binding");
806        }
807    }
808}