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 nu_engine::{eval_block, CallExt};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
use nu_protocol::{Category, PipelineData, Signature, SyntaxShape, Value};
#[derive(Clone)]
@ -39,16 +39,12 @@ impl Command for Do {
call: &Call,
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let block: Value = call.req(engine_state, stack, 0)?;
let block_id = block.as_block()?;
let block: CaptureBlock = call.req(engine_state, stack, 0)?;
let rest: Vec<Value> = call.rest(engine_state, stack, 1)?;
let ignore_errors = call.has_flag("ignore-errors");
let rest: Vec<Value> = call.rest(engine_state, stack, 1)?;
let block = engine_state.get_block(block_id);
let mut stack = stack.collect_captures(&block.captures);
let mut stack = stack.captures_to_stack(&block.captures);
let block = engine_state.get_block(block.block_id);
let params: Vec<_> = block
.signature

View File

@ -1,6 +1,6 @@
use nu_engine::{eval_block, eval_expression};
use nu_engine::{eval_block, eval_expression, CallExt};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoInterruptiblePipelineData, PipelineData, Signature, Span, SyntaxShape,
Value,
@ -61,16 +61,14 @@ impl Command for For {
.expect("internal error: missing keyword");
let values = eval_expression(engine_state, stack, keyword_expr)?;
let block_id = call.positional[2]
.as_block()
.expect("internal error: expected block");
let capture_block: CaptureBlock = call.req(engine_state, stack, 2)?;
let numbered = call.has_flag("numbered");
let ctrlc = engine_state.ctrlc.clone();
let engine_state = engine_state.clone();
let block = engine_state.get_block(block_id).clone();
let mut stack = stack.collect_captures(&block.captures);
let block = engine_state.get_block(capture_block.block_id).clone();
let mut stack = stack.captures_to_stack(&capture_block.captures);
let orig_env_vars = stack.env_vars.clone();
let orig_env_hidden = stack.env_hidden.clone();

View File

@ -1,8 +1,9 @@
use nu_engine::{eval_block, eval_expression};
use nu_engine::{eval_block, eval_expression, CallExt};
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
use nu_protocol::{
Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, SyntaxShape, Value,
Category, Example, FromValue, IntoPipelineData, PipelineData, ShellError, Signature,
SyntaxShape, Value,
};
#[derive(Clone)]
@ -41,23 +42,24 @@ impl Command for If {
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let cond = &call.positional[0];
let then_block = call.positional[1]
.as_block()
.expect("internal error: expected block");
let then_block: CaptureBlock = call.req(engine_state, stack, 1)?;
let else_case = call.positional.get(2);
let result = eval_expression(engine_state, stack, cond)?;
match &result {
Value::Bool { val, .. } => {
if *val {
let block = engine_state.get_block(then_block);
let mut stack = stack.collect_captures(&block.captures);
let block = engine_state.get_block(then_block.block_id);
let mut stack = stack.captures_to_stack(&then_block.captures);
eval_block(engine_state, &mut stack, block, input)
} else if let Some(else_case) = else_case {
if let Some(else_expr) = else_case.as_keyword() {
if let Some(block_id) = else_expr.as_block() {
let result = eval_expression(engine_state, stack, else_expr)?;
let else_block: CaptureBlock = FromValue::from_value(&result)?;
let mut stack = stack.captures_to_stack(&else_block.captures);
let block = engine_state.get_block(block_id);
let mut stack = stack.collect_captures(&block.captures);
eval_block(engine_state, &mut stack, block, input)
} else {
eval_expression(engine_state, stack, else_expr)