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:
parent
ba911d48ea
commit
ec94230294
|
@ -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 {
|
||||
|
|
|
@ -404,6 +404,7 @@ impl TypedExpr {
|
|||
pub enum FnStyle {
|
||||
Plain,
|
||||
Capture,
|
||||
BinOp(BinOp),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
})],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue