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, 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 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()?; 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()?; 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 let mut lookahead = self.lex.clone();
214 lookahead.next(); 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()?; 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 Token::Spawn => {
236 let node_addr = if let Ok(Token::Remote) = self.peek_token() {
237 self.next_token()?; 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 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 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 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 return Ok(Expr::Cast { expr: Box::new(inner), ty: Type::Trit });
283 }
284 }
285
286 if let Ok(Token::LParen) = self.peek_token() {
287 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 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 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 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 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 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 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 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 Token::Loop => {
484 self.next_token()?;
485 let body = Box::new(self.parse_block()?);
486 Ok(Stmt::Loop { body })
487 }
488
489 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 let expr = self.parse_expr()?;
522
523 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()?; 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()?; 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 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 _ => 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 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 } 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 } else {
805 panic!("Expected await in let binding");
806 }
807 }
808}