Support all binary operator in the anonymous binop parser.

This commit is contained in:
KtorZ 2023-06-17 08:35:22 +02:00
parent d0b4c1c3b5
commit 91f03abb7b
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
3 changed files with 666 additions and 38 deletions

View File

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

View File

@ -947,8 +947,32 @@ pub fn expr_parser(
Token::LessEqual => BinOp::LtEqInt,
Token::Greater => BinOp::GtInt,
Token::GreaterEqual => BinOp::GtEqInt,
Token::VbarVbar => BinOp::Or,
Token::AmperAmper => BinOp::And,
Token::Plus => BinOp::AddInt,
Token::Minus => BinOp::SubInt,
Token::Slash => BinOp::DivInt,
Token::Star => BinOp::MultInt,
Token::Percent => BinOp::ModInt,
}
.map_with_span(|name, location| {
use BinOp::*;
let arg_annotation = match name {
Or | And => Some(ast::Annotation::boolean(location)),
Eq | NotEq => None,
LtInt | LtEqInt | GtInt | GtEqInt | AddInt | SubInt | MultInt | DivInt | ModInt => {
Some(ast::Annotation::int(location))
}
};
let return_annotation = match name {
Or | And | Eq | NotEq | LtInt | LtEqInt | GtInt | GtEqInt => {
Some(ast::Annotation::boolean(location))
}
AddInt | SubInt | MultInt | DivInt | ModInt => Some(ast::Annotation::int(location)),
};
let arguments = vec![
ast::Arg {
arg_name: ast::ArgName::Named {
@ -957,7 +981,7 @@ pub fn expr_parser(
location,
is_validator_param: false,
},
annotation: Some(ast::Annotation::boolean(location)),
annotation: arg_annotation.clone(),
location,
tipo: (),
},
@ -968,7 +992,7 @@ pub fn expr_parser(
location,
is_validator_param: false,
},
annotation: Some(ast::Annotation::boolean(location)),
annotation: arg_annotation,
location,
tipo: (),
},
@ -990,7 +1014,7 @@ pub fn expr_parser(
expr::UntypedExpr::Fn {
arguments,
body: Box::new(body),
return_annotation: Some(ast::Annotation::boolean(location)),
return_annotation,
fn_style: expr::FnStyle::BinOp(name),
location,
}
@ -1296,7 +1320,20 @@ pub fn expr_parser(
// Negate
let op = choice((
just(Token::Bang).to(UnOp::Not),
just(Token::Minus).to(UnOp::Negate),
just(Token::Minus)
// NOTE: Prevent conflict with usage for '-' as a standalone binary op.
// This will make '-' parse when used as standalone binop in a function call.
// For example:
//
// foo(a, -, b)
//
// but it'll fail in a let-binding:
//
// let foo = -
//
// which seems acceptable.
.then_ignore(just(Token::Comma).not().rewind())
.to(UnOp::Negate),
));
let unary = op

View File

@ -3681,6 +3681,13 @@ fn first_class_binop() {
compare_with(a, <=, b)
compare_with(a, ==, b)
compare_with(a, !=, b)
combine_with(a, &&, b)
combine_with(a, ||, b)
compute_with(a, +, b)
compute_with(a, -, b)
compute_with(a, /, b)
compute_with(a, *, b)
compute_with(a, %, b)
}
"#};
@ -3689,7 +3696,7 @@ fn first_class_binop() {
vec![ast::Definition::Fn(Function {
arguments: vec![],
body: Sequence {
location: Span::new((), 13..158),
location: Span::new((), 13..328),
expressions: vec![
Call {
arguments: vec![
@ -3719,7 +3726,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 29..30),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -3735,7 +3742,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 29..30),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -3804,7 +3811,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 53..55),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -3820,7 +3827,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 53..55),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -3889,7 +3896,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 78..79),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -3905,7 +3912,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 78..79),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -3974,7 +3981,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 102..104),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -3990,7 +3997,7 @@ fn first_class_binop() {
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 102..104),
module: None,
name: "Bool".to_string(),
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
@ -4056,12 +4063,7 @@ fn first_class_binop() {
is_validator_param: false,
},
location: Span::new((), 127..129),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 127..129),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
annotation: None,
tipo: (),
},
Arg {
@ -4072,12 +4074,7 @@ fn first_class_binop() {
is_validator_param: false,
},
location: Span::new((), 127..129),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 127..129),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
annotation: None,
tipo: (),
},
],
@ -4141,12 +4138,7 @@ fn first_class_binop() {
is_validator_param: false,
},
location: Span::new((), 152..154),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 152..154),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
annotation: None,
tipo: (),
},
Arg {
@ -4157,12 +4149,7 @@ fn first_class_binop() {
is_validator_param: false,
},
location: Span::new((), 152..154),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 152..154),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
annotation: None,
tipo: (),
},
],
@ -4201,6 +4188,601 @@ fn first_class_binop() {
}),
location: Span::new((), 136..158),
},
Call {
arguments: vec![
CallArg {
label: None,
location: Span::new((), 174..175),
value: Var {
location: Span::new((), 174..175),
name: "a".to_string(),
},
},
CallArg {
label: None,
location: Span::new((), 177..179),
value: Fn {
location: Span::new((), 177..179),
fn_style: expr::FnStyle::BinOp(And),
arguments: vec![
Arg {
arg_name: Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 177..179),
is_validator_param: false,
},
location: Span::new((), 177..179),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 177..179),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
tipo: (),
},
Arg {
arg_name: Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 177..179),
is_validator_param: false,
},
location: Span::new((), 177..179),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 177..179),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 177..179),
name: And,
left: Box::new(Var {
location: Span::new((), 177..179),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 177..179),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 177..179),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
},
},
CallArg {
label: None,
location: Span::new((), 181..182),
value: Var {
location: Span::new((), 181..182),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 161..173),
name: "combine_with".to_string(),
}),
location: Span::new((), 161..183),
},
Call {
arguments: vec![
CallArg {
label: None,
location: Span::new((), 199..200),
value: Var {
location: Span::new((), 199..200),
name: "a".to_string(),
},
},
CallArg {
label: None,
location: Span::new((), 202..204),
value: Fn {
location: Span::new((), 202..204),
fn_style: expr::FnStyle::BinOp(Or),
arguments: vec![
Arg {
arg_name: Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 202..204),
is_validator_param: false,
},
location: Span::new((), 202..204),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 202..204),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
tipo: (),
},
Arg {
arg_name: Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 202..204),
is_validator_param: false,
},
location: Span::new((), 202..204),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 202..204),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 202..204),
name: Or,
left: Box::new(Var {
location: Span::new((), 202..204),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 202..204),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 202..204),
module: None,
name: "Bool".to_string(),
arguments: vec![],
}),
},
},
CallArg {
label: None,
location: Span::new((), 206..207),
value: Var {
location: Span::new((), 206..207),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 186..198),
name: "combine_with".to_string(),
}),
location: Span::new((), 186..208),
},
Call {
arguments: vec![
CallArg {
label: None,
location: Span::new((), 224..225),
value: Var {
location: Span::new((), 224..225),
name: "a".to_string(),
},
},
CallArg {
label: None,
location: Span::new((), 227..228),
value: Fn {
location: Span::new((), 227..228),
fn_style: expr::FnStyle::BinOp(AddInt),
arguments: vec![
Arg {
arg_name: Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 227..228),
is_validator_param: false,
},
location: Span::new((), 227..228),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 227..228),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
Arg {
arg_name: Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 227..228),
is_validator_param: false,
},
location: Span::new((), 227..228),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 227..228),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 227..228),
name: AddInt,
left: Box::new(Var {
location: Span::new((), 227..228),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 227..228),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 227..228),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
},
},
CallArg {
label: None,
location: Span::new((), 230..231),
value: Var {
location: Span::new((), 230..231),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 211..223),
name: "compute_with".to_string(),
}),
location: Span::new((), 211..232),
},
Call {
arguments: vec![
CallArg {
label: None,
location: Span::new((), 248..249),
value: Var {
location: Span::new((), 248..249),
name: "a".to_string(),
},
},
CallArg {
label: None,
location: Span::new((), 251..252),
value: Fn {
location: Span::new((), 251..252),
fn_style: expr::FnStyle::BinOp(SubInt),
arguments: vec![
Arg {
arg_name: Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 251..252),
is_validator_param: false,
},
location: Span::new((), 251..252),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 251..252),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
Arg {
arg_name: Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 251..252),
is_validator_param: false,
},
location: Span::new((), 251..252),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 251..252),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 251..252),
name: SubInt,
left: Box::new(Var {
location: Span::new((), 251..252),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 251..252),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 251..252),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
},
},
CallArg {
label: None,
location: Span::new((), 254..255),
value: Var {
location: Span::new((), 254..255),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 235..247),
name: "compute_with".to_string(),
}),
location: Span::new((), 235..256),
},
Call {
arguments: vec![
CallArg {
label: None,
location: Span::new((), 272..273),
value: Var {
location: Span::new((), 272..273),
name: "a".to_string(),
},
},
CallArg {
label: None,
location: Span::new((), 275..276),
value: Fn {
location: Span::new((), 275..276),
fn_style: expr::FnStyle::BinOp(DivInt),
arguments: vec![
Arg {
arg_name: Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 275..276),
is_validator_param: false,
},
location: Span::new((), 275..276),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 275..276),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
Arg {
arg_name: Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 275..276),
is_validator_param: false,
},
location: Span::new((), 275..276),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 275..276),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 275..276),
name: DivInt,
left: Box::new(Var {
location: Span::new((), 275..276),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 275..276),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 275..276),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
},
},
CallArg {
label: None,
location: Span::new((), 278..279),
value: Var {
location: Span::new((), 278..279),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 259..271),
name: "compute_with".to_string(),
}),
location: Span::new((), 259..280),
},
Call {
arguments: vec![
CallArg {
label: None,
location: Span::new((), 296..297),
value: Var {
location: Span::new((), 296..297),
name: "a".to_string(),
},
},
CallArg {
label: None,
location: Span::new((), 299..300),
value: Fn {
location: Span::new((), 299..300),
fn_style: expr::FnStyle::BinOp(MultInt),
arguments: vec![
Arg {
arg_name: Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 299..300),
is_validator_param: false,
},
location: Span::new((), 299..300),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 299..300),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
Arg {
arg_name: Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 299..300),
is_validator_param: false,
},
location: Span::new((), 299..300),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 299..300),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 299..300),
name: MultInt,
left: Box::new(Var {
location: Span::new((), 299..300),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 299..300),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 299..300),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
},
},
CallArg {
label: None,
location: Span::new((), 302..303),
value: Var {
location: Span::new((), 302..303),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 283..295),
name: "compute_with".to_string(),
}),
location: Span::new((), 283..304),
},
Call {
arguments: vec![
CallArg {
label: None,
location: Span::new((), 320..321),
value: Var {
location: Span::new((), 320..321),
name: "a".to_string(),
},
},
CallArg {
label: None,
location: Span::new((), 323..324),
value: Fn {
location: Span::new((), 323..324),
fn_style: expr::FnStyle::BinOp(ModInt),
arguments: vec![
Arg {
arg_name: Named {
name: "left".to_string(),
label: "left".to_string(),
location: Span::new((), 323..324),
is_validator_param: false,
},
location: Span::new((), 323..324),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 323..324),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
Arg {
arg_name: Named {
name: "right".to_string(),
label: "right".to_string(),
location: Span::new((), 323..324),
is_validator_param: false,
},
location: Span::new((), 323..324),
annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 323..324),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
tipo: (),
},
],
body: Box::new(BinOp {
location: Span::new((), 323..324),
name: ModInt,
left: Box::new(Var {
location: Span::new((), 323..324),
name: "left".to_string(),
}),
right: Box::new(Var {
location: Span::new((), 323..324),
name: "right".to_string(),
}),
}),
return_annotation: Some(ast::Annotation::Constructor {
location: Span::new((), 323..324),
module: None,
name: "Int".to_string(),
arguments: vec![],
}),
},
},
CallArg {
label: None,
location: Span::new((), 326..327),
value: Var {
location: Span::new((), 326..327),
name: "b".to_string(),
},
},
],
fun: Box::new(Var {
location: Span::new((), 307..319),
name: "compute_with".to_string(),
}),
location: Span::new((), 307..328),
},
],
},
doc: None,
@ -4209,7 +4791,7 @@ fn first_class_binop() {
public: false,
return_annotation: None,
return_type: (),
end_position: 159,
end_position: 329,
can_error: true,
})],
);