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 {
|
pub fn is_logically_equal(&self, other: &Annotation) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Annotation::Constructor {
|
Annotation::Constructor {
|
||||||
|
|
|
@ -404,6 +404,7 @@ impl TypedExpr {
|
||||||
pub enum FnStyle {
|
pub enum FnStyle {
|
||||||
Plain,
|
Plain,
|
||||||
Capture,
|
Capture,
|
||||||
|
BinOp(BinOp),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
|
@ -773,6 +773,14 @@ impl<'comments> Formatter<'comments> {
|
||||||
..
|
..
|
||||||
} => self.fn_capture(body),
|
} => self.fn_capture(body),
|
||||||
|
|
||||||
|
UntypedExpr::Fn {
|
||||||
|
fn_style: FnStyle::BinOp(op),
|
||||||
|
body,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
UntypedExpr::Fn {
|
UntypedExpr::Fn {
|
||||||
fn_style: FnStyle::Plain,
|
fn_style: FnStyle::Plain,
|
||||||
return_annotation,
|
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()
|
let when_clause_parser = pattern_parser()
|
||||||
.then(
|
.then(
|
||||||
just(Token::Vbar)
|
just(Token::Vbar)
|
||||||
|
@ -1083,6 +1134,7 @@ pub fn expr_parser(
|
||||||
bytearray,
|
bytearray,
|
||||||
list_parser,
|
list_parser,
|
||||||
anon_fn_parser,
|
anon_fn_parser,
|
||||||
|
anon_binop_parser,
|
||||||
block_parser,
|
block_parser,
|
||||||
when_parser,
|
when_parser,
|
||||||
let_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