1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use ExitStatus;
use conch_parser::ast::Parameter;
use env::{ArgumentsEnvironment, LastStatusEnvironment, StringWrapper, VariableEnvironment};
use eval::{Fields, ParamEval};
use io::getpid;
use std::borrow::Borrow;
const EXIT_SIGNAL_OFFSET: u32 = 128;
impl<T, E: ?Sized> ParamEval<E> for Parameter<T>
where T: StringWrapper,
E: ArgumentsEnvironment<Arg = T> + LastStatusEnvironment + VariableEnvironment<Var = T>,
E::VarName: Borrow<String>,
{
type EvalResult = T;
fn eval(&self, split_fields_further: bool, env: &E) -> Option<Fields<Self::EvalResult>> {
use conch_parser::ast::Parameter;
let get_args = || {
let args = env.args();
if args.is_empty() {
None
} else {
Some(args.iter().cloned().collect())
}
};
let ret = match *self {
Parameter::At => Some(get_args().map_or(Fields::Zero, Fields::At)),
Parameter::Star => Some(get_args().map_or(Fields::Zero, Fields::Star)),
Parameter::Pound => Some(Fields::Single(env.args_len().to_string().into())),
Parameter::Dollar => Some(Fields::Single(getpid().to_string().into())),
Parameter::Dash |
Parameter::Bang => None,
Parameter::Question => Some(Fields::Single(match env.last_status() {
ExitStatus::Code(c) => c as u32,
ExitStatus::Signal(c) => c as u32 + EXIT_SIGNAL_OFFSET,
}.to_string().into())),
Parameter::Positional(0) => Some(Fields::Single(env.name().clone())),
Parameter::Positional(p) => env.arg(p as usize).cloned().map(Fields::Single),
Parameter::Var(ref var) => env.var(var.borrow()).cloned().map(Fields::Single),
};
ret.map(|f| {
if split_fields_further {
f.split(env)
} else {
f
}
})
}
fn assig_name(&self) -> Option<Self::EvalResult> {
use conch_parser::ast::Parameter;
match *self {
Parameter::At |
Parameter::Star |
Parameter::Pound |
Parameter::Dollar |
Parameter::Dash |
Parameter::Bang |
Parameter::Question |
Parameter::Positional(_) => None,
Parameter::Var(ref var) => Some(var.clone()),
}
}
}