Fixing captures (#723)

* WIP fixing captures

* small fix

* WIP

* Rewrite to proof-of-concept better parse_def

* Add missing file

* Finish capture refactor

* Fix tests

* Add more tests
This commit is contained in:
JT
2022-01-12 15:06:56 +11:00
committed by GitHub
parent 47495715a6
commit 186da4d725
30 changed files with 424 additions and 164 deletions

View File

@ -1,6 +1,6 @@
use crate::{
lex, lite_parse,
parse_keywords::parse_source,
parse_keywords::{parse_for, parse_source},
type_check::{math_result_type, type_compatible},
LiteBlock, ParseError, Token, TokenContents,
};
@ -13,7 +13,7 @@ use nu_protocol::{
},
engine::StateWorkingSet,
span, Flag, PositionalArg, Signature, Span, Spanned, SyntaxShape, Type, Unit, VarId,
CONFIG_VARIABLE_ID,
CONFIG_VARIABLE_ID, ENV_VARIABLE_ID, IN_VARIABLE_ID,
};
use crate::parse_keywords::{
@ -3402,6 +3402,7 @@ pub fn parse_statement(
match name {
b"def" => parse_def(working_set, spans),
b"let" => parse_let(working_set, spans),
b"for" => parse_for(working_set, spans),
b"alias" => parse_alias(working_set, spans),
b"module" => parse_module(working_set, spans),
b"use" => parse_use(working_set, spans),
@ -3577,13 +3578,15 @@ pub fn parse_block(
(block, error)
}
fn find_captures_in_block(
pub fn find_captures_in_block(
working_set: &StateWorkingSet,
block: &Block,
seen: &mut Vec<VarId>,
) -> Vec<VarId> {
let mut output = vec![];
// println!("sig: {:#?}", block.signature);
for flag in &block.signature.named {
if let Some(var_id) = flag.var_id {
seen.push(var_id);
@ -3654,6 +3657,13 @@ pub fn find_captures_in_expr(
}
Expr::Bool(_) => {}
Expr::Call(call) => {
let decl = working_set.get_decl(call.decl_id);
if let Some(block_id) = decl.get_block_id() {
let block = working_set.get_block(block_id);
let result = find_captures_in_block(working_set, block, seen);
output.extend(&result);
}
for named in &call.named {
if let Some(arg) = &named.1 {
let result = find_captures_in_expr(working_set, arg, seen);
@ -3715,7 +3725,30 @@ pub fn find_captures_in_expr(
output.extend(&find_captures_in_expr(working_set, field_value, seen));
}
}
Expr::Signature(_) => {}
Expr::Signature(sig) => {
// println!("Signature found! Adding var_ids");
// Something with a declaration, similar to a var decl, will introduce more VarIds into the stack at eval
for pos in &sig.required_positional {
if let Some(var_id) = pos.var_id {
seen.push(var_id);
}
}
for pos in &sig.optional_positional {
if let Some(var_id) = pos.var_id {
seen.push(var_id);
}
}
if let Some(rest) = &sig.rest_positional {
if let Some(var_id) = rest.var_id {
seen.push(var_id);
}
}
for named in &sig.named {
if let Some(var_id) = named.var_id {
seen.push(var_id);
}
}
}
Expr::String(_) => {}
Expr::StringInterpolation(exprs) => {
for expr in exprs {
@ -3745,7 +3778,7 @@ pub fn find_captures_in_expr(
output.extend(&result);
}
Expr::Var(var_id) => {
if !seen.contains(var_id) {
if (*var_id > ENV_VARIABLE_ID || *var_id == IN_VARIABLE_ID) && !seen.contains(var_id) {
output.push(*var_id);
}
}