Extend parser to accept anonymous binop as expressions.

This is simply a syntactic sugar which desugarize to a function call with two arguments mapped to the specified binary operator.
  Only works for '>' at this stage as a PoC, extending to all binop in the next commit.
This commit is contained in:
KtorZ 2023-06-17 07:36:11 +02:00
parent ba911d48ea
commit ec94230294
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
5 changed files with 181 additions and 0 deletions

View File

@ -647,6 +647,15 @@ impl Annotation {
}
}
pub fn boolean(location: Span) -> Self {
Annotation::Constructor {
name: "Bool".to_string(),
module: None,
arguments: vec![],
location,
}
}
pub fn is_logically_equal(&self, other: &Annotation) -> bool {
match self {
Annotation::Constructor {

View File

@ -404,6 +404,7 @@ impl TypedExpr {
pub enum FnStyle {
Plain,
Capture,
BinOp(BinOp),
}
#[derive(Debug, Clone, PartialEq)]

View File

@ -773,6 +773,14 @@ impl<'comments> Formatter<'comments> {
..
} => self.fn_capture(body),
UntypedExpr::Fn {
fn_style: FnStyle::BinOp(op),
body,
..
} => {
unimplemented!()
}
UntypedExpr::Fn {
fn_style: FnStyle::Plain,
return_annotation,

View File

@ -940,6 +940,57 @@ pub fn expr_parser(
},
);
let anon_binop_parser = select! {
Token::Greater => BinOp::GtInt,
}
.map_with_span(|name, location| {
let arguments = vec![
ast::Arg {
arg_name: ast::ArgName::Named {
name: "left".to_string(),
label: "left".to_string(),
location,
is_validator_param: false,
},
annotation: Some(ast::Annotation::boolean(location)),
location,
tipo: (),
},
ast::Arg {
arg_name: ast::ArgName::Named {
name: "right".to_string(),
label: "right".to_string(),
location,
is_validator_param: false,
},
annotation: Some(ast::Annotation::boolean(location)),
location,
tipo: (),
},
];
let body = expr::UntypedExpr::BinOp {
location,
name,
left: Box::new(expr::UntypedExpr::Var {
location,
name: "left".to_string(),
}),
right: Box::new(expr::UntypedExpr::Var {
location,
name: "right".to_string(),
}),
};
expr::UntypedExpr::Fn {
arguments,
body: Box::new(body),
return_annotation: Some(ast::Annotation::boolean(location)),
fn_style: expr::FnStyle::BinOp(name),
location,
}
});
let when_clause_parser = pattern_parser()
.then(
just(Token::Vbar)
@ -1083,6 +1134,7 @@ pub fn expr_parser(
bytearray,
list_parser,
anon_fn_parser,
anon_binop_parser,
block_parser,
when_parser,
let_parser,

View File

@ -3667,3 +3667,114 @@ fn int_parsing_numeric_underscore() {
})],
)
}
#[test]
fn first_class_binop() {
use expr::UntypedExpr::*;
let code = indoc! {r#"
fn foo() {
compare_with(a, >, b)
}
"#};
assert_definitions(
code,
vec![ast::Definition::Fn(Function {
arguments: vec![],
body: Call {
arguments: vec![
ast::CallArg {
label: None,
location: Span::new((), 26..27),
value: Var {
location: Span::new((), 26..27),
name: "a".to_string(),
},
},
ast::CallArg {
label: None,
location: Span::new((), 29..30),
value: Fn {
location: Span::new((), 29..30),
fn_style: expr::FnStyle::BinOp(ast::BinOp::GtInt),
arguments: vec![
ast::Arg {
arg_name: ast::ArgName::Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 29..30),
is_validator_param: false,
},
location: Span::new((), 29..30),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 29..30),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
tipo: (),
},
ast::Arg {
arg_name: ast::ArgName::Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 29..30),
is_validator_param: false,
},
location: Span::new((), 29..30),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 29..30),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 29..30),
name: ast::BinOp::GtInt,
left: Box::new(Var {
location: Span::new((), 29..30),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 29..30),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 29..30),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
},
},
ast::CallArg {
label: None,
location: Span::new((), 32..33),
value: Var {
location: Span::new((), 32..33),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 13..25),
name: "compare_with".to_string(),
}),
location: Span::new((), 13..34),
},
doc: None,
location: Span::new((), 0..8),
name: "foo".to_string(),
public: false,
return_annotation: None,
return_type: (),
end_position: 35,
can_error: true,
})],
);
}