diff --git a/examples/make_counter.puyo b/examples/make_counter.puyo new file mode 100644 index 0000000..d865068 --- /dev/null +++ b/examples/make_counter.puyo @@ -0,0 +1,24 @@ +fn make_counter([] [inc]) ( + i := 0; + + fn ^inc([] [i]) ( + i := i + 1; + ^i := i; + ); +); + +a := make_counter!; +b := make_counter!; + +put 65; put 10; +println {^a}.a.inc!; +println a.inc!; +println a.inc!; + +put 66; put 10; +println (b.inc!).i; +println (b.inc!).i; +println (b.inc!).i; + +# TODO: comments at eof don't parse +println 42; diff --git a/src/parser.rs b/src/parser.rs index 021c36a..c82f379 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -15,6 +15,9 @@ use logos::Logos; #[logos(skip r"[ \t\n\r\f]+")] #[logos(skip r"#[^\n]*?\n")] enum Token<'a> { + #[token("!")] + Bang, + #[token(":")] Colon, @@ -66,6 +69,7 @@ enum Token<'a> { impl fmt::Display for Token<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { + Token::Bang => write!(f, "!"), Token::Colon => write!(f, ":"), Token::Period => write!(f, "."), Token::Comma => write!(f, ","), @@ -234,14 +238,20 @@ where let e2 = access.or(e1); - let app = e2 + let bang = e2.clone().foldl(just(Token::Bang).repeated(), |thunk, _| { + Ast::App(Box::new(thunk), Box::new(Ast::Block(vec![]))) + }); + + let e3 = bang.or(e2); + + let app = e3 .clone() - .foldl(e2.clone().repeated(), |f, x| { + .foldl(e3.clone().repeated(), |f, x| { Ast::App(Box::new(f), Box::new(x)) }) .labelled("function application"); - let atom = app.or(e2); + let atom = app.or(e3); atom.pratt(( infix(none(1), just(Token::BinOp("=")), |l, _, r, _| { diff --git a/src/tests/parser.rs b/src/tests/parser.rs index c084063..f9c4547 100644 --- a/src/tests/parser.rs +++ b/src/tests/parser.rs @@ -215,3 +215,31 @@ if [wow = cool]() [ ", ); } + +#[test] +fn bang() { + test( + " +a := make_counter!; +b := make_counter!; + +println {^a}.a.inc!; +println a.inc!; +println a.inc!; + +println b.inc!; +println b.inc!; +println b.inc!; +", + " +(set! a (make_counter ())); +(set! b (make_counter ())); +(println ({^a}.a.inc ())); +(println (a.inc ())); +(println (a.inc ())); +(println (b.inc ())); +(println (b.inc ())); +(println (b.inc ())) +", + ); +}