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

@ -112,6 +112,10 @@ impl Expression {
Expr::Block(block_id) => {
let block = working_set.get_block(*block_id);
if block.captures.contains(&IN_VARIABLE_ID) {
return true;
}
if let Some(Statement::Pipeline(pipeline)) = block.stmts.get(0) {
match pipeline.expressions.get(0) {
Some(expr) => expr.has_in_variable(working_set),

View File

@ -0,0 +1,9 @@
use std::collections::HashMap;
use crate::{BlockId, Value, VarId};
#[derive(Clone, Debug)]
pub struct CaptureBlock {
pub block_id: BlockId,
pub captures: HashMap<VarId, Value>,
}

View File

@ -154,6 +154,7 @@ pub const SCOPE_VARIABLE_ID: usize = 1;
pub const IN_VARIABLE_ID: usize = 2;
pub const CONFIG_VARIABLE_ID: usize = 3;
pub const ENV_VARIABLE_ID: usize = 4;
// NOTE: If you add more to this list, make sure to update the > checks based on the last in the list
impl EngineState {
pub fn new() -> Self {

View File

@ -1,9 +1,11 @@
mod call_info;
mod capture_block;
mod command;
mod engine_state;
mod stack;
pub use call_info::*;
pub use capture_block::*;
pub use command::*;
pub use engine_state::*;
pub use stack::*;

View File

@ -62,7 +62,10 @@ impl Stack {
return Ok(v.clone());
}
Err(ShellError::NushellFailed("variable not found".into()))
Err(ShellError::NushellFailed(format!(
"variable (var_id: {}) not found",
var_id
)))
}
pub fn add_var(&mut self, var_id: VarId, value: Value) {
@ -80,7 +83,24 @@ impl Stack {
}
}
pub fn collect_captures(&self, captures: &[VarId]) -> Stack {
pub fn captures_to_stack(&self, captures: &HashMap<VarId, Value>) -> Stack {
let mut output = Stack::new();
output.vars = captures.clone();
// FIXME: this is probably slow
output.env_vars = self.env_vars.clone();
output.env_vars.push(HashMap::new());
let config = self
.get_var(CONFIG_VARIABLE_ID)
.expect("internal error: config is missing");
output.vars.insert(CONFIG_VARIABLE_ID, config);
output
}
pub fn gather_captures(&self, captures: &[VarId]) -> Stack {
let mut output = Stack::new();
for capture in captures {

View File

@ -6,6 +6,7 @@ use std::str::FromStr;
use chrono::{DateTime, FixedOffset};
// use nu_path::expand_path;
use crate::ast::{CellPath, PathMember};
use crate::engine::CaptureBlock;
use crate::ShellError;
use crate::{Range, Spanned, Value};
@ -351,3 +352,42 @@ impl FromValue for Vec<Value> {
}
}
}
impl FromValue for CaptureBlock {
fn from_value(v: &Value) -> Result<Self, ShellError> {
match v {
Value::Block { val, captures, .. } => Ok(CaptureBlock {
block_id: *val,
captures: captures.clone(),
}),
v => Err(ShellError::CantConvert(
"Block".into(),
v.get_type().to_string(),
v.span()?,
)),
}
}
}
impl FromValue for Spanned<CaptureBlock> {
fn from_value(v: &Value) -> Result<Self, ShellError> {
match v {
Value::Block {
val,
captures,
span,
} => Ok(Spanned {
item: CaptureBlock {
block_id: *val,
captures: captures.clone(),
},
span: *span,
}),
v => Err(ShellError::CantConvert(
"Block".into(),
v.get_type().to_string(),
v.span()?,
)),
}
}
}

View File

@ -22,7 +22,7 @@ use std::path::PathBuf;
use std::{cmp::Ordering, fmt::Debug};
use crate::ast::{CellPath, PathMember};
use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type};
use crate::{did_you_mean, span, BlockId, Config, Span, Spanned, Type, VarId};
use crate::ast::Operator;
pub use custom_value::CustomValue;
@ -75,6 +75,7 @@ pub enum Value {
},
Block {
val: BlockId,
captures: HashMap<VarId, Value>,
span: Span,
},
Nothing {
@ -141,8 +142,13 @@ impl Clone for Value {
vals: vals.clone(),
span: *span,
},
Value::Block { val, span } => Value::Block {
Value::Block {
val,
captures,
span,
} => Value::Block {
val: *val,
captures: captures.clone(),
span: *span,
},
Value::Nothing { span } => Value::Nothing { span: *span },