Move row condition to block (#368)

This commit is contained in:
JT 2021-11-26 16:49:03 +13:00 committed by GitHub
parent 8043516d75
commit f052b3313d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 65 additions and 171 deletions

View file

@ -1,4 +1,4 @@
use nu_engine::eval_expression;
use nu_engine::eval_block;
use nu_protocol::ast::{Call, Expr, Expression};
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{Category, PipelineData, ShellError, Signature, SyntaxShape};
@ -28,30 +28,34 @@ impl Command for Where {
call: &Call,
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let span = call.head;
let cond = call.positional[0].clone();
let ctrlc = engine_state.ctrlc.clone();
let engine_state = engine_state.clone();
// FIXME: expensive
let mut stack = stack.clone();
let (var_id, cond) = match cond {
let block_id = match cond {
Expression {
expr: Expr::RowCondition(var_id, expr),
expr: Expr::RowCondition(block_id),
..
} => (var_id, expr),
} => block_id,
_ => return Err(ShellError::InternalError("Expected row condition".into())),
};
let block = engine_state.get_block(block_id).clone();
let mut stack = stack.collect_captures(&block.captures);
input.filter(
move |value| {
stack.add_var(var_id, value.clone());
let result = eval_expression(&engine_state, &mut stack, &cond);
if let Some(var) = block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
stack.add_var(*var_id, value.clone());
}
}
let result = eval_block(&engine_state, &mut stack, &block, PipelineData::new(span));
match result {
Ok(result) => result.is_true(),
Ok(result) => result.into_value(span).is_true(),
_ => false,
}
},

View file

@ -1,8 +1,7 @@
use nu_protocol::ast::{Call, PathMember};
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError,
Signature, Value,
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Value,
};
#[derive(Clone)]
@ -15,12 +14,6 @@ impl Command for ToJson {
fn signature(&self) -> Signature {
Signature::build("to json").category(Category::Formats)
// .named(
// "pretty",
// SyntaxShape::Int,
// "Formats the JSON text with the provided indentation setting",
// Some('p'),
// )
}
fn usage(&self) -> &str {
@ -29,12 +22,12 @@ impl Command for ToJson {
fn run(
&self,
engine_state: &EngineState,
_engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<nu_protocol::PipelineData, ShellError> {
to_json(engine_state, call, input)
to_json(call, input)
}
fn examples(&self) -> Vec<Example> {
@ -95,143 +88,23 @@ fn json_list(input: &[Value]) -> Result<Vec<nu_json::Value>, ShellError> {
Ok(out)
}
fn to_json(
engine_state: &EngineState,
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let name_span = call.head;
// let pretty: Option<Value> = args.get_flag("pretty")?;
fn to_json(call: &Call, input: PipelineData) -> Result<PipelineData, ShellError> {
let span = call.head;
//let input: Vec<Value> = input.collect();
let value = input.into_value(span);
// let to_process_input = match input.len() {
// x if x > 1 => {
// let tag = input[0].tag.clone();
// vec![Value:: {
// value: UntaggedValue::Table(input),
// tag,
// }]
// }
// 1 => input,
// _ => vec![],
// };
match input {
PipelineData::Value(value) => {
let json_value = value_to_json_value(&value)?;
match nu_json::to_string(&json_value) {
Ok(serde_json_string) => Ok(Value::String {
val: serde_json_string,
span: name_span,
}
.into_pipeline_data()),
_ => Ok(Value::Error {
error: ShellError::CantConvert(
"JSON".into(),
value.get_type().to_string(),
name_span,
),
}
.into_pipeline_data()),
}
let json_value = value_to_json_value(&value)?;
match nu_json::to_string(&json_value) {
Ok(serde_json_string) => Ok(Value::String {
val: serde_json_string,
span,
}
PipelineData::Stream(stream) => Ok(stream
.map(move |value| {
if let Ok(json_value) = value_to_json_value(&value) {
match nu_json::to_string(&json_value) {
Ok(serde_json_string) => Value::String {
val: serde_json_string,
span: name_span,
},
_ => Value::Error {
error: ShellError::CantConvert(
"JSON".into(),
value.get_type().to_string(),
name_span,
),
},
}
} else {
Value::Error {
error: ShellError::CantConvert(
"JSON".into(),
value.get_type().to_string(),
name_span,
),
}
}
})
.into_pipeline_data(engine_state.ctrlc.clone())),
.into_pipeline_data()),
_ => Ok(Value::Error {
error: ShellError::CantConvert("JSON".into(), value.get_type().to_string(), span),
}
.into_pipeline_data()),
}
// input
// // .into_iter()
// .map(
// move |value| {
// let value_span = value.span().expect("non-error");
// match value_to_json_value(&value) {
// Ok(json_value) => {
// match nu_json::to_string(&json_value) {
// Ok(serde_json_string) => {
// // if let Some(pretty_value) = &pretty {
// // let mut pretty_format_failed = true;
// // if let Ok(pretty_u64) = pretty_value.as_u64() {
// // if let Ok(serde_json_value) =
// // serde_json::from_str::<serde_json::Value>(&serde_json_string)
// // {
// // let indentation_string = " ".repeat(pretty_u64 as usize);
// // let serde_formatter =
// // serde_json::ser::PrettyFormatter::with_indent(
// // indentation_string.as_bytes(),
// // );
// // let serde_buffer = Vec::new();
// // let mut serde_serializer =
// // serde_json::Serializer::with_formatter(
// // serde_buffer,
// // serde_formatter,
// // );
// // let serde_json_object = json!(serde_json_value);
// // if let Ok(()) =
// // serde_json_object.serialize(&mut serde_serializer)
// // {
// // if let Ok(ser_json_string) =
// // String::from_utf8(serde_serializer.into_inner())
// // {
// // pretty_format_failed = false;
// // serde_json_string = ser_json_string
// // }
// // }
// // }
// // }
// // if pretty_format_failed {
// // return Value::error(ShellError::labeled_error(
// // "Pretty formatting failed",
// // "failed",
// // pretty_value.tag(),
// // ));
// // }
// // }
// Value::String {
// val: serde_json_string,
// span: value_span,
// }
// }
// _ => Value::Error {
// error: ShellError::CantConvert("JSON".into(), value_span),
// },
// }
// }
// _ => Value::Error {
// error: ShellError::CantConvert("JSON".into(), value_span),
// },
// }
// },
// engine_state.ctrlc.clone(),
// )
}
#[cfg(test)]

View file

@ -228,7 +228,6 @@ pub fn eval_expression(
Expr::ImportPattern(_) => Ok(Value::Nothing {
span: Span::unknown(),
}),
Expr::RowCondition(_, expr) => eval_expression(engine_state, stack, expr),
Expr::Call(call) => {
// FIXME: protect this collect with ctrl-c
Ok(
@ -277,7 +276,7 @@ pub fn eval_expression(
Operator::Pow => lhs.pow(op_span, &rhs),
}
}
Expr::Subexpression(block_id) => {
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
let block = engine_state.get_block(*block_id);
// FIXME: protect this collect with ctrl-c

View file

@ -207,8 +207,7 @@ pub fn flatten_expression(
Expr::String(_) => {
vec![(expr.span, FlatShape::String)]
}
Expr::RowCondition(_, expr) => flatten_expression(working_set, expr),
Expr::Subexpression(block_id) => {
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
flatten_block(working_set, working_set.get_block(*block_id))
}
Expr::Table(headers, cells) => {

View file

@ -1990,11 +1990,38 @@ pub fn parse_row_condition(
let var_id = working_set.add_variable(b"$it".to_vec(), Type::Unknown);
let (expression, err) = parse_math_expression(working_set, spans, Some(var_id));
let span = span(spans);
let block_id = match expression.expr {
Expr::Block(block_id) => block_id,
_ => {
// We have an expression, so let's convert this into a block.
let mut block = Block::new();
let mut pipeline = Pipeline::new();
pipeline.expressions.push(expression);
block.stmts.push(Statement::Pipeline(pipeline));
block.signature.required_positional.push(PositionalArg {
name: "$it".into(),
desc: "row condition".into(),
shape: SyntaxShape::Any,
var_id: Some(var_id),
});
let mut seen = vec![];
let captures = find_captures_in_block(working_set, &block, &mut seen);
block.captures = captures;
working_set.add_block(block)
}
};
(
Expression {
ty: Type::Bool,
span,
expr: Expr::RowCondition(var_id, Box::new(expression)),
expr: Expr::RowCondition(block_id),
custom_completion: None,
},
err,
@ -3481,15 +3508,9 @@ pub fn find_captures_in_expr(
output.extend(&find_captures_in_expr(working_set, field_value, seen));
}
}
Expr::RowCondition(var_id, expr) => {
seen.push(*var_id);
let result = find_captures_in_expr(working_set, expr, seen);
output.extend(&result);
}
Expr::Signature(_) => {}
Expr::String(_) => {}
Expr::Subexpression(block_id) => {
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
let block = working_set.get_block(*block_id);
let result = find_captures_in_block(working_set, block, seen);
output.extend(&result);

View file

@ -17,7 +17,7 @@ pub enum Expr {
Call(Box<Call>),
ExternalCall(String, Span, Vec<Expression>),
Operator(Operator),
RowCondition(VarId, Box<Expression>),
RowCondition(BlockId),
BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), //lhs, op, rhs
Subexpression(BlockId),
Block(BlockId),

View file

@ -182,10 +182,9 @@ impl Expression {
}
false
}
Expr::RowCondition(_, expr) => expr.has_in_variable(working_set),
Expr::Signature(_) => false,
Expr::String(_) => false,
Expr::Subexpression(block_id) => {
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
let block = working_set.get_block(*block_id);
if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {
@ -311,10 +310,9 @@ impl Expression {
field_value.replace_in_variable(working_set, new_var_id);
}
}
Expr::RowCondition(_, expr) => expr.replace_in_variable(working_set, new_var_id),
Expr::Signature(_) => {}
Expr::String(_) => {}
Expr::Subexpression(block_id) => {
Expr::RowCondition(block_id) | Expr::Subexpression(block_id) => {
let block = working_set.get_block(*block_id);
let new_expr = if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {