aboutsummaryrefslogtreecommitdiff
path: root/compiler/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src')
-rw-r--r--compiler/src/ast/models.rs5
-rw-r--r--compiler/src/ast/parser.rs33
-rw-r--r--compiler/src/ast/tests.rs311
3 files changed, 346 insertions, 3 deletions
diff --git a/compiler/src/ast/models.rs b/compiler/src/ast/models.rs
index 64fec19..1cb705d 100644
--- a/compiler/src/ast/models.rs
+++ b/compiler/src/ast/models.rs
@@ -31,6 +31,11 @@ pub enum Expr {
31 vars: Vec<Spanned<LetVar>>, 31 vars: Vec<Spanned<LetVar>>,
32 body: Vec<Spanned<Expr>>, 32 body: Vec<Spanned<Expr>>,
33 }, 33 },
34 If {
35 condition: Spanned<Box<Expr>>,
36 then_expr: Spanned<Box<Expr>>,
37 else_expr: Option<Spanned<Box<Expr>>>,
38 },
34 For { 39 For {
35 loop_var: Spanned<Rc<str>>, 40 loop_var: Spanned<Rc<str>>,
36 from: Spanned<Box<Expr>>, 41 from: Spanned<Box<Expr>>,
diff --git a/compiler/src/ast/parser.rs b/compiler/src/ast/parser.rs
index 12a6f0d..88ba8c7 100644
--- a/compiler/src/ast/parser.rs
+++ b/compiler/src/ast/parser.rs
@@ -244,14 +244,40 @@ where
244 Ok(Spanned::new(let_vars, span)) 244 Ok(Spanned::new(let_vars, span))
245 } 245 }
246 246
247 fn parse_if(&mut self, open_span: Span) -> Result<Spanned<Expr>, Spanned<Error>> {
248 self.consume()?;
249
250 let condition = self.parse_expr()?.map(Into::into);
251 let then_expr = self.parse_expr()?.map(Into::into);
252 let else_expr = match self.peek_token()?.inner {
253 Token::RightPar => {
254 self.consume()?;
255 None
256 }
257 _ => {
258 let expr = self.parse_expr()?.map(Into::into);
259 self.require_right_par()?;
260 Some(expr)
261 }
262 };
263
264 let if_stmt = Expr::If {
265 condition,
266 then_expr,
267 else_expr,
268 };
269 let span = Span::new(open_span.start, self.last_token_span.end);
270 Ok(Spanned::new(if_stmt, span))
271 }
272
247 fn parse_for(&mut self, open_span: Span) -> Result<Spanned<Expr>, Spanned<Error>> { 273 fn parse_for(&mut self, open_span: Span) -> Result<Spanned<Expr>, Spanned<Error>> {
248 self.consume()?; 274 self.consume()?;
249 275
250 let loop_var = self.parse_sym()?.map(Into::into); 276 let loop_var = self.parse_sym()?.map(Into::into);
251 self.require_sym("from")?; 277 self.require_sym("from")?;
252 let from = self.parse_expr()?.map(Box::new); 278 let from = self.parse_expr()?.map(Into::into);
253 self.require_sym("to")?; 279 self.require_sym("to")?;
254 let to = self.parse_expr()?.map(Box::new); 280 let to = self.parse_expr()?.map(Into::into);
255 let body = self.parse_body(open_span, true)?; 281 let body = self.parse_body(open_span, true)?;
256 282
257 let for_loop = Expr::For { 283 let for_loop = Expr::For {
@@ -268,7 +294,7 @@ where
268 self.consume()?; 294 self.consume()?;
269 295
270 let target_var = self.parse_sym()?.map(Into::into); 296 let target_var = self.parse_sym()?.map(Into::into);
271 let expr = self.parse_expr()?.map(Box::new); 297 let expr = self.parse_expr()?.map(Into::into);
272 self.require_right_par()?; 298 self.require_right_par()?;
273 299
274 let set = Expr::Set { target_var, expr }; 300 let set = Expr::Set { target_var, expr };
@@ -312,6 +338,7 @@ where
312 "fn" => self.parse_fn(open_span), 338 "fn" => self.parse_fn(open_span),
313 "const" => self.parse_const(open_span), 339 "const" => self.parse_const(open_span),
314 "let" => self.parse_let(open_span), 340 "let" => self.parse_let(open_span),
341 "if" => self.parse_if(open_span),
315 "for" => self.parse_for(open_span), 342 "for" => self.parse_for(open_span),
316 "set" => self.parse_set(open_span), 343 "set" => self.parse_set(open_span),
317 "do" => self.parse_do(open_span), 344 "do" => self.parse_do(open_span),
diff --git a/compiler/src/ast/tests.rs b/compiler/src/ast/tests.rs
index 5b2399f..d2a27a1 100644
--- a/compiler/src/ast/tests.rs
+++ b/compiler/src/ast/tests.rs
@@ -16,6 +16,7 @@ enum E {
16 Fn(&'static str, Vec<&'static str>, Vec<E>), 16 Fn(&'static str, Vec<&'static str>, Vec<E>),
17 Const(Vec<(&'static str, E)>), 17 Const(Vec<(&'static str, E)>),
18 Let(Vec<(&'static str, E)>, Vec<E>), 18 Let(Vec<(&'static str, E)>, Vec<E>),
19 If(Box<E>, Box<E>, Option<Box<E>>),
19 For(&'static str, Box<E>, Box<E>, Vec<E>), 20 For(&'static str, Box<E>, Box<E>, Vec<E>),
20 Set(&'static str, Box<E>), 21 Set(&'static str, Box<E>),
21 Do(Vec<E>), 22 Do(Vec<E>),
@@ -50,6 +51,15 @@ impl From<Expr> for E {
50 vars.into_iter().map(|v| convert_var(v.inner)).collect(), 51 vars.into_iter().map(|v| convert_var(v.inner)).collect(),
51 body.into_iter().map(|e| e.inner.into()).collect(), 52 body.into_iter().map(|e| e.inner.into()).collect(),
52 ), 53 ),
54 Expr::If {
55 condition,
56 then_expr,
57 else_expr,
58 } => If(
59 Box::new(E::from(*condition.inner)),
60 Box::new(E::from(*then_expr.inner)),
61 else_expr.map(|e| Box::new(E::from(*e.inner))),
62 ),
53 Expr::For { 63 Expr::For {
54 loop_var, 64 loop_var,
55 from, 65 from,
@@ -388,6 +398,141 @@ fn test_let() {
388} 398}
389 399
390#[test] 400#[test]
401fn test_if() {
402 let cases = vec![
403 // (if true 1 2)
404 (
405 vec![
406 LeftPar,
407 Symbol("if"),
408 Symbol("true"),
409 Number("1"),
410 Number("2"),
411 RightPar,
412 ],
413 vec![If(
414 Box::new(Bool(true)),
415 Box::new(Int(1)),
416 Some(Box::new(Int(2))),
417 )],
418 ),
419 // (if true 1)
420 (
421 vec![LeftPar, Symbol("if"), Symbol("true"), Number("1"), RightPar],
422 vec![If(Box::new(Bool(true)), Box::new(Int(1)), None)],
423 ),
424 // (if (= x 0) a b)
425 (
426 vec![
427 LeftPar,
428 Symbol("if"),
429 LeftPar,
430 Symbol("="),
431 Symbol("x"),
432 Number("0"),
433 RightPar,
434 Symbol("a"),
435 Symbol("b"),
436 RightPar,
437 ],
438 vec![If(
439 Box::new(Call("=", vec![Sym("x"), Int(0)])),
440 Box::new(Sym("a")),
441 Some(Box::new(Sym("b"))),
442 )],
443 ),
444 // (if true (do 1 2) (do 3 4))
445 (
446 vec![
447 LeftPar,
448 Symbol("if"),
449 Symbol("true"),
450 LeftPar,
451 Symbol("do"),
452 Number("1"),
453 Number("2"),
454 RightPar,
455 LeftPar,
456 Symbol("do"),
457 Number("3"),
458 Number("4"),
459 RightPar,
460 RightPar,
461 ],
462 vec![If(
463 Box::new(Bool(true)),
464 Box::new(Do(vec![Int(1), Int(2)])),
465 Some(Box::new(Do(vec![Int(3), Int(4)]))),
466 )],
467 ),
468 // (if nil nil)
469 (
470 vec![
471 LeftPar,
472 Symbol("if"),
473 Symbol("nil"),
474 Symbol("nil"),
475 RightPar,
476 ],
477 vec![If(Box::new(Nil), Box::new(Nil), None)],
478 ),
479 // (if true (if false 1 2) 3)
480 (
481 vec![
482 LeftPar,
483 Symbol("if"),
484 Symbol("true"),
485 LeftPar,
486 Symbol("if"),
487 Symbol("false"),
488 Number("1"),
489 Number("2"),
490 RightPar,
491 Number("3"),
492 RightPar,
493 ],
494 vec![If(
495 Box::new(Bool(true)),
496 Box::new(If(
497 Box::new(Bool(false)),
498 Box::new(Int(1)),
499 Some(Box::new(Int(2))),
500 )),
501 Some(Box::new(Int(3))),
502 )],
503 ),
504 // (if true 1 (if false 2 3))
505 (
506 vec![
507 LeftPar,
508 Symbol("if"),
509 Symbol("true"),
510 Number("1"),
511 LeftPar,
512 Symbol("if"),
513 Symbol("false"),
514 Number("2"),
515 Number("3"),
516 RightPar,
517 RightPar,
518 ],
519 vec![If(
520 Box::new(Bool(true)),
521 Box::new(Int(1)),
522 Some(Box::new(If(
523 Box::new(Bool(false)),
524 Box::new(Int(2)),
525 Some(Box::new(Int(3))),
526 ))),
527 )],
528 ),
529 ];
530 for (tokens, ast) in cases {
531 assert_eq!(parse(tokens.clone()), ast, "input: {tokens:?}");
532 }
533}
534
535#[test]
391fn test_for() { 536fn test_for() {
392 let cases = vec![ 537 let cases = vec![
393 // (for i from 0 to 10 i) 538 // (for i from 0 to 10 i)
@@ -947,6 +1092,9 @@ fn test_keyword_prefixed_symbols() {
947 (vec![Symbol("set?")], vec![Sym("set?")]), 1092 (vec![Symbol("set?")], vec![Sym("set?")]),
948 (vec![Symbol("for-each")], vec![Sym("for-each")]), 1093 (vec![Symbol("for-each")], vec![Sym("for-each")]),
949 (vec![Symbol("const-x")], vec![Sym("const-x")]), 1094 (vec![Symbol("const-x")], vec![Sym("const-x")]),
1095 (vec![Symbol("if-then")], vec![Sym("if-then")]),
1096 (vec![Symbol("iffy")], vec![Sym("iffy")]),
1097 (vec![Symbol("if?")], vec![Sym("if?")]),
950 // (fn-foo 1) 1098 // (fn-foo 1)
951 ( 1099 (
952 vec![LeftPar, Symbol("fn-foo"), Number("1"), RightPar], 1100 vec![LeftPar, Symbol("fn-foo"), Number("1"), RightPar],
@@ -1150,6 +1298,16 @@ fn test_special_form_errors() {
1150 vec![LeftPar, Symbol("const"), LeftPar, RightPar, RightPar], 1298 vec![LeftPar, Symbol("const"), LeftPar, RightPar, RightPar],
1151 Error::UnexpectedToken, 1299 Error::UnexpectedToken,
1152 ), 1300 ),
1301 // (if)
1302 (
1303 vec![LeftPar, Symbol("if"), RightPar],
1304 Error::UnexpectedClosePar,
1305 ),
1306 // (if true)
1307 (
1308 vec![LeftPar, Symbol("if"), Symbol("true"), RightPar],
1309 Error::UnexpectedClosePar,
1310 ),
1153 ]; 1311 ];
1154 for (tokens, expected) in cases { 1312 for (tokens, expected) in cases {
1155 assert_eq!(parse_err(tokens.clone()), expected, "input: {tokens:?}"); 1313 assert_eq!(parse_err(tokens.clone()), expected, "input: {tokens:?}");
@@ -1301,6 +1459,79 @@ fn test_nested_special_forms() {
1301 vec![Sym("x"), Call("+", vec![Sym("x"), Int(1)])], 1459 vec![Sym("x"), Call("+", vec![Sym("x"), Int(1)])],
1302 )], 1460 )],
1303 ), 1461 ),
1462 // (if (if a b c) (if d e) (if f g h))
1463 (
1464 vec![
1465 LeftPar,
1466 Symbol("if"),
1467 LeftPar,
1468 Symbol("if"),
1469 Symbol("a"),
1470 Symbol("b"),
1471 Symbol("c"),
1472 RightPar,
1473 LeftPar,
1474 Symbol("if"),
1475 Symbol("d"),
1476 Symbol("e"),
1477 RightPar,
1478 LeftPar,
1479 Symbol("if"),
1480 Symbol("f"),
1481 Symbol("g"),
1482 Symbol("h"),
1483 RightPar,
1484 RightPar,
1485 ],
1486 vec![If(
1487 Box::new(If(
1488 Box::new(Sym("a")),
1489 Box::new(Sym("b")),
1490 Some(Box::new(Sym("c"))),
1491 )),
1492 Box::new(If(Box::new(Sym("d")), Box::new(Sym("e")), None)),
1493 Some(Box::new(If(
1494 Box::new(Sym("f")),
1495 Box::new(Sym("g")),
1496 Some(Box::new(Sym("h"))),
1497 ))),
1498 )],
1499 ),
1500 // (fn abs (x) (if (< x 0) (- 0 x) x))
1501 (
1502 vec![
1503 LeftPar,
1504 Symbol("fn"),
1505 Symbol("abs"),
1506 LeftPar,
1507 Symbol("x"),
1508 RightPar,
1509 LeftPar,
1510 Symbol("if"),
1511 LeftPar,
1512 Symbol("<"),
1513 Symbol("x"),
1514 Number("0"),
1515 RightPar,
1516 LeftPar,
1517 Symbol("-"),
1518 Number("0"),
1519 Symbol("x"),
1520 RightPar,
1521 Symbol("x"),
1522 RightPar,
1523 RightPar,
1524 ],
1525 vec![Fn(
1526 "abs",
1527 vec!["x"],
1528 vec![If(
1529 Box::new(Call("<", vec![Sym("x"), Int(0)])),
1530 Box::new(Call("-", vec![Int(0), Sym("x")])),
1531 Some(Box::new(Sym("x"))),
1532 )],
1533 )],
1534 ),
1304 ]; 1535 ];
1305 for (tokens, ast) in cases { 1536 for (tokens, ast) in cases {
1306 assert_eq!(parse(tokens.clone()), ast, "input: {tokens:?}"); 1537 assert_eq!(parse(tokens.clone()), ast, "input: {tokens:?}");
@@ -1471,6 +1702,86 @@ fn test_span_let() {
1471} 1702}
1472 1703
1473#[test] 1704#[test]
1705fn test_span_if() {
1706 // (if true 1 2)
1707 let lp = sp((1, 0, 0), (1, 1, 1));
1708 let kw = sp((1, 1, 1), (1, 3, 3));
1709 let cond = sp((1, 4, 4), (1, 8, 8));
1710 let then_t = sp((1, 9, 9), (1, 10, 10));
1711 let else_t = sp((1, 11, 11), (1, 12, 12));
1712 let rp = sp((1, 12, 12), (1, 13, 13));
1713
1714 let tokens = vec![
1715 tsp(LeftPar, lp),
1716 tsp(Symbol("if"), kw),
1717 tsp(Symbol("true"), cond),
1718 tsp(Number("1"), then_t),
1719 tsp(Number("2"), else_t),
1720 tsp(RightPar, rp),
1721 ];
1722 let prog = parse_sp(tokens.clone());
1723
1724 assert_eq!(
1725 prog[0].span,
1726 sp((1, 0, 0), (1, 13, 13)),
1727 "input: {tokens:?}"
1728 );
1729 if let Expr::If {
1730 condition,
1731 then_expr,
1732 else_expr,
1733 } = &prog[0].inner
1734 {
1735 assert_eq!(condition.span, cond, "input: {tokens:?}");
1736 assert_eq!(then_expr.span, then_t, "input: {tokens:?}");
1737 assert_eq!(
1738 else_expr.as_ref().unwrap().span,
1739 else_t,
1740 "input: {tokens:?}"
1741 );
1742 } else {
1743 panic!("expected If, input: {tokens:?}");
1744 }
1745}
1746
1747#[test]
1748fn test_span_if_no_else() {
1749 // (if true 1)
1750 let lp = sp((1, 0, 0), (1, 1, 1));
1751 let kw = sp((1, 1, 1), (1, 3, 3));
1752 let cond = sp((1, 4, 4), (1, 8, 8));
1753 let then_t = sp((1, 9, 9), (1, 10, 10));
1754 let rp = sp((1, 10, 10), (1, 11, 11));
1755
1756 let tokens = vec![
1757 tsp(LeftPar, lp),
1758 tsp(Symbol("if"), kw),
1759 tsp(Symbol("true"), cond),
1760 tsp(Number("1"), then_t),
1761 tsp(RightPar, rp),
1762 ];
1763 let prog = parse_sp(tokens.clone());
1764
1765 assert_eq!(
1766 prog[0].span,
1767 sp((1, 0, 0), (1, 11, 11)),
1768 "input: {tokens:?}"
1769 );
1770 if let Expr::If {
1771 condition,
1772 then_expr,
1773 else_expr,
1774 } = &prog[0].inner
1775 {
1776 assert_eq!(condition.span, cond, "input: {tokens:?}");
1777 assert_eq!(then_expr.span, then_t, "input: {tokens:?}");
1778 assert!(else_expr.is_none(), "input: {tokens:?}");
1779 } else {
1780 panic!("expected If, input: {tokens:?}");
1781 }
1782}
1783
1784#[test]
1474fn test_span_for() { 1785fn test_span_for() {
1475 // (for i from 0 to 10 i) 1786 // (for i from 0 to 10 i)
1476 let lp = sp((1, 0, 0), (1, 1, 1)); 1787 let lp = sp((1, 0, 0), (1, 1, 1));