use super::*;
pub struct Func {
args: Vec,
name: Option,
ret: Option,
body: Expr,
span: Span,
}
impl Node for Func {
fn parse(ctx: &mut ParseCtx) -> Result {
let mut name = None;
if let Token::Ident(ident) = ctx.expect_peek()? {
// yucky
let ident = ident.to_string();
ctx.next();
let ident = ctx.ident(ident);
name = Some(ident);
}
ctx.expect(Token::OpenParen)?;
let args = ctx.list(Token::Comma, Token::CloseParen)?;
let mut ret = None;
if ctx.next_if(Token::Arrow) {
ret = Some(ctx.parse()?);
}
let body = Expr::body(ctx)?;
Ok(Self {
args,
ret,
body,
name,
span: ctx.span(),
})
}
fn fmt(&self, f: &mut std::fmt::Formatter, ctx: DisplayCtx) -> std::fmt::Result {
write!(f, "fn")?;
if let Some(name) = &self.name {
write!(f, " {name}")?;
}
write!(f, "(")?;
if let Some((last, rest)) = self.args.split_last() {
for arg in rest {
write!(f, "{}, ", arg.dsp(ctx))?;
}
write!(f, "{}", last.dsp(ctx))?;
}
write!(f, ") ")?;
if let Some(ret) = &self.ret {
write!(f, "-> {} ", ret.dsp(ctx))?;
}
self.body.fmt_body(f, ctx)?;
Ok(())
}
}
impl Func {
pub fn ends_with_block(&self) -> bool {
self.body.ends_with_block()
}
}