Implement closure in ast building, unparsing, and pretty printing.

This commit is contained in:
Jesse Brault 2025-05-17 10:32:14 -05:00
parent 2de45817d4
commit 35d616a538
6 changed files with 320 additions and 10 deletions

View File

@ -0,0 +1,8 @@
fn main() {
let x = 42;
let cl = mut |&mut x| { i ->
let result = x + i;
x = x + 1;
result
};
}

View File

@ -1214,7 +1214,98 @@ fn build_object_index(file_id: usize, inner_pair: Pair<Rule>) -> ObjectNavigatio
}
fn build_closure(file_id: usize, closure_pair: Pair<Rule>) -> Closure {
todo!()
let mut modifier = None;
let mut is_move = false;
let mut captures = ClosureCaptures::default();
let mut parameters = ClosureParameters::default();
let mut statements = vec![];
let mut expression = None;
for inner_pair in closure_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Cons => {
modifier = Some(ClosureModifier::Cons)
},
Rule::Mut => {
modifier = Some(ClosureModifier::Mut)
},
Rule::ClosureCaptures => {
captures = build_closure_captures(file_id, inner_pair);
},
Rule::ClosureParameters => {
parameters = build_closure_parameters(file_id, inner_pair);
},
Rule::Statement => {
statements.push(build_statement(file_id, inner_pair));
},
Rule::Expression => {
expression = Some(Box::new(build_expression(file_id, inner_pair)));
}
_ => unreachable!(),
}
}
Closure {
modifier,
is_move,
captures,
parameters,
statements,
expression,
}
}
fn build_closure_captures(file_id: usize, captures_pair: Pair<Rule>) -> ClosureCaptures {
ClosureCaptures(captures_pair.into_inner().map(|capture_pair| {
expect_and_use(file_id, capture_pair, Rule::ClosureCapture, build_closure_capture)
}).collect())
}
fn build_closure_capture(file_id: usize, capture_pair: Pair<Rule>) -> ClosureCapture {
let mut borrow_count = 0;
let mut is_mutable = false;
let mut identifier = None;
for inner_pair in capture_pair.into_inner() {
match inner_pair.as_rule() {
Rule::Borrow => {
borrow_count += 1;
},
Rule::Mut => {
is_mutable = true;
},
Rule::Identifier => {
identifier = Some(Box::new(build_identifier(file_id, inner_pair)));
}
_ => unreachable!(),
}
}
ClosureCapture {
borrow_count,
is_mutable,
identifier: identifier.unwrap()
}
}
fn build_closure_parameters(file_id: usize, parameters_pair: Pair<Rule>) -> ClosureParameters {
ClosureParameters(parameters_pair.into_inner().map(|parameter_pair| {
expect_and_use(file_id, parameter_pair, Rule::ClosureParameter, build_closure_parameter)
}).collect())
}
fn build_closure_parameter(file_id: usize, parameter_pair: Pair<Rule>) -> ClosureParameter {
let mut inner = parameter_pair.into_inner();
let identifier = expect_and_use(file_id, inner.next().unwrap(), Rule::Identifier, build_identifier);
let type_use = if let Some(type_use_pair) = inner.next() {
Some(expect_and_use(file_id, type_use_pair, Rule::TypeUse, build_type_use))
} else {
None
};
ClosureParameter {
identifier,
type_use
}
}
fn build_literal(file_id: usize, literal_pair: Pair<Rule>) -> Literal {

View File

@ -575,7 +575,51 @@ pub struct CallArguments(pub Vec<CallArgument>);
pub struct CallArgument(pub Box<Expression>);
#[derive(Debug)]
pub struct Closure {}
pub struct Closure {
pub modifier: Option<ClosureModifier>,
pub is_move: bool,
pub captures: ClosureCaptures,
pub parameters: ClosureParameters,
pub statements: Vec<Statement>,
pub expression: Option<Box<Expression>>,
}
#[derive(Debug)]
pub enum ClosureModifier {
Cons,
Mut
}
#[derive(Debug, Default)]
pub struct ClosureCaptures(pub Vec<ClosureCapture>);
impl ClosureCaptures {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ClosureCapture {
pub borrow_count: usize,
pub is_mutable: bool,
pub identifier: Box<Identifier>,
}
#[derive(Debug, Default)]
pub struct ClosureParameters(pub Vec<ClosureParameter>);
impl ClosureParameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ClosureParameter {
pub identifier: Identifier,
pub type_use: Option<TypeUse>,
}
#[derive(Debug)]
pub struct ObjectAccess {

View File

@ -820,7 +820,85 @@ impl PrettyPrint for CallArgument {
impl PrettyPrint for Closure {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
todo!()
writer.writeln_indented(&format!("Closure(is_move = {})", self.is_move))?;
writer.increase_indent();
if let Some(modifier) = &self.modifier {
modifier.pretty_print(writer)?;
}
self.captures.pretty_print(writer)?;
self.parameters.pretty_print(writer)?;
if !self.statements.is_empty() {
writer.writeln_indented("ClosureStatements")?;
writer.increase_indent();
for statement in &self.statements {
statement.pretty_print(writer)?;
}
writer.decrease_indent();
}
if let Some(expression) = &self.expression {
expression.pretty_print(writer)?;
}
writer.decrease_indent();
Ok(())
}
}
impl PrettyPrint for ClosureModifier {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented(&format!("ClosureModifier({})", match self {
ClosureModifier::Mut => "mut",
ClosureModifier::Cons => "cons"
}))
}
}
impl PrettyPrint for ClosureCaptures {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("ClosureCaptures")?;
writer.increase_indent();
for capture in &self.0 {
capture.pretty_print(writer)?;
}
writer.decrease_indent();
Ok(())
}
}
impl PrettyPrint for ClosureCapture {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented(&format!(
"ClosureCapture(borrow_count = {}, is_mutable = {})",
self.borrow_count, self.is_mutable
))?;
writer.increase_indent();
self.identifier.pretty_print(writer)?;
writer.decrease_indent();
Ok(())
}
}
impl PrettyPrint for ClosureParameters {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("ClosureParameters")?;
writer.increase_indent();
for parameter in &self.0 {
parameter.pretty_print(writer)?;
}
writer.decrease_indent();
Ok(())
}
}
impl PrettyPrint for ClosureParameter {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("ClosureParameter")?;
writer.increase_indent();
self.identifier.pretty_print(writer)?;
if let Some(type_use) = &self.type_use {
type_use.pretty_print(writer)?;
}
writer.decrease_indent();
Ok(())
}
}

View File

@ -653,9 +653,7 @@ impl Unparse for FunctionBody {
}
Block(body) => {
writer.writeln("{")?;
writer.increase_indent();
body.unparse_inner(writer)?;
writer.decrease_indent();
writer.writeln_indented("}")
}
Alias(identifier) => {
@ -994,7 +992,100 @@ impl Unparse for CallArgument {
impl Unparse for Closure {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.write("{{ -> TODO }}")
if let Some(modifier) = &self.modifier {
match modifier {
ClosureModifier::Cons => writer.write("cons "),
ClosureModifier::Mut => writer.write("mut "),
}?;
}
if self.is_move {
writer.write("move ")?;
}
if !self.captures.is_empty() {
self.captures.unparse(writer)?;
writer.write(" ")?;
}
writer.write("{ ")?;
if !self.parameters.is_empty() {
self.parameters.unparse(writer)?;
writer.write(" -> ")?;
}
if !self.statements.is_empty() {
writer.write("\n")?;
writer.increase_indent();
for statement in &self.statements {
statement.unparse(writer)?;
}
writer.decrease_indent();
}
if let Some(expression) = &self.expression {
if self.statements.is_empty() {
expression.unparse(writer)?;
writer.write(" }")?;
} else {
writer.increase_indent();
writer.write_indented("")?;
expression.unparse(writer)?;
writer.write("\n")?;
writer.decrease_indent();
writer.write_indented("}")?;
}
} else if !self.statements.is_empty() {
writer.write_indented(" }")?;
} else {
writer.write(" }")?;
}
Ok(())
}
}
impl Unparse for ClosureCaptures {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.write("|")?;
for (i, capture) in self.0.iter().enumerate() {
capture.unparse(writer)?;
if i != self.0.len() - 1 {
writer.write(", ")?;
}
}
writer.write("|")?;
Ok(())
}
}
impl Unparse for ClosureCapture {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
for _ in 0..self.borrow_count {
writer.write("&")?;
}
if self.is_mutable {
writer.write("mut ")?;
}
self.identifier.unparse(writer)?;
Ok(())
}
}
impl Unparse for ClosureParameters {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
for parameter in &self.0 {
parameter.unparse(writer)?;
}
Ok(())
}
}
impl Unparse for ClosureParameter {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
self.identifier.unparse(writer)?;
if let Some(type_use) = &self.type_use {
writer.write(": ")?;
type_use.unparse(writer)?;
}
Ok(())
}
}

View File

@ -721,10 +721,8 @@ ClosureCaptures = {
}
ClosureCapture = {
(
Mut
| ( Borrow ~ Mut? )*
)?
Borrow*
~ Mut?
~ Identifier
}