From b5bade618732407a76d0e0c14d7054137d81a2d3 Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Mon, 8 Nov 2021 12:18:00 +1300 Subject: [PATCH] Let list and table exprs get indexed (#307) --- crates/nu-engine/src/eval.rs | 17 +++-- crates/nu-parser/src/lex.rs | 2 +- crates/nu-parser/src/parse_keywords.rs | 11 +-- crates/nu-parser/src/parser.rs | 92 +++++++++++--------------- src/tests.rs | 7 +- 5 files changed, 57 insertions(+), 72 deletions(-) diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index d331ff46cf..c124830fdd 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -502,17 +502,18 @@ pub fn eval_variable( let mut output_cols = vec![]; let mut output_vals = vec![]; - let mut vars = vec![]; + let mut var_names = vec![]; + let mut var_types = vec![]; let mut commands = vec![]; let mut aliases = vec![]; let mut modules = vec![]; for frame in &engine_state.scope { for var in &frame.vars { - vars.push(Value::String { - val: String::from_utf8_lossy(var.0).to_string(), - span, - }); + var_names.push(String::from_utf8_lossy(var.0).to_string()); + + let var = engine_state.get_var(*var.1); + var_types.push(Value::string(var.to_string(), span)); } for command in &frame.decls { @@ -538,7 +539,11 @@ pub fn eval_variable( } output_cols.push("vars".to_string()); - output_vals.push(Value::List { vals: vars, span }); + output_vals.push(Value::Record { + cols: var_names, + vals: var_types, + span, + }); output_cols.push("commands".to_string()); output_vals.push(Value::List { diff --git a/crates/nu-parser/src/lex.rs b/crates/nu-parser/src/lex.rs index b1b50f99be..c8df9c0dea 100644 --- a/crates/nu-parser/src/lex.rs +++ b/crates/nu-parser/src/lex.rs @@ -145,7 +145,7 @@ pub fn lex_item( let _ = block_level.pop(); } } else if c == b'(' { - // We enceountered an opening `(` delimiter. + // We encountered an opening `(` delimiter. block_level.push(BlockKind::Paren); } else if c == b')' { // We encountered a closing `)` delimiter. Pop off the opening `(`. diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index 30c9092c78..2a138bbc26 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -429,15 +429,8 @@ pub fn parse_module( if block_bytes.ends_with(b"}") { end -= 1; } else { - error = error.or_else(|| { - Some(ParseError::Unclosed( - "}".into(), - Span { - start: end, - end: end + 1, - }, - )) - }); + error = + error.or_else(|| Some(ParseError::Unclosed("}".into(), Span { start: end, end }))); } let block_span = Span { start, end }; diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index cab7dacef9..51976f553d 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -1302,15 +1302,8 @@ pub fn parse_full_cell_path( if bytes.ends_with(b")") { end -= 1; } else { - error = error.or_else(|| { - Some(ParseError::Unclosed( - ")".into(), - Span { - start: end, - end: end + 1, - }, - )) - }); + error = error + .or_else(|| Some(ParseError::Unclosed(")".into(), Span { start: end, end }))); } let span = Span { start, end }; @@ -1338,6 +1331,13 @@ pub fn parse_full_cell_path( }, true, ) + } else if bytes.starts_with(b"[") { + let (output, err) = parse_table_expression(working_set, head.span); + error = error.or(err); + + tokens.next(); + + (output, true) } else if bytes.starts_with(b"$") { let (out, err) = parse_variable_expr(working_set, head.span); error = error.or(err); @@ -1369,15 +1369,28 @@ pub fn parse_full_cell_path( let (tail, err) = parse_cell_path(working_set, tokens, expect_dot, span); error = error.or(err); - ( - Expression { - expr: Expr::FullCellPath(Box::new(FullCellPath { head, tail })), - ty: Type::Unknown, - span: full_cell_span, - custom_completion: None, - }, - error, - ) + if !tail.is_empty() { + ( + Expression { + expr: Expr::FullCellPath(Box::new(FullCellPath { head, tail })), + ty: Type::Unknown, + span: full_cell_span, + custom_completion: None, + }, + error, + ) + } else { + let ty = head.ty.clone(); + ( + Expression { + expr: Expr::FullCellPath(Box::new(FullCellPath { head, tail })), + ty, + span: full_cell_span, + custom_completion: None, + }, + error, + ) + } } else { (garbage(span), error) } @@ -1963,15 +1976,7 @@ pub fn parse_signature( if bytes.ends_with(b"]") { end -= 1; } else { - error = error.or_else(|| { - Some(ParseError::Unclosed( - "]".into(), - Span { - start: end, - end: end + 1, - }, - )) - }); + error = error.or_else(|| Some(ParseError::Unclosed("]".into(), Span { start: end, end }))); } let (sig, err) = parse_signature_helper(working_set, Span { start, end }); @@ -2328,15 +2333,7 @@ pub fn parse_list_expression( if bytes.ends_with(b"]") { end -= 1; } else { - error = error.or_else(|| { - Some(ParseError::Unclosed( - "]".into(), - Span { - start: end, - end: end + 1, - }, - )) - }); + error = error.or_else(|| Some(ParseError::Unclosed("]".into(), Span { start: end, end }))); } let span = Span { start, end }; @@ -2407,15 +2404,7 @@ pub fn parse_table_expression( if bytes.ends_with(b"]") { end -= 1; } else { - error = error.or_else(|| { - Some(ParseError::Unclosed( - "]".into(), - Span { - start: end, - end: end + 1, - }, - )) - }); + error = error.or_else(|| Some(ParseError::Unclosed("]".into(), Span { start: end, end }))); } let span = Span { start, end }; @@ -2530,15 +2519,7 @@ pub fn parse_block_expression( if bytes.ends_with(b"}") { end -= 1; } else { - error = error.or_else(|| { - Some(ParseError::Unclosed( - "}".into(), - Span { - start: end, - end: end + 1, - }, - )) - }); + error = error.or_else(|| Some(ParseError::Unclosed("}".into(), Span { start: end, end }))); } let span = Span { start, end }; @@ -2798,7 +2779,8 @@ pub fn parse_value( } SyntaxShape::Any => { if bytes.starts_with(b"[") { - parse_value(working_set, span, &SyntaxShape::Table) + //parse_value(working_set, span, &SyntaxShape::Table) + parse_full_cell_path(working_set, None, span) } else { let shapes = [ SyntaxShape::Int, diff --git a/src/tests.rs b/src/tests.rs index dc5e40326f..1c58272a46 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -804,7 +804,7 @@ fn help_works_with_missing_requirements() -> TestResult { #[test] fn scope_variable() -> TestResult { - run_test(r#"let x = 3; $scope.vars.0"#, "$x") + run_test(r#"let x = 3; $scope.vars.'$x'"#, "int") } #[test] @@ -854,3 +854,8 @@ fn precedence_of_or_groups() -> TestResult { fn where_on_ranges() -> TestResult { run_test(r#"1..10 | where $it > 8 | math sum"#, "19") } + +#[test] +fn index_on_list() -> TestResult { + run_test(r#"[1, 2, 3].1"#, "2") +}