From 3616c71d1b46c2d6b9a4b2ea2c707d0777866062 Mon Sep 17 00:00:00 2001 From: MuhamedMagdi Date: Mon, 29 Jul 2024 23:10:02 +0300 Subject: [PATCH 1/3] feat(builtin): `rm` builtin --- src/modules/builtin/mod.rs | 1 + src/modules/builtin/rm.rs | 66 +++++++++++++++++++++++++++++++++++ src/modules/statement/stmt.rs | 6 ++-- src/modules/types.rs | 2 +- src/modules/variable/mod.rs | 2 +- 5 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 src/modules/builtin/rm.rs diff --git a/src/modules/builtin/mod.rs b/src/modules/builtin/mod.rs index 608297bc..147f5a95 100644 --- a/src/modules/builtin/mod.rs +++ b/src/modules/builtin/mod.rs @@ -2,3 +2,4 @@ pub mod cd; pub mod echo; pub mod mv; pub mod nameof; +pub mod rm; diff --git a/src/modules/builtin/rm.rs b/src/modules/builtin/rm.rs new file mode 100644 index 00000000..d8d0f665 --- /dev/null +++ b/src/modules/builtin/rm.rs @@ -0,0 +1,66 @@ +use std::mem::swap; + +use heraclitus_compiler::prelude::*; +use crate::modules::command::modifier::CommandModifier; +use crate::modules::condition::failed::Failed; +use crate::modules::expression::expr::Expr; +use crate::docs::module::DocumentationModule; +use crate::modules::types::{Type, Typed}; +use crate::translate::module::TranslateModule; +use crate::utils::{ParserMetadata, TranslateMetadata}; + +#[derive(Debug, Clone)] +pub struct Rm { + path: Expr, + modifier: CommandModifier, + failed: Failed, +} + +impl SyntaxModule for Rm { + syntax_name!("Remove"); + + fn new() -> Self { + Rm { + path: Expr::new(), + failed: Failed::new(), + modifier: CommandModifier::new().parse_expr(), + } + } + + fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { + syntax(meta, &mut self.modifier)?; + self.modifier.use_modifiers(meta, |_this, meta| { + let tok = meta.get_current_token(); + token(meta, "rm")?; + syntax(meta, &mut self.path)?; + let path_type = self.path.get_type(); + if path_type != Type::Text { + return error!(meta, tok => { + message: "'rm' can only be used with values of type Text", + comment: format!("Given type: {}, expected type: {}", path_type, Type::Text) + }); + } + syntax(meta, &mut self.failed)?; + Ok(()) + }) + } +} + +impl TranslateModule for Rm { + fn translate(&self, meta: &mut TranslateMetadata) -> String { + let path = self.path.translate(meta); + let failed = self.failed.translate(meta); + let mut is_silent = self.modifier.is_silent || meta.silenced; + swap(&mut is_silent, &mut meta.silenced); + let silent = meta.gen_silent(); + swap(&mut is_silent, &mut meta.silenced); + format!("rm -rf {path}{silent}\n{failed}").trim_end().to_string() + } +} + +impl DocumentationModule for Rm { + fn document(&self, _meta: &ParserMetadata) -> String { + "".to_string() + } +} + diff --git a/src/modules/statement/stmt.rs b/src/modules/statement/stmt.rs index 018dc4a4..aef9fa38 100644 --- a/src/modules/statement/stmt.rs +++ b/src/modules/statement/stmt.rs @@ -37,7 +37,8 @@ use crate::modules::main::Main; use crate::modules::builtin::{ echo::Echo, mv::Mv, - cd::Cd + cd::Cd, + rm:: Rm, }; use super::comment_doc::CommentDoc; @@ -65,6 +66,7 @@ pub enum StatementType { Cd(Cd), Echo(Echo), Mv(Mv), + Rm(Rm), CommandModifier(CommandModifier), CommentDoc(CommentDoc) } @@ -91,7 +93,7 @@ impl Statement { ShorthandMul, ShorthandDiv, ShorthandModulo, // Command - CommandModifier, Echo, Mv, Cd, + CommandModifier, Echo, Mv, Cd, Rm, // Comment doc CommentDoc, // Expression diff --git a/src/modules/types.rs b/src/modules/types.rs index d6ce868e..fe4085d7 100644 --- a/src/modules/types.rs +++ b/src/modules/types.rs @@ -98,4 +98,4 @@ pub fn try_parse_type(meta: &mut ParserMetadata) -> Result { Err(Failure::Quiet(PositionInfo::at_eof(meta))) } } -} \ No newline at end of file +} diff --git a/src/modules/variable/mod.rs b/src/modules/variable/mod.rs index 62361776..4898727d 100644 --- a/src/modules/variable/mod.rs +++ b/src/modules/variable/mod.rs @@ -32,7 +32,7 @@ pub fn variable_name_keywords() -> Vec<&'static str> { // Command Modifiers "silent", "unsafe", // Misc - "echo", "status", "nameof", "mv", "cd" + "echo", "status", "nameof", "mv", "cd", "rm" ] } From 127d157a93f5d592742de81e700c11f9ddc051b6 Mon Sep 17 00:00:00 2001 From: MuhamedMagdi Date: Sun, 11 Aug 2024 11:30:24 +0300 Subject: [PATCH 2/3] test: builtin funtion `rm` --- src/modules/builtin/rm.rs | 6 +++--- src/tests/validity/rm.ab | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 src/tests/validity/rm.ab diff --git a/src/modules/builtin/rm.rs b/src/modules/builtin/rm.rs index d8d0f665..e9c9d32d 100644 --- a/src/modules/builtin/rm.rs +++ b/src/modules/builtin/rm.rs @@ -30,13 +30,13 @@ impl SyntaxModule for Rm { fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult { syntax(meta, &mut self.modifier)?; self.modifier.use_modifiers(meta, |_this, meta| { - let tok = meta.get_current_token(); token(meta, "rm")?; syntax(meta, &mut self.path)?; let path_type = self.path.get_type(); if path_type != Type::Text { - return error!(meta, tok => { - message: "'rm' can only be used with values of type Text", + let position = self.path.get_position(meta); + return error_pos!(meta, position => { + message: "Builtin function `rm` can only be used with values of type Text", comment: format!("Given type: {}, expected type: {}", path_type, Type::Text) }); } diff --git a/src/tests/validity/rm.ab b/src/tests/validity/rm.ab new file mode 100644 index 00000000..c140e364 --- /dev/null +++ b/src/tests/validity/rm.ab @@ -0,0 +1,12 @@ +import * from "std/fs" +main { + let tmpdir = unsafe $mktemp -d /tmp/amber-XXXX$ + unsafe $touch {tmpdir}/a$ + unsafe rm "{tmpdir}/a" + if not file_exist("{tmpdir}/a") { + echo "Succeded" + } else { + echo "Found" + unsafe $rm -fr {tmpdir}$ + } +} From 9392c83e2a03b1b3f8ef658cec2aa7844c8f0f38 Mon Sep 17 00:00:00 2001 From: MuhamedMagdi Date: Sun, 11 Aug 2024 11:38:30 +0300 Subject: [PATCH 3/3] fix: test fails if file did't get created --- src/tests/validity/rm.ab | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tests/validity/rm.ab b/src/tests/validity/rm.ab index c140e364..81364a7e 100644 --- a/src/tests/validity/rm.ab +++ b/src/tests/validity/rm.ab @@ -2,11 +2,14 @@ import * from "std/fs" main { let tmpdir = unsafe $mktemp -d /tmp/amber-XXXX$ unsafe $touch {tmpdir}/a$ + if not file_exist("{tmpdir}/a") { + echo "Not Found" + } unsafe rm "{tmpdir}/a" if not file_exist("{tmpdir}/a") { echo "Succeded" } else { echo "Found" - unsafe $rm -fr {tmpdir}$ } + unsafe $rm -fr {tmpdir}$ }