From a844a711b99a146df4adc9c01ae7888987dc668d Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Fri, 20 Sep 2024 01:42:16 -0400 Subject: [PATCH 01/13] Variable increament support --- crates/deno_task_shell/src/grammar.pest | 10 +- crates/deno_task_shell/src/parser.rs | 124 +++++++++++++++++++----- scripts/arithmetic.sh | 6 +- 3 files changed, 112 insertions(+), 28 deletions(-) diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index c3e081f..3ef741d 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -203,10 +203,18 @@ logical_and = { "&&" } logical_or = { "||" } unary_arithmetic_expr = !{ - (unary_arithmetic_op | post_arithmetic_op) ~ (parentheses_expr | VARIABLE | NUMBER) | + unary_pre_arithmetic_expr | unary_post_arithmatic_expr +} + +unary_pre_arithmetic_expr = !{ + (post_arithmetic_op | unary_arithmetic_op) ~ (parentheses_expr | VARIABLE | NUMBER) +} + +unary_post_arithmatic_expr = !{ (parentheses_expr | VARIABLE | NUMBER) ~ post_arithmetic_op } + unary_arithmetic_op = _{ unary_plus | unary_minus | logical_not | bitwise_not } diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index c438ece..f59e0f0 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -1422,21 +1422,11 @@ fn parse_unary_arithmetic_expr(pair: Pair) -> Result { let first = inner.next().unwrap(); match first.as_rule() { - Rule::unary_arithmetic_op => { - let op = parse_unary_arithmetic_op(first)?; - let operand = parse_arithmetic_expr(inner.next().unwrap())?; - Ok(ArithmeticPart::UnaryArithmeticExpr { - operator: op, - operand: Box::new(operand), - }) + Rule::unary_pre_arithmetic_expr => { + unary_pre_arithmetic_expr(first) } - Rule::post_arithmetic_op => { - let operand = parse_arithmetic_expr(inner.next().unwrap())?; - let op = parse_post_arithmetic_op(first)?; - Ok(ArithmeticPart::PostArithmeticExpr { - operand: Box::new(operand), - operator: op, - }) + Rule::unary_post_arithmatic_expr => { + unary_post_arithmatic_expr(first) } _ => { let operand = parse_arithmetic_expr(first)?; @@ -1449,26 +1439,108 @@ fn parse_unary_arithmetic_expr(pair: Pair) -> Result { } } +fn parse_unary_arithmetic_op_type(pair: Pair) -> Result { + match pair.as_rule() { + Rule::unary_arithmetic_op => Ok(true), + Rule::post_arithmetic_op => Ok(false), + _ => { + Err(miette!( + "Unexpected rule in unary arithmetic operator: {:?}", + pair.as_rule() + )) + } + } +} + +fn unary_pre_arithmetic_expr(pair: Pair) -> Result { + let mut inner = pair.into_inner(); + let first = inner.next().unwrap(); + let second = inner.next().unwrap(); + let operand = + match second.as_rule() { + Rule::parentheses_expr => { + let inner = second.into_inner().next().unwrap(); + let parts = parse_arithmetic_sequence(inner)?; + Ok(ArithmeticPart::ParenthesesExpr(Box::new(Arithmetic { + parts, + }))) + }, + Rule::VARIABLE => { + Ok(ArithmeticPart::Variable(second.as_str().to_string())) + } + Rule::NUMBER => Ok(ArithmeticPart::Number(second.as_str().to_string())), + _ => Err(miette!( + "Unexpected rule in arithmetic expression: {:?}", + second.as_rule() + )), + }?; + + if parse_unary_arithmetic_op_type(first.clone())? { + let op = parse_unary_arithmetic_op(first)?; + Ok(ArithmeticPart::UnaryArithmeticExpr { + operator: (op), + operand: (Box::new(operand)) + }) + } else { + let op = parse_post_arithmetic_op(first)?; + Ok(ArithmeticPart::PostArithmeticExpr { + operator: (op), + operand: (Box::new(operand)) + }) + } +} + +fn unary_post_arithmatic_expr(pair: Pair) -> Result { + let mut inner = pair.into_inner(); + let first = inner.next().unwrap(); + let second = inner.next().unwrap(); + let operand = + match first.as_rule() { + Rule::parentheses_expr => { + let inner = first.into_inner().next().unwrap(); + let parts = parse_arithmetic_sequence(inner)?; + Ok(ArithmeticPart::ParenthesesExpr(Box::new(Arithmetic { + parts, + }))) + }, + Rule::VARIABLE => { + Ok(ArithmeticPart::Variable(first.as_str().to_string())) + } + Rule::NUMBER => Ok(ArithmeticPart::Number(first.as_str().to_string())), + _ => Err(miette!( + "Unexpected rule in arithmetic expression: {:?}", + first.as_rule() + )), + }?; + let op = parse_post_arithmetic_op(second)?; + Ok(ArithmeticPart::PostArithmeticExpr { + operator: (op), + operand: (Box::new(operand)) + }) +} + fn parse_unary_arithmetic_op(pair: Pair) -> Result { - match pair.as_str() { - "+" => Ok(UnaryArithmeticOp::Plus), - "-" => Ok(UnaryArithmeticOp::Minus), - "!" => Ok(UnaryArithmeticOp::LogicalNot), - "~" => Ok(UnaryArithmeticOp::BitwiseNot), + let first = pair.into_inner().next().unwrap(); + match first.as_rule() { + Rule::add => Ok(UnaryArithmeticOp::Plus), + Rule::subtract => Ok(UnaryArithmeticOp::Minus), + Rule::logical_not => Ok(UnaryArithmeticOp::LogicalNot), + Rule::bitwise_not => Ok(UnaryArithmeticOp::BitwiseNot), _ => Err(miette!( - "Invalid unary arithmetic operator: {}", - pair.as_str() + "Unexpected rule in unary arithmetic operator: {:?}", + first.as_rule() )), } } fn parse_post_arithmetic_op(pair: Pair) -> Result { - match pair.as_str() { - "++" => Ok(PostArithmeticOp::Increment), - "--" => Ok(PostArithmeticOp::Decrement), + let first = pair.into_inner().next().unwrap(); + match first.as_rule() { + Rule::increment => Ok(PostArithmeticOp::Increment), + Rule::decrement => Ok(PostArithmeticOp::Decrement), _ => Err(miette!( - "Invalid post arithmetic operator: {}", - pair.as_str() + "Unexpected rule in post arithmetic operator: {:?}", + first.as_rule() )), } } diff --git a/scripts/arithmetic.sh b/scripts/arithmetic.sh index 50c0752..2eb883d 100644 --- a/scripts/arithmetic.sh +++ b/scripts/arithmetic.sh @@ -1 +1,5 @@ -echo $((2 ** 3)) \ No newline at end of file +echo $((2 ** 3)) + +echo $((a++)) + +echo $((--a)) From f38c5aecc74ef03525636d7faad354db6f8f656e Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Fri, 20 Sep 2024 17:53:33 -0400 Subject: [PATCH 02/13] Run fmt and fix typos --- crates/deno_task_shell/src/grammar.pest | 4 +- crates/deno_task_shell/src/parser.rs | 50 ++++++++++--------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index 3ef741d..9d9b84f 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -203,14 +203,14 @@ logical_and = { "&&" } logical_or = { "||" } unary_arithmetic_expr = !{ - unary_pre_arithmetic_expr | unary_post_arithmatic_expr + unary_pre_arithmetic_expr | unary_post_arithmetic_expr } unary_pre_arithmetic_expr = !{ (post_arithmetic_op | unary_arithmetic_op) ~ (parentheses_expr | VARIABLE | NUMBER) } -unary_post_arithmatic_expr = !{ +unary_post_arithmetic_expr = !{ (parentheses_expr | VARIABLE | NUMBER) ~ post_arithmetic_op } diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index f59e0f0..0a7b5cf 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -1422,12 +1422,8 @@ fn parse_unary_arithmetic_expr(pair: Pair) -> Result { let first = inner.next().unwrap(); match first.as_rule() { - Rule::unary_pre_arithmetic_expr => { - unary_pre_arithmetic_expr(first) - } - Rule::unary_post_arithmatic_expr => { - unary_post_arithmatic_expr(first) - } + Rule::unary_pre_arithmetic_expr => unary_pre_arithmetic_expr(first), + Rule::unary_post_arithmetic_expr => unary_post_arithmetic_expr(first), _ => { let operand = parse_arithmetic_expr(first)?; let op = parse_post_arithmetic_op(inner.next().unwrap())?; @@ -1443,12 +1439,10 @@ fn parse_unary_arithmetic_op_type(pair: Pair) -> Result { match pair.as_rule() { Rule::unary_arithmetic_op => Ok(true), Rule::post_arithmetic_op => Ok(false), - _ => { - Err(miette!( - "Unexpected rule in unary arithmetic operator: {:?}", - pair.as_rule() - )) - } + _ => Err(miette!( + "Unexpected rule in unary arithmetic operator: {:?}", + pair.as_rule() + )), } } @@ -1456,18 +1450,15 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); let first = inner.next().unwrap(); let second = inner.next().unwrap(); - let operand = - match second.as_rule() { + let operand = match second.as_rule() { Rule::parentheses_expr => { let inner = second.into_inner().next().unwrap(); let parts = parse_arithmetic_sequence(inner)?; Ok(ArithmeticPart::ParenthesesExpr(Box::new(Arithmetic { parts, }))) - }, - Rule::VARIABLE => { - Ok(ArithmeticPart::Variable(second.as_str().to_string())) } + Rule::VARIABLE => Ok(ArithmeticPart::Variable(second.as_str().to_string())), Rule::NUMBER => Ok(ArithmeticPart::Number(second.as_str().to_string())), _ => Err(miette!( "Unexpected rule in arithmetic expression: {:?}", @@ -1478,34 +1469,31 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { if parse_unary_arithmetic_op_type(first.clone())? { let op = parse_unary_arithmetic_op(first)?; Ok(ArithmeticPart::UnaryArithmeticExpr { - operator: (op), - operand: (Box::new(operand)) + operator: (op), + operand: (Box::new(operand)), }) } else { let op = parse_post_arithmetic_op(first)?; - Ok(ArithmeticPart::PostArithmeticExpr { - operator: (op), - operand: (Box::new(operand)) + Ok(ArithmeticPart::PostArithmeticExpr { + operator: (op), + operand: (Box::new(operand)), }) } } -fn unary_post_arithmatic_expr(pair: Pair) -> Result { +fn unary_post_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); let first = inner.next().unwrap(); let second = inner.next().unwrap(); - let operand = - match first.as_rule() { + let operand = match first.as_rule() { Rule::parentheses_expr => { let inner = first.into_inner().next().unwrap(); let parts = parse_arithmetic_sequence(inner)?; Ok(ArithmeticPart::ParenthesesExpr(Box::new(Arithmetic { parts, }))) - }, - Rule::VARIABLE => { - Ok(ArithmeticPart::Variable(first.as_str().to_string())) } + Rule::VARIABLE => Ok(ArithmeticPart::Variable(first.as_str().to_string())), Rule::NUMBER => Ok(ArithmeticPart::Number(first.as_str().to_string())), _ => Err(miette!( "Unexpected rule in arithmetic expression: {:?}", @@ -1513,9 +1501,9 @@ fn unary_post_arithmatic_expr(pair: Pair) -> Result { )), }?; let op = parse_post_arithmetic_op(second)?; - Ok(ArithmeticPart::PostArithmeticExpr { - operator: (op), - operand: (Box::new(operand)) + Ok(ArithmeticPart::PostArithmeticExpr { + operator: (op), + operand: (Box::new(operand)), }) } From 2870dfb775e24f192d6da200e4bacc5bdf317153 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Sat, 21 Sep 2024 16:02:02 -0400 Subject: [PATCH 03/13] Fixed issues --- crates/deno_task_shell/src/grammar.pest | 5 +- crates/deno_task_shell/src/parser.rs | 66 +++++++++++-------------- 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index 9d9b84f..892acf3 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -207,7 +207,8 @@ unary_arithmetic_expr = !{ } unary_pre_arithmetic_expr = !{ - (post_arithmetic_op | unary_arithmetic_op) ~ (parentheses_expr | VARIABLE | NUMBER) + (post_arithmetic_op | pre_arithmetic_op) ~ (parentheses_expr | VARIABLE | NUMBER) + } unary_post_arithmetic_expr = !{ @@ -215,7 +216,7 @@ unary_post_arithmetic_expr = !{ } -unary_arithmetic_op = _{ +pre_arithmetic_op= _{ unary_plus | unary_minus | logical_not | bitwise_not } diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index 0a7b5cf..c5b0ae7 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -1419,37 +1419,22 @@ fn parse_arithmetic_expr(pair: Pair) -> Result { fn parse_unary_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); - let first = inner.next().unwrap(); + let first = inner.next().ok_or_else(|| miette!("Expected unary operator"))?; match first.as_rule() { Rule::unary_pre_arithmetic_expr => unary_pre_arithmetic_expr(first), Rule::unary_post_arithmetic_expr => unary_post_arithmetic_expr(first), - _ => { - let operand = parse_arithmetic_expr(first)?; - let op = parse_post_arithmetic_op(inner.next().unwrap())?; - Ok(ArithmeticPart::PostArithmeticExpr { - operand: Box::new(operand), - operator: op, - }) - } - } -} - -fn parse_unary_arithmetic_op_type(pair: Pair) -> Result { - match pair.as_rule() { - Rule::unary_arithmetic_op => Ok(true), - Rule::post_arithmetic_op => Ok(false), _ => Err(miette!( - "Unexpected rule in unary arithmetic operator: {:?}", - pair.as_rule() + "Unexpected rule in unary arithmetic expression: {:?}", + first.as_rule() )), } } fn unary_pre_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); - let first = inner.next().unwrap(); - let second = inner.next().unwrap(); + let first = inner.next().ok_or_else(|| miette!("Expected unary pre operator"))?; + let second = inner.next().ok_or_else(|| miette!("Expected operand"))?; let operand = match second.as_rule() { Rule::parentheses_expr => { let inner = second.into_inner().next().unwrap(); @@ -1466,25 +1451,33 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { )), }?; - if parse_unary_arithmetic_op_type(first.clone())? { - let op = parse_unary_arithmetic_op(first)?; - Ok(ArithmeticPart::UnaryArithmeticExpr { - operator: (op), - operand: (Box::new(operand)), - }) - } else { - let op = parse_post_arithmetic_op(first)?; - Ok(ArithmeticPart::PostArithmeticExpr { - operator: (op), - operand: (Box::new(operand)), - }) + match first.as_rule() { + Rule::pre_arithmetic_op => { + let op = parse_unary_arithmetic_op(first)?; + Ok(ArithmeticPart::UnaryArithmeticExpr { + operator: (op), + operand: (Box::new(operand)), + }) + }, + Rule::post_arithmetic_op => { + let op = parse_post_arithmetic_op(first)?; + Ok(ArithmeticPart::PostArithmeticExpr { + operator: (op), + operand: (Box::new(operand)), + }) + }, + _ => Err(miette!( + "Unexpected rule in unary arithmetic operator: {:?}", + first.as_rule() + )), } } fn unary_post_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); - let first = inner.next().unwrap(); - let second = inner.next().unwrap(); + let first = inner.next().ok_or_else(|| miette!("Expected unary post operator"))?; + let second = inner.next().ok_or_else(|| miette!("Expected operand"))?; + let operand = match first.as_rule() { Rule::parentheses_expr => { let inner = first.into_inner().next().unwrap(); @@ -1508,7 +1501,8 @@ fn unary_post_arithmetic_expr(pair: Pair) -> Result { } fn parse_unary_arithmetic_op(pair: Pair) -> Result { - let first = pair.into_inner().next().unwrap(); + let first = pair.into_inner().next().ok_or_else(|| miette!("Expected unary operator"))?; + match first.as_rule() { Rule::add => Ok(UnaryArithmeticOp::Plus), Rule::subtract => Ok(UnaryArithmeticOp::Minus), @@ -1522,7 +1516,7 @@ fn parse_unary_arithmetic_op(pair: Pair) -> Result { } fn parse_post_arithmetic_op(pair: Pair) -> Result { - let first = pair.into_inner().next().unwrap(); + let first = pair.into_inner().next().ok_or_else(|| miette!("Expected increament or decreament operator"))?; match first.as_rule() { Rule::increment => Ok(PostArithmeticOp::Increment), Rule::decrement => Ok(PostArithmeticOp::Decrement), From 15e78cc450b27f05cf9da54e6969a54b1ad276af Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Tue, 24 Sep 2024 12:21:22 -0400 Subject: [PATCH 04/13] Added variable incrementation --- crates/deno_task_shell/src/parser.rs | 60 +++++-- crates/deno_task_shell/src/shell/execute.rs | 60 ++++++- crates/deno_task_shell/src/shell/types.rs | 173 ++++++++++++++++++++ scripts/arithmetic.sh | 9 +- 4 files changed, 287 insertions(+), 15 deletions(-) diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index c5b0ae7..026bb7b 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -431,6 +431,11 @@ pub enum ArithmeticPart { operator: UnaryArithmeticOp, operand: Box, }, + #[error("Invalid pre arithmetic expression")] + PreArithmeticExpr { + operator: PreArithmeticOp, + operand: Box, + }, #[error("Invalid post arithmetic expression")] PostArithmeticExpr { operand: Box, @@ -490,7 +495,15 @@ pub enum UnaryArithmeticOp { #[cfg_attr(feature = "serialization", derive(serde::Serialize))] #[cfg_attr(feature = "serialization", serde(rename_all = "camelCase"))] -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum PreArithmeticOp { + Increment, // ++ + Decrement, // -- +} + +#[cfg_attr(feature = "serialization", derive(serde::Serialize))] +#[cfg_attr(feature = "serialization", serde(rename_all = "camelCase"))] +#[derive(Debug, Clone, PartialEq, Eq, Copy)] pub enum PostArithmeticOp { Increment, // ++ Decrement, // -- @@ -1419,7 +1432,9 @@ fn parse_arithmetic_expr(pair: Pair) -> Result { fn parse_unary_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); - let first = inner.next().ok_or_else(|| miette!("Expected unary operator"))?; + let first = inner + .next() + .ok_or_else(|| miette!("Expected unary operator"))?; match first.as_rule() { Rule::unary_pre_arithmetic_expr => unary_pre_arithmetic_expr(first), @@ -1433,7 +1448,9 @@ fn parse_unary_arithmetic_expr(pair: Pair) -> Result { fn unary_pre_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); - let first = inner.next().ok_or_else(|| miette!("Expected unary pre operator"))?; + let first = inner + .next() + .ok_or_else(|| miette!("Expected unary pre operator"))?; let second = inner.next().ok_or_else(|| miette!("Expected operand"))?; let operand = match second.as_rule() { Rule::parentheses_expr => { @@ -1458,14 +1475,14 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { operator: (op), operand: (Box::new(operand)), }) - }, + } Rule::post_arithmetic_op => { - let op = parse_post_arithmetic_op(first)?; - Ok(ArithmeticPart::PostArithmeticExpr { + let op = parse_pre_arithmetic_op(first)?; + Ok(ArithmeticPart::PreArithmeticExpr { operator: (op), operand: (Box::new(operand)), }) - }, + } _ => Err(miette!( "Unexpected rule in unary arithmetic operator: {:?}", first.as_rule() @@ -1475,7 +1492,9 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { fn unary_post_arithmetic_expr(pair: Pair) -> Result { let mut inner = pair.into_inner(); - let first = inner.next().ok_or_else(|| miette!("Expected unary post operator"))?; + let first = inner + .next() + .ok_or_else(|| miette!("Expected unary post operator"))?; let second = inner.next().ok_or_else(|| miette!("Expected operand"))?; let operand = match first.as_rule() { @@ -1501,7 +1520,10 @@ fn unary_post_arithmetic_expr(pair: Pair) -> Result { } fn parse_unary_arithmetic_op(pair: Pair) -> Result { - let first = pair.into_inner().next().ok_or_else(|| miette!("Expected unary operator"))?; + let first = pair + .into_inner() + .next() + .ok_or_else(|| miette!("Expected unary operator"))?; match first.as_rule() { Rule::add => Ok(UnaryArithmeticOp::Plus), @@ -1515,8 +1537,26 @@ fn parse_unary_arithmetic_op(pair: Pair) -> Result { } } +fn parse_pre_arithmetic_op(pair: Pair) -> Result { + let first = pair + .into_inner() + .next() + .ok_or_else(|| miette!("Expected increament or decreament operator"))?; + match first.as_rule() { + Rule::increment => Ok(PreArithmeticOp::Increment), + Rule::decrement => Ok(PreArithmeticOp::Decrement), + _ => Err(miette!( + "Unexpected rule in post arithmetic operator: {:?}", + first.as_rule() + )), + } +} + fn parse_post_arithmetic_op(pair: Pair) -> Result { - let first = pair.into_inner().next().ok_or_else(|| miette!("Expected increament or decreament operator"))?; + let first = pair + .into_inner() + .next() + .ok_or_else(|| miette!("Expected increament or decreament operator"))?; match first.as_rule() { Rule::increment => Ok(PostArithmeticOp::Increment), Rule::decrement => Ok(PostArithmeticOp::Decrement), diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index f2accae..bf00060 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -19,6 +19,8 @@ use crate::parser::Condition; use crate::parser::ConditionInner; use crate::parser::ElsePart; use crate::parser::IoFile; +use crate::parser::PostArithmeticOp; +use crate::parser::PreArithmeticOp; use crate::parser::RedirectOpInput; use crate::parser::RedirectOpOutput; use crate::parser::UnaryOp; @@ -599,7 +601,10 @@ async fn evaluate_arithmetic_part( }? } }; - state.apply_env_var(name, &applied_value.to_string()); + state.apply_change(&EnvChange::SetShellVar( + (&name).to_string(), + applied_value.value.to_string(), + )); Ok( applied_value .clone() @@ -643,9 +648,13 @@ async fn evaluate_arithmetic_part( let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; apply_unary_op(*operator, val) } - ArithmeticPart::PostArithmeticExpr { operand, .. } => { + ArithmeticPart::PostArithmeticExpr { operand, operator } => { let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; - Ok(val) + apply_post_op(state, *operator, val, operand) + } + ArithmeticPart::PreArithmeticExpr { operator, operand } => { + let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; + apply_pre_op(state, *operator, val, operand) } ArithmeticPart::Variable(name) => state .get_var(name) @@ -744,6 +753,50 @@ fn apply_unary_op( } } +fn apply_pre_op( + state: &mut ShellState, + op: PreArithmeticOp, + val: ArithmeticResult, + operand: &ArithmeticPart, +) -> Result { + match op { + PreArithmeticOp::Increment => { + let result = val.pre_increament(operand)?; + let result_clone = result.clone(); + state.apply_changes(&result_clone.changes); + Ok(result) + } + PreArithmeticOp::Decrement => { + let result = val.pre_decreament(operand)?; + let result_clone = result.clone(); + state.apply_changes(&result_clone.changes); + Ok(result) + } + } +} + +fn apply_post_op( + state: &mut ShellState, + op: PostArithmeticOp, + val: ArithmeticResult, + operand: &ArithmeticPart, +) -> Result { + match op { + PostArithmeticOp::Increment => { + let result = val.post_increament(operand)?; + let result_clone = result.clone(); + state.apply_changes(&result_clone.changes); + Ok(result) + } + PostArithmeticOp::Decrement => { + let result = val.post_decreament(operand)?; + let result_clone = result.clone(); + state.apply_changes(&result_clone.changes); + Ok(result) + } + } +} + async fn execute_pipe_sequence( pipe_sequence: PipeSequence, state: ShellState, @@ -1350,6 +1403,7 @@ fn evaluate_word_parts( if !current_text.is_empty() { result.extend(evaluate_word_text(state, current_text, is_quoted)?); } + result.with_changes(changes); Ok(result) } .boxed_local() diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index bf079d9..bbfbb1f 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -18,6 +18,7 @@ use futures::future::LocalBoxFuture; use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; +use crate::parser::ArithmeticPart; use crate::shell::fs_util; use super::commands::builtin_commands; @@ -574,6 +575,174 @@ impl ArithmeticResult { } } + pub fn pre_increament( + &self, + operand: &ArithmeticPart, + ) -> Result { + match &self.value { + ArithmeticValue::Integer(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val + 1).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Integer(*val + 1), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + ArithmeticValue::Float(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val + 1.0).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Float(*val + 1.0), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + } + } + + pub fn pre_decreament( + &self, + operand: &ArithmeticPart, + ) -> Result { + match &self.value { + ArithmeticValue::Integer(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val - 1).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Integer(*val - 1), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + ArithmeticValue::Float(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val - 1.0).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Float(*val - 1.0), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + } + } + + pub fn post_increament( + &self, + operand: &ArithmeticPart, + ) -> Result { + match &self.value { + ArithmeticValue::Integer(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val + 1).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Integer(*val), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + ArithmeticValue::Float(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val + 1.0).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Float(*val), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + } + } + + pub fn post_decreament( + &self, + operand: &ArithmeticPart, + ) -> Result { + match &self.value { + ArithmeticValue::Integer(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val - 1).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Integer(*val), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + ArithmeticValue::Float(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + (*val - 1.0).to_string(), + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Float(*val), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increament: {}", + self + )), + }, + } + } + pub fn checked_add( &self, other: &ArithmeticResult, @@ -1112,4 +1281,8 @@ impl WordEvalResult { pub fn join(&self, sep: &str) -> String { self.value.join(sep) } + + pub fn with_changes(&mut self, changes: Vec) { + self.changes.extend(changes); + } } diff --git a/scripts/arithmetic.sh b/scripts/arithmetic.sh index 2eb883d..a046099 100644 --- a/scripts/arithmetic.sh +++ b/scripts/arithmetic.sh @@ -1,5 +1,10 @@ echo $((2 ** 3)) -echo $((a++)) +a=1 -echo $((--a)) +echo $a + +echo $((++(a))) + + +echo $a From d07ed7c6792b5eadd1640408d87cfda8e5844251 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Tue, 24 Sep 2024 12:24:18 -0400 Subject: [PATCH 05/13] Fix arithmetic.sh --- scripts/arithmetic.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/arithmetic.sh b/scripts/arithmetic.sh index a046099..1596791 100644 --- a/scripts/arithmetic.sh +++ b/scripts/arithmetic.sh @@ -4,7 +4,10 @@ a=1 echo $a -echo $((++(a))) +echo $((++a)) +echo $a + +echo $((a--)) echo $a From c6da08e10db5c8c91a79c9191582b4c9519bd0ca Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Tue, 24 Sep 2024 17:43:39 -0400 Subject: [PATCH 06/13] Added tests for incrementation --- crates/tests/src/lib.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index eb6e23e..afde640 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -868,6 +868,31 @@ async fn arithmetic() { .assert_stdout("16\n") .run() .await; + + TestBuilder::new() + .command("echo $((a=1, ++a))") + .assert_stdout("2\n") + .run() + .await; + + TestBuilder::new() + .command("echo $((a=1, a++))") + .assert_stdout("1\n") + .run() + .await; + + TestBuilder::new() + .command("echo $((a=1, a--))") + .assert_stdout("1\n") + .run() + .await; + + TestBuilder::new() + .command("echo $((a=1, --a))") + .assert_stdout("0\n") + .run() + .await; + } #[tokio::test] From 781b0b8fab61f8695e397abb9642c69beea9b993 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Tue, 24 Sep 2024 17:45:47 -0400 Subject: [PATCH 07/13] Run fmt --- crates/deno_task_shell/src/grammar.pest | 1 - crates/tests/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index 892acf3..1a6d9a7 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -215,7 +215,6 @@ unary_post_arithmetic_expr = !{ (parentheses_expr | VARIABLE | NUMBER) ~ post_arithmetic_op } - pre_arithmetic_op= _{ unary_plus | unary_minus | logical_not | bitwise_not } diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index afde640..8c638bf 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -892,7 +892,6 @@ async fn arithmetic() { .assert_stdout("0\n") .run() .await; - } #[tokio::test] From 237ac4ed994fcca128a9cb76c3305a2cd53ab4b7 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Tue, 24 Sep 2024 18:06:39 -0400 Subject: [PATCH 08/13] Combined unary and pre expr --- crates/deno_task_shell/src/grammar.pest | 1 - crates/deno_task_shell/src/parser.rs | 49 +++++---------------- crates/deno_task_shell/src/shell/execute.rs | 24 ++-------- crates/deno_task_shell/src/shell/types.rs | 39 ---------------- 4 files changed, 15 insertions(+), 98 deletions(-) diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index 1a6d9a7..1481416 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -208,7 +208,6 @@ unary_arithmetic_expr = !{ unary_pre_arithmetic_expr = !{ (post_arithmetic_op | pre_arithmetic_op) ~ (parentheses_expr | VARIABLE | NUMBER) - } unary_post_arithmetic_expr = !{ diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index 026bb7b..a848bc1 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -426,11 +426,6 @@ pub enum ArithmeticPart { operator: BinaryOp, right: Box, }, - #[error("Invalid unary arithmetic expression")] - UnaryArithmeticExpr { - operator: UnaryArithmeticOp, - operand: Box, - }, #[error("Invalid pre arithmetic expression")] PreArithmeticExpr { operator: PreArithmeticOp, @@ -486,21 +481,15 @@ pub enum AssignmentOp { #[cfg_attr(feature = "serialization", derive(serde::Serialize))] #[cfg_attr(feature = "serialization", serde(rename_all = "camelCase"))] #[derive(Debug, Clone, PartialEq, Eq, Copy)] -pub enum UnaryArithmeticOp { +pub enum PreArithmeticOp { + Increment, // ++ + Decrement, // -- Plus, // + Minus, // - LogicalNot, // ! BitwiseNot, // ~ } -#[cfg_attr(feature = "serialization", derive(serde::Serialize))] -#[cfg_attr(feature = "serialization", serde(rename_all = "camelCase"))] -#[derive(Debug, Clone, PartialEq, Eq, Copy)] -pub enum PreArithmeticOp { - Increment, // ++ - Decrement, // -- -} - #[cfg_attr(feature = "serialization", derive(serde::Serialize))] #[cfg_attr(feature = "serialization", serde(rename_all = "camelCase"))] #[derive(Debug, Clone, PartialEq, Eq, Copy)] @@ -1470,16 +1459,16 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { match first.as_rule() { Rule::pre_arithmetic_op => { - let op = parse_unary_arithmetic_op(first)?; - Ok(ArithmeticPart::UnaryArithmeticExpr { - operator: (op), + let op = parse_pre_arithmetic_op(first)?; + Ok(ArithmeticPart::PreArithmeticExpr { + operator: op, operand: (Box::new(operand)), }) } Rule::post_arithmetic_op => { let op = parse_pre_arithmetic_op(first)?; Ok(ArithmeticPart::PreArithmeticExpr { - operator: (op), + operator: op, operand: (Box::new(operand)), }) } @@ -1514,29 +1503,11 @@ fn unary_post_arithmetic_expr(pair: Pair) -> Result { }?; let op = parse_post_arithmetic_op(second)?; Ok(ArithmeticPart::PostArithmeticExpr { - operator: (op), + operator: op, operand: (Box::new(operand)), }) } -fn parse_unary_arithmetic_op(pair: Pair) -> Result { - let first = pair - .into_inner() - .next() - .ok_or_else(|| miette!("Expected unary operator"))?; - - match first.as_rule() { - Rule::add => Ok(UnaryArithmeticOp::Plus), - Rule::subtract => Ok(UnaryArithmeticOp::Minus), - Rule::logical_not => Ok(UnaryArithmeticOp::LogicalNot), - Rule::bitwise_not => Ok(UnaryArithmeticOp::BitwiseNot), - _ => Err(miette!( - "Unexpected rule in unary arithmetic operator: {:?}", - first.as_rule() - )), - } -} - fn parse_pre_arithmetic_op(pair: Pair) -> Result { let first = pair .into_inner() @@ -1545,6 +1516,10 @@ fn parse_pre_arithmetic_op(pair: Pair) -> Result { match first.as_rule() { Rule::increment => Ok(PreArithmeticOp::Increment), Rule::decrement => Ok(PreArithmeticOp::Decrement), + Rule::add => Ok(PreArithmeticOp::Plus), + Rule::subtract => Ok(PreArithmeticOp::Minus), + Rule::logical_not => Ok(PreArithmeticOp::LogicalNot), + Rule::bitwise_not => Ok(PreArithmeticOp::BitwiseNot), _ => Err(miette!( "Unexpected rule in post arithmetic operator: {:?}", first.as_rule() diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index bf00060..1ad4feb 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -52,7 +52,6 @@ use crate::parser::RedirectOp; use crate::parser::Sequence; use crate::parser::SequentialList; use crate::parser::SimpleCommand; -use crate::parser::UnaryArithmeticOp; use crate::parser::Word; use crate::parser::WordPart; use crate::shell::types::WordEvalResult; @@ -644,10 +643,6 @@ async fn evaluate_arithmetic_part( let rhs = Box::pin(evaluate_arithmetic_part(right, state)).await?; apply_conditional_binary_op(lhs, operator, rhs) } - ArithmeticPart::UnaryArithmeticExpr { operator, operand } => { - let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; - apply_unary_op(*operator, val) - } ArithmeticPart::PostArithmeticExpr { operand, operator } => { let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; apply_post_op(state, *operator, val, operand) @@ -737,22 +732,6 @@ fn apply_conditional_binary_op( } } -fn apply_unary_op( - op: UnaryArithmeticOp, - val: ArithmeticResult, -) -> Result { - match op { - UnaryArithmeticOp::Plus => Ok(val), - UnaryArithmeticOp::Minus => val.checked_neg(), - UnaryArithmeticOp::LogicalNot => Ok(if val.is_zero() { - ArithmeticResult::new(ArithmeticValue::Integer(1)) - } else { - ArithmeticResult::new(ArithmeticValue::Integer(0)) - }), - UnaryArithmeticOp::BitwiseNot => val.checked_not(), - } -} - fn apply_pre_op( state: &mut ShellState, op: PreArithmeticOp, @@ -772,6 +751,9 @@ fn apply_pre_op( state.apply_changes(&result_clone.changes); Ok(result) } + _ => { + todo!("Pre arithmetic operator {:?} is not implemented", op) + } } } diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index bbfbb1f..92a484c 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -1044,45 +1044,6 @@ impl ArithmeticResult { }) } - pub fn checked_neg(&self) -> Result { - let result = match &self.value { - ArithmeticValue::Integer(val) => val - .checked_neg() - .map(ArithmeticValue::Integer) - .ok_or_else(|| anyhow::anyhow!("Integer overflow: -{}", val))?, - ArithmeticValue::Float(val) => { - let result = -val; - if result.is_finite() { - ArithmeticValue::Float(result) - } else { - return Err(anyhow::anyhow!("Float overflow: -{}", val)); - } - } - }; - - Ok(ArithmeticResult { - value: result, - changes: self.changes.clone(), - }) - } - - pub fn checked_not(&self) -> Result { - let result = match &self.value { - ArithmeticValue::Integer(val) => ArithmeticValue::Integer(!val), - ArithmeticValue::Float(_) => { - return Err(anyhow::anyhow!( - "Invalid arithmetic result type for bitwise NOT: {}", - self - )) - } - }; - - Ok(ArithmeticResult { - value: result, - changes: self.changes.clone(), - }) - } - pub fn checked_shl( &self, other: &ArithmeticResult, From 681725a46c1ab5837d492f16b9fd345d48fb3370 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Tue, 24 Sep 2024 18:18:41 -0400 Subject: [PATCH 09/13] Fix typo --- crates/deno_task_shell/src/parser.rs | 4 ++-- crates/deno_task_shell/src/shell/execute.rs | 4 ++-- crates/deno_task_shell/src/shell/types.rs | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index a848bc1..800f541 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -1512,7 +1512,7 @@ fn parse_pre_arithmetic_op(pair: Pair) -> Result { let first = pair .into_inner() .next() - .ok_or_else(|| miette!("Expected increament or decreament operator"))?; + .ok_or_else(|| miette!("Expected increment or decreament operator"))?; match first.as_rule() { Rule::increment => Ok(PreArithmeticOp::Increment), Rule::decrement => Ok(PreArithmeticOp::Decrement), @@ -1531,7 +1531,7 @@ fn parse_post_arithmetic_op(pair: Pair) -> Result { let first = pair .into_inner() .next() - .ok_or_else(|| miette!("Expected increament or decreament operator"))?; + .ok_or_else(|| miette!("Expected increment or decreament operator"))?; match first.as_rule() { Rule::increment => Ok(PostArithmeticOp::Increment), Rule::decrement => Ok(PostArithmeticOp::Decrement), diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index 1ad4feb..15bd9e9 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -740,7 +740,7 @@ fn apply_pre_op( ) -> Result { match op { PreArithmeticOp::Increment => { - let result = val.pre_increament(operand)?; + let result = val.pre_increment(operand)?; let result_clone = result.clone(); state.apply_changes(&result_clone.changes); Ok(result) @@ -765,7 +765,7 @@ fn apply_post_op( ) -> Result { match op { PostArithmeticOp::Increment => { - let result = val.post_increament(operand)?; + let result = val.post_increment(operand)?; let result_clone = result.clone(); state.apply_changes(&result_clone.changes); Ok(result) diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index 92a484c..dac6a99 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -575,7 +575,7 @@ impl ArithmeticResult { } } - pub fn pre_increament( + pub fn pre_increment( &self, operand: &ArithmeticPart, ) -> Result { @@ -593,7 +593,7 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, @@ -610,7 +610,7 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, @@ -635,7 +635,7 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, @@ -652,14 +652,14 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, } } - pub fn post_increament( + pub fn post_increment( &self, operand: &ArithmeticPart, ) -> Result { @@ -677,7 +677,7 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, @@ -694,7 +694,7 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, @@ -719,7 +719,7 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, @@ -736,7 +736,7 @@ impl ArithmeticResult { }) } _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increament: {}", + "Invalid arithmetic result type for pre-increment: {}", self )), }, From 5ced0794fcd54f0c8f26cb190c3ede3fc82b8130 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Tue, 24 Sep 2024 19:18:56 -0400 Subject: [PATCH 10/13] Clean up --- crates/deno_task_shell/src/parser.rs | 41 +-- crates/deno_task_shell/src/shell/execute.rs | 122 +++------ crates/deno_task_shell/src/shell/types.rs | 278 +++++++++----------- 3 files changed, 173 insertions(+), 268 deletions(-) diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index 800f541..18669f6 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -426,16 +426,11 @@ pub enum ArithmeticPart { operator: BinaryOp, right: Box, }, - #[error("Invalid pre arithmetic expression")] - PreArithmeticExpr { - operator: PreArithmeticOp, + #[error("Invalid unary arithmetic expression")] + UnaryAritheticExpr { + operator: UnaryArithmeticOp, operand: Box, }, - #[error("Invalid post arithmetic expression")] - PostArithmeticExpr { - operand: Box, - operator: PostArithmeticOp, - }, #[error("Invalid variable")] Variable(String), #[error("Invalid number")] @@ -498,6 +493,14 @@ pub enum PostArithmeticOp { Decrement, // -- } +#[cfg_attr(feature = "serialization", derive(serde::Serialize))] +#[cfg_attr(feature = "serialization", serde(rename_all = "camelCase"))] +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum UnaryArithmeticOp { + Pre(PreArithmeticOp), + Post(PostArithmeticOp), +} + #[cfg_attr(feature = "serialization", derive(serde::Serialize))] #[cfg_attr( feature = "serialization", @@ -1460,16 +1463,16 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { match first.as_rule() { Rule::pre_arithmetic_op => { let op = parse_pre_arithmetic_op(first)?; - Ok(ArithmeticPart::PreArithmeticExpr { - operator: op, - operand: (Box::new(operand)), + Ok(ArithmeticPart::UnaryAritheticExpr { + operator: UnaryArithmeticOp::Pre(op), + operand: Box::new(operand), }) } Rule::post_arithmetic_op => { let op = parse_pre_arithmetic_op(first)?; - Ok(ArithmeticPart::PreArithmeticExpr { - operator: op, - operand: (Box::new(operand)), + Ok(ArithmeticPart::UnaryAritheticExpr { + operator: UnaryArithmeticOp::Pre(op), + operand: Box::new(operand), }) } _ => Err(miette!( @@ -1502,9 +1505,9 @@ fn unary_post_arithmetic_expr(pair: Pair) -> Result { )), }?; let op = parse_post_arithmetic_op(second)?; - Ok(ArithmeticPart::PostArithmeticExpr { - operator: op, - operand: (Box::new(operand)), + Ok(ArithmeticPart::UnaryAritheticExpr { + operator: UnaryArithmeticOp::Post(op), + operand: Box::new(operand), }) } @@ -1512,7 +1515,7 @@ fn parse_pre_arithmetic_op(pair: Pair) -> Result { let first = pair .into_inner() .next() - .ok_or_else(|| miette!("Expected increment or decreament operator"))?; + .ok_or_else(|| miette!("Expected increment or decrement operator"))?; match first.as_rule() { Rule::increment => Ok(PreArithmeticOp::Increment), Rule::decrement => Ok(PreArithmeticOp::Decrement), @@ -1531,7 +1534,7 @@ fn parse_post_arithmetic_op(pair: Pair) -> Result { let first = pair .into_inner() .next() - .ok_or_else(|| miette!("Expected increment or decreament operator"))?; + .ok_or_else(|| miette!("Expected increment or decrement operator"))?; match first.as_rule() { Rule::increment => Ok(PostArithmeticOp::Increment), Rule::decrement => Ok(PostArithmeticOp::Decrement), diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index 15bd9e9..bf1b8aa 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -13,48 +13,23 @@ use thiserror::Error; use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; -use crate::parser::AssignmentOp; -use crate::parser::BinaryOp; -use crate::parser::Condition; -use crate::parser::ConditionInner; -use crate::parser::ElsePart; -use crate::parser::IoFile; -use crate::parser::PostArithmeticOp; -use crate::parser::PreArithmeticOp; -use crate::parser::RedirectOpInput; -use crate::parser::RedirectOpOutput; -use crate::parser::UnaryOp; -use crate::shell::commands::ShellCommand; -use crate::shell::commands::ShellCommandContext; -use crate::shell::types::pipe; -use crate::shell::types::ArithmeticResult; -use crate::shell::types::ArithmeticValue; -use crate::shell::types::EnvChange; -use crate::shell::types::ExecuteResult; -use crate::shell::types::FutureExecuteResult; -use crate::shell::types::ShellPipeReader; -use crate::shell::types::ShellPipeWriter; -use crate::shell::types::ShellState; - -use crate::parser::Arithmetic; -use crate::parser::ArithmeticPart; -use crate::parser::BinaryArithmeticOp; -use crate::parser::Command; -use crate::parser::CommandInner; -use crate::parser::IfClause; -use crate::parser::PipeSequence; -use crate::parser::PipeSequenceOperator; -use crate::parser::Pipeline; -use crate::parser::PipelineInner; -use crate::parser::Redirect; -use crate::parser::RedirectFd; -use crate::parser::RedirectOp; -use crate::parser::Sequence; -use crate::parser::SequentialList; -use crate::parser::SimpleCommand; -use crate::parser::Word; -use crate::parser::WordPart; -use crate::shell::types::WordEvalResult; +use crate::parser::{ + AssignmentOp, BinaryOp, Condition, ConditionInner, ElsePart, IoFile, + RedirectOpInput, RedirectOpOutput, UnaryArithmeticOp, UnaryOp, +}; +use crate::shell::commands::{ShellCommand, ShellCommandContext}; +use crate::shell::types::{ + pipe, ArithmeticResult, ArithmeticValue, EnvChange, ExecuteResult, + FutureExecuteResult, ShellPipeReader, ShellPipeWriter, ShellState, + WordEvalResult, +}; + +use crate::parser::{ + Arithmetic, ArithmeticPart, BinaryArithmeticOp, Command, CommandInner, + IfClause, PipeSequence, PipeSequenceOperator, Pipeline, PipelineInner, + Redirect, RedirectFd, RedirectOp, Sequence, SequentialList, SimpleCommand, + Word, WordPart, +}; use super::command::execute_unresolved_command_name; use super::command::UnresolvedCommandName; @@ -643,13 +618,17 @@ async fn evaluate_arithmetic_part( let rhs = Box::pin(evaluate_arithmetic_part(right, state)).await?; apply_conditional_binary_op(lhs, operator, rhs) } - ArithmeticPart::PostArithmeticExpr { operand, operator } => { + // ArithmeticPart::PostArithmeticExpr { operand, operator } => { + // let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; + // apply_post_op(state, *operator, val, operand) + // } + // ArithmeticPart::PreArithmeticExpr { operator, operand } => { + // let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; + // apply_pre_op(state, *operator, val, operand) + // } + ArithmeticPart::UnaryAritheticExpr { operator, operand } => { let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; - apply_post_op(state, *operator, val, operand) - } - ArithmeticPart::PreArithmeticExpr { operator, operand } => { - let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; - apply_pre_op(state, *operator, val, operand) + apply_unary_op(state, *operator, val, operand) } ArithmeticPart::Variable(name) => state .get_var(name) @@ -732,51 +711,16 @@ fn apply_conditional_binary_op( } } -fn apply_pre_op( - state: &mut ShellState, - op: PreArithmeticOp, - val: ArithmeticResult, - operand: &ArithmeticPart, -) -> Result { - match op { - PreArithmeticOp::Increment => { - let result = val.pre_increment(operand)?; - let result_clone = result.clone(); - state.apply_changes(&result_clone.changes); - Ok(result) - } - PreArithmeticOp::Decrement => { - let result = val.pre_decreament(operand)?; - let result_clone = result.clone(); - state.apply_changes(&result_clone.changes); - Ok(result) - } - _ => { - todo!("Pre arithmetic operator {:?} is not implemented", op) - } - } -} - -fn apply_post_op( +fn apply_unary_op( state: &mut ShellState, - op: PostArithmeticOp, + op: UnaryArithmeticOp, val: ArithmeticResult, operand: &ArithmeticPart, ) -> Result { - match op { - PostArithmeticOp::Increment => { - let result = val.post_increment(operand)?; - let result_clone = result.clone(); - state.apply_changes(&result_clone.changes); - Ok(result) - } - PostArithmeticOp::Decrement => { - let result = val.post_decreament(operand)?; - let result_clone = result.clone(); - state.apply_changes(&result_clone.changes); - Ok(result) - } - } + let result = val.unary_op(operand, op)?; + let result_clone = result.clone(); + state.apply_changes(&result_clone.changes); + Ok(result) } async fn execute_pipe_sequence( diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index dac6a99..7dbed41 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -19,6 +19,9 @@ use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; use crate::parser::ArithmeticPart; +use crate::parser::PostArithmeticOp; +use crate::parser::PreArithmeticOp; +use crate::parser::UnaryArithmeticOp; use crate::shell::fs_util; use super::commands::builtin_commands; @@ -575,170 +578,125 @@ impl ArithmeticResult { } } - pub fn pre_increment( + pub fn unary_op( &self, operand: &ArithmeticPart, + op: UnaryArithmeticOp, ) -> Result { - match &self.value { - ArithmeticValue::Integer(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val + 1).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Integer(*val + 1), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), - }, - ArithmeticValue::Float(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val + 1.0).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Float(*val + 1.0), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), - }, - } - } - - pub fn pre_decreament( - &self, - operand: &ArithmeticPart, - ) -> Result { - match &self.value { - ArithmeticValue::Integer(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val - 1).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Integer(*val - 1), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), - }, - ArithmeticValue::Float(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val - 1.0).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Float(*val - 1.0), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), - }, - } - } - - pub fn post_increment( - &self, - operand: &ArithmeticPart, - ) -> Result { - match &self.value { - ArithmeticValue::Integer(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val + 1).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Integer(*val), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), - }, - ArithmeticValue::Float(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val + 1.0).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Float(*val), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), - }, - } - } - - pub fn post_decreament( - &self, - operand: &ArithmeticPart, - ) -> Result { - match &self.value { - ArithmeticValue::Integer(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val - 1).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Integer(*val), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), + match op { + UnaryArithmeticOp::Post(op_type) => match &self.value { + ArithmeticValue::Integer(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + match op_type { + PostArithmeticOp::Increment => (*val + 1).to_string(), + PostArithmeticOp::Decrement => (*val - 1).to_string(), + }, + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Integer(*val), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for post-increment: {}", + self + )), + }, + ArithmeticValue::Float(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + match op_type { + PostArithmeticOp::Increment => (*val + 1.0).to_string(), + PostArithmeticOp::Decrement => (*val - 1.0).to_string(), + }, + )); + Ok(ArithmeticResult { + value: ArithmeticValue::Float(*val), + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for post-increment: {}", + self + )), + }, }, - ArithmeticValue::Float(val) => match operand { - ArithmeticPart::Variable(name) => { - let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - (*val - 1.0).to_string(), - )); - Ok(ArithmeticResult { - value: ArithmeticValue::Float(*val), - changes: new_changes, - }) - } - _ => Err(anyhow::anyhow!( - "Invalid arithmetic result type for pre-increment: {}", - self - )), + UnaryArithmeticOp::Pre(op_type) => match &self.value { + ArithmeticValue::Integer(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + match op_type { + PreArithmeticOp::Increment => (*val + 1).to_string(), + PreArithmeticOp::Decrement => (*val - 1).to_string(), + _ => todo!( + "Unary arithmetic operation not implemented {:?}", + op_type + ), + }, + )); + Ok(ArithmeticResult { + value: match op_type { + PreArithmeticOp::Increment => { + ArithmeticValue::Integer(*val + 1) + } + PreArithmeticOp::Decrement => { + ArithmeticValue::Integer(*val - 1) + } + _ => todo!( + "Unary arithmetic operation not implemented {:?}", + op_type + ), + }, + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increment: {}", + self + )), + }, + ArithmeticValue::Float(val) => match operand { + ArithmeticPart::Variable(name) => { + let mut new_changes = self.changes.clone(); + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + match op_type { + PreArithmeticOp::Increment => (*val + 1.0).to_string(), + PreArithmeticOp::Decrement => (*val - 1.0).to_string(), + _ => todo!( + "Unary arithmetic operation not implemented {:?}", + op_type + ), + }, + )); + Ok(ArithmeticResult { + value: match op_type { + PreArithmeticOp::Increment => { + ArithmeticValue::Float(*val + 1.0) + } + PreArithmeticOp::Decrement => { + ArithmeticValue::Float(*val - 1.0) + } + _ => todo!( + "Unary arithmetic operation not implemented {:?}", + op_type + ), + }, + changes: new_changes, + }) + } + _ => Err(anyhow::anyhow!( + "Invalid arithmetic result type for pre-increment: {}", + self + )), + }, }, } } From 44d8f1e40f7fa0346d50fc96fa673d4abc91b690 Mon Sep 17 00:00:00 2001 From: Parsa Bahraminejad Date: Thu, 26 Sep 2024 03:16:59 -0400 Subject: [PATCH 11/13] Update execute.rs --- crates/deno_task_shell/src/shell/execute.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index bf1b8aa..b2680c7 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -618,14 +618,6 @@ async fn evaluate_arithmetic_part( let rhs = Box::pin(evaluate_arithmetic_part(right, state)).await?; apply_conditional_binary_op(lhs, operator, rhs) } - // ArithmeticPart::PostArithmeticExpr { operand, operator } => { - // let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; - // apply_post_op(state, *operator, val, operand) - // } - // ArithmeticPart::PreArithmeticExpr { operator, operand } => { - // let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; - // apply_pre_op(state, *operator, val, operand) - // } ArithmeticPart::UnaryAritheticExpr { operator, operand } => { let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; apply_unary_op(state, *operator, val, operand) From 73a063dd31d4fcbb7e1896db6de60e2b30a32866 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Thu, 26 Sep 2024 13:28:13 -0400 Subject: [PATCH 12/13] Fixed function names --- crates/deno_task_shell/src/parser.rs | 8 ++++---- crates/deno_task_shell/src/shell/execute.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index 18669f6..cff0f5f 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -427,7 +427,7 @@ pub enum ArithmeticPart { right: Box, }, #[error("Invalid unary arithmetic expression")] - UnaryAritheticExpr { + UnaryArithmeticExpr { operator: UnaryArithmeticOp, operand: Box, }, @@ -1463,14 +1463,14 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { match first.as_rule() { Rule::pre_arithmetic_op => { let op = parse_pre_arithmetic_op(first)?; - Ok(ArithmeticPart::UnaryAritheticExpr { + Ok(ArithmeticPart::UnaryArithmeticExpr { operator: UnaryArithmeticOp::Pre(op), operand: Box::new(operand), }) } Rule::post_arithmetic_op => { let op = parse_pre_arithmetic_op(first)?; - Ok(ArithmeticPart::UnaryAritheticExpr { + Ok(ArithmeticPart::UnaryArithmeticExpr { operator: UnaryArithmeticOp::Pre(op), operand: Box::new(operand), }) @@ -1505,7 +1505,7 @@ fn unary_post_arithmetic_expr(pair: Pair) -> Result { )), }?; let op = parse_post_arithmetic_op(second)?; - Ok(ArithmeticPart::UnaryAritheticExpr { + Ok(ArithmeticPart::UnaryArithmeticExpr { operator: UnaryArithmeticOp::Post(op), operand: Box::new(operand), }) diff --git a/crates/deno_task_shell/src/shell/execute.rs b/crates/deno_task_shell/src/shell/execute.rs index b2680c7..4c8076f 100644 --- a/crates/deno_task_shell/src/shell/execute.rs +++ b/crates/deno_task_shell/src/shell/execute.rs @@ -618,7 +618,7 @@ async fn evaluate_arithmetic_part( let rhs = Box::pin(evaluate_arithmetic_part(right, state)).await?; apply_conditional_binary_op(lhs, operator, rhs) } - ArithmeticPart::UnaryAritheticExpr { operator, operand } => { + ArithmeticPart::UnaryArithmeticExpr { operator, operand } => { let val = Box::pin(evaluate_arithmetic_part(operand, state)).await?; apply_unary_op(state, *operator, val, operand) } From 6c19d8c793b1cae312954e370fbd9045b9739ea0 Mon Sep 17 00:00:00 2001 From: Alireza Mohaghegh Date: Mon, 7 Oct 2024 00:07:11 -0400 Subject: [PATCH 13/13] Added remaining unary operations --- crates/deno_task_shell/src/grammar.pest | 21 ++++--- crates/deno_task_shell/src/parser.rs | 10 ++-- crates/deno_task_shell/src/shell/types.rs | 72 +++++++++++++---------- crates/tests/src/lib.rs | 24 ++++++++ 4 files changed, 81 insertions(+), 46 deletions(-) diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest index 68657bf..6289e84 100644 --- a/crates/deno_task_shell/src/grammar.pest +++ b/crates/deno_task_shell/src/grammar.pest @@ -202,34 +202,33 @@ bitwise_or = { "|" } logical_and = { "&&" } logical_or = { "||" } +unary_plus = { "+" } +unary_minus = { "-" } +logical_not = { "!" } +bitwise_not = { "~" } +increment = { "++" } +decrement = { "--" } + unary_arithmetic_expr = !{ unary_pre_arithmetic_expr | unary_post_arithmetic_expr } unary_pre_arithmetic_expr = !{ - (post_arithmetic_op | pre_arithmetic_op) ~ (parentheses_expr | VARIABLE | NUMBER) + pre_arithmetic_op ~ (parentheses_expr | VARIABLE | NUMBER) } unary_post_arithmetic_expr = !{ (parentheses_expr | VARIABLE | NUMBER) ~ post_arithmetic_op } -pre_arithmetic_op= _{ - unary_plus | unary_minus | logical_not | bitwise_not +pre_arithmetic_op= !{ + increment | decrement | unary_plus | unary_minus | logical_not | bitwise_not } -unary_plus = { "+" } -unary_minus = { "-" } -logical_not = { "!" } -bitwise_not = { "~" } - post_arithmetic_op = !{ increment | decrement } -increment = { "++" } -decrement = { "--" } - assignment_operator = _{ assign | multiply_assign | divide_assign | modulo_assign | add_assign | subtract_assign | left_shift_assign | right_shift_assign | bitwise_and_assign | bitwise_xor_assign | bitwise_or_assign diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs index 2e4fb0d..9a3cbf8 100644 --- a/crates/deno_task_shell/src/parser.rs +++ b/crates/deno_task_shell/src/parser.rs @@ -1469,9 +1469,9 @@ fn unary_pre_arithmetic_expr(pair: Pair) -> Result { }) } Rule::post_arithmetic_op => { - let op = parse_pre_arithmetic_op(first)?; + let op = parse_post_arithmetic_op(first)?; Ok(ArithmeticPart::UnaryArithmeticExpr { - operator: UnaryArithmeticOp::Pre(op), + operator: UnaryArithmeticOp::Post(op), operand: Box::new(operand), }) } @@ -1519,12 +1519,12 @@ fn parse_pre_arithmetic_op(pair: Pair) -> Result { match first.as_rule() { Rule::increment => Ok(PreArithmeticOp::Increment), Rule::decrement => Ok(PreArithmeticOp::Decrement), - Rule::add => Ok(PreArithmeticOp::Plus), - Rule::subtract => Ok(PreArithmeticOp::Minus), + Rule::unary_plus => Ok(PreArithmeticOp::Plus), + Rule::unary_minus => Ok(PreArithmeticOp::Minus), Rule::logical_not => Ok(PreArithmeticOp::LogicalNot), Rule::bitwise_not => Ok(PreArithmeticOp::BitwiseNot), _ => Err(miette!( - "Unexpected rule in post arithmetic operator: {:?}", + "Unexpected rule in pre arithmetic operator: {:?}", first.as_rule() )), } diff --git a/crates/deno_task_shell/src/shell/types.rs b/crates/deno_task_shell/src/shell/types.rs index 1ca905b..f8db925 100644 --- a/crates/deno_task_shell/src/shell/types.rs +++ b/crates/deno_task_shell/src/shell/types.rs @@ -636,17 +636,19 @@ impl ArithmeticResult { ArithmeticValue::Integer(val) => match operand { ArithmeticPart::Variable(name) => { let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - match op_type { - PreArithmeticOp::Increment => (*val + 1).to_string(), - PreArithmeticOp::Decrement => (*val - 1).to_string(), - _ => todo!( - "Unary arithmetic operation not implemented {:?}", - op_type - ), - }, - )); + if op_type == PreArithmeticOp::Increment + || op_type == PreArithmeticOp::Decrement + { + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + match op_type { + PreArithmeticOp::Increment => (*val + 1).to_string(), + PreArithmeticOp::Decrement => (*val - 1).to_string(), + _ => Err(miette!("No change to ENV need for: {}", self))?, + }, + )); + } + Ok(ArithmeticResult { value: match op_type { PreArithmeticOp::Increment => { @@ -655,10 +657,14 @@ impl ArithmeticResult { PreArithmeticOp::Decrement => { ArithmeticValue::Integer(*val - 1) } - _ => todo!( - "Unary arithmetic operation not implemented {:?}", - op_type - ), + PreArithmeticOp::Plus => ArithmeticValue::Integer((*val).abs()), + PreArithmeticOp::Minus => { + ArithmeticValue::Integer(-(*val).abs()) + } + PreArithmeticOp::BitwiseNot => ArithmeticValue::Integer(!*val), + PreArithmeticOp::LogicalNot => { + ArithmeticValue::Integer(if *val == 0 { 1 } else { 0 }) + } }, changes: new_changes, }) @@ -671,17 +677,19 @@ impl ArithmeticResult { ArithmeticValue::Float(val) => match operand { ArithmeticPart::Variable(name) => { let mut new_changes = self.changes.clone(); - new_changes.push(EnvChange::SetShellVar( - name.to_string(), - match op_type { - PreArithmeticOp::Increment => (*val + 1.0).to_string(), - PreArithmeticOp::Decrement => (*val - 1.0).to_string(), - _ => todo!( - "Unary arithmetic operation not implemented {:?}", - op_type - ), - }, - )); + if op_type == PreArithmeticOp::Increment + || op_type == PreArithmeticOp::Decrement + { + new_changes.push(EnvChange::SetShellVar( + name.to_string(), + match op_type { + PreArithmeticOp::Increment => (*val + 1.0).to_string(), + PreArithmeticOp::Decrement => (*val - 1.0).to_string(), + _ => Err(miette!("No change to ENV need for: {}", self))?, + }, + )); + } + Ok(ArithmeticResult { value: match op_type { PreArithmeticOp::Increment => { @@ -690,10 +698,14 @@ impl ArithmeticResult { PreArithmeticOp::Decrement => { ArithmeticValue::Float(*val - 1.0) } - _ => todo!( - "Unary arithmetic operation not implemented {:?}", - op_type - ), + PreArithmeticOp::Plus => ArithmeticValue::Float((*val).abs()), + PreArithmeticOp::Minus => ArithmeticValue::Float(-(*val).abs()), + PreArithmeticOp::BitwiseNot => { + ArithmeticValue::Integer(!(*val as i64)) + } + PreArithmeticOp::LogicalNot => { + ArithmeticValue::Float(if *val == 0.0 { 1.0 } else { 0.0 }) + } }, changes: new_changes, }) diff --git a/crates/tests/src/lib.rs b/crates/tests/src/lib.rs index a489b98..6c73b7e 100644 --- a/crates/tests/src/lib.rs +++ b/crates/tests/src/lib.rs @@ -904,6 +904,30 @@ async fn arithmetic() { .assert_stdout("0\n") .run() .await; + + TestBuilder::new() + .command("echo $((a=1, +a))") + .assert_stdout("1\n") + .run() + .await; + + TestBuilder::new() + .command("echo $((a=1, -a))") + .assert_stdout("-1\n") + .run() + .await; + + TestBuilder::new() + .command("echo $((a=3, ~a))") + .assert_stdout("-4\n") + .run() + .await; + + TestBuilder::new() + .command("echo $((a=0, !a))") + .assert_stdout("1\n") + .run() + .await; } #[tokio::test]