create separate variables for each $in wrapping
This commit is contained in:
parent
46b5e510ac
commit
eee815b015
|
@ -6308,7 +6308,12 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
|
|||
if let Some(decl_id) = working_set.find_decl(b"collect") {
|
||||
let mut output = vec![];
|
||||
|
||||
let var_id = IN_VARIABLE_ID;
|
||||
// IN_VARIABLE_ID should get replaced with a unique variable, so that we don't have to
|
||||
// execute as a closure
|
||||
let var_id = working_set.add_variable(b"$in".into(), expr.span, Type::Any, false);
|
||||
let mut expr = expr.clone();
|
||||
expr.replace_in_variable(working_set, var_id);
|
||||
|
||||
let mut signature = Signature::new("");
|
||||
signature.required_positional.push(PositionalArg {
|
||||
var_id: Some(var_id),
|
||||
|
|
|
@ -78,6 +78,19 @@ impl Block {
|
|||
Type::Nothing
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace any `$in` variables in the initial element of pipelines within the block
|
||||
pub fn replace_in_variable(
|
||||
&mut self,
|
||||
working_set: &mut StateWorkingSet<'_>,
|
||||
new_var_id: usize,
|
||||
) {
|
||||
for pipeline in self.pipelines.iter_mut() {
|
||||
if let Some(element) = pipeline.elements.first_mut() {
|
||||
element.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Block
|
||||
|
|
|
@ -6,6 +6,8 @@ use crate::{
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::ListItem;
|
||||
|
||||
/// Wrapper around [`Expr`]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Expression {
|
||||
|
@ -106,38 +108,9 @@ impl Expression {
|
|||
left.has_in_variable(working_set) || right.has_in_variable(working_set)
|
||||
}
|
||||
Expr::UnaryNot(expr) => expr.has_in_variable(working_set),
|
||||
Expr::Block(block_id) => {
|
||||
let block = working_set.get_block(*block_id);
|
||||
|
||||
if block.captures.contains(&IN_VARIABLE_ID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(pipeline) = block.pipelines.first() {
|
||||
match pipeline.elements.first() {
|
||||
Some(element) => element.has_in_variable(working_set),
|
||||
None => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
Expr::Closure(block_id) => {
|
||||
let block = working_set.get_block(*block_id);
|
||||
|
||||
if block.captures.contains(&IN_VARIABLE_ID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(pipeline) = block.pipelines.first() {
|
||||
match pipeline.elements.first() {
|
||||
Some(element) => element.has_in_variable(working_set),
|
||||
None => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
// The $in variable in blocks and closures is local, as they have their own input
|
||||
Expr::Block(_) => false,
|
||||
Expr::Closure(_) => false,
|
||||
Expr::Binary(_) => false,
|
||||
Expr::Bool(_) => false,
|
||||
Expr::Call(call) => {
|
||||
|
@ -443,6 +416,126 @@ impl Expression {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn replace_in_variable(&mut self, working_set: &mut StateWorkingSet, new_var_id: VarId) {
|
||||
match &mut self.expr {
|
||||
Expr::Bool(_) => {}
|
||||
Expr::Int(_) => {}
|
||||
Expr::Float(_) => {}
|
||||
Expr::Binary(_) => {}
|
||||
Expr::Range(_) => {}
|
||||
Expr::Var(var_id) | Expr::VarDecl(var_id) => {
|
||||
if *var_id == IN_VARIABLE_ID {
|
||||
*var_id = new_var_id;
|
||||
}
|
||||
}
|
||||
Expr::Call(call) => {
|
||||
for arg in call.arguments.iter_mut() {
|
||||
match arg {
|
||||
Argument::Positional(expr)
|
||||
| Argument::Unknown(expr)
|
||||
| Argument::Named((_, _, Some(expr)))
|
||||
| Argument::Spread(expr) => {
|
||||
expr.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
Argument::Named((_, _, None)) => {}
|
||||
}
|
||||
}
|
||||
for expr in call.parser_info.values_mut() {
|
||||
expr.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
}
|
||||
Expr::ExternalCall(head, args) => {
|
||||
head.replace_in_variable(working_set, new_var_id);
|
||||
for arg in args.iter_mut() {
|
||||
match arg {
|
||||
ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) => {
|
||||
expr.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Operator(_) => {}
|
||||
// These have their own input
|
||||
Expr::Block(_) | Expr::Closure(_) => {}
|
||||
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
||||
let mut block = Block::clone(working_set.get_block(*block_id));
|
||||
block.replace_in_variable(working_set, new_var_id);
|
||||
*working_set.get_block_mut(*block_id) = block;
|
||||
}
|
||||
Expr::UnaryNot(expr) => {
|
||||
expr.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
Expr::BinaryOp(lhs, op, rhs) => {
|
||||
for expr in [lhs, op, rhs] {
|
||||
expr.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
}
|
||||
Expr::MatchBlock(match_patterns) => {
|
||||
for (_, expr) in match_patterns.iter_mut() {
|
||||
expr.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
}
|
||||
Expr::List(items) => {
|
||||
for item in items.iter_mut() {
|
||||
match item {
|
||||
ListItem::Item(expr) | ListItem::Spread(_, expr) => {
|
||||
expr.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Table(table) => {
|
||||
for col_expr in table.columns.iter_mut() {
|
||||
col_expr.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
for row in table.rows.iter_mut() {
|
||||
for row_expr in row.iter_mut() {
|
||||
row_expr.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Record(items) => {
|
||||
for item in items.iter_mut() {
|
||||
match item {
|
||||
RecordItem::Pair(key, val) => {
|
||||
key.replace_in_variable(working_set, new_var_id);
|
||||
val.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
RecordItem::Spread(_, expr) => {
|
||||
expr.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Keyword(kw) => kw.expr.replace_in_variable(working_set, new_var_id),
|
||||
Expr::ValueWithUnit(value_with_unit) => value_with_unit
|
||||
.expr
|
||||
.replace_in_variable(working_set, new_var_id),
|
||||
Expr::DateTime(_) => {}
|
||||
Expr::Filepath(_, _) => {}
|
||||
Expr::Directory(_, _) => {}
|
||||
Expr::GlobPattern(_, _) => {}
|
||||
Expr::String(_) => {}
|
||||
Expr::RawString(_) => {}
|
||||
Expr::CellPath(_) => {}
|
||||
Expr::FullCellPath(full_cell_path) => {
|
||||
full_cell_path
|
||||
.head
|
||||
.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
Expr::ImportPattern(_) => {}
|
||||
Expr::Overlay(_) => {}
|
||||
Expr::Signature(_) => {}
|
||||
Expr::StringInterpolation(exprs) | Expr::GlobInterpolation(exprs, _) => {
|
||||
for expr in exprs.iter_mut() {
|
||||
expr.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
}
|
||||
Expr::Nothing => {}
|
||||
Expr::Garbage => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(working_set: &mut StateWorkingSet, expr: Expr, span: Span, ty: Type) -> Expression {
|
||||
let span_id = working_set.add_span(span);
|
||||
Expression {
|
||||
|
|
|
@ -62,6 +62,19 @@ impl RedirectionTarget {
|
|||
RedirectionTarget::Pipe { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_in_variable(
|
||||
&mut self,
|
||||
working_set: &mut StateWorkingSet<'_>,
|
||||
new_var_id: usize,
|
||||
) {
|
||||
match self {
|
||||
RedirectionTarget::File { expr, .. } => {
|
||||
expr.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
RedirectionTarget::Pipe { .. } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
|
@ -75,6 +88,23 @@ pub enum PipelineRedirection {
|
|||
err: RedirectionTarget,
|
||||
},
|
||||
}
|
||||
impl PipelineRedirection {
|
||||
pub fn replace_in_variable(
|
||||
&mut self,
|
||||
working_set: &mut StateWorkingSet<'_>,
|
||||
new_var_id: usize,
|
||||
) {
|
||||
match self {
|
||||
PipelineRedirection::Single { source: _, target } => {
|
||||
target.replace_in_variable(working_set, new_var_id)
|
||||
}
|
||||
PipelineRedirection::Separate { out, err } => {
|
||||
out.replace_in_variable(working_set, new_var_id);
|
||||
err.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PipelineElement {
|
||||
|
@ -120,6 +150,17 @@ impl PipelineElement {
|
|||
) -> (Option<OutDest>, Option<OutDest>) {
|
||||
self.expr.expr.pipe_redirection(working_set)
|
||||
}
|
||||
|
||||
pub fn replace_in_variable(
|
||||
&mut self,
|
||||
working_set: &mut StateWorkingSet<'_>,
|
||||
new_var_id: usize,
|
||||
) {
|
||||
self.expr.replace_in_variable(working_set, new_var_id);
|
||||
if let Some(redirection) = &mut self.redirection {
|
||||
redirection.replace_in_variable(working_set, new_var_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
|
Loading…
Reference in New Issue
Block a user