From db2cb6845a414c366d47f2d239a9cafae097494f Mon Sep 17 00:00:00 2001 From: Ph0enixKM Date: Wed, 27 Sep 2023 22:45:22 +0200 Subject: [PATCH 1/4] feat: ref feature support for variable assignment and addition --- src/modules/command/expr.rs | 3 +- src/modules/condition/ternary.rs | 2 +- src/modules/expression/binop/eq.rs | 2 +- src/modules/expression/binop/neq.rs | 2 +- src/modules/expression/literal/range.rs | 4 +- src/modules/shorthand/add.rs | 21 ++- src/tests/validity.rs | 226 +++++++++++++++++++++++- src/translate/compute.rs | 10 +- src/utils/metadata/translate.rs | 6 + 9 files changed, 263 insertions(+), 13 deletions(-) diff --git a/src/modules/command/expr.rs b/src/modules/command/expr.rs index faf134d7..ca5f5e42 100644 --- a/src/modules/command/expr.rs +++ b/src/modules/command/expr.rs @@ -73,7 +73,8 @@ impl TranslateModule for CommandExpr { let failed = self.failed.translate(meta); let silent = self.is_silent_expr.then(|| " 2>/dev/null").unwrap_or(""); if failed.is_empty() { - format!("$({}{silent})", translate_interpolated_region(self.strings.clone(), interps, false)) + let translation = translate_interpolated_region(self.strings.clone(), interps, false); + meta.gen_subprocess(&(translation + silent)) } else { let id = meta.gen_value_id(); let quote = meta.gen_quote(); diff --git a/src/modules/condition/ternary.rs b/src/modules/condition/ternary.rs index d5bbb820..1f7f8268 100644 --- a/src/modules/condition/ternary.rs +++ b/src/modules/condition/ternary.rs @@ -53,6 +53,6 @@ impl TranslateModule for Ternary { let cond = self.cond.translate(meta); let true_expr = self.true_expr.translate(meta); let false_expr = self.false_expr.translate(meta); - format!("$(if [ {} != 0 ]; then echo {}; else echo {}; fi)", cond, true_expr, false_expr) + meta.gen_subprocess(&format!("if [ {} != 0 ]; then echo {}; else echo {}; fi", cond, true_expr, false_expr)) } } \ No newline at end of file diff --git a/src/modules/expression/binop/eq.rs b/src/modules/expression/binop/eq.rs index 59449690..fdf7471c 100644 --- a/src/modules/expression/binop/eq.rs +++ b/src/modules/expression/binop/eq.rs @@ -49,7 +49,7 @@ impl TranslateModule for Eq { if self.left.get_type() == Type::Text && self.right.get_type() == Type::Text { strip_text_quotes(&mut left); strip_text_quotes(&mut right); - format!("$([ \"_{left}\" != \"_{right}\" ]; echo $?)") + meta.gen_subprocess(&format!("[ \"_{left}\" != \"_{right}\" ]; echo $?")) } else { translate_computation(meta, ArithOp::Eq, Some(left), Some(right)) } diff --git a/src/modules/expression/binop/neq.rs b/src/modules/expression/binop/neq.rs index fa36ea40..214d28a3 100644 --- a/src/modules/expression/binop/neq.rs +++ b/src/modules/expression/binop/neq.rs @@ -48,7 +48,7 @@ impl TranslateModule for Neq { if self.left.get_type() == Type::Text && self.right.get_type() == Type::Text { strip_text_quotes(&mut left); strip_text_quotes(&mut right); - format!("$([ \"_{left}\" == \"_{right}\" ]; echo $?)") + meta.gen_subprocess(&format!("[ \"_{left}\" == \"_{right}\" ]; echo $?")) } else { translate_computation(meta, ArithOp::Neq, Some(left), Some(right)) } diff --git a/src/modules/expression/literal/range.rs b/src/modules/expression/literal/range.rs index 5e9f40f0..adc29e9d 100644 --- a/src/modules/expression/literal/range.rs +++ b/src/modules/expression/literal/range.rs @@ -48,9 +48,9 @@ impl TranslateModule for Range { let to = self.to.translate(meta); if self.neq { let to_neq = translate_computation(meta, ArithOp::Sub, Some(to), Some("1".to_string())); - format!("$(seq {} {})", from, to_neq) + meta.gen_subprocess(&format!("seq {} {}", from, to_neq)) } else { - format!("$(seq {} {})", from, to) + meta.gen_subprocess(&format!("seq {} {}", from, to)) } } } \ No newline at end of file diff --git a/src/modules/shorthand/add.rs b/src/modules/shorthand/add.rs index cbaa643f..40cbbe23 100644 --- a/src/modules/shorthand/add.rs +++ b/src/modules/shorthand/add.rs @@ -1,6 +1,7 @@ use heraclitus_compiler::prelude::*; use crate::modules::expression::{expr::Expr, binop::expression_arms_of_type}; use crate::modules::variable::{variable_name_extensions, handle_variable_reference}; +use crate::translate::compute::translate_computation_eval; use crate::utils::{ParserMetadata, TranslateMetadata}; use crate::translate::{module::TranslateModule, compute::{ArithOp, translate_computation}}; use crate::modules::types::{Type, Typed}; @@ -49,17 +50,27 @@ impl TranslateModule for ShorthandAdd { let expr = self.is_ref .then(|| self.expr.translate_eval(meta, true)) .unwrap_or_else(|| self.expr.translate(meta)); - let name = match self.global_id { + let name: String = match self.global_id { Some(id) => format!("__{id}_{}", self.var), - None => if self.is_ref { format!("eval \"${{{}}}\"", self.var) } else { self.var.clone() } + None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() } }; - match self.kind { + let stmt = match self.kind { Type::Text => format!("{}+={}", name, expr), Type::Array(_) => format!("{}+=({})", name, expr), _ => { - let var = format!("${{{name}}}"); - format!("{}={}", name, translate_computation(meta, ArithOp::Add, Some(var), Some(expr))) + let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") }; + let translated_computation = if self.is_ref { + translate_computation_eval(meta, ArithOp::Add, Some(var), Some(expr)) + } else { + translate_computation(meta, ArithOp::Add, Some(var), Some(expr)) + }; + format!("{}={}", name, translated_computation) } + }; + if self.is_ref { + format!("eval \"{}\"", stmt) + } else { + stmt } } } \ No newline at end of file diff --git a/src/tests/validity.rs b/src/tests/validity.rs index f8a4c35b..b19049c2 100644 --- a/src/tests/validity.rs +++ b/src/tests/validity.rs @@ -844,4 +844,228 @@ fn chained_modifiers_functions() { silent bar() "; test_amber!(code, "one\ntwo"); -} \ No newline at end of file +} + +#[test] +fn variable_ref_set_text() { + let code = " + fun foo(ref a) { + a = \"one\" + } + + let a = \"two\" + foo(a) + echo a + "; + test_amber!(code, "one"); +} + +#[test] +fn variable_ref_set_num() { + let code = " + fun foo(ref a) { + a = 42 + } + + let a = 24 + foo(a) + echo a + "; + test_amber!(code, "42"); +} + +#[test] +fn variable_ref_set_bool() { + let code = " + fun foo(ref a) { + a = false + } + + let a = true + foo(a) + echo a + "; + test_amber!(code, "0"); +} + +#[test] +fn variable_ref_set_array() { + let code = " + fun foo(ref a) { + a = [1, 2, 3] + } + + let a = [3, 2, 1] + foo(a) + echo a + "; + test_amber!(code, "1 2 3"); +} + +#[test] +fn variable_ref_add_shorthand_text() { + let code = " + fun foo(ref a) { + a += \"one\" + } + + let a = \"two\" + foo(a) + echo a + "; + test_amber!(code, "twoone"); +} + +#[test] +fn variable_ref_add_shorthand_num() { + let code = " + fun foo(ref a) { + a += 12 + } + + let a = 24 + foo(a) + echo a + "; + test_amber!(code, "36"); +} + +#[test] +fn variable_ref_add_shorthand_array() { + let code = " + fun foo(ref a) { + a += [4, 5, 6] + } + + let a = [1, 2, 3] + foo(a) + echo a + "; + test_amber!(code, "1 2 3 4 5 6"); +} + +#[test] +fn variable_ref_sub_shorthand_num() { + let code = " + fun foo(ref a) { + a -= 12 + } + + let a = 36 + foo(a) + echo a + "; + test_amber!(code, "24"); +} + +#[test] +fn variable_ref_mul_shorthand_num() { + let code = " + fun foo(ref a) { + a *= 2 + } + + let a = 6 + foo(a) + echo a + "; + test_amber!(code, "12"); +} + +#[test] +fn variable_ref_div_shorthand_num() { + let code = " + fun foo(ref a) { + a /= 3 + } + + let a = 15 + foo(a) + echo a + "; + test_amber!(code, "5"); +} + +#[test] +fn variable_ref_mod_shorthand_num() { + let code = " + fun foo(ref a) { + a %= 5 + } + + let a = 17 + foo(a) + echo a + "; + test_amber!(code, "2"); +} + +#[test] +fn variable_ref_add_arithmetic_text() { + let code = " + fun foo(ref a, b) { + a = a + b + } + + let a = \"two\" + foo(a, \"one\") + echo a + "; + test_amber!(code, "twoone"); +} + +#[test] +fn variable_ref_sub_arithmetic_text() { + let code = " + fun foo(ref a, b) { + a = a - b + } + + let a = \"twoone\" + foo(a, \"one\") + echo a + "; + test_amber!(code, "two"); +} + +#[test] +fn variable_ref_mul_arithmetic_num() { + let code = " + fun foo(ref a, b) { + a = a * b + } + + let a = 6 + foo(a, 2) + echo a + "; + test_amber!(code, "12"); +} + +#[test] +fn variable_ref_div_arithmetic_num() { + let code = " + fun foo(ref a, b) { + a = a / b + } + + let a = 15 + foo(a, 3) + echo a + "; + test_amber!(code, "5"); +} + +#[test] +fn variable_ref_mod_arithmetic_num() { + let code = " + fun foo(ref a, b) { + a = a % b + } + + let a = 17 + foo(a, 5) + echo a + "; + test_amber!(code, "2"); +} diff --git a/src/translate/compute.rs b/src/translate/compute.rs index 632c18d0..4fe169d8 100644 --- a/src/translate/compute.rs +++ b/src/translate/compute.rs @@ -48,7 +48,15 @@ pub fn translate_computation(meta: &mut TranslateMetadata, operation: ArithOp, l ArithOp::Or => "||" }; let math_lib_flag = if math_lib_flag { "-l" } else { "" }; - format!("$(echo {left} '{op}' {right} | bc {math_lib_flag} | sed '{sed_regex}')") + meta.gen_subprocess(&format!("echo {left} '{op}' {right} | bc {math_lib_flag} | sed '{sed_regex}'")) } } +} + +pub fn translate_computation_eval(meta: &mut TranslateMetadata, operation: ArithOp, left: Option, right: Option) -> String { + let old_eval = meta.eval_ctx; + meta.eval_ctx = true; + let result = translate_computation(meta, operation, left, right); + meta.eval_ctx = old_eval; + return result; } \ No newline at end of file diff --git a/src/utils/metadata/translate.rs b/src/utils/metadata/translate.rs index 41d8acd5..f539fa2a 100644 --- a/src/utils/metadata/translate.rs +++ b/src/utils/metadata/translate.rs @@ -75,4 +75,10 @@ impl TranslateMetadata { .then(|| "\\\"") .unwrap_or("\"") } + + pub fn gen_subprocess(&mut self, stmt: &str) -> String { + self.eval_ctx + .then(|| format!("$(eval \"{}\")", stmt)) + .unwrap_or_else(|| format!("$({})", stmt)) + } } From 3e228d6d76351d161230c2c6470d8b27ae54b0ea Mon Sep 17 00:00:00 2001 From: Ph0enixKM Date: Thu, 28 Sep 2023 20:28:11 +0200 Subject: [PATCH 2/4] feat: add support for the rest of the operations --- src/modules/command/expr.rs | 3 +- src/modules/expression/literal/array.rs | 3 +- src/modules/function/invocation.rs | 18 ++++++----- src/modules/shorthand/div.rs | 13 ++++++-- src/modules/shorthand/modulo.rs | 13 ++++++-- src/modules/shorthand/mul.rs | 13 ++++++-- src/modules/shorthand/sub.rs | 13 ++++++-- src/tests/validity.rs | 41 ++++++++++++++++++++++--- src/utils/metadata/translate.rs | 8 ++++- 9 files changed, 98 insertions(+), 27 deletions(-) diff --git a/src/modules/command/expr.rs b/src/modules/command/expr.rs index ca5f5e42..e87c7f15 100644 --- a/src/modules/command/expr.rs +++ b/src/modules/command/expr.rs @@ -78,10 +78,11 @@ impl TranslateModule for CommandExpr { } else { let id = meta.gen_value_id(); let quote = meta.gen_quote(); + let dollar = meta.gen_dollar(); let translation = translate_interpolated_region(self.strings.clone(), interps, false); meta.stmt_queue.push_back(format!("__AMBER_VAL_{id}=$({translation}{silent})")); meta.stmt_queue.push_back(failed); - format!("{quote}${{__AMBER_VAL_{id}}}{quote}") + format!("{quote}{dollar}{{__AMBER_VAL_{id}}}{quote}") } } } \ No newline at end of file diff --git a/src/modules/expression/literal/array.rs b/src/modules/expression/literal/array.rs index 48ac81da..78a0f525 100644 --- a/src/modules/expression/literal/array.rs +++ b/src/modules/expression/literal/array.rs @@ -84,7 +84,8 @@ impl TranslateModule for Array { let name = format!("__AMBER_ARRAY_{}", meta.gen_array_id()); let args = self.exprs.iter().map(|expr| expr.translate_eval(meta, false)).collect::>().join(" "); let quote = meta.gen_quote(); + let dollar = meta.gen_dollar(); meta.stmt_queue.push_back(format!("{name}=({args})")); - format!("{quote}${{{name}[@]}}{quote}") + format!("{quote}{dollar}{{{name}[@]}}{quote}") } } \ No newline at end of file diff --git a/src/modules/function/invocation.rs b/src/modules/function/invocation.rs index c275b403..fe68d568 100644 --- a/src/modules/function/invocation.rs +++ b/src/modules/function/invocation.rs @@ -95,12 +95,13 @@ impl SyntaxModule for FunctionInvocation { } impl FunctionInvocation { - fn get_variable(&self, meta: &mut TranslateMetadata, name: &str) -> String { + fn get_variable(&self, meta: &mut TranslateMetadata, name: &str, dollar_override: bool) -> String { + let dollar = dollar_override.then(|| "$").unwrap_or_else(|| meta.gen_dollar()); if matches!(self.kind, Type::Array(_)) { let quote = meta.gen_quote(); - format!("{quote}${{{name}[@]}}{quote}") + format!("{quote}{dollar}{{{name}[@]}}{quote}") } else { - format!("${{{name}}}") + format!("{dollar}{{{name}}}") } } } @@ -121,8 +122,9 @@ impl TranslateModule for FunctionInvocation { } }).collect::>().join(" "); meta.stmt_queue.push_back(format!("{name} {args}{silent}")); - let invocation_return = self.get_variable(meta, &format!("__AMBER_FUN_{}{}_v{}", self.name, self.id, self.variant_id)); - let invocation_instance = self.get_variable(meta, &format!("__AMBER_FUN_{}{}_v{}__{}", self.name, self.id, self.variant_id, self.line)); + let invocation_return = &format!("__AMBER_FUN_{}{}_v{}", self.name, self.id, self.variant_id); + let invocation_instance = &format!("__AMBER_FUN_{}{}_v{}__{}", self.name, self.id, self.variant_id, self.line); + let parsed_invocation_return = self.get_variable(meta, invocation_return, true); if self.is_failable { let failed = self.failed.translate(meta); meta.stmt_queue.push_back(failed); @@ -130,11 +132,11 @@ impl TranslateModule for FunctionInvocation { meta.stmt_queue.push_back( format!("__AMBER_FUN_{}{}_v{}__{}={}", self.name, self.id, self.variant_id, self.line, if matches!(self.kind, Type::Array(_)) { // If the function returns an array we have to store the intermediate result in a variable that is of type array - format!("({})", invocation_return) + format!("({})", parsed_invocation_return) } else { - invocation_return + parsed_invocation_return }) ); - invocation_instance + self.get_variable(meta, invocation_instance, false) } } \ No newline at end of file diff --git a/src/modules/shorthand/div.rs b/src/modules/shorthand/div.rs index 89b30a0d..76d70eca 100644 --- a/src/modules/shorthand/div.rs +++ b/src/modules/shorthand/div.rs @@ -1,6 +1,7 @@ use heraclitus_compiler::prelude::*; use crate::modules::expression::{expr::Expr, binop::expression_arms_of_type}; use crate::modules::variable::{variable_name_extensions, handle_variable_reference}; +use crate::translate::compute::translate_computation_eval; use crate::utils::{ParserMetadata, TranslateMetadata}; use crate::translate::{module::TranslateModule, compute::{ArithOp, translate_computation}}; use crate::modules::types::{Type, Typed}; @@ -51,9 +52,15 @@ impl TranslateModule for ShorthandDiv { .unwrap_or_else(|| self.expr.translate(meta)); let name = match self.global_id { Some(id) => format!("__{id}_{}", self.var), - None => if self.is_ref { format!("eval \"${{{}}}\"", self.var) } else { self.var.clone() } + None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() } }; - let var = format!("${{{name}}}"); - format!("{}={}", name, translate_computation(meta, ArithOp::Div, Some(var), Some(expr))) + let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") }; + if self.is_ref { + let eval = translate_computation_eval(meta, ArithOp::Div, Some(var), Some(expr)); + format!("eval \"{}={}\"", name, eval) + } else { + let eval = translate_computation(meta, ArithOp::Div, Some(var), Some(expr)); + format!("{}={}", name, eval) + } } } \ No newline at end of file diff --git a/src/modules/shorthand/modulo.rs b/src/modules/shorthand/modulo.rs index 6df39f5c..0ab0800b 100644 --- a/src/modules/shorthand/modulo.rs +++ b/src/modules/shorthand/modulo.rs @@ -1,6 +1,7 @@ use heraclitus_compiler::prelude::*; use crate::modules::expression::{expr::Expr, binop::expression_arms_of_type}; use crate::modules::variable::{variable_name_extensions, handle_variable_reference}; +use crate::translate::compute::translate_computation_eval; use crate::utils::{ParserMetadata, TranslateMetadata}; use crate::translate::{module::TranslateModule, compute::{ArithOp, translate_computation}}; use crate::modules::types::{Type, Typed}; @@ -51,9 +52,15 @@ impl TranslateModule for ShorthandModulo { .unwrap_or_else(|| self.expr.translate(meta)); let name = match self.global_id { Some(id) => format!("__{id}_{}", self.var), - None => if self.is_ref { format!("eval \"${{{}}}\"", self.var) } else { self.var.clone() } + None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() } }; - let var = format!("${{{name}}}"); - format!("{}={}", name, translate_computation(meta, ArithOp::Modulo, Some(var), Some(expr))) + let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") }; + if self.is_ref { + let expr = translate_computation_eval(meta, ArithOp::Modulo, Some(var), Some(expr)); + format!("eval \"{}={}\"", name, expr) + } else { + let expr = translate_computation(meta, ArithOp::Modulo, Some(var), Some(expr)); + format!("{}={}", name, expr) + } } } \ No newline at end of file diff --git a/src/modules/shorthand/mul.rs b/src/modules/shorthand/mul.rs index 0f83445d..c9bfaeaa 100644 --- a/src/modules/shorthand/mul.rs +++ b/src/modules/shorthand/mul.rs @@ -1,6 +1,7 @@ use heraclitus_compiler::prelude::*; use crate::modules::expression::{expr::Expr, binop::expression_arms_of_type}; use crate::modules::variable::{variable_name_extensions, handle_variable_reference}; +use crate::translate::compute::translate_computation_eval; use crate::utils::{ParserMetadata, TranslateMetadata}; use crate::translate::{module::TranslateModule, compute::{ArithOp, translate_computation}}; use crate::modules::types::{Type, Typed}; @@ -51,9 +52,15 @@ impl TranslateModule for ShorthandMul { .unwrap_or_else(|| self.expr.translate(meta)); let name = match self.global_id { Some(id) => format!("__{id}_{}", self.var), - None => if self.is_ref { format!("eval \"${{{}}}\"", self.var) } else { self.var.clone() } + None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() } }; - let var = format!("${{{name}}}"); - format!("{}={}", name, translate_computation(meta, ArithOp::Mul, Some(var), Some(expr))) + let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") }; + if self.is_ref { + let expr = translate_computation_eval(meta, ArithOp::Mul, Some(var), Some(expr)); + format!("eval \"{}={}\"", name, expr) + } else { + let expr = translate_computation(meta, ArithOp::Mul, Some(var), Some(expr)); + format!("{}={}", name, expr) + } } } \ No newline at end of file diff --git a/src/modules/shorthand/sub.rs b/src/modules/shorthand/sub.rs index c78982e9..978c6308 100644 --- a/src/modules/shorthand/sub.rs +++ b/src/modules/shorthand/sub.rs @@ -1,6 +1,7 @@ use heraclitus_compiler::prelude::*; use crate::modules::expression::{expr::Expr, binop::expression_arms_of_type}; use crate::modules::variable::{variable_name_extensions, handle_variable_reference}; +use crate::translate::compute::translate_computation_eval; use crate::utils::{ParserMetadata, TranslateMetadata}; use crate::translate::{module::TranslateModule, compute::{ArithOp, translate_computation}}; use crate::modules::types::{Type, Typed}; @@ -51,9 +52,15 @@ impl TranslateModule for ShorthandSub { .unwrap_or_else(|| self.expr.translate(meta)); let name = match self.global_id { Some(id) => format!("__{id}_{}", self.var), - None => if self.is_ref { format!("eval \"${{{}}}\"", self.var) } else { self.var.clone() } + None => if self.is_ref { format!("${{{}}}", self.var) } else { self.var.clone() } }; - let var = format!("${{{name}}}"); - format!("{}={}", name, translate_computation(meta, ArithOp::Sub, Some(var), Some(expr))) + let var = if self.is_ref { format!("\\${{{name}}}") } else { format!("${{{name}}}") }; + if self.is_ref { + let expr = translate_computation_eval(meta, ArithOp::Sub, Some(var), Some(expr)); + format!("eval \"{}={}\"", name, expr) + } else { + let expr = translate_computation(meta, ArithOp::Sub, Some(var), Some(expr)); + format!("{}={}", name, expr) + } } } \ No newline at end of file diff --git a/src/tests/validity.rs b/src/tests/validity.rs index b19049c2..865a4062 100644 --- a/src/tests/validity.rs +++ b/src/tests/validity.rs @@ -1015,19 +1015,20 @@ fn variable_ref_add_arithmetic_text() { } #[test] -fn variable_ref_sub_arithmetic_text() { +fn variable_ref_sub_arithmetic_num() { let code = " fun foo(ref a, b) { a = a - b } - let a = \"twoone\" - foo(a, \"one\") + let a = 36 + foo(a, 12) echo a "; - test_amber!(code, "two"); + test_amber!(code, "24"); } + #[test] fn variable_ref_mul_arithmetic_num() { let code = " @@ -1069,3 +1070,35 @@ fn variable_ref_mod_arithmetic_num() { "; test_amber!(code, "2"); } + +#[test] +fn variable_ref_command() { + let code = " + fun foo(ref a) { + a = $echo Test$? + } + + let a = \"\" + unsafe foo(a) + echo a + "; + test_amber!(code, "Test"); +} + +#[test] +fn variable_ref_function_invocation() { + let code = " + fun reverse(input: Text): Text { + return unsafe $echo {input} | rev$ + } + + fun foo(ref a) { + a = reverse(\"mars\") + } + + let a = \"\" + unsafe foo(a) + echo a + "; + test_amber!(code, "sram"); +} diff --git a/src/utils/metadata/translate.rs b/src/utils/metadata/translate.rs index f539fa2a..ce874758 100644 --- a/src/utils/metadata/translate.rs +++ b/src/utils/metadata/translate.rs @@ -76,9 +76,15 @@ impl TranslateMetadata { .unwrap_or("\"") } - pub fn gen_subprocess(&mut self, stmt: &str) -> String { + pub fn gen_subprocess(&self, stmt: &str) -> String { self.eval_ctx .then(|| format!("$(eval \"{}\")", stmt)) .unwrap_or_else(|| format!("$({})", stmt)) } + + pub fn gen_dollar(&self) -> &'static str { + self.eval_ctx + .then(|| "\\$") + .unwrap_or_else(|| "$") + } } From b1759f105c387ff730ec63cd07aa3a2436ea7a51 Mon Sep 17 00:00:00 2001 From: Ph0enixKM Date: Thu, 28 Sep 2023 20:33:23 +0200 Subject: [PATCH 3/4] linting fixes --- src/modules/expression/binop/mod.rs | 4 ++-- src/modules/function/declaration_utils.rs | 2 +- src/modules/function/invocation.rs | 2 +- src/modules/function/invocation_utils.rs | 4 ++-- src/modules/imports/import.rs | 2 +- src/modules/imports/import_string.rs | 2 +- src/modules/variable/mod.rs | 6 +++--- src/translate/compute.rs | 4 ++-- src/translate/mod.rs | 2 +- src/utils/function_interface.rs | 4 ++-- src/utils/metadata/parser.rs | 6 +++--- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/modules/expression/binop/mod.rs b/src/modules/expression/binop/mod.rs index e153de1c..1c3422b5 100644 --- a/src/modules/expression/binop/mod.rs +++ b/src/modules/expression/binop/mod.rs @@ -16,7 +16,7 @@ pub mod le; pub mod eq; pub mod neq; -pub fn expression_arms_of_type(meta: &mut ParserMetadata, left: &Type, right: &Type, predicate: impl Fn(Type) -> bool, tok_pos: Option, message: &str) -> Result { +pub fn expression_arms_of_type(meta: &ParserMetadata, left: &Type, right: &Type, predicate: impl Fn(Type) -> bool, tok_pos: Option, message: &str) -> Result { if left == right && [left, right].iter().all(|kind| predicate((*kind).clone())) { Ok(left.clone()) } else { @@ -24,7 +24,7 @@ pub fn expression_arms_of_type(meta: &mut ParserMetadata, left: &Type, right: &T } } -pub fn expression_arms_of_same_type(meta: &mut ParserMetadata, left: &Expr, right: &Expr, tok_pos: Option, message: &str) -> SyntaxResult { +pub fn expression_arms_of_same_type(meta: &ParserMetadata, left: &Expr, right: &Expr, tok_pos: Option, message: &str) -> SyntaxResult { if left.get_type() != right.get_type() { error!(meta, tok_pos, message) } else { diff --git a/src/modules/function/declaration_utils.rs b/src/modules/function/declaration_utils.rs index df69b2f1..a776228c 100644 --- a/src/modules/function/declaration_utils.rs +++ b/src/modules/function/declaration_utils.rs @@ -25,7 +25,7 @@ pub fn skip_function_body(meta: &mut ParserMetadata) -> (usize, usize, bool) { (index_begin, index_end, is_failable) } -pub fn handle_existing_function(meta: &mut ParserMetadata, tok: Option) -> Result<(), Failure> { +pub fn handle_existing_function(meta: &ParserMetadata, tok: Option) -> Result<(), Failure> { let name = tok.as_ref().unwrap().word.clone(); handle_identifier_name(meta, &name, tok.clone())?; if meta.get_fun_declaration(&name).is_some() { diff --git a/src/modules/function/invocation.rs b/src/modules/function/invocation.rs index fe68d568..290ce5c5 100644 --- a/src/modules/function/invocation.rs +++ b/src/modules/function/invocation.rs @@ -95,7 +95,7 @@ impl SyntaxModule for FunctionInvocation { } impl FunctionInvocation { - fn get_variable(&self, meta: &mut TranslateMetadata, name: &str, dollar_override: bool) -> String { + fn get_variable(&self, meta: &TranslateMetadata, name: &str, dollar_override: bool) -> String { let dollar = dollar_override.then(|| "$").unwrap_or_else(|| meta.gen_dollar()); if matches!(self.kind, Type::Array(_)) { let quote = meta.gen_quote(); diff --git a/src/modules/function/invocation_utils.rs b/src/modules/function/invocation_utils.rs index 03182b09..52b4843c 100644 --- a/src/modules/function/invocation_utils.rs +++ b/src/modules/function/invocation_utils.rs @@ -78,7 +78,7 @@ fn run_function_with_args(meta: &mut ParserMetadata, mut fun: FunctionDecl, args Ok((fun.returns.clone(), meta.add_fun_instance(fun.to_interface(), block))) } -pub fn handle_function_reference(meta: &mut ParserMetadata, tok: Option, name: &str) -> Result { +pub fn handle_function_reference(meta: &ParserMetadata, tok: Option, name: &str) -> Result { match meta.get_fun_declaration(name) { Some(fun_decl) => Ok(fun_decl.id), None => { @@ -109,7 +109,7 @@ pub fn handle_function_parameters(meta: &mut ParserMetadata, id: usize, fun: Fun } } -fn handle_similar_function(meta: &mut ParserMetadata, name: &str) -> Option { +fn handle_similar_function(meta: &ParserMetadata, name: &str) -> Option { let vars = Vec::from_iter(meta.get_fun_names()); find_best_similarity(name, &vars) .map(|(match_name, score)| (score >= 0.75).then(|| format!("Did you mean '{match_name}'?"))) diff --git a/src/modules/imports/import.rs b/src/modules/imports/import.rs index 2148340e..bf264aca 100644 --- a/src/modules/imports/import.rs +++ b/src/modules/imports/import.rs @@ -51,7 +51,7 @@ impl Import { Ok(()) } - fn resolve_import(&mut self, meta: &mut ParserMetadata) -> Result { + fn resolve_import(&mut self, meta: &ParserMetadata) -> Result { match fs::read_to_string(self.path.value.clone()) { Ok(content) => Ok(content), Err(err) => error!(meta, self.token_path.clone() => { diff --git a/src/modules/imports/import_string.rs b/src/modules/imports/import_string.rs index 125bb0d1..cceb4d75 100644 --- a/src/modules/imports/import_string.rs +++ b/src/modules/imports/import_string.rs @@ -8,7 +8,7 @@ pub struct ImportString { } impl ImportString { - fn resolve_path(&mut self, meta: &mut ParserMetadata, tok: Option) -> SyntaxResult { + fn resolve_path(&mut self, meta: &ParserMetadata, tok: Option) -> SyntaxResult { if self.value == "std" { self.value = "[standard library]".to_string(); return Ok(()) diff --git a/src/modules/variable/mod.rs b/src/modules/variable/mod.rs index 3ee4ea72..0dbae876 100644 --- a/src/modules/variable/mod.rs +++ b/src/modules/variable/mod.rs @@ -37,7 +37,7 @@ pub fn variable_name_keywords() -> Vec<&'static str> { } -pub fn handle_variable_reference(meta: &mut ParserMetadata, tok: Option, name: &str) -> Result { +pub fn handle_variable_reference(meta: &ParserMetadata, tok: Option, name: &str) -> Result { handle_identifier_name(meta, name, tok.clone())?; match meta.get_var(name) { Some(variable_unit) => Ok(variable_unit.clone()), @@ -53,14 +53,14 @@ pub fn handle_variable_reference(meta: &mut ParserMetadata, tok: Option, } } -fn handle_similar_variable(meta: &mut ParserMetadata, name: &str) -> Option { +fn handle_similar_variable(meta: &ParserMetadata, name: &str) -> Option { let vars = Vec::from_iter(meta.get_var_names()); find_best_similarity(name, &vars) .map(|(match_name, score)| (score >= 0.75).then(|| format!("Did you mean '{match_name}'?"))) .flatten() } -pub fn handle_identifier_name(meta: &mut ParserMetadata, name: &str, tok: Option) -> Result<(), Failure> { +pub fn handle_identifier_name(meta: &ParserMetadata, name: &str, tok: Option) -> Result<(), Failure> { // Validate if the variable name uses the reserved prefix if name.chars().take(2).all(|chr| chr == '_') && name.len() > 2 { let new_name = name.get(1..).unwrap(); diff --git a/src/translate/compute.rs b/src/translate/compute.rs index 4fe169d8..4187cc26 100644 --- a/src/translate/compute.rs +++ b/src/translate/compute.rs @@ -21,7 +21,7 @@ pub enum ArithOp { Or } -pub fn translate_computation(meta: &mut TranslateMetadata, operation: ArithOp, left: Option, right: Option) -> String { +pub fn translate_computation(meta: &TranslateMetadata, operation: ArithOp, left: Option, right: Option) -> String { match meta.arith_module { ArithType::BcSed => { let (left, right) = (left.unwrap_or_default(), right.unwrap_or_default()); @@ -58,5 +58,5 @@ pub fn translate_computation_eval(meta: &mut TranslateMetadata, operation: Arith meta.eval_ctx = true; let result = translate_computation(meta, operation, left, right); meta.eval_ctx = old_eval; - return result; + result } \ No newline at end of file diff --git a/src/translate/mod.rs b/src/translate/mod.rs index 26c97eca..e5c4ffcd 100644 --- a/src/translate/mod.rs +++ b/src/translate/mod.rs @@ -5,7 +5,7 @@ use crate::utils::ParserMetadata; pub mod module; pub mod compute; -pub fn check_all_blocks(meta: &mut ParserMetadata) -> SyntaxResult { +pub fn check_all_blocks(meta: &ParserMetadata) -> SyntaxResult { let mut stack = 0; for token in meta.context.expr.iter() { match token.word.as_str() { diff --git a/src/utils/function_interface.rs b/src/utils/function_interface.rs index cac051d1..d56656c8 100644 --- a/src/utils/function_interface.rs +++ b/src/utils/function_interface.rs @@ -16,7 +16,7 @@ pub struct FunctionInterface { } impl FunctionInterface { - pub fn to_fun_declaration(self, id: usize) -> FunctionDecl { + pub fn as_fun_declaration(self, id: usize) -> FunctionDecl { let is_args_typed = self.arg_types.iter().all(|t| t != &Type::Generic); FunctionDecl { name: self.name, @@ -31,7 +31,7 @@ impl FunctionInterface { } } - pub fn to_fun_instance(self, block: Block) -> FunctionInstance { + pub fn as_fun_instance(self, block: Block) -> FunctionInstance { FunctionInstance { variant_id: 0, args: self.arg_types, diff --git a/src/utils/metadata/parser.rs b/src/utils/metadata/parser.rs index 7702e93a..742a9673 100644 --- a/src/utils/metadata/parser.rs +++ b/src/utils/metadata/parser.rs @@ -114,12 +114,12 @@ impl ParserMetadata { let global_id = self.gen_fun_id(); // Add the function to the public function list if fun.is_public { - let decl = fun.clone().to_fun_declaration(global_id); + let decl = fun.clone().as_fun_declaration(global_id); self.context.pub_funs.push(decl); } // Add the function to the current scope let scope = self.context.scopes.last_mut().unwrap(); - scope.add_fun(fun.to_fun_declaration(global_id)).then(|| { + scope.add_fun(fun.as_fun_declaration(global_id)).then(|| { // Add the function to the function cache self.fun_cache.add_declaration(global_id, ctx); global_id @@ -142,7 +142,7 @@ impl ParserMetadata { /// This function returns the id of the function instance variant pub fn add_fun_instance(&mut self, fun: FunctionInterface, block: Block) -> usize { let id = fun.id.expect("Function id is not set"); - self.fun_cache.add_instance(id, fun.to_fun_instance(block)) + self.fun_cache.add_instance(id, fun.as_fun_instance(block)) } /// Gets a function declaration from the current scope or any parent scope From f44481db6b5d68c4aa93f9b0abba41d8864a49b0 Mon Sep 17 00:00:00 2001 From: Ph0enixKM Date: Thu, 28 Sep 2023 20:38:53 +0200 Subject: [PATCH 4/4] linting fixes --- src/compiler.rs | 2 +- src/modules/command/expr.rs | 4 ++-- src/modules/command/modifier.rs | 2 +- src/modules/condition/failed.rs | 18 ++++++------------ src/modules/condition/ifchain.rs | 4 +--- src/modules/expression/literal/array.rs | 2 +- src/modules/expression/literal/bool.rs | 2 +- src/modules/expression/literal/mod.rs | 2 +- src/modules/expression/literal/status.rs | 2 +- src/modules/expression/unop/cast.rs | 2 +- src/modules/function/declaration.rs | 6 +++--- src/modules/function/invocation.rs | 4 ++-- src/modules/function/invocation_utils.rs | 9 ++++----- src/modules/function/ret.rs | 4 ++-- src/modules/loops/infinite_loop.rs | 6 ++---- src/modules/loops/iter_loop.rs | 14 +++++--------- src/modules/statement/stmt.rs | 2 +- src/modules/types.rs | 3 ++- src/modules/variable/init.rs | 4 +--- src/modules/variable/mod.rs | 3 +-- src/modules/variable/set.rs | 2 +- src/utils/context.rs | 6 +++--- src/utils/function_interface.rs | 4 ++-- src/utils/import_cache.rs | 5 ++--- src/utils/metadata/parser.rs | 8 ++++---- src/utils/metadata/translate.rs | 10 +++------- 26 files changed, 54 insertions(+), 76 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 6a31313d..0bb5afd6 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -68,7 +68,7 @@ impl AmberCompiler { pub fn parse(&self, tokens: Vec) -> Result<(Block, ParserMetadata), Message> { let code = self.cc.code.as_ref().expect(NO_CODE_PROVIDED).clone(); let mut meta = ParserMetadata::new(tokens, self.path.clone(), Some(code)); - if let Err(Failure::Loud(err)) = check_all_blocks(&mut meta) { + if let Err(Failure::Loud(err)) = check_all_blocks(&meta) { return Err(err); } let mut block = Block::new(); diff --git a/src/modules/command/expr.rs b/src/modules/command/expr.rs index e87c7f15..950d433c 100644 --- a/src/modules/command/expr.rs +++ b/src/modules/command/expr.rs @@ -47,7 +47,7 @@ impl SyntaxModule for CommandExpr { } Ok(()) }, - Err(Failure::Loud(err)) => return Err(Failure::Loud(err)), + Err(Failure::Loud(err)) => Err(Failure::Loud(err)), Err(Failure::Quiet(_)) => { let tok = meta.get_current_token(); (self.strings, self.interps) = parse_interpolated_region(meta, '$')?; @@ -71,7 +71,7 @@ impl TranslateModule for CommandExpr { .map(|item| item.translate(meta)) .collect::>(); let failed = self.failed.translate(meta); - let silent = self.is_silent_expr.then(|| " 2>/dev/null").unwrap_or(""); + let silent = if self.is_silent_expr { " 2>/dev/null" } else { "" }; if failed.is_empty() { let translation = translate_interpolated_region(self.strings.clone(), interps, false); meta.gen_subprocess(&(translation + silent)) diff --git a/src/modules/command/modifier.rs b/src/modules/command/modifier.rs index 1bc44d66..faa8d1a5 100644 --- a/src/modules/command/modifier.rs +++ b/src/modules/command/modifier.rs @@ -61,7 +61,7 @@ impl SyntaxModule for CommandModifier { match meta.get_current_token() { Some(tok) => { sequence.push_str(tok.word.as_str()); - sequence.push_str(" "); + sequence.push(' '); match tok.word.as_str() { "unsafe" => { self.is_unsafe = true; diff --git a/src/modules/condition/failed.rs b/src/modules/condition/failed.rs index 4bf7f16b..5605b299 100644 --- a/src/modules/condition/failed.rs +++ b/src/modules/condition/failed.rs @@ -26,7 +26,7 @@ impl SyntaxModule for Failed { fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { let tok = meta.get_current_token(); - if let Ok(_) = token(meta, "?") { + if token(meta, "?").is_ok() { if !meta.context.is_fun_ctx && !meta.context.is_main_ctx && !meta.context.is_unsafe_ctx { return error!(meta, tok, "The '?' operator can only be used in the main block or function body") } @@ -76,9 +76,7 @@ impl TranslateModule for Failed { fn translate(&self, meta: &mut TranslateMetadata) -> String { if self.is_parsed { let block = self.block.translate(meta); - let ret = self.is_main - .then(|| "exit $__AMBER_STATUS") - .unwrap_or("return $__AMBER_STATUS"); + let ret = if self.is_main { "exit $__AMBER_STATUS" } else { "return $__AMBER_STATUS" }; // the condition of '$?' clears the status code thus we need to store it in a variable if self.is_question_mark { // if the failed expression is in the main block we need to clear the return value @@ -88,20 +86,16 @@ impl TranslateModule for Failed { } else { String::new() }; - vec![ - "__AMBER_STATUS=$?;", + ["__AMBER_STATUS=$?;", "if [ $__AMBER_STATUS != 0 ]; then", &clear_return, ret, - "fi" - ].join("\n") + "fi"].join("\n") } else { - vec![ - "__AMBER_STATUS=$?;", + ["__AMBER_STATUS=$?;", "if [ $__AMBER_STATUS != 0 ]; then", &block, - "fi" - ].join("\n") + "fi"].join("\n") } } else { String::new() diff --git a/src/modules/condition/ifchain.rs b/src/modules/condition/ifchain.rs index d9458566..b9fad677 100644 --- a/src/modules/condition/ifchain.rs +++ b/src/modules/condition/ifchain.rs @@ -56,9 +56,7 @@ impl SyntaxModule for IfChain { return Ok(()) } // Handle end of the if chain - if let Err(err) = syntax(meta, &mut cond) { - return Err(err) - } + syntax(meta, &mut cond)?; match token(meta, "{") { Ok(_) => { syntax(meta, &mut block)?; diff --git a/src/modules/expression/literal/array.rs b/src/modules/expression/literal/array.rs index 78a0f525..c6138e2f 100644 --- a/src/modules/expression/literal/array.rs +++ b/src/modules/expression/literal/array.rs @@ -47,7 +47,7 @@ impl SyntaxModule for Array { Err(Failure::Quiet(_)) => { loop { let tok = meta.get_current_token(); - if let Ok(_) = token(meta, "[") { + if token(meta, "[").is_ok() { return error!(meta, tok, "Arrays cannot be nested due to the Bash limitations") } // Parse array value diff --git a/src/modules/expression/literal/bool.rs b/src/modules/expression/literal/bool.rs index df489362..12fab70a 100644 --- a/src/modules/expression/literal/bool.rs +++ b/src/modules/expression/literal/bool.rs @@ -24,7 +24,7 @@ impl SyntaxModule for Bool { } fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { - let value = token_by(meta, |value| vec!["true", "false"].contains(&value.as_str()))?; + let value = token_by(meta, |value| ["true", "false"].contains(&value.as_str()))?; self.value = value == "true"; Ok(()) } diff --git a/src/modules/expression/literal/mod.rs b/src/modules/expression/literal/mod.rs index 11cd739f..253da54e 100644 --- a/src/modules/expression/literal/mod.rs +++ b/src/modules/expression/literal/mod.rs @@ -146,7 +146,7 @@ pub fn translate_interpolated_region(strings: Vec, interps: Vec, match value { Some(translated) => { if is_even { - if translated.starts_with("\"") && translated.ends_with("\"") { + if translated.starts_with('\"') && translated.ends_with('\"') { result.push(translated.get(1..translated.len() - 1).unwrap().to_string()); } else { result.push(translated); diff --git a/src/modules/expression/literal/status.rs b/src/modules/expression/literal/status.rs index 3337b30d..43c0c498 100644 --- a/src/modules/expression/literal/status.rs +++ b/src/modules/expression/literal/status.rs @@ -27,6 +27,6 @@ impl SyntaxModule for Status { impl TranslateModule for Status { fn translate(&self, _meta: &mut TranslateMetadata) -> String { - format!("$__AMBER_STATUS") + "$__AMBER_STATUS".to_string() } } \ No newline at end of file diff --git a/src/modules/expression/unop/cast.rs b/src/modules/expression/unop/cast.rs index 054b2d31..87a8c686 100644 --- a/src/modules/expression/unop/cast.rs +++ b/src/modules/expression/unop/cast.rs @@ -25,7 +25,7 @@ impl SyntaxModule for Cast { } fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { - parse_left_expr(meta, &mut *self.expr, "as")?; + parse_left_expr(meta, &mut self.expr, "as")?; let tok = meta.get_current_token(); token(meta, "as")?; self.kind = parse_type(meta)?; diff --git a/src/modules/function/declaration.rs b/src/modules/function/declaration.rs index 1a0702f2..62e697e6 100644 --- a/src/modules/function/declaration.rs +++ b/src/modules/function/declaration.rs @@ -78,7 +78,7 @@ impl SyntaxModule for FunctionDeclaration { self.is_public = true; } if let Err(err) = token(meta, "fun") { - if flags.len() > 0 { + if !flags.is_empty() { return error!(meta, tok, "Compiler flags can only be used in function declarations") } return Err(err) @@ -145,7 +145,7 @@ impl SyntaxModule for FunctionDeclaration { arg_refs: self.arg_refs.clone(), returns: self.returns.clone(), is_public: self.is_public, - is_failable: is_failable + is_failable }, ctx)?; // Restore the compiler flags swap(&mut meta.context.cc_flags, &mut flags); @@ -167,7 +167,7 @@ impl TranslateModule for FunctionDeclaration { meta.fun_name = Some((self.name.clone(), self.id, index)); // Parse the function body result.push(format!("function {name} {{")); - if let Some(args) = self.set_args_as_variables(meta, &function, &self.arg_refs) { + if let Some(args) = self.set_args_as_variables(meta, function, &self.arg_refs) { result.push(args); } result.push(function.block.translate(meta)); diff --git a/src/modules/function/invocation.rs b/src/modules/function/invocation.rs index 290ce5c5..a8631acf 100644 --- a/src/modules/function/invocation.rs +++ b/src/modules/function/invocation.rs @@ -96,7 +96,7 @@ impl SyntaxModule for FunctionInvocation { impl FunctionInvocation { fn get_variable(&self, meta: &TranslateMetadata, name: &str, dollar_override: bool) -> String { - let dollar = dollar_override.then(|| "$").unwrap_or_else(|| meta.gen_dollar()); + let dollar = dollar_override.then_some("$").unwrap_or_else(|| meta.gen_dollar()); if matches!(self.kind, Type::Array(_)) { let quote = meta.gen_quote(); format!("{quote}{dollar}{{{name}[@]}}{quote}") @@ -118,7 +118,7 @@ impl TranslateModule for FunctionInvocation { // If the argument is an array, we have to get just the "name[@]" part (translation.starts_with("\"${") && translation.ends_with("[@]}\"")) .then(|| translation.get(3..translation.len() - 2).unwrap().to_string()) - .unwrap_or_else(|| translation) + .unwrap_or(translation) } }).collect::>().join(" "); meta.stmt_queue.push_back(format!("{name} {args}{silent}")); diff --git a/src/modules/function/invocation_utils.rs b/src/modules/function/invocation_utils.rs index 52b4843c..0818cbd6 100644 --- a/src/modules/function/invocation_utils.rs +++ b/src/modules/function/invocation_utils.rs @@ -54,7 +54,7 @@ fn run_function_with_args(meta: &mut ParserMetadata, mut fun: FunctionDecl, args // Create a sub context for new variables meta.push_scope(); for (kind, name, is_ref) in izip!(args, &fun.arg_names, &fun.arg_refs) { - meta.add_param(name, kind.clone(), is_ref.clone()); + meta.add_param(name, kind.clone(), *is_ref); } // Set the expected return type if specified if fun.returns != Type::Generic { @@ -73,9 +73,9 @@ fn run_function_with_args(meta: &mut ParserMetadata, mut fun: FunctionDecl, args fun.returns = ctx.fun_ret_type.clone().unwrap_or_else(|| Type::Null); }; // Set the new argument types - fun.arg_types = args.iter().cloned().collect(); + fun.arg_types = args.to_vec(); // Persist the new function instance - Ok((fun.returns.clone(), meta.add_fun_instance(fun.to_interface(), block))) + Ok((fun.returns.clone(), meta.add_fun_instance(fun.into_interface(), block))) } pub fn handle_function_reference(meta: &ParserMetadata, tok: Option, name: &str) -> Result { @@ -112,6 +112,5 @@ pub fn handle_function_parameters(meta: &mut ParserMetadata, id: usize, fun: Fun fn handle_similar_function(meta: &ParserMetadata, name: &str) -> Option { let vars = Vec::from_iter(meta.get_fun_names()); find_best_similarity(name, &vars) - .map(|(match_name, score)| (score >= 0.75).then(|| format!("Did you mean '{match_name}'?"))) - .flatten() + .and_then(|(match_name, score)| (score >= 0.75).then(|| format!("Did you mean '{match_name}'?"))) } \ No newline at end of file diff --git a/src/modules/function/ret.rs b/src/modules/function/ret.rs index 2008e6b2..39331adc 100644 --- a/src/modules/function/ret.rs +++ b/src/modules/function/ret.rs @@ -55,8 +55,8 @@ impl TranslateModule for Return { let result = self.expr.translate_eval(meta, false); let result = matches!(self.expr.get_type(), Type::Array(_)) .then(|| format!("({result})")) - .unwrap_or_else(|| result); + .unwrap_or(result); meta.stmt_queue.push_back(format!("__AMBER_FUN_{name}{id}_v{variant}={result}")); - format!("return 0") + "return 0".to_string() } } \ No newline at end of file diff --git a/src/modules/loops/infinite_loop.rs b/src/modules/loops/infinite_loop.rs index 9648e3c5..c92ad9a7 100644 --- a/src/modules/loops/infinite_loop.rs +++ b/src/modules/loops/infinite_loop.rs @@ -36,11 +36,9 @@ impl SyntaxModule for InfiniteLoop { impl TranslateModule for InfiniteLoop { fn translate(&self, meta: &mut TranslateMetadata) -> String { - vec![ - "while :".to_string(), + ["while :".to_string(), "do".to_string(), self.block.translate(meta), - "done".to_string() - ].join("\n") + "done".to_string()].join("\n") } } \ No newline at end of file diff --git a/src/modules/loops/iter_loop.rs b/src/modules/loops/iter_loop.rs index c4ad5aea..40922bcf 100644 --- a/src/modules/loops/iter_loop.rs +++ b/src/modules/loops/iter_loop.rs @@ -33,7 +33,7 @@ impl SyntaxModule for IterLoop { fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { token(meta, "loop")?; self.iter_name = variable(meta, variable_name_extensions())?; - if let Ok(_) = token(meta, ",") { + if token(meta, ",").is_ok() { self.iter_index = Some(self.iter_name.clone()); self.iter_name = variable(meta, variable_name_extensions())?; } @@ -79,22 +79,18 @@ impl TranslateModule for IterLoop { meta.increase_indent(); let indent = meta.gen_indent(); meta.decrease_indent(); - vec![ - format!("{index}=0;"), + [format!("{index}=0;"), format!("for {name} in {iterable}"), "do".to_string(), self.block.translate(meta), format!("{indent}let {index}=${{{index}}}+1"), - "done".to_string() - ].join("\n") + "done".to_string()].join("\n") }, None => { - vec![ - format!("for {name} in {iterable}"), + [format!("for {name} in {iterable}"), "do".to_string(), self.block.translate(meta), - "done".to_string() - ].join("\n") + "done".to_string()].join("\n") } } } diff --git a/src/modules/statement/stmt.rs b/src/modules/statement/stmt.rs index e2d8651c..3f95e044 100644 --- a/src/modules/statement/stmt.rs +++ b/src/modules/statement/stmt.rs @@ -153,7 +153,7 @@ impl TranslateModule for Statement { // This is a workaround that handles $(...) which cannot be used as a statement let translated = (matches!(self.value, Some(StatementType::Expr(_))) || translated.starts_with("$(") || translated.starts_with("\"$(")) .then(|| format!("echo {} > /dev/null 2>&1", translated)) - .unwrap_or_else(|| translated); + .unwrap_or(translated); // Get all the required supplemental statements let indentation = meta.gen_indent(); let statements = meta.stmt_queue.drain(..).map(|st| indentation.clone() + &st + ";\n").join(""); diff --git a/src/modules/types.rs b/src/modules/types.rs index 2f1dda5c..890bad44 100644 --- a/src/modules/types.rs +++ b/src/modules/types.rs @@ -36,7 +36,8 @@ pub trait Typed { // Tries to parse the type - if it fails, it fails loudly pub fn parse_type(meta: &mut ParserMetadata) -> Result { let tok = meta.get_current_token(); - try_parse_type(meta).or_else(|_| error!(meta, tok, "Expected a data type")) + try_parse_type(meta) + .map_err(|_| Failure::Loud(Message::new_err_at_token(meta, tok).message("Expected a data type"))) } // Tries to parse the type - if it fails, it fails quietly diff --git a/src/modules/variable/init.rs b/src/modules/variable/init.rs index add24c57..f1df0ef2 100644 --- a/src/modules/variable/init.rs +++ b/src/modules/variable/init.rs @@ -58,9 +58,7 @@ impl TranslateModule for VariableInit { if let Type::Array(_) = self.expr.get_type() { expr = format!("({expr})"); } - let local = self.is_fun_ctx - .then(|| "local ") - .unwrap_or_else(|| ""); + let local = if self.is_fun_ctx { "local " } else { "" }; match self.global_id { Some(id) => format!("__{id}_{name}={expr}"), None => format!("{local}{name}={expr}") diff --git a/src/modules/variable/mod.rs b/src/modules/variable/mod.rs index 0dbae876..dd5688e1 100644 --- a/src/modules/variable/mod.rs +++ b/src/modules/variable/mod.rs @@ -56,8 +56,7 @@ pub fn handle_variable_reference(meta: &ParserMetadata, tok: Option, name fn handle_similar_variable(meta: &ParserMetadata, name: &str) -> Option { let vars = Vec::from_iter(meta.get_var_names()); find_best_similarity(name, &vars) - .map(|(match_name, score)| (score >= 0.75).then(|| format!("Did you mean '{match_name}'?"))) - .flatten() + .and_then(|(match_name, score)| (score >= 0.75).then(|| format!("Did you mean '{match_name}'?"))) } pub fn handle_identifier_name(meta: &ParserMetadata, name: &str, tok: Option) -> Result<(), Failure> { diff --git a/src/modules/variable/set.rs b/src/modules/variable/set.rs index a9909fda..d9abb8ac 100644 --- a/src/modules/variable/set.rs +++ b/src/modules/variable/set.rs @@ -67,7 +67,7 @@ impl TranslateModule for VariableSet { .map(|index| format!("[{}]", self.is_ref .then(|| index.translate_eval(meta, true)) .unwrap_or_else(|| index.translate(meta)))) - .unwrap_or_else(|| String::new()); + .unwrap_or_default(); let mut expr = self.is_ref .then(|| self.value.translate_eval(meta, true)) .unwrap_or_else(|| self.value.translate(meta)); diff --git a/src/utils/context.rs b/src/utils/context.rs index 0a6599d5..17568940 100644 --- a/src/utils/context.rs +++ b/src/utils/context.rs @@ -18,7 +18,7 @@ pub struct FunctionDecl { } impl FunctionDecl { - pub fn to_interface(self) -> FunctionInterface { + pub fn into_interface(self) -> FunctionInterface { FunctionInterface { id: Some(self.id), name: self.name, @@ -145,9 +145,9 @@ impl Context { self } - pub fn file_import(mut self, trace: &Vec, position: PositionInfo) -> Self { + pub fn file_import(mut self, trace: &[PositionInfo], position: PositionInfo) -> Self { // Initialize the trace - self.trace = trace.clone(); + self.trace = trace.to_vec(); // Push the position to the trace self.trace.push(position); self diff --git a/src/utils/function_interface.rs b/src/utils/function_interface.rs index d56656c8..c518df41 100644 --- a/src/utils/function_interface.rs +++ b/src/utils/function_interface.rs @@ -16,7 +16,7 @@ pub struct FunctionInterface { } impl FunctionInterface { - pub fn as_fun_declaration(self, id: usize) -> FunctionDecl { + pub fn into_fun_declaration(self, id: usize) -> FunctionDecl { let is_args_typed = self.arg_types.iter().all(|t| t != &Type::Generic); FunctionDecl { name: self.name, @@ -31,7 +31,7 @@ impl FunctionInterface { } } - pub fn as_fun_instance(self, block: Block) -> FunctionInstance { + pub fn into_fun_instance(self, block: Block) -> FunctionInstance { FunctionInstance { variant_id: 0, args: self.arg_types, diff --git a/src/utils/import_cache.rs b/src/utils/import_cache.rs index 6249270a..e29a4194 100644 --- a/src/utils/import_cache.rs +++ b/src/utils/import_cache.rs @@ -70,7 +70,7 @@ impl ImportCache { // If so add it to the graph Some(dst_path_id) => { self.import_graph[src_path_id].push(dst_path_id); - (!self.contains_cycle(src_path_id)).then(|| dst_path_id) + (!self.contains_cycle(src_path_id)).then_some(dst_path_id) } // If not add it to the graph and create a new import entry None => { @@ -93,8 +93,7 @@ impl ImportCache { pub fn get_import_pub_funs(&mut self, path: Option) -> Option> { self.get_path_id(&Self::get_path(path)) - .map(|path_id| self.files[path_id].metadata.as_ref().map(|meta| meta.pub_funs.clone())) - .flatten() + .and_then(|path_id| self.files[path_id].metadata.as_ref().map(|meta| meta.pub_funs.clone())) } fn topological_sort_util(&self, v: usize, visited: &mut Vec, stack: &mut Vec) { diff --git a/src/utils/metadata/parser.rs b/src/utils/metadata/parser.rs index 742a9673..0a0ffff8 100644 --- a/src/utils/metadata/parser.rs +++ b/src/utils/metadata/parser.rs @@ -114,12 +114,12 @@ impl ParserMetadata { let global_id = self.gen_fun_id(); // Add the function to the public function list if fun.is_public { - let decl = fun.clone().as_fun_declaration(global_id); + let decl = fun.clone().into_fun_declaration(global_id); self.context.pub_funs.push(decl); } // Add the function to the current scope let scope = self.context.scopes.last_mut().unwrap(); - scope.add_fun(fun.as_fun_declaration(global_id)).then(|| { + scope.add_fun(fun.into_fun_declaration(global_id)).then(|| { // Add the function to the function cache self.fun_cache.add_declaration(global_id, ctx); global_id @@ -135,14 +135,14 @@ impl ParserMetadata { } // Add the function to the current scope let scope = self.context.scopes.last_mut().unwrap(); - scope.add_fun(fun).then(|| global_id) + scope.add_fun(fun).then_some(global_id) } /// Adds a function instance to the cache /// This function returns the id of the function instance variant pub fn add_fun_instance(&mut self, fun: FunctionInterface, block: Block) -> usize { let id = fun.id.expect("Function id is not set"); - self.fun_cache.add_instance(id, fun.as_fun_instance(block)) + self.fun_cache.add_instance(id, fun.into_fun_instance(block)) } /// Gets a function declaration from the current scope or any parent scope diff --git a/src/utils/metadata/translate.rs b/src/utils/metadata/translate.rs index ce874758..2e414e9f 100644 --- a/src/utils/metadata/translate.rs +++ b/src/utils/metadata/translate.rs @@ -65,15 +65,13 @@ impl TranslateMetadata { } pub fn gen_silent(&self) -> &'static str { - self.silenced.then(|| " > /dev/null 2>&1").unwrap_or("") + if self.silenced { " > /dev/null 2>&1" } else { "" } } // Returns the appropriate amount of quotes with escape symbols. // This helps to avoid problems with `eval` expressions. pub fn gen_quote(&self) -> &'static str { - self.eval_ctx - .then(|| "\\\"") - .unwrap_or("\"") + if self.eval_ctx { "\\\"" } else { "\"" } } pub fn gen_subprocess(&self, stmt: &str) -> String { @@ -83,8 +81,6 @@ impl TranslateMetadata { } pub fn gen_dollar(&self) -> &'static str { - self.eval_ctx - .then(|| "\\$") - .unwrap_or_else(|| "$") + if self.eval_ctx { "\\$" } else { "$" } } }