yash_semantics/expansion/
initial.rs

1// This file is part of yash, an extended POSIX shell.
2// Copyright (C) 2022 WATANABE Yuki
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17//! Initial expansion
18//!
19//! The initial expansion evaluates a word to a phrase. This module defines the
20//! [`Expand`] trait and its implementors that perform the expansion.
21
22use super::Error;
23use super::phrase::Phrase;
24use std::fmt::Debug;
25use yash_env::semantics::ExitStatus;
26
27/// Environment in which initial expansion is performed
28///
29/// This sturct extends [`yash_env::Env`] with some properties.
30#[derive(Debug)]
31pub struct Env<'a> {
32    /// Main part of the environment
33    pub inner: &'a mut yash_env::Env,
34
35    /// Exit status of the last executed command substitution
36    ///
37    /// This value is `None` by default.
38    /// When performing a command substitution during expansion, you must set
39    /// its exit status to this field.
40    pub last_command_subst_exit_status: Option<ExitStatus>,
41
42    /// Whether the expansion result will be subjected to field splitting.
43    ///
44    /// This flag will affect the expansion of the `$*` special parameter.
45    pub will_split: bool,
46}
47
48impl<'a> Env<'a> {
49    /// Creates a new `Env` instance.
50    ///
51    /// The `last_command_subst_exit_status` and `will_split` field are
52    /// initialized to be `None` and `true`, respectively.
53    pub fn new(inner: &'a mut yash_env::Env) -> Self {
54        Env {
55            inner,
56            last_command_subst_exit_status: None,
57            will_split: true,
58        }
59    }
60}
61
62/// Syntactic construct that can be subjected to the word expansion.
63///
64/// Syntactic elements like [`TextUnit`](yash_syntax::syntax::TextUnit) and
65/// [`Word`](yash_syntax::syntax::Word) implement this trait to
66/// [`expand`](Self::expand) themselves to a [`Phrase`].
67pub trait Expand {
68    /// Performs initial expansion.
69    #[allow(async_fn_in_trait)] // We don't support Send
70    async fn expand(&self, env: &mut Env<'_>) -> Result<Phrase, Error>;
71}
72
73mod arith;
74mod command_subst;
75mod param;
76mod slice;
77mod text;
78mod tilde;
79mod word;
80
81pub use arith::ArithError;
82pub use param::NonassignableError;
83pub use param::Vacancy;
84pub use param::VacantError;