From 3e228d6d76351d161230c2c6470d8b27ae54b0ea Mon Sep 17 00:00:00 2001 From: Ph0enixKM Date: Thu, 28 Sep 2023 20:28:11 +0200 Subject: [PATCH] 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(|| "$") + } }