63 lines
1.6 KiB
Rust
63 lines
1.6 KiB
Rust
use super::*;
|
|
|
|
pub struct Func {
|
|
args: Vec<Param>,
|
|
name: Option<Ident>,
|
|
ret: Option<Type>,
|
|
body: Expr,
|
|
span: Span,
|
|
}
|
|
|
|
impl Node for Func {
|
|
fn parse(ctx: &mut ParseCtx) -> Result<Self, CompilerMsg> {
|
|
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()
|
|
}
|
|
}
|