Skip to content

Commit

Permalink
refactor(parser): decouple function signature from it's body.
Browse files Browse the repository at this point in the history
  • Loading branch information
rzvxa committed Mar 9, 2024
1 parent 31f256d commit 6614827
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 193 deletions.
27 changes: 26 additions & 1 deletion crates/fuse-ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub enum Statement {
EnumDeclaration(Box<EnumDeclaration>),
/// A struct declaration using struct keyword.
StructDeclaration(Box<StructDeclaration>),
/// A struct declaration using struct keyword.
ImplStatement(Box<ImplStatement>),
}

#[serializable]
Expand Down Expand Up @@ -188,11 +190,18 @@ pub struct Identifier {
#[serializable]
#[derive(Debug, PartialEq)]
pub struct Function {
pub span: Span,
pub signature: FunctionSignature,
pub body: FunctionBody,
}

#[serializable]
#[derive(Debug, PartialEq)]
pub struct FunctionSignature {
pub span: Span,
pub identifier: Option<Identifier>,
pub params: FunctionParameters,
pub return_type: Option<TypeAnnotation>,
pub body: FunctionBody,
}

#[serializable]
Expand Down Expand Up @@ -408,3 +417,19 @@ pub enum ConstructionField {
KeyValueArgument(KeyValueArgument),
Spread(SpreadArgument),
}

#[serializable]
#[derive(Debug, PartialEq)]
pub struct ImplStatement {
pub span: Span,
pub target: TypeAnnotation,
pub r#trait: Option<()>,
pub methods: Vec<ImplMethod>,
}

#[serializable]
#[derive(Debug, PartialEq)]
pub struct ImplMethod {
pub modifier: VisibilityModifier,
pub function: Function,
}
4 changes: 4 additions & 0 deletions crates/fuse-ast/src/ast_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ impl AstFactory {
Statement::StructDeclaration(Box::from(decl))
}

pub fn impl_statement(&self, r#impl: ImplStatement) -> Statement {
Statement::ImplStatement(Box::from(r#impl))
}

pub fn expression_statement(&self, expr: Expression) -> Statement {
Statement::Expression(Box::from(expr))
}
Expand Down
22 changes: 18 additions & 4 deletions crates/fuse-parser/src/parsers/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,25 @@ use crate::{
};
use fuse_ast::{
BindingPattern, BindingPatternKind, Function, FunctionBody, FunctionParameter,
FunctionParameters, TypeAnnotation,
FunctionParameters, FunctionSignature, TypeAnnotation,
};
use fuse_common::Span;
impl<'a> Parser<'a> {
pub(crate) fn parse_function(&mut self, expect_identifier: bool) -> ParserResult<Function> {
let start = self.start_span();
let signature = self.parse_function_signature(expect_identifier)?;
let body = self.parse_function_body()?;
Ok(Function {
span: self.end_span(start),
signature,
body,
})
}

pub(crate) fn parse_function_signature(
&mut self,
expect_identifier: bool,
) -> ParserResult<FunctionSignature> {
let start = self.start_span();
// Consume the keyword
self.consume();
Expand All @@ -19,15 +33,15 @@ impl<'a> Parser<'a> {
};
let params = self.parse_function_parameters()?;
let return_type = self.parse_function_return_type()?;
let body = self.parse_function_body()?;
Ok(Function {

Ok(FunctionSignature {
span: self.end_span(start),
identifier,
params,
return_type,
body,
})
}

pub(crate) fn parse_function_parameters(&mut self) -> ParserResult<FunctionParameters> {
let open = self.consume_expect(TokenKind::LParen)?;
// Empty function parameters
Expand Down
26 changes: 25 additions & 1 deletion crates/fuse-parser/src/parsers/statements.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use fuse_ast::{Block, Statement};
use fuse_ast::{Block, Function, FunctionSignature, ImplMethod, ImplStatement, Statement};

use crate::{lexer::TokenKind, Parser, ParserResult};

Expand Down Expand Up @@ -70,6 +70,7 @@ impl<'a> Parser<'a> {
TokenKind::Struct => self
.parse_struct_declaration()
.map(|decl| self.ast.struct_declaration_statement(decl)),
TokenKind::Impl => self.parse_impl_statement(),

kind if kind.is_trivial() => {
unreachable!("All trivial tokens should be eaten by a `TokenReference`.")
Expand All @@ -88,4 +89,27 @@ impl<'a> Parser<'a> {
let span = self.end_span(start);
self.ast.empty_statement(span)
}

fn parse_impl_statement(&mut self) -> ParserResult<Statement> {
debug_assert!(self.at(TokenKind::Trait));
let start = self.start_span();
// Consume the struct keyword.
self.consume();

let target = self.parse_type_annotation()?;
let mut methods: Vec<ImplMethod> = Vec::new();
while !self.at(TokenKind::End) {
let modifier = self.try_parse_visibility_modifier();
let function = self.parse_function(true)?;
methods.push(ImplMethod { modifier, function });
}
// consume the end token
self.consume();
Ok(self.ast.impl_statement(ImplStatement {
span: self.end_span(start),
target,
r#trait: None,
methods,
}))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,28 @@ Some(Chunk(
start: 0,
end: 19,
),
identifier: Some(Identifier(
signature: FunctionSignature(
span: Span(
start: 9,
end: 13,
),
name: Atom("test"),
)),
params: FunctionParameters(
span: Span(
start: 13,
start: 0,
end: 15,
),
items: [],
rest: None,
identifier: Some(Identifier(
span: Span(
start: 9,
end: 13,
),
name: Atom("test"),
)),
params: FunctionParameters(
span: Span(
start: 13,
end: 15,
),
items: [],
rest: None,
),
return_type: None,
),
return_type: None,
body: Block(Block(
statements: [],
)),
Expand Down
132 changes: 69 additions & 63 deletions crates/fuse-parser/tests/cases/pass/function-declaration-02/ast.snap
Original file line number Diff line number Diff line change
Expand Up @@ -16,77 +16,83 @@ Some(Chunk(
start: 0,
end: 30,
),
identifier: Some(Identifier(
signature: FunctionSignature(
span: Span(
start: 9,
end: 13,
),
name: Atom("test"),
)),
params: FunctionParameters(
span: Span(
start: 13,
start: 0,
end: 23,
),
items: [
FunctionParameter(
span: Span(
start: 14,
end: 15,
),
pattern: BindingPattern(
kind: Identifier(BindingIdentifier(
span: Span(
start: 14,
end: 15,
),
atom: Atom("a"),
mutable: false,
)),
type_annotation: None,
optional: false,
),
identifier: Some(Identifier(
span: Span(
start: 9,
end: 13,
),
FunctionParameter(
span: Span(
start: 17,
end: 18,
),
pattern: BindingPattern(
kind: Identifier(BindingIdentifier(
span: Span(
start: 17,
end: 18,
),
atom: Atom("b"),
mutable: false,
)),
type_annotation: None,
optional: false,
),
name: Atom("test"),
)),
params: FunctionParameters(
span: Span(
start: 13,
end: 23,
),
FunctionParameter(
span: Span(
start: 20,
end: 21,
items: [
FunctionParameter(
span: Span(
start: 14,
end: 15,
),
pattern: BindingPattern(
kind: Identifier(BindingIdentifier(
span: Span(
start: 14,
end: 15,
),
atom: Atom("a"),
mutable: false,
)),
type_annotation: None,
optional: false,
),
),
pattern: BindingPattern(
kind: Identifier(BindingIdentifier(
span: Span(
start: 20,
end: 21,
),
atom: Atom("c"),
mutable: false,
)),
type_annotation: None,
optional: false,
FunctionParameter(
span: Span(
start: 17,
end: 18,
),
pattern: BindingPattern(
kind: Identifier(BindingIdentifier(
span: Span(
start: 17,
end: 18,
),
atom: Atom("b"),
mutable: false,
)),
type_annotation: None,
optional: false,
),
),
),
],
rest: None,
FunctionParameter(
span: Span(
start: 20,
end: 21,
),
pattern: BindingPattern(
kind: Identifier(BindingIdentifier(
span: Span(
start: 20,
end: 21,
),
atom: Atom("c"),
mutable: false,
)),
type_annotation: None,
optional: false,
),
),
],
rest: None,
),
return_type: None,
),
return_type: None,
body: Block(Block(
statements: [
Expression(Identifier(Identifier(
Expand Down
Loading

0 comments on commit 6614827

Please sign in to comment.