forked from extern/nushell
It expansion (#1668)
* First step in it-expansion * Fix tests * fix clippy warnings
This commit is contained in:
@ -77,6 +77,36 @@ pub enum ClassifiedCommand {
|
||||
Error(ParseError),
|
||||
}
|
||||
|
||||
impl ClassifiedCommand {
|
||||
pub fn has_it_iteration(&self) -> bool {
|
||||
match self {
|
||||
ClassifiedCommand::Internal(command) => {
|
||||
if let SpannedExpression {
|
||||
expr: Expression::Literal(Literal::String(s)),
|
||||
..
|
||||
} = &*command.args.head
|
||||
{
|
||||
if s == "run_external" {
|
||||
// For now, don't it-expand externals
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let mut result = command.args.head.has_shallow_it_usage();
|
||||
|
||||
if let Some(positionals) = &command.args.positional {
|
||||
for arg in positionals {
|
||||
result = result || arg.has_shallow_it_usage();
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
ClassifiedCommand::Expr(expr) => expr.has_shallow_it_usage(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Commands {
|
||||
pub list: Vec<ClassifiedCommand>,
|
||||
@ -91,6 +121,37 @@ impl Commands {
|
||||
pub fn push(&mut self, command: ClassifiedCommand) {
|
||||
self.list.push(command);
|
||||
}
|
||||
|
||||
/// Convert all shallow uses of $it to `each { use of $it }`, converting each to a per-row command
|
||||
pub fn expand_it_usage(&mut self) {
|
||||
for idx in 0..self.list.len() {
|
||||
if self.list[idx].has_it_iteration() {
|
||||
self.list[idx] = ClassifiedCommand::Internal(InternalCommand {
|
||||
name: "each".to_string(),
|
||||
name_span: self.span,
|
||||
args: hir::Call {
|
||||
head: Box::new(SpannedExpression {
|
||||
expr: Expression::Synthetic(Synthetic::String("each".to_string())),
|
||||
span: self.span,
|
||||
}),
|
||||
named: None,
|
||||
span: self.span,
|
||||
positional: Some(vec![SpannedExpression {
|
||||
expr: Expression::Block(Block {
|
||||
block: vec![Commands {
|
||||
list: vec![self.list[idx].clone()],
|
||||
span: self.span,
|
||||
}],
|
||||
span: self.span,
|
||||
}),
|
||||
span: self.span,
|
||||
}]),
|
||||
is_last: false, // FIXME
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||
@ -110,6 +171,13 @@ impl Block {
|
||||
pub fn push(&mut self, commands: Commands) {
|
||||
self.block.push(commands);
|
||||
}
|
||||
|
||||
/// Convert all shallow uses of $it to `each { use of $it }`, converting each to a per-row command
|
||||
pub fn expand_it_usage(&mut self) {
|
||||
for commands in &mut self.block {
|
||||
commands.expand_it_usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Deserialize, Serialize)]
|
||||
@ -201,14 +269,6 @@ pub enum Member {
|
||||
}
|
||||
|
||||
impl Member {
|
||||
// pub fn int(span: Span, source: &Text) -> Member {
|
||||
// if let Ok(big_int) = BigInt::from_str(span.slice(source)) {
|
||||
// Member::Int(big_int, span)
|
||||
// } else {
|
||||
// unreachable!("Internal error: could not convert text to BigInt as expected")
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn to_path_member(&self) -> PathMember {
|
||||
match self {
|
||||
//Member::String(outer, inner) => PathMember::string(inner.slice(source), *outer),
|
||||
@ -459,6 +519,17 @@ impl SpannedExpression {
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_shallow_it_usage(&self) -> bool {
|
||||
match &self.expr {
|
||||
Expression::Binary(binary) => {
|
||||
binary.left.has_shallow_it_usage() || binary.right.has_shallow_it_usage()
|
||||
}
|
||||
Expression::Variable(Variable::It(_)) => true,
|
||||
Expression::Path(path) => path.head.has_shallow_it_usage(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for SpannedExpression {
|
||||
|
Reference in New Issue
Block a user