Skip to content

Commit

Permalink
Various fixes (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
magicant authored Apr 23, 2024
2 parents a12c23f + 82704c2 commit b9e09e9
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 94 deletions.
1 change: 0 additions & 1 deletion yash-cli/tests/scripted_test/for-p.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ A
B
__OUT__

: TODO yash is broken <<\__IN__
test_x -e 0 'exit status with no words'
false
for i do
Expand Down
2 changes: 0 additions & 2 deletions yash-cli/tests/scripted_test/option-p.sh
Original file line number Diff line number Diff line change
Expand Up @@ -286,14 +286,12 @@ __IN__
[unset]
__OUT__

: TODO yash is broken <<\__OUT__
test_oE -e 0 'nounset on: unset variable ${foo+bar}' -u
bracket "${x+set}"
__IN__
[]
__OUT__

: TODO yash is broken <<\__OUT__
test_oE -e 0 'nounset on: unset variable ${foo:+bar}' -u
bracket "${x:+set}"
__IN__
Expand Down
1 change: 0 additions & 1 deletion yash-cli/tests/scripted_test/param-p.sh
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ __IN__
${#?} 1
__OUT__

: TODO yash is broken <<\__OUT__
test_oE -e 0 'length of unset variables, success'
unset u
echoraw ${#u}
Expand Down
15 changes: 15 additions & 0 deletions yash-semantics/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- In the `expansion::initial` module:
- `ValueState` was renamed to `Vacancy`.
- `EmptyError` was renamed to `VacantError`.
- `EmptyError::state` was renamed to `VacantError::vacancy`.
- `expansion::ErrorCause::EmptyExpansion` was renamed to `expansion::ErrorCause::VacantExpansion`.
- `<expansion::Error as handle::Handle>::handle` now returns `Divert::Exit`
instead of `Divert::Interrupt` when the `ErrExit` shell option is applicable.

### Fixed

- A `for` loop without any words after `in` now correctly returns an exit status
of `0` rather than keeping the previous exit status.
- `<TextUnit as Expand>::expand` now correctly expands an unset parameter with a
switch to an empty string regardless of the `Unset` shell option. Previously,
it would expand to an empty string only if the `Unset` shell option was on.
- The parameter expansion of an unset variable with a `Length` modifier now
correctly expands to `0` rather than an empty string.

## [0.1.0] - 2024-04-13

### Added
Expand Down
8 changes: 7 additions & 1 deletion yash-semantics/src/command/compound_command/for_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::Handle;
use std::fmt::Write;
use std::ops::ControlFlow::{Break, Continue};
use yash_env::semantics::Divert;
use yash_env::semantics::ExitStatus;
use yash_env::semantics::Field;
use yash_env::semantics::Result;
use yash_env::stack::Frame;
Expand Down Expand Up @@ -71,6 +72,11 @@ pub async fn execute(

let env = &mut env.push_frame(Frame::Loop);

if values.is_empty() && !body.0.is_empty() {
env.exit_status = ExitStatus::SUCCESS;
return Continue(());
}

for Field { value, origin } in values {
let mut var = env.get_or_create_variable(name.value.clone(), Scope::Global);
match var.assign(value, origin) {
Expand Down Expand Up @@ -123,14 +129,14 @@ mod tests {
use yash_env::builtin::Builtin;
use yash_env::option::Option::ErrExit;
use yash_env::option::State::On;
use yash_env::semantics::ExitStatus;
use yash_env::VirtualSystem;
use yash_syntax::source::Location;
use yash_syntax::syntax::CompoundCommand;

#[test]
fn without_words_without_positional_parameters() {
let mut env = Env::new_virtual();
env.exit_status = ExitStatus(123);
let command: CompoundCommand = "for v do unreached; done".parse().unwrap();

let result = command.execute(&mut env).now_or_never().unwrap();
Expand Down
10 changes: 5 additions & 5 deletions yash-semantics/src/expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ use self::attr::Origin;
use self::attr_strip::Strip;
use self::glob::glob;
use self::initial::ArithError;
use self::initial::EmptyError;
#[cfg(doc)]
use self::initial::Expand;
use self::initial::Expand as _;
use self::initial::NonassignableError;
use self::initial::VacantError;
use self::quote_removal::skip_quotes;
use self::split::Ifs;
use std::borrow::Cow;
Expand Down Expand Up @@ -135,7 +135,7 @@ pub enum ErrorCause {

/// Expansion of an empty value with an error switch
#[error(transparent)]
EmptyExpansion(#[from] EmptyError),
VacantExpansion(#[from] VacantError),

/// Assignment to a nonassignable parameter
#[error(transparent)]
Expand All @@ -153,7 +153,7 @@ impl ErrorCause {
ArithError(_) => "error evaluating the arithmetic expansion",
AssignReadOnly(_) => "error assigning to variable",
UnsetParameter => "unset parameter",
EmptyExpansion(error) => error.message_or_default(),
VacantExpansion(error) => error.message_or_default(),
NonassignableParameter(_) => "cannot assign to parameter",
}
}
Expand All @@ -168,7 +168,7 @@ impl ErrorCause {
ArithError(e) => e.to_string().into(),
AssignReadOnly(e) => e.to_string().into(),
UnsetParameter => "unset parameter disallowed by the nounset option".into(),
EmptyExpansion(e) => e.state.description().into(),
VacantExpansion(e) => e.vacancy.description().into(),
NonassignableParameter(e) => e.to_string().into(),
}
}
Expand All @@ -187,7 +187,7 @@ impl ErrorCause {
"the variable was made read-only here",
)),
UnsetParameter => None,
EmptyExpansion(_) => None,
VacantExpansion(_) => None,
NonassignableParameter(_) => None,
}
}
Expand Down
4 changes: 2 additions & 2 deletions yash-semantics/src/expansion/initial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ mod tilde;
mod word;

pub use arith::ArithError;
pub use param::EmptyError;
pub use param::NonassignableError;
pub use param::ValueState;
pub use param::Vacancy;
pub use param::VacantError;
52 changes: 41 additions & 11 deletions yash-semantics/src/expansion/initial/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ mod resolve;
mod switch;
mod trim;

pub use switch::EmptyError;
pub use switch::NonassignableError;
pub use switch::ValueState;
pub use switch::Vacancy;
pub use switch::VacantError;

impl Expand for ParamRef<'_> {
/// Performs parameter expansion.
Expand All @@ -80,14 +80,14 @@ impl Expand for ParamRef<'_> {
{
return result;
}
}

// Check for nounset option error //
if value.is_none() && env.inner.options.get(Unset) == Off {
return Err(Error {
cause: ErrorCause::UnsetParameter,
location: self.location.clone(),
});
} else {
// Check for nounset option error //
if value.is_none() && env.inner.options.get(Unset) == Off {
return Err(Error {
cause: ErrorCause::UnsetParameter,
location: self.location.clone(),
});
}
}

// TODO Reject POSIXly unspecified combinations of name and modifier
Expand All @@ -99,7 +99,7 @@ impl Expand for ParamRef<'_> {
Modifier::Length => {
// TODO Reject ${#*} and ${#@} in POSIX mode
match &mut value {
None => (),
None => value = Some(Value::scalar("0")),
Some(Value::Scalar(v)) => to_length(v),
Some(Value::Array(vs)) => vs.iter_mut().for_each(to_length),
}
Expand Down Expand Up @@ -154,6 +154,7 @@ pub mod tests {
use super::*;
use futures_util::FutureExt;
use yash_env::variable::Scope;
use yash_syntax::syntax::{Switch, SwitchCondition, SwitchType};

pub fn env_with_positional_params_and_ifs() -> yash_env::Env {
let mut env = yash_env::Env::new_virtual();
Expand Down Expand Up @@ -188,6 +189,18 @@ pub mod tests {
assert_eq!(phrase, Phrase::Field(to_field("a1\u{30A4}")));
}

#[test]
fn length_of_unset() {
let mut env = yash_env::Env::new_virtual();
let mut env = Env::new(&mut env);
let mut param = param("foo");
param.modifier = Modifier::Length;
let param = ParamRef::from(&param);

let phrase = param.expand(&mut env).now_or_never().unwrap().unwrap();
assert_eq!(phrase, Phrase::Field(to_field("0")));
}

#[test]
fn length_of_scalar() {
let mut env = yash_env::Env::new_virtual();
Expand Down Expand Up @@ -314,6 +327,23 @@ pub mod tests {
assert_eq!(e.location, Location::dummy(""));
}

#[test]
fn nounset_option_is_ignored_if_there_is_switch() {
let mut env = yash_env::Env::new_virtual();
env.options.set(Unset, Off);
let mut env = Env::new(&mut env);
let mut param = param("foo");
param.modifier = Modifier::Switch(Switch {
r#type: SwitchType::Alter,
condition: SwitchCondition::Unset,
word: "".parse().unwrap(),
});
let param = ParamRef::from(&param);

let phrase = param.expand(&mut env).now_or_never().unwrap().unwrap();
assert_eq!(phrase, Phrase::one_empty_field());
}

#[test]
fn expand_at_no_join_in_non_splitting_context() {
let mut env = env_with_positional_params_and_ifs();
Expand Down
Loading

0 comments on commit b9e09e9

Please sign in to comment.