mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Remove statements, replaced by pipelines (#4482)
This commit is contained in:
parent
66669d7839
commit
56b3fc61a3
16 changed files with 660 additions and 750 deletions
|
@ -1,7 +1,7 @@
|
||||||
use nu_engine::eval_block;
|
use nu_engine::eval_block;
|
||||||
use nu_parser::{flatten_expression, parse, trim_quotes, FlatShape};
|
use nu_parser::{flatten_expression, parse, trim_quotes, FlatShape};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Expr, Statement},
|
ast::Expr,
|
||||||
engine::{EngineState, Stack, StateWorkingSet},
|
engine::{EngineState, Stack, StateWorkingSet},
|
||||||
PipelineData, Span, Value, CONFIG_VARIABLE_ID,
|
PipelineData, Span, Value, CONFIG_VARIABLE_ID,
|
||||||
};
|
};
|
||||||
|
@ -174,228 +174,214 @@ impl NuCompleter {
|
||||||
let pos = offset + pos;
|
let pos = offset + pos;
|
||||||
let (output, _err) = parse(&mut working_set, Some("completer"), line.as_bytes(), false);
|
let (output, _err) = parse(&mut working_set, Some("completer"), line.as_bytes(), false);
|
||||||
|
|
||||||
for stmt in output.stmts.into_iter() {
|
for pipeline in output.pipelines.into_iter() {
|
||||||
if let Statement::Pipeline(pipeline) = stmt {
|
for expr in pipeline.expressions {
|
||||||
for expr in pipeline.expressions {
|
let flattened: Vec<_> = flatten_expression(&working_set, &expr);
|
||||||
let flattened: Vec<_> = flatten_expression(&working_set, &expr);
|
|
||||||
|
|
||||||
for (flat_idx, flat) in flattened.iter().enumerate() {
|
for (flat_idx, flat) in flattened.iter().enumerate() {
|
||||||
if pos >= flat.0.start && pos < flat.0.end {
|
if pos >= flat.0.start && pos < flat.0.end {
|
||||||
let new_span = Span {
|
let new_span = Span {
|
||||||
start: flat.0.start,
|
start: flat.0.start,
|
||||||
end: flat.0.end - 1,
|
end: flat.0.end - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut prefix = working_set.get_span_contents(flat.0).to_vec();
|
let mut prefix = working_set.get_span_contents(flat.0).to_vec();
|
||||||
prefix.remove(pos - flat.0.start);
|
prefix.remove(pos - flat.0.start);
|
||||||
|
|
||||||
if prefix.starts_with(b"$") {
|
if prefix.starts_with(b"$") {
|
||||||
return self.complete_variables(
|
return self.complete_variables(
|
||||||
&working_set,
|
&working_set,
|
||||||
&prefix,
|
&prefix,
|
||||||
new_span,
|
new_span,
|
||||||
offset,
|
offset,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if prefix.starts_with(b"-") {
|
if prefix.starts_with(b"-") {
|
||||||
// this might be a flag, let's see
|
// this might be a flag, let's see
|
||||||
if let Expr::Call(call) = &expr.expr {
|
if let Expr::Call(call) = &expr.expr {
|
||||||
let decl = working_set.get_decl(call.decl_id);
|
let decl = working_set.get_decl(call.decl_id);
|
||||||
let sig = decl.signature();
|
let sig = decl.signature();
|
||||||
|
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
for named in &sig.named {
|
for named in &sig.named {
|
||||||
let mut named = named.long.as_bytes().to_vec();
|
let mut named = named.long.as_bytes().to_vec();
|
||||||
named.insert(0, b'-');
|
named.insert(0, b'-');
|
||||||
named.insert(0, b'-');
|
named.insert(0, b'-');
|
||||||
if named.starts_with(&prefix) {
|
if named.starts_with(&prefix) {
|
||||||
output.push((
|
output.push((
|
||||||
reedline::Span {
|
reedline::Span {
|
||||||
start: new_span.start - offset,
|
start: new_span.start - offset,
|
||||||
end: new_span.end - offset,
|
end: new_span.end - offset,
|
||||||
},
|
|
||||||
String::from_utf8_lossy(&named).to_string(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match &flat.1 {
|
|
||||||
FlatShape::Custom(custom_completion) => {
|
|
||||||
//let prefix = working_set.get_span_contents(flat.0).to_vec();
|
|
||||||
|
|
||||||
let (block, ..) = parse(
|
|
||||||
&mut working_set,
|
|
||||||
None,
|
|
||||||
custom_completion.as_bytes(),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut stack = Stack::new();
|
|
||||||
// Set up our initial config to start from
|
|
||||||
stack.vars.insert(
|
|
||||||
CONFIG_VARIABLE_ID,
|
|
||||||
Value::Record {
|
|
||||||
cols: vec![],
|
|
||||||
vals: vec![],
|
|
||||||
span: Span { start: 0, end: 0 },
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let result = eval_block(
|
|
||||||
&self.engine_state,
|
|
||||||
&mut stack,
|
|
||||||
&block,
|
|
||||||
PipelineData::new(new_span),
|
|
||||||
);
|
|
||||||
|
|
||||||
let v: Vec<_> = match result {
|
|
||||||
Ok(pd) => pd
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(move |x| {
|
|
||||||
let s = x.as_string();
|
|
||||||
|
|
||||||
match s {
|
|
||||||
Ok(s) => Some((
|
|
||||||
reedline::Span {
|
|
||||||
start: new_span.start - offset,
|
|
||||||
end: new_span.end - offset,
|
|
||||||
},
|
|
||||||
s,
|
|
||||||
)),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(|x| x.1.as_bytes().starts_with(&prefix))
|
|
||||||
.collect(),
|
|
||||||
_ => vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
FlatShape::Filepath | FlatShape::GlobPattern => {
|
|
||||||
let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD")
|
|
||||||
{
|
|
||||||
match d.as_string() {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => "".to_string(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"".to_string()
|
|
||||||
};
|
|
||||||
let prefix = String::from_utf8_lossy(&prefix).to_string();
|
|
||||||
return file_path_completion(new_span, &prefix, &cwd)
|
|
||||||
.into_iter()
|
|
||||||
.map(move |x| {
|
|
||||||
(
|
|
||||||
reedline::Span {
|
|
||||||
start: x.0.start - offset,
|
|
||||||
end: x.0.end - offset,
|
|
||||||
},
|
|
||||||
x.1,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
flat_shape => {
|
|
||||||
let last = flattened
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.skip_while(|x| x.0.end > pos)
|
|
||||||
.take_while(|x| {
|
|
||||||
matches!(
|
|
||||||
x.1,
|
|
||||||
FlatShape::InternalCall
|
|
||||||
| FlatShape::External
|
|
||||||
| FlatShape::ExternalArg
|
|
||||||
| FlatShape::Literal
|
|
||||||
| FlatShape::String
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.last();
|
|
||||||
|
|
||||||
// The last item here would be the earliest shape that could possible by part of this subcommand
|
|
||||||
let subcommands = if let Some(last) = last {
|
|
||||||
self.complete_commands(
|
|
||||||
&working_set,
|
|
||||||
Span {
|
|
||||||
start: last.0.start,
|
|
||||||
end: pos,
|
|
||||||
},
|
},
|
||||||
offset,
|
String::from_utf8_lossy(&named).to_string(),
|
||||||
false,
|
));
|
||||||
)
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
};
|
|
||||||
|
|
||||||
if !subcommands.is_empty() {
|
|
||||||
return subcommands;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let commands =
|
match &flat.1 {
|
||||||
if matches!(flat_shape, nu_parser::FlatShape::External)
|
FlatShape::Custom(custom_completion) => {
|
||||||
|| matches!(
|
//let prefix = working_set.get_span_contents(flat.0).to_vec();
|
||||||
flat_shape,
|
|
||||||
nu_parser::FlatShape::InternalCall
|
|
||||||
)
|
|
||||||
|| ((new_span.end - new_span.start) == 0)
|
|
||||||
{
|
|
||||||
// we're in a gap or at a command
|
|
||||||
self.complete_commands(
|
|
||||||
&working_set,
|
|
||||||
new_span,
|
|
||||||
offset,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
};
|
|
||||||
|
|
||||||
let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD")
|
let (block, ..) = parse(
|
||||||
|
&mut working_set,
|
||||||
|
None,
|
||||||
|
custom_completion.as_bytes(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut stack = Stack::new();
|
||||||
|
// Set up our initial config to start from
|
||||||
|
stack.vars.insert(
|
||||||
|
CONFIG_VARIABLE_ID,
|
||||||
|
Value::Record {
|
||||||
|
cols: vec![],
|
||||||
|
vals: vec![],
|
||||||
|
span: Span { start: 0, end: 0 },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let result = eval_block(
|
||||||
|
&self.engine_state,
|
||||||
|
&mut stack,
|
||||||
|
&block,
|
||||||
|
PipelineData::new(new_span),
|
||||||
|
);
|
||||||
|
|
||||||
|
let v: Vec<_> = match result {
|
||||||
|
Ok(pd) => pd
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(move |x| {
|
||||||
|
let s = x.as_string();
|
||||||
|
|
||||||
|
match s {
|
||||||
|
Ok(s) => Some((
|
||||||
|
reedline::Span {
|
||||||
|
start: new_span.start - offset,
|
||||||
|
end: new_span.end - offset,
|
||||||
|
},
|
||||||
|
s,
|
||||||
|
)),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(|x| x.1.as_bytes().starts_with(&prefix))
|
||||||
|
.collect(),
|
||||||
|
_ => vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
FlatShape::Filepath | FlatShape::GlobPattern => {
|
||||||
|
let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD") {
|
||||||
|
match d.as_string() {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(_) => "".to_string(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
};
|
||||||
|
let prefix = String::from_utf8_lossy(&prefix).to_string();
|
||||||
|
return file_path_completion(new_span, &prefix, &cwd)
|
||||||
|
.into_iter()
|
||||||
|
.map(move |x| {
|
||||||
|
(
|
||||||
|
reedline::Span {
|
||||||
|
start: x.0.start - offset,
|
||||||
|
end: x.0.end - offset,
|
||||||
|
},
|
||||||
|
x.1,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
flat_shape => {
|
||||||
|
let last = flattened
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.skip_while(|x| x.0.end > pos)
|
||||||
|
.take_while(|x| {
|
||||||
|
matches!(
|
||||||
|
x.1,
|
||||||
|
FlatShape::InternalCall
|
||||||
|
| FlatShape::External
|
||||||
|
| FlatShape::ExternalArg
|
||||||
|
| FlatShape::Literal
|
||||||
|
| FlatShape::String
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.last();
|
||||||
|
|
||||||
|
// The last item here would be the earliest shape that could possible by part of this subcommand
|
||||||
|
let subcommands = if let Some(last) = last {
|
||||||
|
self.complete_commands(
|
||||||
|
&working_set,
|
||||||
|
Span {
|
||||||
|
start: last.0.start,
|
||||||
|
end: pos,
|
||||||
|
},
|
||||||
|
offset,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
if !subcommands.is_empty() {
|
||||||
|
return subcommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
let commands =
|
||||||
|
if matches!(flat_shape, nu_parser::FlatShape::External)
|
||||||
|
|| matches!(flat_shape, nu_parser::FlatShape::InternalCall)
|
||||||
|
|| ((new_span.end - new_span.start) == 0)
|
||||||
{
|
{
|
||||||
match d.as_string() {
|
// we're in a gap or at a command
|
||||||
Ok(s) => s,
|
self.complete_commands(&working_set, new_span, offset, true)
|
||||||
Err(_) => "".to_string(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"".to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
let preceding_byte = if new_span.start > offset {
|
|
||||||
working_set
|
|
||||||
.get_span_contents(Span {
|
|
||||||
start: new_span.start - 1,
|
|
||||||
end: new_span.start,
|
|
||||||
})
|
|
||||||
.to_vec()
|
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
// let prefix = working_set.get_span_contents(flat.0);
|
|
||||||
let prefix = String::from_utf8_lossy(&prefix).to_string();
|
|
||||||
let output = file_path_completion(new_span, &prefix, &cwd)
|
|
||||||
.into_iter()
|
|
||||||
.map(move |x| {
|
|
||||||
if flat_idx == 0 {
|
|
||||||
// We're in the command position
|
|
||||||
if x.1.starts_with('"')
|
|
||||||
&& !matches!(preceding_byte.get(0), Some(b'^'))
|
|
||||||
{
|
|
||||||
let trimmed = trim_quotes(x.1.as_bytes());
|
|
||||||
let trimmed = String::from_utf8_lossy(trimmed)
|
|
||||||
.to_string();
|
|
||||||
let expanded =
|
|
||||||
nu_path::canonicalize_with(trimmed, &cwd);
|
|
||||||
|
|
||||||
if let Ok(expanded) = expanded {
|
let cwd = if let Some(d) = self.engine_state.env_vars.get("PWD") {
|
||||||
if is_executable::is_executable(expanded) {
|
match d.as_string() {
|
||||||
(x.0, format!("^{}", x.1))
|
Ok(s) => s,
|
||||||
} else {
|
Err(_) => "".to_string(),
|
||||||
(x.0, x.1)
|
}
|
||||||
}
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let preceding_byte = if new_span.start > offset {
|
||||||
|
working_set
|
||||||
|
.get_span_contents(Span {
|
||||||
|
start: new_span.start - 1,
|
||||||
|
end: new_span.start,
|
||||||
|
})
|
||||||
|
.to_vec()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
// let prefix = working_set.get_span_contents(flat.0);
|
||||||
|
let prefix = String::from_utf8_lossy(&prefix).to_string();
|
||||||
|
let output = file_path_completion(new_span, &prefix, &cwd)
|
||||||
|
.into_iter()
|
||||||
|
.map(move |x| {
|
||||||
|
if flat_idx == 0 {
|
||||||
|
// We're in the command position
|
||||||
|
if x.1.starts_with('"')
|
||||||
|
&& !matches!(preceding_byte.get(0), Some(b'^'))
|
||||||
|
{
|
||||||
|
let trimmed = trim_quotes(x.1.as_bytes());
|
||||||
|
let trimmed =
|
||||||
|
String::from_utf8_lossy(trimmed).to_string();
|
||||||
|
let expanded =
|
||||||
|
nu_path::canonicalize_with(trimmed, &cwd);
|
||||||
|
|
||||||
|
if let Ok(expanded) = expanded {
|
||||||
|
if is_executable::is_executable(expanded) {
|
||||||
|
(x.0, format!("^{}", x.1))
|
||||||
} else {
|
} else {
|
||||||
(x.0, x.1)
|
(x.0, x.1)
|
||||||
}
|
}
|
||||||
|
@ -405,23 +391,25 @@ impl NuCompleter {
|
||||||
} else {
|
} else {
|
||||||
(x.0, x.1)
|
(x.0, x.1)
|
||||||
}
|
}
|
||||||
})
|
} else {
|
||||||
.map(move |x| {
|
(x.0, x.1)
|
||||||
(
|
}
|
||||||
reedline::Span {
|
})
|
||||||
start: x.0.start - offset,
|
.map(move |x| {
|
||||||
end: x.0.end - offset,
|
(
|
||||||
},
|
reedline::Span {
|
||||||
x.1,
|
start: x.0.start - offset,
|
||||||
)
|
end: x.0.end - offset,
|
||||||
})
|
},
|
||||||
.chain(subcommands.into_iter())
|
x.1,
|
||||||
.chain(commands.into_iter())
|
)
|
||||||
.collect::<Vec<_>>();
|
})
|
||||||
//output.dedup_by(|a, b| a.1 == b.1);
|
.chain(subcommands.into_iter())
|
||||||
|
.chain(commands.into_iter())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
//output.dedup_by(|a, b| a.1 == b.1);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use nu_path::expand_path_with;
|
use nu_path::expand_path_with;
|
||||||
use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement};
|
use nu_protocol::ast::{Block, Call, Expr, Expression, Operator};
|
||||||
use nu_protocol::engine::{EngineState, Stack};
|
use nu_protocol::engine::{EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Range, ShellError, Span,
|
IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Range, ShellError, Span,
|
||||||
|
@ -471,21 +471,19 @@ pub fn eval_block(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
mut input: PipelineData,
|
mut input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let num_stmts = block.stmts.len();
|
let num_pipelines = block.len();
|
||||||
for (stmt_idx, stmt) in block.stmts.iter().enumerate() {
|
for (pipeline_idx, pipeline) in block.pipelines.iter().enumerate() {
|
||||||
if let Statement::Pipeline(pipeline) = stmt {
|
for (i, elem) in pipeline.expressions.iter().enumerate() {
|
||||||
for (i, elem) in pipeline.expressions.iter().enumerate() {
|
input = eval_expression_with_input(
|
||||||
input = eval_expression_with_input(
|
engine_state,
|
||||||
engine_state,
|
stack,
|
||||||
stack,
|
elem,
|
||||||
elem,
|
input,
|
||||||
input,
|
i == pipeline.expressions.len() - 1,
|
||||||
i == pipeline.expressions.len() - 1,
|
)?
|
||||||
)?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if stmt_idx < (num_stmts) - 1 {
|
if pipeline_idx < (num_pipelines) - 1 {
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::Nothing { .. }, ..) => {}
|
PipelineData::Value(Value::Nothing { .. }, ..) => {}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -551,15 +549,13 @@ pub fn eval_block_with_redirect(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
mut input: PipelineData,
|
mut input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let num_stmts = block.stmts.len();
|
let num_pipelines = block.len();
|
||||||
for (stmt_idx, stmt) in block.stmts.iter().enumerate() {
|
for (pipeline_idx, pipeline) in block.pipelines.iter().enumerate() {
|
||||||
if let Statement::Pipeline(pipeline) = stmt {
|
for elem in pipeline.expressions.iter() {
|
||||||
for elem in pipeline.expressions.iter() {
|
input = eval_expression_with_input(engine_state, stack, elem, input, false)?
|
||||||
input = eval_expression_with_input(engine_state, stack, elem, input, false)?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if stmt_idx < (num_stmts) - 1 {
|
if pipeline_idx < (num_pipelines) - 1 {
|
||||||
match input {
|
match input {
|
||||||
PipelineData::Value(Value::Nothing { .. }, ..) => {}
|
PipelineData::Value(Value::Nothing { .. }, ..) => {}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -625,11 +621,9 @@ pub fn eval_subexpression(
|
||||||
block: &Block,
|
block: &Block,
|
||||||
mut input: PipelineData,
|
mut input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
for stmt in block.stmts.iter() {
|
for pipeline in block.pipelines.iter() {
|
||||||
if let Statement::Pipeline(pipeline) = stmt {
|
for expr in pipeline.expressions.iter() {
|
||||||
for expr in pipeline.expressions.iter() {
|
input = eval_expression_with_input(engine_state, stack, expr, input, false)?
|
||||||
input = eval_expression_with_input(engine_state, stack, expr, input, false)?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,6 @@ pub enum ParseError {
|
||||||
#[diagnostic(code(nu::parser::unclosed_delimiter), url(docsrs))]
|
#[diagnostic(code(nu::parser::unclosed_delimiter), url(docsrs))]
|
||||||
Unclosed(String, #[label("unclosed {0}")] Span),
|
Unclosed(String, #[label("unclosed {0}")] Span),
|
||||||
|
|
||||||
#[error("Unknown statement.")]
|
|
||||||
#[diagnostic(code(nu::parser::unknown_statement), url(docsrs))]
|
|
||||||
UnknownStatement(#[label("unknown statement")] Span),
|
|
||||||
|
|
||||||
#[error("Parse mismatch during operation.")]
|
#[error("Parse mismatch during operation.")]
|
||||||
#[diagnostic(code(nu::parser::parse_mismatch), url(docsrs))]
|
#[diagnostic(code(nu::parser::parse_mismatch), url(docsrs))]
|
||||||
Expected(String, #[label("expected {0}")] Span),
|
Expected(String, #[label("expected {0}")] Span),
|
||||||
|
@ -73,7 +69,7 @@ pub enum ParseError {
|
||||||
"'{0}' keyword is not allowed in pipeline. Use '{0}' by itself, outside of a pipeline."
|
"'{0}' keyword is not allowed in pipeline. Use '{0}' by itself, outside of a pipeline."
|
||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
StatementInPipeline(String, #[label("not allowed in pipeline")] Span),
|
BuiltinCommandInPipeline(String, #[label("not allowed in pipeline")] Span),
|
||||||
|
|
||||||
#[error("Incorrect value")]
|
#[error("Incorrect value")]
|
||||||
#[diagnostic(code(nu::parser::incorrect_value), url(docsrs), help("{2}"))]
|
#[diagnostic(code(nu::parser::incorrect_value), url(docsrs), help("{2}"))]
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use nu_protocol::ast::{
|
use nu_protocol::ast::{Block, Expr, Expression, ImportPatternMember, PathMember, Pipeline};
|
||||||
Block, Expr, Expression, ImportPatternMember, PathMember, Pipeline, Statement,
|
|
||||||
};
|
|
||||||
use nu_protocol::{engine::StateWorkingSet, Span};
|
use nu_protocol::{engine::StateWorkingSet, Span};
|
||||||
use std::fmt::{Display, Formatter, Result};
|
use std::fmt::{Display, Formatter, Result};
|
||||||
|
|
||||||
|
@ -63,22 +61,12 @@ impl Display for FlatShape {
|
||||||
|
|
||||||
pub fn flatten_block(working_set: &StateWorkingSet, block: &Block) -> Vec<(Span, FlatShape)> {
|
pub fn flatten_block(working_set: &StateWorkingSet, block: &Block) -> Vec<(Span, FlatShape)> {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
for stmt in &block.stmts {
|
for pipeline in &block.pipelines {
|
||||||
output.extend(flatten_statement(working_set, stmt));
|
output.extend(flatten_pipeline(working_set, pipeline));
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flatten_statement(
|
|
||||||
working_set: &StateWorkingSet,
|
|
||||||
stmt: &Statement,
|
|
||||||
) -> Vec<(Span, FlatShape)> {
|
|
||||||
match stmt {
|
|
||||||
Statement::Pipeline(pipeline) => flatten_pipeline(working_set, pipeline),
|
|
||||||
_ => vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flatten_expression(
|
pub fn flatten_expression(
|
||||||
working_set: &StateWorkingSet,
|
working_set: &StateWorkingSet,
|
||||||
expr: &Expression,
|
expr: &Expression,
|
||||||
|
|
|
@ -8,9 +8,7 @@ mod parser;
|
||||||
mod type_check;
|
mod type_check;
|
||||||
|
|
||||||
pub use errors::ParseError;
|
pub use errors::ParseError;
|
||||||
pub use flatten::{
|
pub use flatten::{flatten_block, flatten_expression, flatten_pipeline, FlatShape};
|
||||||
flatten_block, flatten_expression, flatten_pipeline, flatten_statement, FlatShape,
|
|
||||||
};
|
|
||||||
pub use known_external::KnownExternal;
|
pub use known_external::KnownExternal;
|
||||||
pub use lex::{lex, Token, TokenContents};
|
pub use lex::{lex, Token, TokenContents};
|
||||||
pub use lite_parse::{lite_parse, LiteBlock};
|
pub use lite_parse::{lite_parse, LiteBlock};
|
||||||
|
|
|
@ -31,17 +31,17 @@ impl LiteCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LiteStatement {
|
pub struct LitePipeline {
|
||||||
pub commands: Vec<LiteCommand>,
|
pub commands: Vec<LiteCommand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LiteStatement {
|
impl Default for LitePipeline {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiteStatement {
|
impl LitePipeline {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self { commands: vec![] }
|
Self { commands: vec![] }
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl LiteStatement {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LiteBlock {
|
pub struct LiteBlock {
|
||||||
pub block: Vec<LiteStatement>,
|
pub block: Vec<LitePipeline>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LiteBlock {
|
impl Default for LiteBlock {
|
||||||
|
@ -71,7 +71,7 @@ impl LiteBlock {
|
||||||
Self { block: vec![] }
|
Self { block: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, pipeline: LiteStatement) {
|
pub fn push(&mut self, pipeline: LitePipeline) {
|
||||||
self.block.push(pipeline);
|
self.block.push(pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ impl LiteBlock {
|
||||||
|
|
||||||
pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
|
pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
|
||||||
let mut block = LiteBlock::new();
|
let mut block = LiteBlock::new();
|
||||||
let mut curr_pipeline = LiteStatement::new();
|
let mut curr_pipeline = LitePipeline::new();
|
||||||
let mut curr_command = LiteCommand::new();
|
let mut curr_command = LiteCommand::new();
|
||||||
|
|
||||||
let mut last_token = TokenContents::Eol;
|
let mut last_token = TokenContents::Eol;
|
||||||
|
@ -117,7 +117,7 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
|
||||||
if !curr_pipeline.is_empty() {
|
if !curr_pipeline.is_empty() {
|
||||||
block.push(curr_pipeline);
|
block.push(curr_pipeline);
|
||||||
|
|
||||||
curr_pipeline = LiteStatement::new();
|
curr_pipeline = LitePipeline::new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
|
||||||
if !curr_pipeline.is_empty() {
|
if !curr_pipeline.is_empty() {
|
||||||
block.push(curr_pipeline);
|
block.push(curr_pipeline);
|
||||||
|
|
||||||
curr_pipeline = LiteStatement::new();
|
curr_pipeline = LitePipeline::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
last_token = TokenContents::Semicolon;
|
last_token = TokenContents::Semicolon;
|
||||||
|
|
|
@ -2,7 +2,7 @@ use nu_path::canonicalize_with;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{
|
ast::{
|
||||||
Block, Call, Expr, Expression, ImportPattern, ImportPatternHead, ImportPatternMember,
|
Block, Call, Expr, Expression, ImportPattern, ImportPatternHead, ImportPatternMember,
|
||||||
Pipeline, Statement,
|
Pipeline,
|
||||||
},
|
},
|
||||||
engine::StateWorkingSet,
|
engine::StateWorkingSet,
|
||||||
span, Exportable, Overlay, PositionalArg, Span, SyntaxShape, Type, CONFIG_VARIABLE_ID,
|
span, Exportable, Overlay, PositionalArg, Span, SyntaxShape, Type, CONFIG_VARIABLE_ID,
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
lex, lite_parse,
|
lex, lite_parse,
|
||||||
lite_parse::LiteCommand,
|
lite_parse::LiteCommand,
|
||||||
parser::{
|
parser::{
|
||||||
check_call, check_name, garbage, garbage_statement, parse, parse_block_expression,
|
check_call, check_name, garbage, garbage_pipeline, parse, parse_block_expression,
|
||||||
parse_internal_call, parse_multispan_value, parse_signature, parse_string,
|
parse_internal_call, parse_multispan_value, parse_signature, parse_string,
|
||||||
parse_var_with_opt_type, trim_quotes,
|
parse_var_with_opt_type, trim_quotes,
|
||||||
},
|
},
|
||||||
|
@ -245,7 +245,7 @@ fn build_usage(working_set: &StateWorkingSet, spans: &[Span]) -> String {
|
||||||
pub fn parse_def(
|
pub fn parse_def(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
lite_command: &LiteCommand,
|
lite_command: &LiteCommand,
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
let spans = &lite_command.parts[..];
|
let spans = &lite_command.parts[..];
|
||||||
|
|
||||||
let usage = build_usage(working_set, &lite_command.comments);
|
let usage = build_usage(working_set, &lite_command.comments);
|
||||||
|
@ -256,7 +256,7 @@ pub fn parse_def(
|
||||||
let def_call = working_set.get_span_contents(spans[0]).to_vec();
|
let def_call = working_set.get_span_contents(spans[0]).to_vec();
|
||||||
if def_call != b"def" && def_call != b"def-env" {
|
if def_call != b"def" && def_call != b"def-env" {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Wrong call name for def function".into(),
|
"internal error: Wrong call name for def function".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -270,7 +270,7 @@ pub fn parse_def(
|
||||||
let (call, call_span) = match working_set.find_decl(&def_call) {
|
let (call, call_span) = match working_set.find_decl(&def_call) {
|
||||||
None => {
|
None => {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: def declaration not found".into(),
|
"internal error: def declaration not found".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -308,12 +308,12 @@ pub fn parse_def(
|
||||||
err = check_call(call_span, &sig, &call).or(err);
|
err = check_call(call_span, &sig, &call).or(err);
|
||||||
if err.is_some() || call.has_flag("help") {
|
if err.is_some() || call.has_flag("help") {
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -365,12 +365,12 @@ pub fn parse_def(
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ pub fn parse_def(
|
||||||
pub fn parse_extern(
|
pub fn parse_extern(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
lite_command: &LiteCommand,
|
lite_command: &LiteCommand,
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
let spans = &lite_command.parts[..];
|
let spans = &lite_command.parts[..];
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
|
||||||
|
@ -390,7 +390,7 @@ pub fn parse_extern(
|
||||||
let extern_call = working_set.get_span_contents(spans[0]).to_vec();
|
let extern_call = working_set.get_span_contents(spans[0]).to_vec();
|
||||||
if extern_call != b"extern" {
|
if extern_call != b"extern" {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Wrong call name for extern function".into(),
|
"internal error: Wrong call name for extern function".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -404,7 +404,7 @@ pub fn parse_extern(
|
||||||
let (call, call_span) = match working_set.find_decl(&extern_call) {
|
let (call, call_span) = match working_set.find_decl(&extern_call) {
|
||||||
None => {
|
None => {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: def declaration not found".into(),
|
"internal error: def declaration not found".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -466,12 +466,12 @@ pub fn parse_extern(
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -479,15 +479,12 @@ pub fn parse_extern(
|
||||||
pub fn parse_alias(
|
pub fn parse_alias(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
let name = working_set.get_span_contents(spans[0]);
|
let name = working_set.get_span_contents(spans[0]);
|
||||||
|
|
||||||
if name == b"alias" {
|
if name == b"alias" {
|
||||||
if let Some((span, err)) = check_name(working_set, spans) {
|
if let Some((span, err)) = check_name(working_set, spans) {
|
||||||
return (
|
return (Pipeline::from_vec(vec![garbage(*span)]), Some(err));
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![garbage(*span)])),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(decl_id) = working_set.find_decl(b"alias") {
|
if let Some(decl_id) = working_set.find_decl(b"alias") {
|
||||||
|
@ -512,19 +509,19 @@ pub fn parse_alias(
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
"Alias statement unparseable".into(),
|
"Alias statement unparseable".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -535,14 +532,14 @@ pub fn parse_alias(
|
||||||
pub fn parse_export(
|
pub fn parse_export(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
lite_command: &LiteCommand,
|
lite_command: &LiteCommand,
|
||||||
) -> (Statement, Option<Exportable>, Option<ParseError>) {
|
) -> (Pipeline, Option<Exportable>, Option<ParseError>) {
|
||||||
let spans = &lite_command.parts[..];
|
let spans = &lite_command.parts[..];
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
|
|
||||||
let export_span = if let Some(sp) = spans.get(0) {
|
let export_span = if let Some(sp) = spans.get(0) {
|
||||||
if working_set.get_span_contents(*sp) != b"export" {
|
if working_set.get_span_contents(*sp) != b"export" {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
None,
|
None,
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"expected export statement".into(),
|
"expected export statement".into(),
|
||||||
|
@ -554,7 +551,7 @@ pub fn parse_export(
|
||||||
*sp
|
*sp
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
None,
|
None,
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"got empty input for parsing export statement".into(),
|
"got empty input for parsing export statement".into(),
|
||||||
|
@ -567,7 +564,7 @@ pub fn parse_export(
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
None,
|
None,
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
"missing export command".into(),
|
"missing export command".into(),
|
||||||
|
@ -591,14 +588,14 @@ pub fn parse_export(
|
||||||
comments: lite_command.comments.clone(),
|
comments: lite_command.comments.clone(),
|
||||||
parts: spans[1..].to_vec(),
|
parts: spans[1..].to_vec(),
|
||||||
};
|
};
|
||||||
let (stmt, err) = parse_def(working_set, &lite_command);
|
let (pipeline, err) = parse_def(working_set, &lite_command);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let export_def_decl_id = if let Some(id) = working_set.find_decl(b"export def") {
|
let export_def_decl_id = if let Some(id) = working_set.find_decl(b"export def") {
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
None,
|
None,
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
"missing 'export def' command".into(),
|
"missing 'export def' command".into(),
|
||||||
|
@ -608,24 +605,15 @@ pub fn parse_export(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Trying to warp the 'def' call into the 'export def' in a very clumsy way
|
// Trying to warp the 'def' call into the 'export def' in a very clumsy way
|
||||||
if let Statement::Pipeline(ref pipe) = stmt {
|
if let Some(Expression {
|
||||||
if let Some(Expression {
|
expr: Expr::Call(ref def_call),
|
||||||
expr: Expr::Call(ref def_call),
|
..
|
||||||
..
|
}) = pipeline.expressions.get(0)
|
||||||
}) = pipe.expressions.get(0)
|
{
|
||||||
{
|
call = def_call.clone();
|
||||||
call = def_call.clone();
|
|
||||||
|
|
||||||
call.head = span(&spans[0..=1]);
|
call.head = span(&spans[0..=1]);
|
||||||
call.decl_id = export_def_decl_id;
|
call.decl_id = export_def_decl_id;
|
||||||
} else {
|
|
||||||
error = error.or_else(|| {
|
|
||||||
Some(ParseError::InternalError(
|
|
||||||
"unexpected output from parsing a definition".into(),
|
|
||||||
span(&spans[1..]),
|
|
||||||
))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
|
@ -658,7 +646,7 @@ pub fn parse_export(
|
||||||
comments: lite_command.comments.clone(),
|
comments: lite_command.comments.clone(),
|
||||||
parts: spans[1..].to_vec(),
|
parts: spans[1..].to_vec(),
|
||||||
};
|
};
|
||||||
let (stmt, err) = parse_def(working_set, &lite_command);
|
let (pipeline, err) = parse_def(working_set, &lite_command);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let export_def_decl_id = if let Some(id) = working_set.find_decl(b"export def-env")
|
let export_def_decl_id = if let Some(id) = working_set.find_decl(b"export def-env")
|
||||||
|
@ -666,7 +654,7 @@ pub fn parse_export(
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
None,
|
None,
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
"missing 'export def-env' command".into(),
|
"missing 'export def-env' command".into(),
|
||||||
|
@ -676,24 +664,15 @@ pub fn parse_export(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Trying to warp the 'def' call into the 'export def' in a very clumsy way
|
// Trying to warp the 'def' call into the 'export def' in a very clumsy way
|
||||||
if let Statement::Pipeline(ref pipe) = stmt {
|
if let Some(Expression {
|
||||||
if let Some(Expression {
|
expr: Expr::Call(ref def_call),
|
||||||
expr: Expr::Call(ref def_call),
|
..
|
||||||
..
|
}) = pipeline.expressions.get(0)
|
||||||
}) = pipe.expressions.get(0)
|
{
|
||||||
{
|
call = def_call.clone();
|
||||||
call = def_call.clone();
|
|
||||||
|
|
||||||
call.head = span(&spans[0..=1]);
|
call.head = span(&spans[0..=1]);
|
||||||
call.decl_id = export_def_decl_id;
|
call.decl_id = export_def_decl_id;
|
||||||
} else {
|
|
||||||
error = error.or_else(|| {
|
|
||||||
Some(ParseError::InternalError(
|
|
||||||
"unexpected output from parsing a definition".into(),
|
|
||||||
span(&spans[1..]),
|
|
||||||
))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| {
|
error = error.or_else(|| {
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
|
@ -726,7 +705,7 @@ pub fn parse_export(
|
||||||
call.decl_id = id;
|
call.decl_id = id;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
None,
|
None,
|
||||||
Some(ParseError::InternalError(
|
Some(ParseError::InternalError(
|
||||||
"missing 'export env' command".into(),
|
"missing 'export env' command".into(),
|
||||||
|
@ -833,12 +812,12 @@ pub fn parse_export(
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
exportable,
|
exportable,
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
|
@ -876,16 +855,16 @@ pub fn parse_module_block(
|
||||||
if pipeline.commands.len() == 1 {
|
if pipeline.commands.len() == 1 {
|
||||||
let name = working_set.get_span_contents(pipeline.commands[0].parts[0]);
|
let name = working_set.get_span_contents(pipeline.commands[0].parts[0]);
|
||||||
|
|
||||||
let (stmt, err) = match name {
|
let (pipeline, err) = match name {
|
||||||
b"def" | b"def-env" => {
|
b"def" | b"def-env" => {
|
||||||
let (stmt, err) = parse_def(working_set, &pipeline.commands[0]);
|
let (pipeline, err) = parse_def(working_set, &pipeline.commands[0]);
|
||||||
|
|
||||||
(stmt, err)
|
(pipeline, err)
|
||||||
}
|
}
|
||||||
b"extern" => {
|
b"extern" => {
|
||||||
let (stmt, err) = parse_extern(working_set, &pipeline.commands[0]);
|
let (pipeline, err) = parse_extern(working_set, &pipeline.commands[0]);
|
||||||
|
|
||||||
(stmt, err)
|
(pipeline, err)
|
||||||
}
|
}
|
||||||
// TODO: Currently, it is not possible to define a private env var.
|
// TODO: Currently, it is not possible to define a private env var.
|
||||||
// TODO: Exported env vars are usable iside the module only if correctly
|
// TODO: Exported env vars are usable iside the module only if correctly
|
||||||
|
@ -896,7 +875,7 @@ pub fn parse_module_block(
|
||||||
// will work only if you call `use foo *; b` but not with `use foo; foo b`
|
// will work only if you call `use foo *; b` but not with `use foo; foo b`
|
||||||
// since in the second case, the name of the env var would be $env."foo a".
|
// since in the second case, the name of the env var would be $env."foo a".
|
||||||
b"export" => {
|
b"export" => {
|
||||||
let (stmt, exportable, err) =
|
let (pipe, exportable, err) =
|
||||||
parse_export(working_set, &pipeline.commands[0]);
|
parse_export(working_set, &pipeline.commands[0]);
|
||||||
|
|
||||||
if err.is_none() {
|
if err.is_none() {
|
||||||
|
@ -915,10 +894,10 @@ pub fn parse_module_block(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(stmt, err)
|
(pipe, err)
|
||||||
}
|
}
|
||||||
_ => (
|
_ => (
|
||||||
garbage_statement(&pipeline.commands[0].parts),
|
garbage_pipeline(&pipeline.commands[0].parts),
|
||||||
Some(ParseError::UnexpectedKeyword(
|
Some(ParseError::UnexpectedKeyword(
|
||||||
"expected def or export keyword".into(),
|
"expected def or export keyword".into(),
|
||||||
pipeline.commands[0].parts[0],
|
pipeline.commands[0].parts[0],
|
||||||
|
@ -930,10 +909,10 @@ pub fn parse_module_block(
|
||||||
error = err;
|
error = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt
|
pipeline
|
||||||
} else {
|
} else {
|
||||||
error = Some(ParseError::Expected("not a pipeline".into(), span));
|
error = Some(ParseError::Expected("not a pipeline".into(), span));
|
||||||
garbage_statement(&[span])
|
garbage_pipeline(&[span])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.into();
|
.into();
|
||||||
|
@ -946,7 +925,7 @@ pub fn parse_module_block(
|
||||||
pub fn parse_module(
|
pub fn parse_module(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
// TODO: Currently, module is closing over its parent scope (i.e., defs in the parent scope are
|
// TODO: Currently, module is closing over its parent scope (i.e., defs in the parent scope are
|
||||||
// visible and usable in this module's scope). We want to disable that for files.
|
// visible and usable in this module's scope). We want to disable that for files.
|
||||||
|
|
||||||
|
@ -970,7 +949,7 @@ pub fn parse_module(
|
||||||
start += 1;
|
start += 1;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::Expected("block".into(), block_span)),
|
Some(ParseError::Expected("block".into(), block_span)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1009,17 +988,17 @@ pub fn parse_module(
|
||||||
});
|
});
|
||||||
|
|
||||||
(
|
(
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"Expected structure: module <name> {}".into(),
|
"Expected structure: module <name> {}".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1031,10 +1010,10 @@ pub fn parse_module(
|
||||||
pub fn parse_use(
|
pub fn parse_use(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
if working_set.get_span_contents(spans[0]) != b"use" {
|
if working_set.get_span_contents(spans[0]) != b"use" {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Wrong call name for 'use' command".into(),
|
"internal error: Wrong call name for 'use' command".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1052,12 +1031,12 @@ pub fn parse_use(
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
err = check_call(call_span, &decl.signature(), &call).or(err);
|
||||||
if err.is_some() || call.has_flag("help") {
|
if err.is_some() || call.has_flag("help") {
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1066,7 +1045,7 @@ pub fn parse_use(
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: 'use' declaration not found".into(),
|
"internal error: 'use' declaration not found".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1080,7 +1059,7 @@ pub fn parse_use(
|
||||||
pattern
|
pattern
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Import pattern positional is not import pattern".into(),
|
"internal error: Import pattern positional is not import pattern".into(),
|
||||||
call_span,
|
call_span,
|
||||||
|
@ -1089,7 +1068,7 @@ pub fn parse_use(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Missing required positional after call parsing".into(),
|
"internal error: Missing required positional after call parsing".into(),
|
||||||
call_span,
|
call_span,
|
||||||
|
@ -1117,12 +1096,12 @@ pub fn parse_use(
|
||||||
stem.to_string_lossy().to_string()
|
stem.to_string_lossy().to_string()
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
Some(ParseError::ModuleNotFound(spans[1])),
|
Some(ParseError::ModuleNotFound(spans[1])),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1152,12 +1131,12 @@ pub fn parse_use(
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
Some(ParseError::ModuleNotFound(spans[1])),
|
Some(ParseError::ModuleNotFound(spans[1])),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1169,10 +1148,7 @@ pub fn parse_use(
|
||||||
(ImportPattern::new(), Overlay::new())
|
(ImportPattern::new(), Overlay::new())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (garbage_pipeline(spans), Some(ParseError::NonUtf8(spans[1])));
|
||||||
garbage_statement(spans),
|
|
||||||
Some(ParseError::NonUtf8(spans[1])),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1228,12 +1204,12 @@ pub fn parse_use(
|
||||||
});
|
});
|
||||||
|
|
||||||
(
|
(
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1241,10 +1217,10 @@ pub fn parse_use(
|
||||||
pub fn parse_hide(
|
pub fn parse_hide(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
if working_set.get_span_contents(spans[0]) != b"hide" {
|
if working_set.get_span_contents(spans[0]) != b"hide" {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Wrong call name for 'hide' command".into(),
|
"internal error: Wrong call name for 'hide' command".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1262,12 +1238,12 @@ pub fn parse_hide(
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
err = check_call(call_span, &decl.signature(), &call).or(err);
|
||||||
if err.is_some() || call.has_flag("help") {
|
if err.is_some() || call.has_flag("help") {
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1276,7 +1252,7 @@ pub fn parse_hide(
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: 'hide' declaration not found".into(),
|
"internal error: 'hide' declaration not found".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1290,7 +1266,7 @@ pub fn parse_hide(
|
||||||
pattern
|
pattern
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Import pattern positional is not import pattern".into(),
|
"internal error: Import pattern positional is not import pattern".into(),
|
||||||
call_span,
|
call_span,
|
||||||
|
@ -1299,7 +1275,7 @@ pub fn parse_hide(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Missing required positional after call parsing".into(),
|
"internal error: Missing required positional after call parsing".into(),
|
||||||
call_span,
|
call_span,
|
||||||
|
@ -1339,7 +1315,7 @@ pub fn parse_hide(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::ModuleNotFound(spans[1])),
|
Some(ParseError::ModuleNotFound(spans[1])),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1427,17 +1403,17 @@ pub fn parse_hide(
|
||||||
});
|
});
|
||||||
|
|
||||||
(
|
(
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"Expected structure: hide <name>".into(),
|
"Expected structure: hide <name>".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1449,15 +1425,12 @@ pub fn parse_hide(
|
||||||
pub fn parse_let(
|
pub fn parse_let(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
let name = working_set.get_span_contents(spans[0]);
|
let name = working_set.get_span_contents(spans[0]);
|
||||||
|
|
||||||
if name == b"let" {
|
if name == b"let" {
|
||||||
if let Some((span, err)) = check_name(working_set, spans) {
|
if let Some((span, err)) = check_name(working_set, spans) {
|
||||||
return (
|
return (Pipeline::from_vec(vec![garbage(*span)]), Some(err));
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![garbage(*span)])),
|
|
||||||
Some(err),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(decl_id) = working_set.find_decl(b"let") {
|
if let Some(decl_id) = working_set.find_decl(b"let") {
|
||||||
|
@ -1511,12 +1484,12 @@ pub fn parse_let(
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: nu_protocol::span(spans),
|
span: nu_protocol::span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1525,20 +1498,20 @@ pub fn parse_let(
|
||||||
let (call, err) = parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
|
let (call, err) = parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline {
|
Pipeline {
|
||||||
expressions: vec![Expression {
|
expressions: vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: nu_protocol::span(spans),
|
span: nu_protocol::span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}],
|
}],
|
||||||
}),
|
},
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: let statement unparseable".into(),
|
"internal error: let statement unparseable".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1549,7 +1522,7 @@ pub fn parse_let(
|
||||||
pub fn parse_source(
|
pub fn parse_source(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
let mut error = None;
|
let mut error = None;
|
||||||
let name = working_set.get_span_contents(spans[0]);
|
let name = working_set.get_span_contents(spans[0]);
|
||||||
|
|
||||||
|
@ -1580,12 +1553,12 @@ pub fn parse_source(
|
||||||
if err.is_some() {
|
if err.is_some() {
|
||||||
// Unsuccessful parse of file
|
// Unsuccessful parse of file
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(&spans[1..]),
|
span: span(&spans[1..]),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
// Return the file parse error
|
// Return the file parse error
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
|
@ -1605,12 +1578,12 @@ pub fn parse_source(
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call_with_block),
|
expr: Expr::Call(call_with_block),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1619,25 +1592,22 @@ pub fn parse_source(
|
||||||
error = error.or(Some(ParseError::FileNotFound(filename, spans[1])));
|
error = error.or(Some(ParseError::FileNotFound(filename, spans[1])));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (garbage_pipeline(spans), Some(ParseError::NonUtf8(spans[1])));
|
||||||
garbage_statement(spans),
|
|
||||||
Some(ParseError::NonUtf8(spans[1])),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: span(spans),
|
span: span(spans),
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: source statement unparseable".into(),
|
"internal error: source statement unparseable".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1649,7 +1619,7 @@ pub fn parse_source(
|
||||||
pub fn parse_register(
|
pub fn parse_register(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
use nu_plugin::{get_signature, EncodingType, PluginDeclaration};
|
use nu_plugin::{get_signature, EncodingType, PluginDeclaration};
|
||||||
use nu_protocol::Signature;
|
use nu_protocol::Signature;
|
||||||
let cwd = working_set.get_cwd();
|
let cwd = working_set.get_cwd();
|
||||||
|
@ -1658,7 +1628,7 @@ pub fn parse_register(
|
||||||
// Maybe this is not necessary but it is a sanity check
|
// Maybe this is not necessary but it is a sanity check
|
||||||
if working_set.get_span_contents(spans[0]) != b"register" {
|
if working_set.get_span_contents(spans[0]) != b"register" {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Wrong call name for parse plugin function".into(),
|
"internal error: Wrong call name for parse plugin function".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1672,7 +1642,7 @@ pub fn parse_register(
|
||||||
let (call, call_span) = match working_set.find_decl(b"register") {
|
let (call, call_span) = match working_set.find_decl(b"register") {
|
||||||
None => {
|
None => {
|
||||||
return (
|
return (
|
||||||
garbage_statement(spans),
|
garbage_pipeline(spans),
|
||||||
Some(ParseError::UnknownState(
|
Some(ParseError::UnknownState(
|
||||||
"internal error: Register declaration not found".into(),
|
"internal error: Register declaration not found".into(),
|
||||||
span(spans),
|
span(spans),
|
||||||
|
@ -1688,12 +1658,12 @@ pub fn parse_register(
|
||||||
err = check_call(call_span, &decl.signature(), &call).or(err);
|
err = check_call(call_span, &decl.signature(), &call).or(err);
|
||||||
if err.is_some() || call.has_flag("help") {
|
if err.is_some() || call.has_flag("help") {
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1779,12 +1749,12 @@ pub fn parse_register(
|
||||||
Ok(path) => Some(path),
|
Ok(path) => Some(path),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return (
|
return (
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Unknown,
|
ty: Type::Unknown,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
Some(err),
|
Some(err),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1829,12 +1799,12 @@ pub fn parse_register(
|
||||||
.err();
|
.err();
|
||||||
|
|
||||||
(
|
(
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
|
Pipeline::from_vec(vec![Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
span: call_span,
|
span: call_span,
|
||||||
ty: Type::Nothing,
|
ty: Type::Nothing,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
}])),
|
}]),
|
||||||
error,
|
error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use nu_protocol::{
|
||||||
ast::{
|
ast::{
|
||||||
Block, Call, CellPath, Expr, Expression, FullCellPath, ImportPattern, ImportPatternHead,
|
Block, Call, CellPath, Expr, Expression, FullCellPath, ImportPattern, ImportPatternHead,
|
||||||
ImportPatternMember, Operator, PathMember, Pipeline, RangeInclusion, RangeOperator,
|
ImportPatternMember, Operator, PathMember, Pipeline, RangeInclusion, RangeOperator,
|
||||||
Statement,
|
|
||||||
},
|
},
|
||||||
engine::StateWorkingSet,
|
engine::StateWorkingSet,
|
||||||
span, BlockId, Flag, PositionalArg, Signature, Span, Spanned, SyntaxShape, Type, Unit, VarId,
|
span, BlockId, Flag, PositionalArg, Signature, Span, Spanned, SyntaxShape, Type, Unit, VarId,
|
||||||
|
@ -34,8 +33,8 @@ pub fn garbage(span: Span) -> Expression {
|
||||||
Expression::garbage(span)
|
Expression::garbage(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn garbage_statement(spans: &[Span]) -> Statement {
|
pub fn garbage_pipeline(spans: &[Span]) -> Pipeline {
|
||||||
Statement::Pipeline(Pipeline::from_vec(vec![garbage(span(spans))]))
|
Pipeline::from_vec(vec![garbage(span(spans))])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_identifier_byte(b: u8) -> bool {
|
fn is_identifier_byte(b: u8) -> bool {
|
||||||
|
@ -2293,7 +2292,7 @@ pub fn parse_row_condition(
|
||||||
let mut pipeline = Pipeline::new();
|
let mut pipeline = Pipeline::new();
|
||||||
pipeline.expressions.push(expression);
|
pipeline.expressions.push(expression);
|
||||||
|
|
||||||
block.stmts.push(Statement::Pipeline(pipeline));
|
block.pipelines.push(pipeline);
|
||||||
|
|
||||||
block.signature.required_positional.push(PositionalArg {
|
block.signature.required_positional.push(PositionalArg {
|
||||||
name: "$it".into(),
|
name: "$it".into(),
|
||||||
|
@ -3413,31 +3412,43 @@ pub fn parse_expression(
|
||||||
match bytes {
|
match bytes {
|
||||||
b"def" => (
|
b"def" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("def".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline("def".into(), spans[0])),
|
||||||
),
|
),
|
||||||
b"extern" => (
|
b"extern" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("extern".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline(
|
||||||
|
"extern".into(),
|
||||||
|
spans[0],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
b"let" => (
|
b"let" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("let".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline("let".into(), spans[0])),
|
||||||
),
|
),
|
||||||
b"alias" => (
|
b"alias" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("alias".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline(
|
||||||
|
"alias".into(),
|
||||||
|
spans[0],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
b"module" => (
|
b"module" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("module".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline(
|
||||||
|
"module".into(),
|
||||||
|
spans[0],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
b"use" => (
|
b"use" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("use".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline("use".into(), spans[0])),
|
||||||
),
|
),
|
||||||
b"source" => (
|
b"source" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("source".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline(
|
||||||
|
"source".into(),
|
||||||
|
spans[0],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
b"export" => (
|
b"export" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
|
@ -3445,12 +3456,18 @@ pub fn parse_expression(
|
||||||
),
|
),
|
||||||
b"hide" => (
|
b"hide" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("hide".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline(
|
||||||
|
"hide".into(),
|
||||||
|
spans[0],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
b"register" => (
|
b"register" => (
|
||||||
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
|
||||||
Some(ParseError::StatementInPipeline("plugin".into(), spans[0])),
|
Some(ParseError::BuiltinCommandInPipeline(
|
||||||
|
"plugin".into(),
|
||||||
|
spans[0],
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
|
|
||||||
b"for" => parse_for(working_set, spans),
|
b"for" => parse_for(working_set, spans),
|
||||||
|
@ -3464,9 +3481,9 @@ pub fn parse_expression(
|
||||||
if let Some(decl_id) = with_env {
|
if let Some(decl_id) = with_env {
|
||||||
let mut block = Block::default();
|
let mut block = Block::default();
|
||||||
let ty = output.ty.clone();
|
let ty = output.ty.clone();
|
||||||
block.stmts = vec![Statement::Pipeline(Pipeline {
|
block.pipelines = vec![Pipeline {
|
||||||
expressions: vec![output],
|
expressions: vec![output],
|
||||||
})];
|
}];
|
||||||
|
|
||||||
let block_id = working_set.add_block(block);
|
let block_id = working_set.add_block(block);
|
||||||
|
|
||||||
|
@ -3530,10 +3547,10 @@ pub fn parse_variable(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_statement(
|
pub fn parse_builtin_commands(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
lite_command: &LiteCommand,
|
lite_command: &LiteCommand,
|
||||||
) -> (Statement, Option<ParseError>) {
|
) -> (Pipeline, Option<ParseError>) {
|
||||||
let name = working_set.get_span_contents(lite_command.parts[0]);
|
let name = working_set.get_span_contents(lite_command.parts[0]);
|
||||||
|
|
||||||
match name {
|
match name {
|
||||||
|
@ -3542,14 +3559,14 @@ pub fn parse_statement(
|
||||||
b"let" => parse_let(working_set, &lite_command.parts),
|
b"let" => parse_let(working_set, &lite_command.parts),
|
||||||
b"for" => {
|
b"for" => {
|
||||||
let (expr, err) = parse_for(working_set, &lite_command.parts);
|
let (expr, err) = parse_for(working_set, &lite_command.parts);
|
||||||
(Statement::Pipeline(Pipeline::from_vec(vec![expr])), err)
|
(Pipeline::from_vec(vec![expr]), err)
|
||||||
}
|
}
|
||||||
b"alias" => parse_alias(working_set, &lite_command.parts),
|
b"alias" => parse_alias(working_set, &lite_command.parts),
|
||||||
b"module" => parse_module(working_set, &lite_command.parts),
|
b"module" => parse_module(working_set, &lite_command.parts),
|
||||||
b"use" => parse_use(working_set, &lite_command.parts),
|
b"use" => parse_use(working_set, &lite_command.parts),
|
||||||
b"source" => parse_source(working_set, &lite_command.parts),
|
b"source" => parse_source(working_set, &lite_command.parts),
|
||||||
b"export" => (
|
b"export" => (
|
||||||
garbage_statement(&lite_command.parts),
|
garbage_pipeline(&lite_command.parts),
|
||||||
Some(ParseError::UnexpectedKeyword(
|
Some(ParseError::UnexpectedKeyword(
|
||||||
"export".into(),
|
"export".into(),
|
||||||
lite_command.parts[0],
|
lite_command.parts[0],
|
||||||
|
@ -3560,7 +3577,7 @@ pub fn parse_statement(
|
||||||
b"register" => parse_register(working_set, &lite_command.parts),
|
b"register" => parse_register(working_set, &lite_command.parts),
|
||||||
_ => {
|
_ => {
|
||||||
let (expr, err) = parse_expression(working_set, &lite_command.parts, true);
|
let (expr, err) = parse_expression(working_set, &lite_command.parts, true);
|
||||||
(Statement::Pipeline(Pipeline::from_vec(vec![expr])), err)
|
(Pipeline::from_vec(vec![expr]), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3691,40 +3708,39 @@ pub fn parse_block(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement::Pipeline(Pipeline {
|
Pipeline {
|
||||||
expressions: output,
|
expressions: output,
|
||||||
})
|
}
|
||||||
} else {
|
} else {
|
||||||
let (mut stmt, err) = parse_statement(working_set, &pipeline.commands[0]);
|
let (mut pipeline, err) =
|
||||||
|
parse_builtin_commands(working_set, &pipeline.commands[0]);
|
||||||
|
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
if let Some(let_decl_id) = working_set.find_decl(b"let") {
|
if let Some(let_decl_id) = working_set.find_decl(b"let") {
|
||||||
if let Some(let_env_decl_id) = working_set.find_decl(b"let-env") {
|
if let Some(let_env_decl_id) = working_set.find_decl(b"let-env") {
|
||||||
if let Statement::Pipeline(pipeline) = &mut stmt {
|
for expr in pipeline.expressions.iter_mut() {
|
||||||
for expr in pipeline.expressions.iter_mut() {
|
if let Expression {
|
||||||
if let Expression {
|
expr: Expr::Call(call),
|
||||||
expr: Expr::Call(call),
|
..
|
||||||
..
|
} = expr
|
||||||
} = expr
|
{
|
||||||
|
if call.decl_id == let_decl_id
|
||||||
|
|| call.decl_id == let_env_decl_id
|
||||||
{
|
{
|
||||||
if call.decl_id == let_decl_id
|
// Do an expansion
|
||||||
|| call.decl_id == let_env_decl_id
|
if let Some(Expression {
|
||||||
|
expr: Expr::Keyword(_, _, expr),
|
||||||
|
..
|
||||||
|
}) = call.positional.get_mut(1)
|
||||||
{
|
{
|
||||||
// Do an expansion
|
if expr.has_in_variable(working_set) {
|
||||||
if let Some(Expression {
|
*expr = Box::new(wrap_expr_with_collect(
|
||||||
expr: Expr::Keyword(_, _, expr),
|
working_set,
|
||||||
..
|
expr,
|
||||||
}) = call.positional.get_mut(1)
|
));
|
||||||
{
|
|
||||||
if expr.has_in_variable(working_set) {
|
|
||||||
*expr = Box::new(wrap_expr_with_collect(
|
|
||||||
working_set,
|
|
||||||
expr,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3736,7 +3752,7 @@ pub fn parse_block(
|
||||||
error = err;
|
error = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt
|
pipeline
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.into();
|
.into();
|
||||||
|
@ -3778,15 +3794,9 @@ pub fn discover_captures_in_block(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for stmt in &block.stmts {
|
for pipeline in &block.pipelines {
|
||||||
match stmt {
|
let result = discover_captures_in_pipeline(working_set, pipeline, seen, seen_blocks);
|
||||||
Statement::Pipeline(pipeline) => {
|
output.extend(&result);
|
||||||
let result =
|
|
||||||
discover_captures_in_pipeline(working_set, pipeline, seen, seen_blocks);
|
|
||||||
output.extend(&result);
|
|
||||||
}
|
|
||||||
Statement::Declaration(_) => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
|
@ -4028,9 +4038,9 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
|
||||||
expr.replace_in_variable(working_set, var_id);
|
expr.replace_in_variable(working_set, var_id);
|
||||||
|
|
||||||
let block = Block {
|
let block = Block {
|
||||||
stmts: vec![Statement::Pipeline(Pipeline {
|
pipelines: vec![Pipeline {
|
||||||
expressions: vec![expr],
|
expressions: vec![expr],
|
||||||
})],
|
}],
|
||||||
signature: Box::new(signature),
|
signature: Box::new(signature),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
|
@ -109,7 +109,7 @@ fn separated_comments_dont_stack() -> Result<(), ParseError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multiple_statements() -> Result<(), ParseError> {
|
fn multiple_pipelines() -> Result<(), ParseError> {
|
||||||
// Code:
|
// Code:
|
||||||
// # A comment
|
// # A comment
|
||||||
// let a = ( 3 + (
|
// let a = ( 3 + (
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use nu_parser::ParseError;
|
use nu_parser::ParseError;
|
||||||
use nu_parser::*;
|
use nu_parser::*;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Expr, Expression, Pipeline, Statement},
|
ast::{Expr, Expression},
|
||||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||||
Signature, SyntaxShape,
|
Signature, SyntaxShape,
|
||||||
};
|
};
|
||||||
|
@ -50,19 +50,15 @@ pub fn parse_int() {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
let expressions = &block[0];
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
assert!(expressions.len() == 1);
|
||||||
assert!(expressions.len() == 1);
|
assert!(matches!(
|
||||||
assert!(matches!(
|
expressions[0],
|
||||||
expressions[0],
|
Expression {
|
||||||
Expression {
|
expr: Expr::Int(3),
|
||||||
expr: Expr::Int(3),
|
..
|
||||||
..
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -78,19 +74,15 @@ pub fn parse_call() {
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
|
|
||||||
match &block[0] {
|
let expressions = &block[0];
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
assert_eq!(expressions.len(), 1);
|
||||||
assert_eq!(expressions.len(), 1);
|
|
||||||
|
|
||||||
if let Expression {
|
if let Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
..
|
..
|
||||||
} = &expressions[0]
|
} = &expressions[0]
|
||||||
{
|
{
|
||||||
assert_eq!(call.decl_id, 0);
|
assert_eq!(call.decl_id, 0);
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("not a call"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,19 +178,16 @@ fn test_nothing_comparisson_eq() {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
&expressions[0],
|
&expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::BinaryOp(..),
|
expr: Expr::BinaryOp(..),
|
||||||
..
|
..
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -209,19 +198,16 @@ fn test_nothing_comparisson_neq() {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
&expressions[0],
|
&expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::BinaryOp(..),
|
expr: Expr::BinaryOp(..),
|
||||||
..
|
..
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod range {
|
mod range {
|
||||||
|
@ -237,27 +223,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -269,27 +252,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::RightExclusive,
|
inclusion: RangeInclusion::RightExclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -301,27 +281,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -333,27 +310,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::RightExclusive,
|
inclusion: RangeInclusion::RightExclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -367,27 +341,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 2);
|
assert!(block.len() == 2);
|
||||||
match &block[1] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[1];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -401,27 +372,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 2);
|
assert!(block.len() == 2);
|
||||||
match &block[1] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[1];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::RightExclusive,
|
inclusion: RangeInclusion::RightExclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -433,27 +401,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -465,27 +430,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -497,27 +459,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
None,
|
None,
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -529,27 +488,24 @@ mod range {
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(block.len() == 1);
|
assert!(block.len() == 1);
|
||||||
match &block[0] {
|
|
||||||
Statement::Pipeline(Pipeline { expressions }) => {
|
let expressions = &block[0];
|
||||||
assert!(expressions.len() == 1);
|
assert!(expressions.len() == 1);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
expressions[0],
|
expressions[0],
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Range(
|
expr: Expr::Range(
|
||||||
Some(_),
|
Some(_),
|
||||||
Some(_),
|
Some(_),
|
||||||
Some(_),
|
Some(_),
|
||||||
RangeOperator {
|
RangeOperator {
|
||||||
inclusion: RangeInclusion::Inclusive,
|
inclusion: RangeInclusion::Inclusive,
|
||||||
..
|
|
||||||
}
|
|
||||||
),
|
|
||||||
..
|
..
|
||||||
}
|
}
|
||||||
))
|
),
|
||||||
|
..
|
||||||
}
|
}
|
||||||
_ => panic!("No match"),
|
))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -2,12 +2,12 @@ use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
use crate::{Signature, Span, VarId};
|
use crate::{Signature, Span, VarId};
|
||||||
|
|
||||||
use super::Statement;
|
use super::Pipeline;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
pub signature: Box<Signature>,
|
pub signature: Box<Signature>,
|
||||||
pub stmts: Vec<Statement>,
|
pub pipelines: Vec<Pipeline>,
|
||||||
pub captures: Vec<VarId>,
|
pub captures: Vec<VarId>,
|
||||||
pub redirect_env: bool,
|
pub redirect_env: bool,
|
||||||
pub span: Option<Span>, // None option encodes no span to avoid using test_span()
|
pub span: Option<Span>, // None option encodes no span to avoid using test_span()
|
||||||
|
@ -15,25 +15,25 @@ pub struct Block {
|
||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.stmts.len()
|
self.pipelines.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.stmts.is_empty()
|
self.pipelines.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for Block {
|
impl Index<usize> for Block {
|
||||||
type Output = Statement;
|
type Output = Pipeline;
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
&self.stmts[index]
|
&self.pipelines[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<usize> for Block {
|
impl IndexMut<usize> for Block {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
&mut self.stmts[index]
|
&mut self.pipelines[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ impl Block {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
signature: Box::new(Signature::new("")),
|
signature: Box::new(Signature::new("")),
|
||||||
stmts: vec![],
|
pipelines: vec![],
|
||||||
captures: vec![],
|
captures: vec![],
|
||||||
redirect_env: false,
|
redirect_env: false,
|
||||||
span: None,
|
span: None,
|
||||||
|
@ -57,12 +57,12 @@ impl Block {
|
||||||
|
|
||||||
impl<T> From<T> for Block
|
impl<T> From<T> for Block
|
||||||
where
|
where
|
||||||
T: Iterator<Item = Statement>,
|
T: Iterator<Item = Pipeline>,
|
||||||
{
|
{
|
||||||
fn from(stmts: T) -> Self {
|
fn from(pipelines: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
signature: Box::new(Signature::new("")),
|
signature: Box::new(Signature::new("")),
|
||||||
stmts: stmts.collect(),
|
pipelines: pipelines.collect(),
|
||||||
captures: vec![],
|
captures: vec![],
|
||||||
redirect_env: false,
|
redirect_env: false,
|
||||||
span: None,
|
span: None,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{Expr, Operator, Statement};
|
use super::{Expr, Operator};
|
||||||
use crate::ast::ImportPattern;
|
use crate::ast::ImportPattern;
|
||||||
use crate::{engine::StateWorkingSet, BlockId, Signature, Span, Type, VarId, IN_VARIABLE_ID};
|
use crate::{engine::StateWorkingSet, BlockId, Signature, Span, Type, VarId, IN_VARIABLE_ID};
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ impl Expression {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {
|
if let Some(pipeline) = block.pipelines.get(0) {
|
||||||
match pipeline.expressions.get(0) {
|
match pipeline.expressions.get(0) {
|
||||||
Some(expr) => expr.has_in_variable(working_set),
|
Some(expr) => expr.has_in_variable(working_set),
|
||||||
None => false,
|
None => false,
|
||||||
|
@ -218,7 +218,7 @@ impl Expression {
|
||||||
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
||||||
let block = working_set.get_block(*block_id);
|
let block = working_set.get_block(*block_id);
|
||||||
|
|
||||||
if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {
|
if let Some(pipeline) = block.pipelines.get(0) {
|
||||||
if let Some(expr) = pipeline.expressions.get(0) {
|
if let Some(expr) = pipeline.expressions.get(0) {
|
||||||
expr.has_in_variable(working_set)
|
expr.has_in_variable(working_set)
|
||||||
} else {
|
} else {
|
||||||
|
@ -261,7 +261,7 @@ impl Expression {
|
||||||
Expr::Block(block_id) => {
|
Expr::Block(block_id) => {
|
||||||
let block = working_set.get_block(*block_id);
|
let block = working_set.get_block(*block_id);
|
||||||
|
|
||||||
let new_expr = if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {
|
let new_expr = if let Some(pipeline) = block.pipelines.get(0) {
|
||||||
if let Some(expr) = pipeline.expressions.get(0) {
|
if let Some(expr) = pipeline.expressions.get(0) {
|
||||||
let mut new_expr = expr.clone();
|
let mut new_expr = expr.clone();
|
||||||
new_expr.replace_in_variable(working_set, new_var_id);
|
new_expr.replace_in_variable(working_set, new_var_id);
|
||||||
|
@ -276,7 +276,7 @@ impl Expression {
|
||||||
let block = working_set.get_block_mut(*block_id);
|
let block = working_set.get_block_mut(*block_id);
|
||||||
|
|
||||||
if let Some(new_expr) = new_expr {
|
if let Some(new_expr) = new_expr {
|
||||||
if let Some(Statement::Pipeline(pipeline)) = block.stmts.get_mut(0) {
|
if let Some(pipeline) = block.pipelines.get_mut(0) {
|
||||||
if let Some(expr) = pipeline.expressions.get_mut(0) {
|
if let Some(expr) = pipeline.expressions.get_mut(0) {
|
||||||
*expr = new_expr
|
*expr = new_expr
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ impl Expression {
|
||||||
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
||||||
let block = working_set.get_block(*block_id);
|
let block = working_set.get_block(*block_id);
|
||||||
|
|
||||||
let new_expr = if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {
|
let new_expr = if let Some(pipeline) = block.pipelines.get(0) {
|
||||||
if let Some(expr) = pipeline.expressions.get(0) {
|
if let Some(expr) = pipeline.expressions.get(0) {
|
||||||
let mut new_expr = expr.clone();
|
let mut new_expr = expr.clone();
|
||||||
new_expr.replace_in_variable(working_set, new_var_id);
|
new_expr.replace_in_variable(working_set, new_var_id);
|
||||||
|
@ -368,7 +368,7 @@ impl Expression {
|
||||||
let block = working_set.get_block_mut(*block_id);
|
let block = working_set.get_block_mut(*block_id);
|
||||||
|
|
||||||
if let Some(new_expr) = new_expr {
|
if let Some(new_expr) = new_expr {
|
||||||
if let Some(Statement::Pipeline(pipeline)) = block.stmts.get_mut(0) {
|
if let Some(pipeline) = block.pipelines.get_mut(0) {
|
||||||
if let Some(expr) = pipeline.expressions.get_mut(0) {
|
if let Some(expr) = pipeline.expressions.get_mut(0) {
|
||||||
*expr = new_expr
|
*expr = new_expr
|
||||||
}
|
}
|
||||||
|
@ -420,11 +420,9 @@ impl Expression {
|
||||||
Expr::Block(block_id) => {
|
Expr::Block(block_id) => {
|
||||||
let mut block = working_set.get_block(*block_id).clone();
|
let mut block = working_set.get_block(*block_id).clone();
|
||||||
|
|
||||||
for stmt in block.stmts.iter_mut() {
|
for pipeline in block.pipelines.iter_mut() {
|
||||||
if let Statement::Pipeline(pipeline) = stmt {
|
for expr in pipeline.expressions.iter_mut() {
|
||||||
for expr in pipeline.expressions.iter_mut() {
|
expr.replace_span(working_set, replaced, new_span)
|
||||||
expr.replace_span(working_set, replaced, new_span)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,11 +495,9 @@ impl Expression {
|
||||||
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
|
||||||
let mut block = working_set.get_block(*block_id).clone();
|
let mut block = working_set.get_block(*block_id).clone();
|
||||||
|
|
||||||
for stmt in block.stmts.iter_mut() {
|
for pipeline in block.pipelines.iter_mut() {
|
||||||
if let Statement::Pipeline(pipeline) = stmt {
|
for expr in pipeline.expressions.iter_mut() {
|
||||||
for expr in pipeline.expressions.iter_mut() {
|
expr.replace_span(working_set, replaced, new_span)
|
||||||
expr.replace_span(working_set, replaced, new_span)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ mod expression;
|
||||||
mod import_pattern;
|
mod import_pattern;
|
||||||
mod operator;
|
mod operator;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod statement;
|
|
||||||
|
|
||||||
pub use block::*;
|
pub use block::*;
|
||||||
pub use call::*;
|
pub use call::*;
|
||||||
|
@ -16,4 +15,3 @@ pub use expression::*;
|
||||||
pub use import_pattern::*;
|
pub use import_pattern::*;
|
||||||
pub use operator::*;
|
pub use operator::*;
|
||||||
pub use pipeline::*;
|
pub use pipeline::*;
|
||||||
pub use statement::*;
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
|
||||||
use crate::ast::Expression;
|
use crate::ast::Expression;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -21,4 +23,26 @@ impl Pipeline {
|
||||||
pub fn from_vec(expressions: Vec<Expression>) -> Pipeline {
|
pub fn from_vec(expressions: Vec<Expression>) -> Pipeline {
|
||||||
Self { expressions }
|
Self { expressions }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.expressions.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.expressions.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<usize> for Pipeline {
|
||||||
|
type Output = Expression;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.expressions[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<usize> for Pipeline {
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
&mut self.expressions[index]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
use super::Pipeline;
|
|
||||||
use crate::DeclId;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Statement {
|
|
||||||
Declaration(DeclId),
|
|
||||||
Pipeline(Pipeline),
|
|
||||||
}
|
|
|
@ -17,7 +17,7 @@ use nu_command::{create_default_context, BufferedReader};
|
||||||
use nu_engine::{get_full_help, CallExt};
|
use nu_engine::{get_full_help, CallExt};
|
||||||
use nu_parser::parse;
|
use nu_parser::parse;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Call, Expr, Expression, Pipeline, Statement},
|
ast::{Call, Expr, Expression},
|
||||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||||
Category, Example, IntoPipelineData, PipelineData, RawStream, ShellError, Signature, Span,
|
Category, Example, IntoPipelineData, PipelineData, RawStream, ShellError, Signature, Span,
|
||||||
Spanned, SyntaxShape, Value, CONFIG_VARIABLE_ID,
|
Spanned, SyntaxShape, Value, CONFIG_VARIABLE_ID,
|
||||||
|
@ -241,11 +241,11 @@ fn parse_commandline_args(
|
||||||
);
|
);
|
||||||
|
|
||||||
// We should have a successful parse now
|
// We should have a successful parse now
|
||||||
if let Some(Statement::Pipeline(Pipeline { expressions })) = block.stmts.get(0) {
|
if let Some(pipeline) = block.pipelines.get(0) {
|
||||||
if let Some(Expression {
|
if let Some(Expression {
|
||||||
expr: Expr::Call(call),
|
expr: Expr::Call(call),
|
||||||
..
|
..
|
||||||
}) = expressions.get(0)
|
}) = pipeline.expressions.get(0)
|
||||||
{
|
{
|
||||||
let redirect_stdin = call.get_named_arg("stdin");
|
let redirect_stdin = call.get_named_arg("stdin");
|
||||||
let login_shell = call.get_named_arg("login");
|
let login_shell = call.get_named_arg("login");
|
||||||
|
|
Loading…
Reference in a new issue