From 6dd9f05ea14f726cd361a6700d436d083099e413 Mon Sep 17 00:00:00 2001 From: JT Date: Wed, 8 Sep 2021 10:00:20 +1200 Subject: [PATCH] Add an experimental record iteration --- crates/nu-command/src/each.rs | 57 +++++++++++++++++++++++++++++++--- crates/nu-parser/src/parser.rs | 1 + src/tests.rs | 5 +++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/crates/nu-command/src/each.rs b/crates/nu-command/src/each.rs index 624370cc76..cd2894e9b2 100644 --- a/crates/nu-command/src/each.rs +++ b/crates/nu-command/src/each.rs @@ -38,7 +38,7 @@ impl Command for Each { let block = engine_state.get_block(block_id); let state = context.enter_scope(); - if let Some(var) = block.signature.required_positional.first() { + if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { state.add_var(*var_id, x); } @@ -60,7 +60,7 @@ impl Command for Each { let block = engine_state.get_block(block_id); let state = context.enter_scope(); - if let Some(var) = block.signature.required_positional.first() { + if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { state.add_var(*var_id, x); } @@ -81,7 +81,7 @@ impl Command for Each { let block = engine_state.get_block(block_id); let state = context.enter_scope(); - if let Some(var) = block.signature.required_positional.first() { + if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { state.add_var(*var_id, x); } @@ -95,13 +95,62 @@ impl Command for Each { .into_value_stream(), span: call.head, }), + Value::Record { cols, vals, .. } => { + let mut output_cols = vec![]; + let mut output_vals = vec![]; + + for (col, val) in cols.into_iter().zip(vals.into_iter()) { + let engine_state = context.engine_state.borrow(); + let block = engine_state.get_block(block_id); + + let state = context.enter_scope(); + if let Some(var) = block.signature.get_positional(0) { + if let Some(var_id) = &var.var_id { + state.add_var( + *var_id, + Value::Record { + cols: vec!["column".into(), "value".into()], + vals: vec![ + Value::String { + val: col.clone(), + span: call.head, + }, + val, + ], + span: call.head, + }, + ); + } + } + + match eval_block(&state, block, Value::nothing())? { + Value::Record { + mut cols, mut vals, .. + } => { + // TODO check that the lengths match + output_cols.append(&mut cols); + output_vals.append(&mut vals); + } + x => { + output_cols.push(col); + output_vals.push(x); + } + } + } + + Ok(Value::Record { + cols: output_cols, + vals: output_vals, + span: call.head, + }) + } x => { //TODO: we need to watch to make sure this is okay let engine_state = context.engine_state.borrow(); let block = engine_state.get_block(block_id); let state = context.enter_scope(); - if let Some(var) = block.signature.required_positional.first() { + if let Some(var) = block.signature.get_positional(0) { if let Some(var_id) = &var.var_id { state.add_var(*var_id, x); } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index c3c05e2d57..86271281be 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1876,6 +1876,7 @@ pub fn parse_block_expression( error = error.or(err); working_set.enter_scope(); + // Check to see if we have parameters let (signature, amt_to_skip): (Option>, usize) = match output.first() { Some(Token { diff --git a/src/tests.rs b/src/tests.rs index 403d9d2b30..d5cb6d3f04 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -287,3 +287,8 @@ fn row_iteration() -> TestResult { "[800, 1600]", ) } + +#[test] +fn record_iteration() -> TestResult { + run_test("([[name, level]; [aa, 100], [bb, 200]] | each { $it | each { |x| if $x.column == \"level\" { $x.value + 100 } else { $x.value } } }).level", "[200, 300]") +}