Implement closure in ast building, unparsing, and pretty printing.
This commit is contained in:
parent
2de45817d4
commit
35d616a538
8
sketching/may_2025/closure.dm
Normal file
8
sketching/may_2025/closure.dm
Normal file
@ -0,0 +1,8 @@
|
||||
fn main() {
|
||||
let x = 42;
|
||||
let cl = mut |&mut x| { i ->
|
||||
let result = x + i;
|
||||
x = x + 1;
|
||||
result
|
||||
};
|
||||
}
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -721,10 +721,8 @@ ClosureCaptures = {
|
||||
}
|
||||
|
||||
ClosureCapture = {
|
||||
(
|
||||
Mut
|
||||
| ( Borrow ~ Mut? )*
|
||||
)?
|
||||
Borrow*
|
||||
~ Mut?
|
||||
~ Identifier
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user