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 {
|
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 {
|
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>);
|
pub struct CallArgument(pub Box<Expression>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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)]
|
#[derive(Debug)]
|
||||||
pub struct ObjectAccess {
|
pub struct ObjectAccess {
|
||||||
|
@ -820,7 +820,85 @@ impl PrettyPrint for CallArgument {
|
|||||||
|
|
||||||
impl PrettyPrint for Closure {
|
impl PrettyPrint for Closure {
|
||||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
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) => {
|
Block(body) => {
|
||||||
writer.writeln("{")?;
|
writer.writeln("{")?;
|
||||||
writer.increase_indent();
|
|
||||||
body.unparse_inner(writer)?;
|
body.unparse_inner(writer)?;
|
||||||
writer.decrease_indent();
|
|
||||||
writer.writeln_indented("}")
|
writer.writeln_indented("}")
|
||||||
}
|
}
|
||||||
Alias(identifier) => {
|
Alias(identifier) => {
|
||||||
@ -994,7 +992,100 @@ impl Unparse for CallArgument {
|
|||||||
|
|
||||||
impl Unparse for Closure {
|
impl Unparse for Closure {
|
||||||
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
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 = {
|
ClosureCapture = {
|
||||||
(
|
Borrow*
|
||||||
Mut
|
~ Mut?
|
||||||
| ( Borrow ~ Mut? )*
|
|
||||||
)?
|
|
||||||
~ Identifier
|
~ Identifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user