From d1aa370c882c02ed70f5df5003e1c2c55260ab95 Mon Sep 17 00:00:00 2001 From: ArjixWasTaken Date: Wed, 9 Apr 2025 23:00:12 +0300 Subject: [PATCH 1/7] feat: support array destructuring --- src/modules/variable/init.rs | 182 ++++++++++++++++++++++++++++++----- 1 file changed, 156 insertions(+), 26 deletions(-) diff --git a/src/modules/variable/init.rs b/src/modules/variable/init.rs index d55846a49..3f1987fe2 100644 --- a/src/modules/variable/init.rs +++ b/src/modules/variable/init.rs @@ -1,14 +1,22 @@ -use heraclitus_compiler::prelude::*; -use crate::{modules::prelude::*, translate::gen_intermediate_variable}; -use crate::modules::types::Typed; +use super::{handle_identifier_name, variable_name_extensions}; +use crate::docs::module::DocumentationModule; use crate::modules::expression::expr::Expr; -use super::{variable_name_extensions, handle_identifier_name}; +use crate::modules::types::Typed; +use heraclitus_compiler::prelude::*; +use itertools::Itertools; #[derive(Debug, Clone)] -pub struct VariableInit { +pub struct VariableDefinition { name: String, - expr: Box, + tok: Option, global_id: Option, +} + +#[derive(Debug, Clone)] +pub struct VariableInit { + definitions: Vec, + expr: Box, + is_global_ctx: bool, is_fun_ctx: bool, is_const: bool, } @@ -17,10 +25,10 @@ impl VariableInit { fn handle_add_variable( &mut self, meta: &mut ParserMetadata, - tok: Option + def: &mut VariableDefinition, ) -> SyntaxResult { - handle_identifier_name(meta, &self.name, tok)?; - self.global_id = meta.add_var(&self.name, self.expr.get_type(), self.is_const); + handle_identifier_name(meta, &def.name, def.tok.clone())?; + def.global_id = meta.add_var(&def.name, self.expr.get_type(), self.is_const); Ok(()) } } @@ -30,39 +38,161 @@ impl SyntaxModule for VariableInit { fn new() -> Self { VariableInit { - name: String::new(), + definitions: vec![], expr: Box::new(Expr::new()), - global_id: None, + is_global_ctx: false, is_fun_ctx: false, - is_const: false + is_const: false, } } fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { let keyword = token_by(meta, |word| ["let", "const"].contains(&word.as_str()))?; self.is_const = keyword == "const"; - // Get the variable name - let tok = meta.get_current_token(); - self.name = variable(meta, variable_name_extensions())?; - context!({ - token(meta, "=")?; - syntax(meta, &mut *self.expr)?; - // Add a variable to the memory - self.handle_add_variable(meta, tok)?; - self.is_fun_ctx = meta.context.is_fun_ctx; - Ok(()) - }, |position| { - error_pos!(meta, position, format!("Expected '=' after variable name '{}'", self.name)) - }) + + let mut definitions: Vec = vec![]; + let mut is_destructured = false; + + match token(meta, "[") { + Ok(_) => { + is_destructured = true; + let mut idx = 0; + loop { + if token(meta, "]").is_ok() { + break; + } + if idx > 0 { + token(meta, ",")?; + } + let tok = meta.get_current_token(); + let name = variable(meta, variable_name_extensions())?; + definitions.push(VariableDefinition { + name: name.clone(), + tok, + global_id: None, + }); + idx += 1; + } + } + Err(_) => { + let tok = meta.get_current_token(); + let name = variable(meta, variable_name_extensions())?; + definitions.push(VariableDefinition { + name: name.clone(), + tok, + global_id: None, + }); + } + } + + context!( + { + token(meta, "=")?; + syntax(meta, &mut *self.expr)?; + + if is_destructured && !self.expr.get_type().is_array() { + panic!("Expected array type for destructured variable"); + } + + for mut def in &mut definitions { + self.handle_add_variable(meta, &mut def)?; + } + + self.is_fun_ctx = meta.context.is_fun_ctx; + self.definitions = definitions.clone(); + Ok(()) + }, + |position| { + error_pos!( + meta, + position, + format!("Expected '=' after variable definition") + ) + } + ) } } impl TranslateModule for VariableInit { fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind { let expr = self.expr.translate(meta); - let (stmt, _var) = gen_intermediate_variable(&self.name, self.global_id, self.expr.get_type(), false, None, "=", expr); + let (stmt, _var) = gen_intermediate_variable( + &self.name, + self.global_id, + self.expr.get_type(), + false, + None, + "=", + expr, + ); stmt } + + /* + fn translate(&self, meta: &mut TranslateMetadata) -> String { + let mut expr = self.expr.translate(meta); + + if self.expr.get_type().is_array() { + expr = format!("({expr})"); + } + + let mut idx = 0; + let is_destructured = self.definitions.len() > 1; + let mut out = String::new(); + + let reference = if is_destructured { + if self.is_global_ctx { + Some(format!( + "__ref_{}_{}", + // all ids + self.definitions + .iter() + .map(|x| x.global_id.unwrap()) + .join("i_i"), + // all names + self.definitions.iter().map(|x| x.name.clone()).join("_") + )) + } else { + Some(format!( + "__ref_{}", + // all names + self.definitions.iter().map(|x| x.name.clone()).join("n_n") + )) + } + } else { + None + }; + + if reference.is_some() { + out += &format!( + "{}{}={};\n", + if self.is_fun_ctx { "local " } else { "" }, + reference.clone().unwrap(), + expr + ); + } + + for def in &self.definitions { + let expr = if is_destructured { + format!("${{{}[{}]}};\n", reference.clone().unwrap(), idx) + } else { + format!("{}", expr) + }; + + if let Some(id) = def.global_id { + out.push_str(format!("__{id}_{name}={expr}", name = def.name).as_str()); + } else if self.is_fun_ctx { + out.push_str(format!("local {name}={expr}", name = def.name).as_str()) + } else { + out.push_str(format!("{name}={expr}", name = def.name).as_str()) + } + + idx += 1; + } + + out + } + */ } impl DocumentationModule for VariableInit { From adaab4664268cfaf157ac94781f40218033a549b Mon Sep 17 00:00:00 2001 From: ArjixWasTaken Date: Thu, 10 Apr 2025 01:10:08 +0300 Subject: [PATCH 2/7] fix: store if the definitions are global --- src/modules/variable/init.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/variable/init.rs b/src/modules/variable/init.rs index 3f1987fe2..b993130ea 100644 --- a/src/modules/variable/init.rs +++ b/src/modules/variable/init.rs @@ -98,6 +98,7 @@ impl SyntaxModule for VariableInit { self.handle_add_variable(meta, &mut def)?; } + self.is_global_ctx = definitions.iter().any(|x| x.global_id.is_some()); self.is_fun_ctx = meta.context.is_fun_ctx; self.definitions = definitions.clone(); Ok(()) From 70453154a1c191c6c22f07fc7d81b132c4d867e2 Mon Sep 17 00:00:00 2001 From: ArjixWasTaken Date: Thu, 10 Apr 2025 09:20:31 +0300 Subject: [PATCH 3/7] chore: make clippy happy again --- src/modules/function/invocation.rs | 94 +++++++++++++++++++----------- src/modules/variable/init.rs | 11 ++-- 2 files changed, 65 insertions(+), 40 deletions(-) diff --git a/src/modules/function/invocation.rs b/src/modules/function/invocation.rs index f465b6f62..b1b9a6f99 100644 --- a/src/modules/function/invocation.rs +++ b/src/modules/function/invocation.rs @@ -1,15 +1,17 @@ use std::mem::swap; -use heraclitus_compiler::prelude::*; -use crate::{fragments, raw_fragment}; -use crate::modules::prelude::*; -use itertools::izip; +use super::invocation_utils::*; use crate::modules::command::modifier::CommandModifier; use crate::modules::condition::failed::Failed; +use crate::modules::expression::expr::Expr; +use crate::modules::expression::expr::{Expr, ExprType}; +use crate::modules::prelude::*; use crate::modules::types::{Type, Typed}; use crate::modules::variable::variable_name_extensions; -use crate::modules::expression::expr::{Expr, ExprType}; -use super::invocation_utils::*; +use crate::translate::module::TranslateModule; +use crate::utils::metadata::{ParserMetadata, TranslateMetadata}; +use heraclitus_compiler::prelude::*; +use itertools::izip; #[derive(Debug, Clone)] pub struct FunctionInvocation { @@ -23,7 +25,7 @@ pub struct FunctionInvocation { col: usize, failed: Failed, modifier: CommandModifier, - is_failable: bool + is_failable: bool, } impl Typed for FunctionInvocation { @@ -54,7 +56,7 @@ impl SyntaxModule for FunctionInvocation { col: 0, failed: Failed::new(), modifier: CommandModifier::new().parse_expr(), - is_failable: false + is_failable: false, } } @@ -72,7 +74,7 @@ impl SyntaxModule for FunctionInvocation { self.id = handle_function_reference(meta, tok.clone(), &self.name)?; loop { if token(meta, ")").is_ok() { - break + break; } let mut arg = Expr::new(); syntax(meta, &mut arg)?; @@ -93,7 +95,7 @@ impl SyntaxModule for FunctionInvocation { if actual_arg_count >= expected_arg_count - optional_count { let missing = expected_arg_count - actual_arg_count; let provided_optional = optional_count - missing; - for exp in function_unit.arg_optionals.iter().skip(provided_optional){ + for exp in function_unit.arg_optionals.iter().skip(provided_optional) { self.args.push(exp.clone()); } } @@ -102,21 +104,31 @@ impl SyntaxModule for FunctionInvocation { let types = self.args.iter().map(Expr::get_type).collect::>(); let var_refs = self.args.iter().map(is_ref).collect::>(); self.refs.clone_from(&function_unit.arg_refs); - (self.kind, self.variant_id) = handle_function_parameters(meta, self.id, function_unit.clone(), &types, &var_refs, tok.clone())?; + (self.kind, self.variant_id) = handle_function_parameters( + meta, + self.id, + function_unit.clone(), + &types, + &var_names, + tok.clone(), + )?; self.is_failable = function_unit.is_failable; if self.is_failable { match syntax(meta, &mut self.failed) { Ok(_) => (), - Err(Failure::Quiet(_)) => return error!(meta, tok => { - message: "This function can fail. Please handle the failure", - comment: "You can use '?' in the end to propagate the failure" - }), - Err(err) => return Err(err) + Err(Failure::Quiet(_)) => { + return error!(meta, tok => { + message: "This function can fail. Please handle the failure", + comment: "You can use '?' in the end to propagate the failure" + }) + } + Err(err) => return Err(err), } } else { let tok = meta.get_current_token(); - if let Ok(symbol) = token_by(meta, |word| ["?", "failed"].contains(&word.as_str())) { + if let Ok(symbol) = token_by(meta, |word| ["?", "failed"].contains(&word.as_str())) + { let message = Message::new_warn_at_token(meta, tok) .message("This function cannot fail") .comment(format!("You can remove the '{symbol}' in the end")); @@ -135,28 +147,44 @@ impl TranslateModule for FunctionInvocation { swap(&mut is_silent, &mut meta.silenced); let silent = meta.gen_silent().to_frag(); - let args = izip!(self.args.iter(), self.refs.iter()).map(| (arg, is_ref) | match arg.translate(meta) { - FragmentKind::Var(var) if *is_ref => var.with_render_type(VarRenderType::BashRef).to_frag(), - FragmentKind::Var(var) if var.kind.is_array() => fragments!(var.with_render_type(VarRenderType::BashRef).to_frag().with_quotes(false), "[@]"), - _ if *is_ref => panic!("Reference value accepts only variables"), - var => var - }).collect::>(); + let args = izip!(self.args.iter(), self.refs.iter()) + .map(|(arg, is_ref)| match arg.translate(meta) { + FragmentKind::Var(var) if *is_ref => { + var.with_render_type(VarRenderType::BashRef).to_frag() + } + FragmentKind::Var(var) if var.kind.is_array() => fragments!( + var.with_render_type(VarRenderType::BashRef) + .to_frag() + .with_quotes(false), + "[@]" + ), + _ if *is_ref => panic!("Reference value accepts only variables"), + var => var, + }) + .collect::>(); let args = ListFragment::new(args).with_spaces().to_frag(); - meta.stmt_queue.push_back(fragments!(name, " ", args, silent)); + meta.stmt_queue + .push_back(fragments!(name, " ", args, silent)); swap(&mut is_silent, &mut meta.silenced); if self.is_failable { let failed = self.failed.translate(meta); meta.stmt_queue.push_back(failed); } - if self.kind != Type::Null { - let invocation_return = &format!("__ret_{}{}_v{}", self.name, self.id, self.variant_id); - let invocation_instance = &format!("__ret_{}{}_v{}__{}_{}", self.name, self.id, self.variant_id, self.line, self.col); - let parsed_invocation_return = VarFragment::new(invocation_return, self.kind.clone(), false, None).to_frag(); - let variable = meta.push_intermediate_variable(invocation_instance, None, self.kind.clone(), parsed_invocation_return); - variable.to_frag() - } else { - fragments!("''") - } + meta.stmt_queue.push_back(format!( + "__AF_{}{}_v{}__{}_{}={}", + self.name, + self.id, + self.variant_id, + self.line, + self.col, + 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!("({})", parsed_invocation_return) + } else { + parsed_invocation_return + } + )); + self.get_variable(meta, invocation_instance, false) } } diff --git a/src/modules/variable/init.rs b/src/modules/variable/init.rs index b993130ea..d7c9adb21 100644 --- a/src/modules/variable/init.rs +++ b/src/modules/variable/init.rs @@ -94,8 +94,8 @@ impl SyntaxModule for VariableInit { panic!("Expected array type for destructured variable"); } - for mut def in &mut definitions { - self.handle_add_variable(meta, &mut def)?; + for def in &mut definitions { + self.handle_add_variable(meta, def)?; } self.is_global_ctx = definitions.iter().any(|x| x.global_id.is_some()); @@ -137,7 +137,6 @@ impl TranslateModule for VariableInit { expr = format!("({expr})"); } - let mut idx = 0; let is_destructured = self.definitions.len() > 1; let mut out = String::new(); @@ -173,11 +172,11 @@ impl TranslateModule for VariableInit { ); } - for def in &self.definitions { + for (idx, def) in self.definitions.iter().enumerate() { let expr = if is_destructured { format!("${{{}[{}]}};\n", reference.clone().unwrap(), idx) } else { - format!("{}", expr) + expr.clone() }; if let Some(id) = def.global_id { @@ -187,8 +186,6 @@ impl TranslateModule for VariableInit { } else { out.push_str(format!("{name}={expr}", name = def.name).as_str()) } - - idx += 1; } out From 347154be42f9ddcc1ce66c1b8d7ee6233c358609 Mon Sep 17 00:00:00 2001 From: ArjixWasTaken Date: Thu, 10 Apr 2025 09:24:28 +0300 Subject: [PATCH 4/7] fix: wrong translation of `let [a] = [1, 2]` --- src/modules/variable/init.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/modules/variable/init.rs b/src/modules/variable/init.rs index d7c9adb21..989b4e4ff 100644 --- a/src/modules/variable/init.rs +++ b/src/modules/variable/init.rs @@ -18,6 +18,7 @@ pub struct VariableInit { expr: Box, is_global_ctx: bool, is_fun_ctx: bool, + is_destructured: bool, is_const: bool, } @@ -42,6 +43,7 @@ impl SyntaxModule for VariableInit { expr: Box::new(Expr::new()), is_global_ctx: false, is_fun_ctx: false, + is_destructured: false, is_const: false, } } @@ -51,11 +53,10 @@ impl SyntaxModule for VariableInit { self.is_const = keyword == "const"; let mut definitions: Vec = vec![]; - let mut is_destructured = false; match token(meta, "[") { Ok(_) => { - is_destructured = true; + self.is_destructured = true; let mut idx = 0; loop { if token(meta, "]").is_ok() { @@ -85,12 +86,16 @@ impl SyntaxModule for VariableInit { } } + if definitions.is_empty() { + panic!("Expected at least one variable definition"); + } + context!( { token(meta, "=")?; syntax(meta, &mut *self.expr)?; - if is_destructured && !self.expr.get_type().is_array() { + if self.is_destructured && !self.expr.get_type().is_array() { panic!("Expected array type for destructured variable"); } @@ -137,10 +142,9 @@ impl TranslateModule for VariableInit { expr = format!("({expr})"); } - let is_destructured = self.definitions.len() > 1; let mut out = String::new(); - let reference = if is_destructured { + let reference = if self.is_destructured { if self.is_global_ctx { Some(format!( "__ref_{}_{}", @@ -173,7 +177,7 @@ impl TranslateModule for VariableInit { } for (idx, def) in self.definitions.iter().enumerate() { - let expr = if is_destructured { + let expr = if self.is_destructured { format!("${{{}[{}]}};\n", reference.clone().unwrap(), idx) } else { expr.clone() From a4a4f8d487825a1f1c03d56b90f1f2d35d89fc99 Mon Sep 17 00:00:00 2001 From: ArjixWasTaken Date: Tue, 15 Apr 2025 21:58:41 +0300 Subject: [PATCH 5/7] revert invocation.rs --- src/modules/function/invocation.rs | 96 +++++++++++------------------- 1 file changed, 34 insertions(+), 62 deletions(-) diff --git a/src/modules/function/invocation.rs b/src/modules/function/invocation.rs index b1b9a6f99..c91c336ea 100644 --- a/src/modules/function/invocation.rs +++ b/src/modules/function/invocation.rs @@ -1,17 +1,15 @@ use std::mem::swap; -use super::invocation_utils::*; +use heraclitus_compiler::prelude::*; +use crate::{fragments, raw_fragment}; +use crate::modules::prelude::*; +use itertools::izip; use crate::modules::command::modifier::CommandModifier; use crate::modules::condition::failed::Failed; -use crate::modules::expression::expr::Expr; -use crate::modules::expression::expr::{Expr, ExprType}; -use crate::modules::prelude::*; use crate::modules::types::{Type, Typed}; use crate::modules::variable::variable_name_extensions; -use crate::translate::module::TranslateModule; -use crate::utils::metadata::{ParserMetadata, TranslateMetadata}; -use heraclitus_compiler::prelude::*; -use itertools::izip; +use crate::modules::expression::expr::{Expr, ExprType}; +use super::invocation_utils::*; #[derive(Debug, Clone)] pub struct FunctionInvocation { @@ -25,7 +23,7 @@ pub struct FunctionInvocation { col: usize, failed: Failed, modifier: CommandModifier, - is_failable: bool, + is_failable: bool } impl Typed for FunctionInvocation { @@ -56,7 +54,7 @@ impl SyntaxModule for FunctionInvocation { col: 0, failed: Failed::new(), modifier: CommandModifier::new().parse_expr(), - is_failable: false, + is_failable: false } } @@ -74,7 +72,7 @@ impl SyntaxModule for FunctionInvocation { self.id = handle_function_reference(meta, tok.clone(), &self.name)?; loop { if token(meta, ")").is_ok() { - break; + break } let mut arg = Expr::new(); syntax(meta, &mut arg)?; @@ -95,7 +93,7 @@ impl SyntaxModule for FunctionInvocation { if actual_arg_count >= expected_arg_count - optional_count { let missing = expected_arg_count - actual_arg_count; let provided_optional = optional_count - missing; - for exp in function_unit.arg_optionals.iter().skip(provided_optional) { + for exp in function_unit.arg_optionals.iter().skip(provided_optional){ self.args.push(exp.clone()); } } @@ -104,31 +102,21 @@ impl SyntaxModule for FunctionInvocation { let types = self.args.iter().map(Expr::get_type).collect::>(); let var_refs = self.args.iter().map(is_ref).collect::>(); self.refs.clone_from(&function_unit.arg_refs); - (self.kind, self.variant_id) = handle_function_parameters( - meta, - self.id, - function_unit.clone(), - &types, - &var_names, - tok.clone(), - )?; + (self.kind, self.variant_id) = handle_function_parameters(meta, self.id, function_unit.clone(), &types, &var_refs, tok.clone())?; self.is_failable = function_unit.is_failable; if self.is_failable { match syntax(meta, &mut self.failed) { Ok(_) => (), - Err(Failure::Quiet(_)) => { - return error!(meta, tok => { - message: "This function can fail. Please handle the failure", - comment: "You can use '?' in the end to propagate the failure" - }) - } - Err(err) => return Err(err), + Err(Failure::Quiet(_)) => return error!(meta, tok => { + message: "This function can fail. Please handle the failure", + comment: "You can use '?' in the end to propagate the failure" + }), + Err(err) => return Err(err) } } else { let tok = meta.get_current_token(); - if let Ok(symbol) = token_by(meta, |word| ["?", "failed"].contains(&word.as_str())) - { + if let Ok(symbol) = token_by(meta, |word| ["?", "failed"].contains(&word.as_str())) { let message = Message::new_warn_at_token(meta, tok) .message("This function cannot fail") .comment(format!("You can remove the '{symbol}' in the end")); @@ -147,44 +135,28 @@ impl TranslateModule for FunctionInvocation { swap(&mut is_silent, &mut meta.silenced); let silent = meta.gen_silent().to_frag(); - let args = izip!(self.args.iter(), self.refs.iter()) - .map(|(arg, is_ref)| match arg.translate(meta) { - FragmentKind::Var(var) if *is_ref => { - var.with_render_type(VarRenderType::BashRef).to_frag() - } - FragmentKind::Var(var) if var.kind.is_array() => fragments!( - var.with_render_type(VarRenderType::BashRef) - .to_frag() - .with_quotes(false), - "[@]" - ), - _ if *is_ref => panic!("Reference value accepts only variables"), - var => var, - }) - .collect::>(); + let args = izip!(self.args.iter(), self.refs.iter()).map(| (arg, is_ref) | match arg.translate(meta) { + FragmentKind::Var(var) if *is_ref => var.with_render_type(VarRenderType::BashRef).to_frag(), + FragmentKind::Var(var) if var.kind.is_array() => fragments!(var.with_render_type(VarRenderType::BashRef).to_frag().with_quotes(false), "[@]"), + _ if *is_ref => panic!("Reference value accepts only variables"), + var => var + }).collect::>(); let args = ListFragment::new(args).with_spaces().to_frag(); - meta.stmt_queue - .push_back(fragments!(name, " ", args, silent)); + meta.stmt_queue.push_back(fragments!(name, " ", args, silent)); swap(&mut is_silent, &mut meta.silenced); if self.is_failable { let failed = self.failed.translate(meta); meta.stmt_queue.push_back(failed); } - meta.stmt_queue.push_back(format!( - "__AF_{}{}_v{}__{}_{}={}", - self.name, - self.id, - self.variant_id, - self.line, - self.col, - 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!("({})", parsed_invocation_return) - } else { - parsed_invocation_return - } - )); - self.get_variable(meta, invocation_instance, false) + if self.kind != Type::Null { + let invocation_return = &format!("__ret_{}{}_v{}", self.name, self.id, self.variant_id); + let invocation_instance = &format!("__ret_{}{}_v{}__{}_{}", self.name, self.id, self.variant_id, self.line, self.col); + let parsed_invocation_return = VarFragment::new(invocation_return, self.kind.clone(), false, None).to_frag(); + let variable = meta.push_intermediate_variable(invocation_instance, None, self.kind.clone(), parsed_invocation_return); + variable.to_frag() + } else { + fragments!("''") + } } } @@ -192,4 +164,4 @@ impl DocumentationModule for FunctionInvocation { fn document(&self, _meta: &ParserMetadata) -> String { "".to_string() } -} +} \ No newline at end of file From 690eb917a0f3d6fa132f405948c16bb3875687eb Mon Sep 17 00:00:00 2001 From: Angelos Bouklis Date: Tue, 15 Apr 2025 21:59:01 +0300 Subject: [PATCH 6/7] Discard changes to src/modules/function/invocation.rs --- src/modules/function/invocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/function/invocation.rs b/src/modules/function/invocation.rs index c91c336ea..f465b6f62 100644 --- a/src/modules/function/invocation.rs +++ b/src/modules/function/invocation.rs @@ -164,4 +164,4 @@ impl DocumentationModule for FunctionInvocation { fn document(&self, _meta: &ParserMetadata) -> String { "".to_string() } -} \ No newline at end of file +} From 0e3ecf5e83f77f01d674bbd16a6d8025263be787 Mon Sep 17 00:00:00 2001 From: ArjixWasTaken Date: Tue, 15 Apr 2025 23:32:22 +0300 Subject: [PATCH 7/7] use new translation layer --- src/modules/variable/init.rs | 117 ++++++++++++++++------------------- 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/src/modules/variable/init.rs b/src/modules/variable/init.rs index 989b4e4ff..0cb250075 100644 --- a/src/modules/variable/init.rs +++ b/src/modules/variable/init.rs @@ -1,7 +1,13 @@ use super::{handle_identifier_name, variable_name_extensions}; use crate::docs::module::DocumentationModule; use crate::modules::expression::expr::Expr; -use crate::modules::types::Typed; +use crate::modules::prelude::{ + BlockFragment, FragmentKind, RawFragment, TranslateModule, VarFragment, +}; +use crate::modules::types::{Type, Typed}; +use crate::translate::fragments::var::VarIndexValue; +use crate::translate::gen_intermediate_variable; +use crate::utils::{ParserMetadata, TranslateMetadata}; use heraclitus_compiler::prelude::*; use itertools::Itertools; @@ -122,79 +128,64 @@ impl SyntaxModule for VariableInit { impl TranslateModule for VariableInit { fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind { let expr = self.expr.translate(meta); - let (stmt, _var) = gen_intermediate_variable( - &self.name, - self.global_id, - self.expr.get_type(), - false, - None, - "=", - expr, - ); - stmt - } - - /* - fn translate(&self, meta: &mut TranslateMetadata) -> String { - let mut expr = self.expr.translate(meta); - if self.expr.get_type().is_array() { - expr = format!("({expr})"); + if !self.is_destructured { + let definition = self.definitions[0].clone(); + let (stmt, _var) = gen_intermediate_variable(&definition.name, definition.global_id, self.expr.get_type(), false, None, "=", expr); + return stmt; } - let mut out = String::new(); - - let reference = if self.is_destructured { - if self.is_global_ctx { - Some(format!( - "__ref_{}_{}", - // all ids - self.definitions - .iter() - .map(|x| x.global_id.unwrap()) - .join("i_i"), - // all names - self.definitions.iter().map(|x| x.name.clone()).join("_") - )) - } else { - Some(format!( - "__ref_{}", - // all names - self.definitions.iter().map(|x| x.name.clone()).join("n_n") - )) - } + // TODO: Add warning when the count of definitions is not equal to the count of elements in the array, or the size of the array is unknown. + + let mut block = BlockFragment::new(vec![], false); + + let reference = if self.is_global_ctx { + format!( + "__ref_{}_{}", + // all ids + self.definitions + .iter() + .map(|x| x.global_id.unwrap()) + .join("i_i"), + // all names + self.definitions.iter().map(|x| x.name.clone()).join("_") + ) } else { - None + format!( + "__ref_{}", + // all names + self.definitions.iter().map(|x| x.name.clone()).join("n_n") + ) }; - if reference.is_some() { - out += &format!( - "{}{}={};\n", - if self.is_fun_ctx { "local " } else { "" }, - reference.clone().unwrap(), - expr - ); - } + let (ref_stmt, _var) = gen_intermediate_variable(&reference, None, self.expr.get_type(), false, None, "=", expr); + block.append(ref_stmt); + + let sub_type = match self.expr.clone().kind.clone() { + Type::Array(expr) => expr, + _ => Box::new(Type::Generic), + }; for (idx, def) in self.definitions.iter().enumerate() { - let expr = if self.is_destructured { - format!("${{{}[{}]}};\n", reference.clone().unwrap(), idx) - } else { - expr.clone() - }; - - if let Some(id) = def.global_id { - out.push_str(format!("__{id}_{name}={expr}", name = def.name).as_str()); - } else if self.is_fun_ctx { - out.push_str(format!("local {name}={expr}", name = def.name).as_str()) - } else { - out.push_str(format!("{name}={expr}", name = def.name).as_str()) - } + let index = VarIndexValue::Index(FragmentKind::Raw(RawFragment::from(idx.to_string()))); + + let mut var_fragment = VarFragment::new(&reference, *sub_type.clone(), false, None); + var_fragment.index = Some(Box::new(index)); + + let (stmt, _var) = gen_intermediate_variable( + &def.name, + def.global_id, + *sub_type.clone(), + false, + None, + "=", + FragmentKind::Var(var_fragment), + ); + block.append(stmt); } - out + FragmentKind::Block(block) } - */ } impl DocumentationModule for VariableInit {