Remove statements, replaced by pipelines (#4482)

This commit is contained in:
JT
2022-02-15 14:31:14 -05:00
committed by GitHub
parent 66669d7839
commit 56b3fc61a3
16 changed files with 660 additions and 750 deletions

View File

@ -27,10 +27,6 @@ pub enum ParseError {
#[diagnostic(code(nu::parser::unclosed_delimiter), url(docsrs))]
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.")]
#[diagnostic(code(nu::parser::parse_mismatch), url(docsrs))]
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."
)
)]
StatementInPipeline(String, #[label("not allowed in pipeline")] Span),
BuiltinCommandInPipeline(String, #[label("not allowed in pipeline")] Span),
#[error("Incorrect value")]
#[diagnostic(code(nu::parser::incorrect_value), url(docsrs), help("{2}"))]

View File

@ -1,6 +1,4 @@
use nu_protocol::ast::{
Block, Expr, Expression, ImportPatternMember, PathMember, Pipeline, Statement,
};
use nu_protocol::ast::{Block, Expr, Expression, ImportPatternMember, PathMember, Pipeline};
use nu_protocol::{engine::StateWorkingSet, Span};
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)> {
let mut output = vec![];
for stmt in &block.stmts {
output.extend(flatten_statement(working_set, stmt));
for pipeline in &block.pipelines {
output.extend(flatten_pipeline(working_set, pipeline));
}
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(
working_set: &StateWorkingSet,
expr: &Expression,

View File

@ -8,9 +8,7 @@ mod parser;
mod type_check;
pub use errors::ParseError;
pub use flatten::{
flatten_block, flatten_expression, flatten_pipeline, flatten_statement, FlatShape,
};
pub use flatten::{flatten_block, flatten_expression, flatten_pipeline, FlatShape};
pub use known_external::KnownExternal;
pub use lex::{lex, Token, TokenContents};
pub use lite_parse::{lite_parse, LiteBlock};

View File

@ -31,17 +31,17 @@ impl LiteCommand {
}
#[derive(Debug)]
pub struct LiteStatement {
pub struct LitePipeline {
pub commands: Vec<LiteCommand>,
}
impl Default for LiteStatement {
impl Default for LitePipeline {
fn default() -> Self {
Self::new()
}
}
impl LiteStatement {
impl LitePipeline {
pub fn new() -> Self {
Self { commands: vec![] }
}
@ -57,7 +57,7 @@ impl LiteStatement {
#[derive(Debug)]
pub struct LiteBlock {
pub block: Vec<LiteStatement>,
pub block: Vec<LitePipeline>,
}
impl Default for LiteBlock {
@ -71,7 +71,7 @@ impl LiteBlock {
Self { block: vec![] }
}
pub fn push(&mut self, pipeline: LiteStatement) {
pub fn push(&mut self, pipeline: LitePipeline) {
self.block.push(pipeline);
}
@ -82,7 +82,7 @@ impl LiteBlock {
pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
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 last_token = TokenContents::Eol;
@ -117,7 +117,7 @@ pub fn lite_parse(tokens: &[Token]) -> (LiteBlock, Option<ParseError>) {
if !curr_pipeline.is_empty() {
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() {
block.push(curr_pipeline);
curr_pipeline = LiteStatement::new();
curr_pipeline = LitePipeline::new();
}
last_token = TokenContents::Semicolon;

View File

@ -2,7 +2,7 @@ use nu_path::canonicalize_with;
use nu_protocol::{
ast::{
Block, Call, Expr, Expression, ImportPattern, ImportPatternHead, ImportPatternMember,
Pipeline, Statement,
Pipeline,
},
engine::StateWorkingSet,
span, Exportable, Overlay, PositionalArg, Span, SyntaxShape, Type, CONFIG_VARIABLE_ID,
@ -14,7 +14,7 @@ use crate::{
lex, lite_parse,
lite_parse::LiteCommand,
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_var_with_opt_type, trim_quotes,
},
@ -245,7 +245,7 @@ fn build_usage(working_set: &StateWorkingSet, spans: &[Span]) -> String {
pub fn parse_def(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
let spans = &lite_command.parts[..];
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();
if def_call != b"def" && def_call != b"def-env" {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Wrong call name for def function".into(),
span(spans),
@ -270,7 +270,7 @@ pub fn parse_def(
let (call, call_span) = match working_set.find_decl(&def_call) {
None => {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: def declaration not found".into(),
span(spans),
@ -308,12 +308,12 @@ pub fn parse_def(
err = check_call(call_span, &sig, &call).or(err);
if err.is_some() || call.has_flag("help") {
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
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),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
error,
)
}
@ -378,7 +378,7 @@ pub fn parse_def(
pub fn parse_extern(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
let spans = &lite_command.parts[..];
let mut error = None;
@ -390,7 +390,7 @@ pub fn parse_extern(
let extern_call = working_set.get_span_contents(spans[0]).to_vec();
if extern_call != b"extern" {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Wrong call name for extern function".into(),
span(spans),
@ -404,7 +404,7 @@ pub fn parse_extern(
let (call, call_span) = match working_set.find_decl(&extern_call) {
None => {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: def declaration not found".into(),
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),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
error,
)
}
@ -479,15 +479,12 @@ pub fn parse_extern(
pub fn parse_alias(
working_set: &mut StateWorkingSet,
spans: &[Span],
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
let name = working_set.get_span_contents(spans[0]);
if name == b"alias" {
if let Some((span, err)) = check_name(working_set, spans) {
return (
Statement::Pipeline(Pipeline::from_vec(vec![garbage(*span)])),
Some(err),
);
return (Pipeline::from_vec(vec![garbage(*span)]), Some(err));
}
if let Some(decl_id) = working_set.find_decl(b"alias") {
@ -512,19 +509,19 @@ pub fn parse_alias(
}
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
None,
);
}
}
(
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::InternalError(
"Alias statement unparseable".into(),
span(spans),
@ -535,14 +532,14 @@ pub fn parse_alias(
pub fn parse_export(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
) -> (Statement, Option<Exportable>, Option<ParseError>) {
) -> (Pipeline, Option<Exportable>, Option<ParseError>) {
let spans = &lite_command.parts[..];
let mut error = None;
let export_span = if let Some(sp) = spans.get(0) {
if working_set.get_span_contents(*sp) != b"export" {
return (
garbage_statement(spans),
garbage_pipeline(spans),
None,
Some(ParseError::UnknownState(
"expected export statement".into(),
@ -554,7 +551,7 @@ pub fn parse_export(
*sp
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
None,
Some(ParseError::UnknownState(
"got empty input for parsing export statement".into(),
@ -567,7 +564,7 @@ pub fn parse_export(
id
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
None,
Some(ParseError::InternalError(
"missing export command".into(),
@ -591,14 +588,14 @@ pub fn parse_export(
comments: lite_command.comments.clone(),
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);
let export_def_decl_id = if let Some(id) = working_set.find_decl(b"export def") {
id
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
None,
Some(ParseError::InternalError(
"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
if let Statement::Pipeline(ref pipe) = stmt {
if let Some(Expression {
expr: Expr::Call(ref def_call),
..
}) = pipe.expressions.get(0)
{
call = def_call.clone();
if let Some(Expression {
expr: Expr::Call(ref def_call),
..
}) = pipeline.expressions.get(0)
{
call = def_call.clone();
call.head = span(&spans[0..=1]);
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..]),
))
});
}
call.head = span(&spans[0..=1]);
call.decl_id = export_def_decl_id;
} else {
error = error.or_else(|| {
Some(ParseError::InternalError(
@ -658,7 +646,7 @@ pub fn parse_export(
comments: lite_command.comments.clone(),
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);
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
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
None,
Some(ParseError::InternalError(
"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
if let Statement::Pipeline(ref pipe) = stmt {
if let Some(Expression {
expr: Expr::Call(ref def_call),
..
}) = pipe.expressions.get(0)
{
call = def_call.clone();
if let Some(Expression {
expr: Expr::Call(ref def_call),
..
}) = pipeline.expressions.get(0)
{
call = def_call.clone();
call.head = span(&spans[0..=1]);
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..]),
))
});
}
call.head = span(&spans[0..=1]);
call.decl_id = export_def_decl_id;
} else {
error = error.or_else(|| {
Some(ParseError::InternalError(
@ -726,7 +705,7 @@ pub fn parse_export(
call.decl_id = id;
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
None,
Some(ParseError::InternalError(
"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),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
exportable,
error,
)
@ -876,16 +855,16 @@ pub fn parse_module_block(
if pipeline.commands.len() == 1 {
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" => {
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" => {
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: 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`
// since in the second case, the name of the env var would be $env."foo a".
b"export" => {
let (stmt, exportable, err) =
let (pipe, exportable, err) =
parse_export(working_set, &pipeline.commands[0]);
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(
"expected def or export keyword".into(),
pipeline.commands[0].parts[0],
@ -930,10 +909,10 @@ pub fn parse_module_block(
error = err;
}
stmt
pipeline
} else {
error = Some(ParseError::Expected("not a pipeline".into(), span));
garbage_statement(&[span])
garbage_pipeline(&[span])
}
})
.into();
@ -946,7 +925,7 @@ pub fn parse_module_block(
pub fn parse_module(
working_set: &mut StateWorkingSet,
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
// 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;
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
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),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
error,
)
} else {
(
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"Expected structure: module <name> {}".into(),
span(spans),
@ -1031,10 +1010,10 @@ pub fn parse_module(
pub fn parse_use(
working_set: &mut StateWorkingSet,
spans: &[Span],
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
if working_set.get_span_contents(spans[0]) != b"use" {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Wrong call name for 'use' command".into(),
span(spans),
@ -1052,12 +1031,12 @@ pub fn parse_use(
err = check_call(call_span, &decl.signature(), &call).or(err);
if err.is_some() || call.has_flag("help") {
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
err,
);
}
@ -1066,7 +1045,7 @@ pub fn parse_use(
}
None => {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: 'use' declaration not found".into(),
span(spans),
@ -1080,7 +1059,7 @@ pub fn parse_use(
pattern
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Import pattern positional is not import pattern".into(),
call_span,
@ -1089,7 +1068,7 @@ pub fn parse_use(
}
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Missing required positional after call parsing".into(),
call_span,
@ -1117,12 +1096,12 @@ pub fn parse_use(
stem.to_string_lossy().to_string()
} else {
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
Some(ParseError::ModuleNotFound(spans[1])),
);
};
@ -1152,12 +1131,12 @@ pub fn parse_use(
)
} else {
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
Some(ParseError::ModuleNotFound(spans[1])),
);
}
@ -1169,10 +1148,7 @@ pub fn parse_use(
(ImportPattern::new(), Overlay::new())
}
} else {
return (
garbage_statement(spans),
Some(ParseError::NonUtf8(spans[1])),
);
return (garbage_pipeline(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),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
error,
)
}
@ -1241,10 +1217,10 @@ pub fn parse_use(
pub fn parse_hide(
working_set: &mut StateWorkingSet,
spans: &[Span],
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
if working_set.get_span_contents(spans[0]) != b"hide" {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Wrong call name for 'hide' command".into(),
span(spans),
@ -1262,12 +1238,12 @@ pub fn parse_hide(
err = check_call(call_span, &decl.signature(), &call).or(err);
if err.is_some() || call.has_flag("help") {
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
err,
);
}
@ -1276,7 +1252,7 @@ pub fn parse_hide(
}
None => {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: 'hide' declaration not found".into(),
span(spans),
@ -1290,7 +1266,7 @@ pub fn parse_hide(
pattern
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Import pattern positional is not import pattern".into(),
call_span,
@ -1299,7 +1275,7 @@ pub fn parse_hide(
}
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Missing required positional after call parsing".into(),
call_span,
@ -1339,7 +1315,7 @@ pub fn parse_hide(
}
} else {
return (
garbage_statement(spans),
garbage_pipeline(spans),
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),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
error,
)
} else {
(
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"Expected structure: hide <name>".into(),
span(spans),
@ -1449,15 +1425,12 @@ pub fn parse_hide(
pub fn parse_let(
working_set: &mut StateWorkingSet,
spans: &[Span],
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
let name = working_set.get_span_contents(spans[0]);
if name == b"let" {
if let Some((span, err)) = check_name(working_set, spans) {
return (
Statement::Pipeline(Pipeline::from_vec(vec![garbage(*span)])),
Some(err),
);
return (Pipeline::from_vec(vec![garbage(*span)]), Some(err));
}
if let Some(decl_id) = working_set.find_decl(b"let") {
@ -1511,12 +1484,12 @@ pub fn parse_let(
});
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
error,
);
}
@ -1525,20 +1498,20 @@ pub fn parse_let(
let (call, err) = parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
return (
Statement::Pipeline(Pipeline {
Pipeline {
expressions: vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: Type::Unknown,
custom_completion: None,
}],
}),
},
err,
);
}
}
(
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: let statement unparseable".into(),
span(spans),
@ -1549,7 +1522,7 @@ pub fn parse_let(
pub fn parse_source(
working_set: &mut StateWorkingSet,
spans: &[Span],
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
let mut error = None;
let name = working_set.get_span_contents(spans[0]);
@ -1580,12 +1553,12 @@ pub fn parse_source(
if err.is_some() {
// Unsuccessful parse of file
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(&spans[1..]),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
// Return the file parse error
err,
);
@ -1605,12 +1578,12 @@ pub fn parse_source(
});
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call_with_block),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
None,
);
}
@ -1619,25 +1592,22 @@ pub fn parse_source(
error = error.or(Some(ParseError::FileNotFound(filename, spans[1])));
}
} else {
return (
garbage_statement(spans),
Some(ParseError::NonUtf8(spans[1])),
);
return (garbage_pipeline(spans), Some(ParseError::NonUtf8(spans[1])));
}
}
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
error,
);
}
}
(
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: source statement unparseable".into(),
span(spans),
@ -1649,7 +1619,7 @@ pub fn parse_source(
pub fn parse_register(
working_set: &mut StateWorkingSet,
spans: &[Span],
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
use nu_plugin::{get_signature, EncodingType, PluginDeclaration};
use nu_protocol::Signature;
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
if working_set.get_span_contents(spans[0]) != b"register" {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Wrong call name for parse plugin function".into(),
span(spans),
@ -1672,7 +1642,7 @@ pub fn parse_register(
let (call, call_span) = match working_set.find_decl(b"register") {
None => {
return (
garbage_statement(spans),
garbage_pipeline(spans),
Some(ParseError::UnknownState(
"internal error: Register declaration not found".into(),
span(spans),
@ -1688,12 +1658,12 @@ pub fn parse_register(
err = check_call(call_span, &decl.signature(), &call).or(err);
if err.is_some() || call.has_flag("help") {
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
err,
);
}
@ -1779,12 +1749,12 @@ pub fn parse_register(
Ok(path) => Some(path),
Err(err) => {
return (
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Unknown,
custom_completion: None,
}])),
}]),
Some(err),
);
}
@ -1829,12 +1799,12 @@ pub fn parse_register(
.err();
(
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Nothing,
custom_completion: None,
}])),
}]),
error,
)
}

View File

@ -10,7 +10,6 @@ use nu_protocol::{
ast::{
Block, Call, CellPath, Expr, Expression, FullCellPath, ImportPattern, ImportPatternHead,
ImportPatternMember, Operator, PathMember, Pipeline, RangeInclusion, RangeOperator,
Statement,
},
engine::StateWorkingSet,
span, BlockId, Flag, PositionalArg, Signature, Span, Spanned, SyntaxShape, Type, Unit, VarId,
@ -34,8 +33,8 @@ pub fn garbage(span: Span) -> Expression {
Expression::garbage(span)
}
pub fn garbage_statement(spans: &[Span]) -> Statement {
Statement::Pipeline(Pipeline::from_vec(vec![garbage(span(spans))]))
pub fn garbage_pipeline(spans: &[Span]) -> Pipeline {
Pipeline::from_vec(vec![garbage(span(spans))])
}
fn is_identifier_byte(b: u8) -> bool {
@ -2293,7 +2292,7 @@ pub fn parse_row_condition(
let mut pipeline = Pipeline::new();
pipeline.expressions.push(expression);
block.stmts.push(Statement::Pipeline(pipeline));
block.pipelines.push(pipeline);
block.signature.required_positional.push(PositionalArg {
name: "$it".into(),
@ -3413,31 +3412,43 @@ pub fn parse_expression(
match bytes {
b"def" => (
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" => (
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" => (
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" => (
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" => (
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" => (
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" => (
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" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
@ -3445,12 +3456,18 @@ pub fn parse_expression(
),
b"hide" => (
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")]
b"register" => (
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),
@ -3464,9 +3481,9 @@ pub fn parse_expression(
if let Some(decl_id) = with_env {
let mut block = Block::default();
let ty = output.ty.clone();
block.stmts = vec![Statement::Pipeline(Pipeline {
block.pipelines = vec![Pipeline {
expressions: vec![output],
})];
}];
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,
lite_command: &LiteCommand,
) -> (Statement, Option<ParseError>) {
) -> (Pipeline, Option<ParseError>) {
let name = working_set.get_span_contents(lite_command.parts[0]);
match name {
@ -3542,14 +3559,14 @@ pub fn parse_statement(
b"let" => parse_let(working_set, &lite_command.parts),
b"for" => {
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"module" => parse_module(working_set, &lite_command.parts),
b"use" => parse_use(working_set, &lite_command.parts),
b"source" => parse_source(working_set, &lite_command.parts),
b"export" => (
garbage_statement(&lite_command.parts),
garbage_pipeline(&lite_command.parts),
Some(ParseError::UnexpectedKeyword(
"export".into(),
lite_command.parts[0],
@ -3560,7 +3577,7 @@ pub fn parse_statement(
b"register" => parse_register(working_set, &lite_command.parts),
_ => {
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,
})
}
} 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 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 Statement::Pipeline(pipeline) = &mut stmt {
for expr in pipeline.expressions.iter_mut() {
if let Expression {
expr: Expr::Call(call),
..
} = expr
for expr in pipeline.expressions.iter_mut() {
if let Expression {
expr: Expr::Call(call),
..
} = expr
{
if call.decl_id == let_decl_id
|| call.decl_id == let_env_decl_id
{
if call.decl_id == let_decl_id
|| call.decl_id == let_env_decl_id
// Do an expansion
if let Some(Expression {
expr: Expr::Keyword(_, _, expr),
..
}) = call.positional.get_mut(1)
{
// Do an expansion
if let Some(Expression {
expr: Expr::Keyword(_, _, expr),
..
}) = call.positional.get_mut(1)
{
if expr.has_in_variable(working_set) {
*expr = Box::new(wrap_expr_with_collect(
working_set,
expr,
));
}
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;
}
stmt
pipeline
}
})
.into();
@ -3778,15 +3794,9 @@ pub fn discover_captures_in_block(
}
}
for stmt in &block.stmts {
match stmt {
Statement::Pipeline(pipeline) => {
let result =
discover_captures_in_pipeline(working_set, pipeline, seen, seen_blocks);
output.extend(&result);
}
Statement::Declaration(_) => {}
}
for pipeline in &block.pipelines {
let result = discover_captures_in_pipeline(working_set, pipeline, seen, seen_blocks);
output.extend(&result);
}
output
@ -4028,9 +4038,9 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
expr.replace_in_variable(working_set, var_id);
let block = Block {
stmts: vec![Statement::Pipeline(Pipeline {
pipelines: vec![Pipeline {
expressions: vec![expr],
})],
}],
signature: Box::new(signature),
..Default::default()
};