forked from extern/nushell
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:
@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user