-
Notifications
You must be signed in to change notification settings - Fork 110
Feat/new builtins #996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Feat/new builtins #996
Conversation
* added builtins: clear, ls, pwd, rm, rmdir and sleep
* added tests for builtins ls, rm, rmdir and pwd
* added builtin function for wait command
* added new builtin for cp * added test for builtin cp
* added builtin to get pid of last command * updated kill test to use pid builtin * don't use reserved keyword pid in stdlib
* added grammar for builtins
* removed const with name lines from pgrep and pgrep_exact as it is a reserved keyword
* added test for sleep builtin
* silenced Terminate message, so it doesn't interfere with the expected output
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
* added test for wait builtin
* removed deprecated calling method for new builtin cp
Mte90
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some changes to do but others are internal discussion for Amber.
src/modules/builtin/rm.rs
Outdated
|
|
||
| impl TranslateModule for Rm { | ||
| fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind { | ||
| fragments!("rm -f ", self.value.translate(meta)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should have parameters in this builtin, like for the f and r parameter.
src/modules/builtin/rmdir.rs
Outdated
|
|
||
| impl TranslateModule for RmDir { | ||
| fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind { | ||
| fragments!("rm -rf ", self.value.translate(meta)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said in the ticket maybe we can use the rmdir command instead of rm.
|
|
||
| impl TranslateModule for Wait { | ||
| fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind { | ||
| fragments!("wait ", self.pids.translate(meta)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About this maybe it is better to implement it as block? #950 @Ph0enixKM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mte90 I'd rename this builtin to be await and let it accept single parameter or a list of parameter:
/// WARNING: This is future Amber code
let pid = async foo()
// Waits until foo finishes
await(pid)
let pids = [async foo(), async bar()]
// Runs in parallel foo and bar and waits for them to finish
await(pids)
// Runs in parallel foo and bar and waits for them to finish
await([async foo(), async bar()])There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems a good idea
|
First of all, Thanks! There are some fixes in tests to do, I suggest to move the discussion about the missing builtin in the ticket itself. |
* fixed typo * use touch builtin when possible * make tests that use SECONDS less volatile
* added force and recursive flag to rm builtin * added test for rm recursive
* use rmdir when translating * added argument to ignore errors for non empty dirs * updated testcase
* removed argument for ignore errors for non empty dirs since it doesn't exist on MacOS
* added optional options to ls builtin
src/modules/builtin/rm.rs
Outdated
| let force_expr = meta.push_ephemeral_variable(force_var_stmt); | ||
| meta.stmt_queue.extend([ | ||
| fragments!( | ||
| raw_fragment!("read -rd '' -a {} < <([[ ", force_expr.get_name()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the purpose of this code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rm builtin now expects an optional 2nd and 3rd param for the -f and -r flag, that are an expr of type Bool. The builtin probably is most often called like rm("file.txt", true, false) where this translation would be somewhat obsolete. But since the params are an expr it could also be called like rm("file.txt", isF(), isR()) where you'd need to evaluate if the flag should be set during runtime, which the translation above does.
This could benefit from Constant folding since in the 1st case, we can tell during compile time that -f has to be set.
Alternatively I could also rewrite the builtin to just expect a [Text] for the params, so it's called like rm("file.txt", ["-f", "-r"]). This of course leaves more room for unexpected behavior during runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should accept bool just like we do it right now. If anyone wants to use some less common option parameter, they can just run a regular command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I think that a boolean is the best, until we don't have dictionaries is the right way
|
I think that we need to update the stdlib to use where needed those new builtins. |
Ph0enixKM
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kryske you did a really good job. I'm really impressed. There are some things that have to be addressed though. Nevertheless I like how cleanly you wrote the rust side of code. Good job!
src/modules/builtin/ls.rs
Outdated
| options_frag.with_quotes(false), | ||
| path_fragment | ||
| ), | ||
| BlockFragment::new(vec![handler], true).to_frag(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider unwrapping the handler from within BlockFragment unless it's here on purpose.
| BlockFragment::new(vec![handler], true).to_frag(), | |
| handler, |
| token(meta, "pid")?; | ||
| token(meta, "(")?; | ||
| token(meta, ")")?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We sould unify this with status syntax. In this case I think that we should update status to also require parentheses:
// Before
status
// After
status()
src/modules/builtin/ls.rs
Outdated
| options_frag.with_quotes(false), | ||
| path_fragment | ||
| ), | ||
| BlockFragment::new(vec![handler], true).to_frag(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider unwrapping handler from within BlockFragment unless this was made on purpose.
| BlockFragment::new(vec![handler], true).to_frag(), | |
| handler, |
src/modules/builtin/pid.rs
Outdated
| fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind { | ||
| let id = meta.gen_value_id(); | ||
| let var_stmt = | ||
| VarStmtFragment::new("__int", Type::Int, fragments!("$!")).with_global_id(id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider calling it __pid instead.
| VarStmtFragment::new("__int", Type::Int, fragments!("$!")).with_global_id(id); | |
| VarStmtFragment::new("__pid", Type::Int, fragments!("$!")).with_global_id(id); |
src/modules/builtin/ls.rs
Outdated
| }; | ||
| let id = meta.gen_value_id(); | ||
| let var_stmt = | ||
| VarStmtFragment::new("__array", Type::array_of(Type::Text), FragmentKind::Empty) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider calling this variable __ls instead.
| VarStmtFragment::new("__array", Type::array_of(Type::Text), FragmentKind::Empty) | |
| VarStmtFragment::new("__ls", Type::array_of(Type::Text), FragmentKind::Empty) |
src/modules/builtin/rm.rs
Outdated
| let force_expr = meta.push_ephemeral_variable(force_var_stmt); | ||
| meta.stmt_queue.extend([ | ||
| fragments!( | ||
| raw_fragment!("read -rd '' -a {} < <([[ ", force_expr.get_name()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should accept bool just like we do it right now. If anyone wants to use some less common option parameter, they can just run a regular command.
src/modules/builtin/ls.rs
Outdated
| fn new() -> Self { | ||
| Ls { | ||
| value: Box::new(None), | ||
| options: Box::new(None), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add only the most important and common flags. I propose to add support for -a (all) and -R (recursive) in the same format as rm does. This makes it easy to switch on/off certain flags with boolean variables. If someone wants to use some less common flag, they can always run a command.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think -A would be better for the all flag in this case. I don't see the value in returning a "." and ".." entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolutely right, @kryske. Let's do -A instead of -a.
src/modules/builtin/rm.rs
Outdated
| let recursive_var_stmt = VarStmtFragment::new("__recursive", Type::Bool, FragmentKind::Empty).with_global_id(recursive_id); | ||
| let recursive_expr = meta.push_ephemeral_variable(recursive_var_stmt); | ||
| meta.stmt_queue.extend([ | ||
| fragments!(raw_fragment!("read -rd '' -a {} < <([[ ", recursive_expr.get_name()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This command reads array from recursive_expr which is of type Bool. Consider rendering the following logic gate:
[[ ${recursive_expr} -neq 0 ]] && __recursive="-r" || __recursive=""Or even cleaner version which uses bash arithmetic to determine the result
(( recursive_expr )) && __recursive="-r" || __recursive=""Consider doing the same for force_expr too in this function.
src/modules/builtin/rmdir.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a point of introducing this builtin since we can already rm("directory", true). I think that we can scrap this module entirely (remember to update grammar.ebnf)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or maybe do an alias to that builtin internally?
rmdir is a command already available/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like the current approach where one builtin can do other builtin's behavior. Let's simplify them to make them all self contained.
Idea 1
Let's either unify them, making the rm(val, true) run rmdir which is a safer option for shell scripting
Idea 2
Let's separate these two builtins so that only one can do its own thing:
rm/rmfile- removes only files withrfand fails to remove directoriesrmdir- removes only directories
Idea 3
Let's just use rm for both files and directories. This could render to the following condition:
[[ -d $target ]] && rmdir "$target" || rm "$target"
|
|
||
| impl TranslateModule for Wait { | ||
| fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind { | ||
| fragments!("wait ", self.pids.translate(meta)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Mte90 I'd rename this builtin to be await and let it accept single parameter or a list of parameter:
/// WARNING: This is future Amber code
let pid = async foo()
// Waits until foo finishes
await(pid)
let pids = [async foo(), async bar()]
// Runs in parallel foo and bar and waits for them to finish
await(pids)
// Runs in parallel foo and bar and waits for them to finish
await([async foo(), async bar()])* switch recursive and force param * made force param optional and default to false * simplified translation * updated tests
* refactored naming in pid builtin
* added parentheses to status to unify syntax * added deprecation warning for use with parentheses * updated use of status throughout the project
* simplified pwd builtin translation * updated prefix of var
* removed rmdir builtin * removed grammer for rmdir builtin
* renamed builtin wait to await * updated grammar
* updated params of builtin ls to only provider optional bool params to provide the -A and -R flag * updated tests
* fixed test because ls -R returns something different on mac * some code cleanup
|
|
||
| main { | ||
| trust $ SECONDS=0 $ | ||
| trust $ sleep 2 & $ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should use the new builtin here
I added a bunch of Builtins + Tests, as described in #908
current test seems unstable with the use of SECONDScurrent test seems unstable with the use of SECONDSI also added
Builtins described in #908 but not added:
I also fixed some variable names in the stdlib because they where using reserved keywords.
Ref: #908