Remove dfr from dataframe commands (#5760)

* input and output tests

* input and output types for dfr

* expression converter

* remove deprecated command

* correct expressions

* cargo clippy

* identifier for ls

* cargo clippy

* type for head and tail expression

* modify full cell path if block
This commit is contained in:
Fernando Herrera
2022-06-12 14:18:00 -05:00
committed by GitHub
parent 2dea9e6f1f
commit 11d7d8ea1e
105 changed files with 2646 additions and 1361 deletions

View File

@ -21,7 +21,7 @@ use crate::{
parser::{
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,
parse_var_with_opt_type, trim_quotes, ParsedInternalCall,
},
unescape_unquote_string, ParseError,
};
@ -127,13 +127,18 @@ pub fn parse_for(
}
Some(decl_id) => {
working_set.enter_scope();
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
decl_id,
expand_aliases_denylist,
);
working_set.exit_scope();
let call_span = span(spans);
@ -165,7 +170,7 @@ pub fn parse_for(
Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
},
err,
@ -296,13 +301,18 @@ pub fn parse_def(
}
Some(decl_id) => {
working_set.enter_scope();
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
decl_id,
expand_aliases_denylist,
);
working_set.exit_scope();
let call_span = span(spans);
@ -334,7 +344,7 @@ pub fn parse_def(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -439,7 +449,9 @@ pub fn parse_extern(
}
Some(decl_id) => {
working_set.enter_scope();
let (call, err) = parse_internal_call(
let ParsedInternalCall {
call, error: err, ..
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -521,7 +533,7 @@ pub fn parse_alias(
}
if let Some(decl_id) = working_set.find_decl(b"alias", &Type::Any) {
let (call, _) = parse_internal_call(
let ParsedInternalCall { call, output, .. } = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -534,7 +546,7 @@ pub fn parse_alias(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
None,
@ -1243,7 +1255,11 @@ pub fn parse_use(
let (call, call_span, use_decl_id) = match working_set.find_decl(b"use", &Type::Any) {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -1260,7 +1276,7 @@ pub fn parse_use(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -1476,7 +1492,11 @@ pub fn parse_hide(
let (call, call_span, hide_decl_id) = match working_set.find_decl(b"hide", &Type::Any) {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -1493,7 +1513,7 @@ pub fn parse_hide(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -1701,7 +1721,11 @@ pub fn parse_overlay(
// TODO: Abstract this code blob, it's repeated all over the place:
let call = match working_set.find_decl(b"overlay list", &Type::Any) {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
span(&spans[..2]),
if spans.len() > 2 { &spans[2..] } else { &[] },
@ -1718,7 +1742,7 @@ pub fn parse_overlay(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -1760,7 +1784,11 @@ pub fn parse_overlay(
let call = match working_set.find_decl(b"overlay", &Type::Any) {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -1777,7 +1805,7 @@ pub fn parse_overlay(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -1825,7 +1853,11 @@ pub fn parse_overlay_new(
let (call, call_span) = match working_set.find_decl(b"overlay new", &Type::Any) {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
span(&spans[0..2]),
&spans[2..],
@ -1842,7 +1874,7 @@ pub fn parse_overlay_new(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -1916,7 +1948,11 @@ pub fn parse_overlay_add(
// TODO: Allow full import pattern as argument (requires custom naming of module/overlay)
let (call, call_span) = match working_set.find_decl(b"overlay add", &Type::Any) {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
span(&spans[0..2]),
&spans[2..],
@ -1933,7 +1969,7 @@ pub fn parse_overlay_add(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -2103,7 +2139,11 @@ pub fn parse_overlay_remove(
let call = match working_set.find_decl(b"overlay remove", &Type::Any) {
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
span(&spans[0..2]),
&spans[2..],
@ -2120,7 +2160,7 @@ pub fn parse_overlay_remove(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,
@ -2247,7 +2287,6 @@ pub fn parse_let(
error = error.or(err);
let var_id = lvalue.as_var();
let rhs_type = rvalue.ty.clone();
if let Some(var_id) = var_id {
@ -2277,7 +2316,11 @@ pub fn parse_let(
}
}
}
let (call, err) = parse_internal_call(
let ParsedInternalCall {
call,
error: err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -2290,7 +2333,7 @@ pub fn parse_let(
expressions: vec![Expression {
expr: Expr::Call(call),
span: nu_protocol::span(spans),
ty: Type::Any,
ty: output,
custom_completion: None,
}],
},
@ -2320,7 +2363,11 @@ pub fn parse_source(
let cwd = working_set.get_cwd();
// Is this the right call to be using here?
// Some of the others (`parse_let`) use it, some of them (`parse_hide`) don't.
let (call, err) = parse_internal_call(
let ParsedInternalCall {
call,
error: err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -2334,7 +2381,7 @@ pub fn parse_source(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
error,
@ -2459,7 +2506,11 @@ pub fn parse_register(
)
}
Some(decl_id) => {
let (call, mut err) = parse_internal_call(
let ParsedInternalCall {
call,
error: mut err,
output,
} = parse_internal_call(
working_set,
spans[0],
&spans[1..],
@ -2476,7 +2527,7 @@ pub fn parse_register(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: call_span,
ty: Type::Any,
ty: output,
custom_completion: None,
}]),
err,

View File

@ -724,13 +724,19 @@ pub fn parse_multispan_value(
}
}
pub struct ParsedInternalCall {
pub call: Box<Call>,
pub output: Type,
pub error: Option<ParseError>,
}
pub fn parse_internal_call(
working_set: &mut StateWorkingSet,
command_span: Span,
spans: &[Span],
decl_id: usize,
expand_aliases_denylist: &[usize],
) -> (Box<Call>, Option<ParseError>) {
) -> ParsedInternalCall {
trace!("parsing: internal call (decl id: {})", decl_id);
let mut error = None;
@ -742,7 +748,8 @@ pub fn parse_internal_call(
let decl = working_set.get_decl(decl_id);
let signature = decl.signature();
let output = decl.output_type();
working_set.found_outputs.push(output);
working_set.type_scope.add_type(output.clone());
if signature.creates_scope {
working_set.enter_scope();
@ -925,8 +932,11 @@ pub fn parse_internal_call(
working_set.exit_scope();
}
// FIXME: output type unknown
(Box::new(call), error)
ParsedInternalCall {
call: Box::new(call),
output,
error,
}
}
pub fn parse_call(
@ -1012,7 +1022,7 @@ pub fn parse_call(
pos += 1;
}
let input = working_set.found_outputs.last().unwrap_or(&Type::Any);
let input = working_set.type_scope.get_previous();
let mut maybe_decl_id = working_set.find_decl(&name, input);
while maybe_decl_id.is_none() {
@ -1060,21 +1070,22 @@ pub fn parse_call(
trace!("parsing: internal call");
// parse internal command
let (call, err) = parse_internal_call(
let parsed_call = parse_internal_call(
working_set,
span(&spans[cmd_start..pos]),
&spans[pos..],
decl_id,
expand_aliases_denylist,
);
(
Expression {
expr: Expr::Call(call),
expr: Expr::Call(parsed_call.call),
span: span(spans),
ty: Type::Any, // FIXME: calls should have known output types
ty: parsed_call.output,
custom_completion: None,
},
err,
parsed_call.error,
)
} else {
// We might be parsing left-unbounded range ("..10")
@ -1853,8 +1864,14 @@ pub fn parse_full_cell_path(
let (output, err) = lite_parse(&output);
error = error.or(err);
// Creating a Type scope to parse the new block. This will keep track of
// the previous input type found in that block
let (output, err) =
parse_block(working_set, &output, true, expand_aliases_denylist, true);
working_set
.type_scope
.add_type(working_set.type_scope.get_last_output());
error = error.or(err);
let block_id = working_set.add_block(output);
@ -1864,7 +1881,7 @@ pub fn parse_full_cell_path(
Expression {
expr: Expr::Subexpression(block_id),
span: head_span,
ty: Type::Any, // FIXME
ty: working_set.type_scope.get_last_output(),
custom_completion: None,
},
true,
@ -1929,8 +1946,8 @@ pub fn parse_full_cell_path(
if !tail.is_empty() {
(
Expression {
ty: head.ty.clone(), // FIXME. How to access the last type of tail?
expr: Expr::FullCellPath(Box::new(FullCellPath { head, tail })),
ty: Type::Any,
span: full_cell_span,
custom_completion: None,
},
@ -4581,6 +4598,9 @@ pub fn parse_variable(
if is_variable(bytes) {
if let Some(var_id) = working_set.find_variable(bytes) {
let input = working_set.get_variable(var_id).ty.clone();
working_set.type_scope.add_type(input);
(Some(var_id), None)
} else {
(None, None)
@ -4612,19 +4632,20 @@ pub fn parse_builtin_commands(
b"source" => parse_source(working_set, &lite_command.parts, expand_aliases_denylist),
b"export" => {
if let Some(decl_id) = working_set.find_decl(b"alias", &Type::Any) {
let (call, _) = parse_internal_call(
let parsed_call = parse_internal_call(
working_set,
lite_command.parts[0],
&lite_command.parts[1..],
decl_id,
expand_aliases_denylist,
);
if call.has_flag("help") {
if parsed_call.call.has_flag("help") {
(
Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
expr: Expr::Call(parsed_call.call),
span: span(&lite_command.parts),
ty: Type::Any,
ty: parsed_call.output,
custom_completion: None,
}]),
None,
@ -4759,6 +4780,7 @@ pub fn parse_block(
if scoped {
working_set.enter_scope();
}
working_set.type_scope.enter_scope();
let mut error = None;
@ -4789,6 +4811,8 @@ pub fn parse_block(
let (expr, err) =
parse_expression(working_set, &command.parts, expand_aliases_denylist);
working_set.type_scope.add_type(expr.ty.clone());
if error.is_none() {
error = err;
}
@ -4872,6 +4896,7 @@ pub fn parse_block(
if scoped {
working_set.exit_scope();
}
working_set.type_scope.exit_scope();
(block, error)
}

View File

@ -35,6 +35,9 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Duration, None),
(Type::Filesize, Type::Filesize) => (Type::Filesize, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
(Type::Int, _) => {
@ -74,6 +77,9 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Duration, None),
(Type::Filesize, Type::Filesize) => (Type::Filesize, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
_ => {
@ -101,6 +107,9 @@ pub fn math_result_type(
(Type::Duration, Type::Int) => (Type::Filesize, None),
(Type::Int, Type::Duration) => (Type::Filesize, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
_ => {
@ -123,6 +132,9 @@ pub fn math_result_type(
(Type::Int, Type::Float) => (Type::Float, None),
(Type::Float, Type::Float) => (Type::Float, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
_ => {
@ -150,6 +162,9 @@ pub fn math_result_type(
(Type::Filesize, Type::Int) => (Type::Filesize, None),
(Type::Duration, Type::Int) => (Type::Duration, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
_ => {
@ -169,6 +184,9 @@ pub fn math_result_type(
Operator::And | Operator::Or => match (&lhs.ty, &rhs.ty) {
(Type::Bool, Type::Bool) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Any, None),
(_, Type::Any) => (Type::Any, None),
_ => {
@ -193,6 +211,9 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
_ => {
@ -217,6 +238,9 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
_ => {
@ -241,6 +265,9 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
_ => {
@ -265,6 +292,9 @@ pub fn math_result_type(
(Type::Duration, Type::Duration) => (Type::Bool, None),
(Type::Filesize, Type::Filesize) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
_ => {
@ -281,12 +311,26 @@ pub fn math_result_type(
)
}
},
Operator::Equal => (Type::Bool, None),
Operator::NotEqual => (Type::Bool, None),
Operator::Equal => match (&lhs.ty, &rhs.ty) {
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
_ => (Type::Bool, None),
},
Operator::NotEqual => match (&lhs.ty, &rhs.ty) {
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
_ => (Type::Bool, None),
},
Operator::RegexMatch => match (&lhs.ty, &rhs.ty) {
(Type::String, Type::String) => (Type::Bool, None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
_ => {
*op = Expression::garbage(op.span);
(
@ -305,6 +349,10 @@ pub fn math_result_type(
(Type::String, Type::String) => (Type::Bool, None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
_ => {
*op = Expression::garbage(op.span);
(
@ -323,6 +371,10 @@ pub fn math_result_type(
(Type::String, Type::String) => (Type::Bool, None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
_ => {
*op = Expression::garbage(op.span);
(
@ -341,6 +393,10 @@ pub fn math_result_type(
(Type::String, Type::String) => (Type::Bool, None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
_ => {
*op = Expression::garbage(op.span);
(
@ -361,6 +417,9 @@ pub fn math_result_type(
(Type::String, Type::String) => (Type::Bool, None),
(Type::String, Type::Record(_)) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
_ => {
@ -383,6 +442,9 @@ pub fn math_result_type(
(Type::String, Type::String) => (Type::Bool, None),
(Type::String, Type::Record(_)) => (Type::Bool, None),
(Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.to_string()), None),
(Type::Custom(a), _) => (Type::Custom(a.to_string()), None),
(Type::Any, _) => (Type::Bool, None),
(_, Type::Any) => (Type::Bool, None),
_ => {

View File

@ -666,7 +666,7 @@ mod range {
#[cfg(test)]
mod input_types {
use super::*;
use nu_protocol::{Category, Type};
use nu_protocol::{ast::Argument, Category, Type};
#[derive(Clone)]
pub struct LsTest;
@ -696,9 +696,9 @@ mod input_types {
}
#[derive(Clone)]
pub struct GroupByList;
pub struct GroupBy;
impl Command for GroupByList {
impl Command for GroupBy {
fn name(&self) -> &str {
"group-by"
}
@ -830,16 +830,118 @@ mod input_types {
}
}
#[derive(Clone)]
pub struct AggMin;
impl Command for AggMin {
fn name(&self) -> &str {
"min"
}
fn usage(&self) -> &str {
"Mock custom min command"
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build(self.name()).category(Category::Custom("custom".into()))
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
_call: &nu_protocol::ast::Call,
_input: nu_protocol::PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
todo!()
}
}
#[derive(Clone)]
pub struct WithColumn;
impl Command for WithColumn {
fn name(&self) -> &str {
"with-column"
}
fn usage(&self) -> &str {
"Mock custom with-column command"
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build(self.name())
.rest("operation", SyntaxShape::Any, "operation")
.category(Category::Custom("custom".into()))
}
fn input_type(&self) -> nu_protocol::Type {
Type::Custom("custom".into())
}
fn output_type(&self) -> nu_protocol::Type {
Type::Custom("custom".into())
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
_call: &nu_protocol::ast::Call,
_input: nu_protocol::PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
todo!()
}
}
#[derive(Clone)]
pub struct Collect;
impl Command for Collect {
fn name(&self) -> &str {
"collect"
}
fn usage(&self) -> &str {
"Mock custom collect command"
}
fn signature(&self) -> nu_protocol::Signature {
Signature::build(self.name()).category(Category::Custom("custom".into()))
}
fn input_type(&self) -> nu_protocol::Type {
Type::Custom("custom".into())
}
fn output_type(&self) -> nu_protocol::Type {
Type::Custom("custom".into())
}
fn run(
&self,
_engine_state: &EngineState,
_stack: &mut Stack,
_call: &nu_protocol::ast::Call,
_input: nu_protocol::PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
todo!()
}
}
fn add_declations(engine_state: &mut EngineState) {
let delta = {
let mut working_set = StateWorkingSet::new(&engine_state);
working_set.add_decl(Box::new(Let));
working_set.add_decl(Box::new(AggCustom));
working_set.add_decl(Box::new(GroupByCustom));
working_set.add_decl(Box::new(GroupByList));
working_set.add_decl(Box::new(GroupBy));
working_set.add_decl(Box::new(LsTest));
working_set.add_decl(Box::new(ToCustom));
working_set.add_decl(Box::new(Let));
working_set.add_decl(Box::new(AggMin));
working_set.add_decl(Box::new(Collect));
working_set.add_decl(Box::new(WithColumn));
working_set.render()
};
@ -917,6 +1019,64 @@ mod input_types {
}
}
#[test]
fn stored_variable_operation_test() {
let mut engine_state = EngineState::new();
add_declations(&mut engine_state);
let mut working_set = StateWorkingSet::new(&engine_state);
let input = r#"let a = (ls | to-custom | group-by name other); ($a + $a) | agg sum"#;
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
assert!(err.is_none());
assert!(block.len() == 2);
let expressions = &block[1];
match &expressions[1].expr {
Expr::Call(call) => {
let expected_id = working_set
.find_decl(b"agg", &Type::Custom("custom".into()))
.unwrap();
assert_eq!(call.decl_id, expected_id)
}
_ => panic!("Expected expression Call not found"),
}
}
#[test]
fn multiple_stored_variable_test() {
let mut engine_state = EngineState::new();
add_declations(&mut engine_state);
let mut working_set = StateWorkingSet::new(&engine_state);
let input = r#"
let a = (ls | to-custom | group-by name other); [1 2 3] | to-custom; [1 2 3] | to-custom"#;
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
assert!(err.is_none());
assert!(block.len() == 3);
let expressions = &block[1];
match &expressions[1].expr {
Expr::Call(call) => {
let expected_id = working_set.find_decl(b"to-custom", &Type::Any).unwrap();
assert_eq!(call.decl_id, expected_id)
}
_ => panic!("Expected expression Call not found"),
}
let expressions = &block[2];
match &expressions[1].expr {
Expr::Call(call) => {
let expected_id = working_set.find_decl(b"to-custom", &Type::Any).unwrap();
assert_eq!(call.decl_id, expected_id)
}
_ => panic!("Expected expression Call not found"),
}
}
#[test]
fn call_non_custom_types_test() {
let mut engine_state = EngineState::new();
@ -949,4 +1109,89 @@ mod input_types {
_ => panic!("Expected expression Call not found"),
}
}
#[test]
fn nested_operations_test() {
let mut engine_state = EngineState::new();
add_declations(&mut engine_state);
let (block, delta) = {
let mut working_set = StateWorkingSet::new(&engine_state);
let input = r#"ls | to-custom | group-by name other | agg ("b" | min)"#;
let (block, _) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
(block, working_set.render())
};
let cwd = std::env::current_dir().expect("Could not get current working directory.");
let _ = engine_state.merge_delta(delta, None, &cwd);
let expressions = &block[0];
match &expressions[3].expr {
Expr::Call(call) => {
let arg = &call.arguments[0];
match arg {
Argument::Positional(a) => match &a.expr {
Expr::FullCellPath(path) => match &path.head.expr {
Expr::Subexpression(id) => {
let block = engine_state.get_block(*id);
let expressions = &block[0];
assert!(expressions.len() == 2);
match &expressions[1].expr {
Expr::Call(call) => {
let working_set = StateWorkingSet::new(&engine_state);
let expected_id =
working_set.find_decl(b"min", &Type::Any).unwrap();
assert_eq!(call.decl_id, expected_id)
}
_ => panic!("Expected expression Call not found"),
}
}
_ => panic!("Expected Subexpression not found"),
},
_ => panic!("Expected FullCellPath not found"),
},
_ => panic!("Expected Argument Positional not found"),
}
}
_ => panic!("Expected expression Call not found"),
}
}
#[test]
fn call_with_list_test() {
let mut engine_state = EngineState::new();
add_declations(&mut engine_state);
let mut working_set = StateWorkingSet::new(&engine_state);
let input = r#"[[a b]; [1 2] [3 4]] | to-custom | with-column [ ("a" | min) ("b" | min) ] | collect"#;
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
assert!(err.is_none());
assert!(block.len() == 1);
let expressions = &block[0];
match &expressions[2].expr {
Expr::Call(call) => {
let expected_id = working_set
.find_decl(b"with-column", &Type::Custom("custom".into()))
.unwrap();
assert_eq!(call.decl_id, expected_id)
}
_ => panic!("Expected expression Call not found"),
}
match &expressions[3].expr {
Expr::Call(call) => {
let expected_id = working_set
.find_decl(b"collect", &Type::Custom("custom".into()))
.unwrap();
assert_eq!(call.decl_id, expected_id)
}
_ => panic!("Expected expression Call not found"),
}
}
}