mirror of
https://github.com/nushell/nushell.git
synced 2024-11-25 18:03:51 +01:00
Refactor scope (#2602)
* Refactor scope to have parents * Refactor scope to have parents * Refactor scope to have parents * Clippy Co-authored-by: Jonathan Turner <jonathan@pop-os.localdomain>
This commit is contained in:
parent
9dc88f8a95
commit
cb7723f423
@ -9,7 +9,7 @@ use crate::EnvironmentSyncer;
|
||||
use futures_codec::FramedRead;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::{ClassifiedCommand, Expression, InternalCommand, Literal, NamedArguments};
|
||||
use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue, Value};
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Scope, UntaggedValue, Value};
|
||||
|
||||
use log::{debug, trace};
|
||||
#[cfg(feature = "rustyline-support")]
|
||||
@ -395,9 +395,7 @@ pub async fn cli(mut context: EvaluationContext) -> Result<(), Box<dyn Error>> {
|
||||
&prompt_block.block,
|
||||
&mut context,
|
||||
InputStream::empty(),
|
||||
&Value::nothing(),
|
||||
&IndexMap::new(),
|
||||
&env,
|
||||
Scope::from_env(env),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@ -862,9 +860,7 @@ pub async fn parse_and_eval(line: &str, ctx: &mut EvaluationContext) -> Result<S
|
||||
&classified_block.block,
|
||||
ctx,
|
||||
input_stream,
|
||||
&Value::nothing(),
|
||||
&IndexMap::new(),
|
||||
&env,
|
||||
Scope::from_env(env),
|
||||
)
|
||||
.await?
|
||||
.collect_string(Tag::unknown())
|
||||
@ -1021,9 +1017,7 @@ pub async fn process_line(
|
||||
&classified_block.block,
|
||||
ctx,
|
||||
input_stream,
|
||||
&Value::nothing(),
|
||||
&IndexMap::new(),
|
||||
&env,
|
||||
Scope::from_env(env),
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
@ -318,7 +318,7 @@ fn create_default_command_args(context: &RunnableContextWithoutInput) -> RawComm
|
||||
external_redirection: ExternalRedirection::Stdout,
|
||||
},
|
||||
name_tag: context.name.clone(),
|
||||
scope: Scope::new(),
|
||||
scope: Scope::create(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -83,16 +83,18 @@ async fn benchmark(
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let (BenchmarkArgs { block, passthrough }, input) = raw_args.process(®istry).await?;
|
||||
|
||||
let mut env = scope.env.clone();
|
||||
let env = scope.env();
|
||||
let name = generate_free_name(&env);
|
||||
let mut env = IndexMap::new();
|
||||
env.insert(name, generate_random_env_value());
|
||||
let scope = Scope::append_env(scope, env);
|
||||
|
||||
let start_time = Instant::now();
|
||||
|
||||
#[cfg(feature = "rich-benchmark")]
|
||||
let start = time().await;
|
||||
|
||||
let result = run_block(&block, &mut context, input, &scope.it, &scope.vars, &env).await;
|
||||
let result = run_block(&block, &mut context, input, scope.clone()).await;
|
||||
let output = result?.into_vec().await;
|
||||
|
||||
#[cfg(feature = "rich-benchmark")]
|
||||
@ -108,7 +110,7 @@ async fn benchmark(
|
||||
|
||||
let real_time = into_big_int(end_time - start_time);
|
||||
indexmap.insert("real time".to_string(), real_time);
|
||||
benchmark_output(indexmap, output, passthrough, &tag, &mut context, &scope).await
|
||||
benchmark_output(indexmap, output, passthrough, &tag, &mut context, scope).await
|
||||
}
|
||||
// return advanced stats
|
||||
#[cfg(feature = "rich-benchmark")]
|
||||
@ -127,7 +129,7 @@ async fn benchmark(
|
||||
let idle_time = into_big_int(end.idle() - start.idle());
|
||||
indexmap.insert("idle time".to_string(), idle_time);
|
||||
|
||||
benchmark_output(indexmap, output, passthrough, &tag, &mut context, &scope).await
|
||||
benchmark_output(indexmap, output, passthrough, &tag, &mut context, scope).await
|
||||
} else {
|
||||
Err(ShellError::untagged_runtime_error(
|
||||
"Could not retreive CPU time",
|
||||
@ -141,7 +143,7 @@ async fn benchmark_output<T, Output>(
|
||||
passthrough: Option<Block>,
|
||||
tag: T,
|
||||
context: &mut EvaluationContext,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<OutputStream, ShellError>
|
||||
where
|
||||
T: Into<Tag> + Copy,
|
||||
@ -161,15 +163,7 @@ where
|
||||
// add autoview for an empty block
|
||||
let time_block = add_implicit_autoview(time_block);
|
||||
|
||||
let _ = run_block(
|
||||
&time_block,
|
||||
context,
|
||||
benchmark_output,
|
||||
&scope.it,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await?;
|
||||
let _ = run_block(&time_block, context, benchmark_output, scope).await?;
|
||||
context.clear_errors();
|
||||
|
||||
Ok(block_output.into())
|
||||
|
@ -6,16 +6,14 @@ use crate::stream::InputStream;
|
||||
use futures::stream::TryStreamExt;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::{Block, ClassifiedCommand, Commands};
|
||||
use nu_protocol::{ReturnSuccess, UntaggedValue, Value};
|
||||
use nu_protocol::{ReturnSuccess, Scope, UntaggedValue, Value};
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
pub(crate) async fn run_block(
|
||||
block: &Block,
|
||||
ctx: &mut EvaluationContext,
|
||||
mut input: InputStream,
|
||||
it: &Value,
|
||||
vars: &IndexMap<String, Value>,
|
||||
env: &IndexMap<String, String>,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
let mut output: Result<InputStream, ShellError> = Ok(InputStream::empty());
|
||||
for pipeline in &block.block {
|
||||
@ -54,7 +52,7 @@ pub(crate) async fn run_block(
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
output = run_pipeline(pipeline, ctx, input, it, vars, env).await;
|
||||
output = run_pipeline(pipeline, ctx, input, scope.clone()).await;
|
||||
|
||||
input = InputStream::empty();
|
||||
}
|
||||
@ -66,9 +64,7 @@ async fn run_pipeline(
|
||||
commands: &Commands,
|
||||
ctx: &mut EvaluationContext,
|
||||
mut input: InputStream,
|
||||
it: &Value,
|
||||
vars: &IndexMap<String, Value>,
|
||||
env: &IndexMap<String, String>,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
for item in commands.list.clone() {
|
||||
input = match item {
|
||||
@ -77,13 +73,13 @@ async fn run_pipeline(
|
||||
}
|
||||
|
||||
ClassifiedCommand::Expr(expr) => {
|
||||
run_expression_block(*expr, ctx, it, vars, env).await?
|
||||
run_expression_block(*expr, ctx, scope.clone()).await?
|
||||
}
|
||||
|
||||
ClassifiedCommand::Error(err) => return Err(err.into()),
|
||||
|
||||
ClassifiedCommand::Internal(left) => {
|
||||
run_internal_command(left, ctx, input, it, vars, env).await?
|
||||
run_internal_command(left, ctx, input, scope.clone()).await?
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -6,14 +6,12 @@ use log::{log_enabled, trace};
|
||||
use futures::stream::once;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::SpannedExpression;
|
||||
use nu_protocol::Value;
|
||||
use nu_protocol::Scope;
|
||||
|
||||
pub(crate) async fn run_expression_block(
|
||||
expr: SpannedExpression,
|
||||
context: &mut EvaluationContext,
|
||||
it: &Value,
|
||||
vars: &IndexMap<String, Value>,
|
||||
env: &IndexMap<String, String>,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
if log_enabled!(log::Level::Trace) {
|
||||
trace!(target: "nu::run::expr", "->");
|
||||
@ -21,7 +19,7 @@ pub(crate) async fn run_expression_block(
|
||||
}
|
||||
|
||||
let registry = context.registry().clone();
|
||||
let output = evaluate_baseline_expr(&expr, ®istry, it, vars, env).await?;
|
||||
let output = evaluate_baseline_expr(&expr, ®istry, scope).await?;
|
||||
|
||||
Ok(once(async { Ok(output) }).to_input_stream())
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ pub(crate) async fn run_external_command(
|
||||
command: ExternalCommand,
|
||||
context: &mut EvaluationContext,
|
||||
input: InputStream,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
external_redirection: ExternalRedirection,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
trace!(target: "nu::run::external", "-> {}", command.name);
|
||||
@ -41,7 +41,7 @@ async fn run_with_stdin(
|
||||
command: ExternalCommand,
|
||||
context: &mut EvaluationContext,
|
||||
input: InputStream,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
external_redirection: ExternalRedirection,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
let path = context.shell_manager.path();
|
||||
@ -50,9 +50,7 @@ async fn run_with_stdin(
|
||||
|
||||
let mut command_args = vec![];
|
||||
for arg in command.args.iter() {
|
||||
let value =
|
||||
evaluate_baseline_expr(arg, &context.registry, &scope.it, &scope.vars, &scope.env)
|
||||
.await?;
|
||||
let value = evaluate_baseline_expr(arg, &context.registry, scope.clone()).await?;
|
||||
|
||||
// Skip any arguments that don't really exist, treating them as optional
|
||||
// FIXME: we may want to preserve the gap in the future, though it's hard to say
|
||||
@ -138,7 +136,7 @@ fn spawn(
|
||||
args: &[String],
|
||||
input: InputStream,
|
||||
external_redirection: ExternalRedirection,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
let command = command.clone();
|
||||
|
||||
@ -169,7 +167,7 @@ fn spawn(
|
||||
trace!(target: "nu::run::external", "cwd = {:?}", &path);
|
||||
|
||||
process.env_clear();
|
||||
process.envs(scope.env.iter());
|
||||
process.envs(scope.env());
|
||||
|
||||
// We want stdout regardless of what
|
||||
// we are doing ($it case or pipe stdin)
|
||||
@ -580,7 +578,7 @@ mod tests {
|
||||
cmd,
|
||||
&mut ctx,
|
||||
input,
|
||||
&Scope::new(),
|
||||
Scope::create(),
|
||||
ExternalRedirection::Stdout
|
||||
)
|
||||
.await
|
||||
|
@ -11,20 +11,13 @@ pub(crate) async fn run_internal_command(
|
||||
command: InternalCommand,
|
||||
context: &mut EvaluationContext,
|
||||
input: InputStream,
|
||||
it: &Value,
|
||||
vars: &IndexMap<String, Value>,
|
||||
env: &IndexMap<String, String>,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<InputStream, ShellError> {
|
||||
if log_enabled!(log::Level::Trace) {
|
||||
trace!(target: "nu::run::internal", "->");
|
||||
trace!(target: "nu::run::internal", "{}", command.name);
|
||||
}
|
||||
|
||||
let scope = Scope {
|
||||
it: it.clone(),
|
||||
vars: vars.clone(),
|
||||
env: env.clone(),
|
||||
};
|
||||
let objects: InputStream = trace_stream!(target: "nu::trace_stream::internal", "input" = input);
|
||||
let internal_command = context.expect_command(&command.name);
|
||||
|
||||
@ -38,7 +31,7 @@ pub(crate) async fn run_internal_command(
|
||||
internal_command?,
|
||||
Tag::unknown_anchor(command.name_span),
|
||||
command.args.clone(),
|
||||
&scope,
|
||||
scope.clone(),
|
||||
objects,
|
||||
)
|
||||
.await?
|
||||
@ -48,8 +41,6 @@ pub(crate) async fn run_internal_command(
|
||||
//let context = Arc::new(context.clone());
|
||||
let context = context.clone();
|
||||
let command = Arc::new(command);
|
||||
let scope = Arc::new(scope);
|
||||
// let scope = scope.clone();
|
||||
|
||||
Ok(InputStream::from_stream(
|
||||
result
|
||||
@ -90,7 +81,7 @@ pub(crate) async fn run_internal_command(
|
||||
external_redirection: ExternalRedirection::Stdout,
|
||||
},
|
||||
name_tag: Tag::unknown_anchor(command.name_span),
|
||||
scope: (&*scope).clone(),
|
||||
scope,
|
||||
},
|
||||
};
|
||||
let result = converter
|
||||
|
@ -130,7 +130,7 @@ async fn run_filter(
|
||||
UntaggedValue::Primitive(Primitive::EndOfStream).into_untagged_value()
|
||||
]);
|
||||
|
||||
let args = args.evaluate_once_with_scope(®istry, &scope).await?;
|
||||
let args = args.evaluate_once_with_scope(®istry, scope).await?;
|
||||
|
||||
let real_path = Path::new(&path);
|
||||
let ext = real_path.extension();
|
||||
|
@ -17,27 +17,12 @@ use std::sync::atomic::AtomicBool;
|
||||
pub struct UnevaluatedCallInfo {
|
||||
pub args: hir::Call,
|
||||
pub name_tag: Tag,
|
||||
pub scope: Scope,
|
||||
pub scope: Arc<Scope>,
|
||||
}
|
||||
|
||||
impl UnevaluatedCallInfo {
|
||||
pub async fn evaluate(self, registry: &CommandRegistry) -> Result<CallInfo, ShellError> {
|
||||
let args = evaluate_args(&self.args, registry, &self.scope).await?;
|
||||
|
||||
Ok(CallInfo {
|
||||
args,
|
||||
name_tag: self.name_tag,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn evaluate_with_new_it(
|
||||
self,
|
||||
registry: &CommandRegistry,
|
||||
it: &Value,
|
||||
) -> Result<CallInfo, ShellError> {
|
||||
let mut scope = self.scope.clone();
|
||||
scope.it = it.clone();
|
||||
let args = evaluate_args(&self.args, registry, &scope).await?;
|
||||
let args = evaluate_args(&self.args, registry, self.scope.clone()).await?;
|
||||
|
||||
Ok(CallInfo {
|
||||
args,
|
||||
@ -115,7 +100,7 @@ impl CommandArgs {
|
||||
pub async fn evaluate_once_with_scope(
|
||||
self,
|
||||
registry: &CommandRegistry,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<EvaluatedWholeStreamCommandArgs, ShellError> {
|
||||
let host = self.host.clone();
|
||||
let ctrl_c = self.ctrl_c.clone();
|
||||
@ -215,37 +200,6 @@ impl EvaluatedWholeStreamCommandArgs {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Getters)]
|
||||
#[get = "pub"]
|
||||
pub struct EvaluatedFilterCommandArgs {
|
||||
args: EvaluatedCommandArgs,
|
||||
}
|
||||
|
||||
impl Deref for EvaluatedFilterCommandArgs {
|
||||
type Target = EvaluatedCommandArgs;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.args
|
||||
}
|
||||
}
|
||||
|
||||
impl EvaluatedFilterCommandArgs {
|
||||
pub fn new(
|
||||
host: Arc<parking_lot::Mutex<dyn Host>>,
|
||||
ctrl_c: Arc<AtomicBool>,
|
||||
shell_manager: ShellManager,
|
||||
call_info: CallInfo,
|
||||
) -> EvaluatedFilterCommandArgs {
|
||||
EvaluatedFilterCommandArgs {
|
||||
args: EvaluatedCommandArgs {
|
||||
host,
|
||||
ctrl_c,
|
||||
shell_manager,
|
||||
call_info,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Getters, new)]
|
||||
#[get = "pub(crate)"]
|
||||
pub struct EvaluatedCommandArgs {
|
||||
@ -381,69 +335,6 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnFilterCommand {
|
||||
name: String,
|
||||
func: fn(EvaluatedFilterCommandArgs) -> Result<OutputStream, ShellError>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for FnFilterCommand {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"usage"
|
||||
}
|
||||
|
||||
async fn run(
|
||||
&self,
|
||||
CommandArgs {
|
||||
host,
|
||||
ctrl_c,
|
||||
shell_manager,
|
||||
call_info,
|
||||
input,
|
||||
..
|
||||
}: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let func = self.func;
|
||||
|
||||
Ok(input
|
||||
.then(move |it| {
|
||||
let host = host.clone();
|
||||
let registry = registry.clone();
|
||||
let ctrl_c = ctrl_c.clone();
|
||||
let shell_manager = shell_manager.clone();
|
||||
let call_info = call_info.clone();
|
||||
async move {
|
||||
let call_info = match call_info.evaluate_with_new_it(&*registry, &it).await {
|
||||
Err(err) => {
|
||||
return OutputStream::one(Err(err));
|
||||
}
|
||||
Ok(args) => args,
|
||||
};
|
||||
|
||||
let args = EvaluatedFilterCommandArgs::new(
|
||||
host.clone(),
|
||||
ctrl_c.clone(),
|
||||
shell_manager.clone(),
|
||||
call_info,
|
||||
);
|
||||
|
||||
match func(args) {
|
||||
Err(err) => return OutputStream::one(Err(err)),
|
||||
Ok(stream) => stream,
|
||||
}
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.to_output_stream())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn whole_stream_command(command: impl WholeStreamCommand + 'static) -> Command {
|
||||
Command(Arc::new(command))
|
||||
}
|
||||
|
@ -37,22 +37,11 @@ impl WholeStreamCommand for Compact {
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Filter out all null entries in a list",
|
||||
example: "echo [1 2 $null 3 $null $null] | compact",
|
||||
result: Some(vec![
|
||||
UntaggedValue::int(1).into(),
|
||||
UntaggedValue::int(2).into(),
|
||||
UntaggedValue::int(3).into(),
|
||||
]),
|
||||
},
|
||||
Example {
|
||||
description: "Filter out all directory entries having no 'target'",
|
||||
example: "ls -la | compact target",
|
||||
result: None,
|
||||
},
|
||||
]
|
||||
vec![Example {
|
||||
description: "Filter out all directory entries having no 'target'",
|
||||
example: "ls -la | compact target",
|
||||
result: None,
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,15 +95,7 @@ async fn do_(
|
||||
|
||||
block.set_redirect(block_redirection);
|
||||
|
||||
let result = run_block(
|
||||
&block,
|
||||
&mut context,
|
||||
input,
|
||||
&scope.it,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let result = run_block(&block, &mut context, input, scope).await;
|
||||
|
||||
if ignore_errors {
|
||||
// To properly ignore errors we need to redirect stderr, consume it, and remove
|
||||
|
@ -97,9 +97,7 @@ pub async fn process_row(
|
||||
&block,
|
||||
Arc::make_mut(&mut context),
|
||||
input_stream,
|
||||
&input,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
Scope::append_it(scope, input),
|
||||
)
|
||||
.await?
|
||||
.to_output_stream())
|
||||
@ -119,7 +117,7 @@ async fn each(
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let head = Arc::new(raw_args.call_info.args.head.clone());
|
||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||
let (each_args, input): (EachArgs, _) = raw_args.process(®istry).await?;
|
||||
let block = Arc::new(each_args.block);
|
||||
|
@ -53,7 +53,7 @@ impl WholeStreamCommand for EachGroup {
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let head = Arc::new(raw_args.call_info.args.head.clone());
|
||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||
let (each_args, input): (EachGroupArgs, _) = raw_args.process(®istry).await?;
|
||||
let block = Arc::new(each_args.block);
|
||||
|
@ -57,7 +57,7 @@ impl WholeStreamCommand for EachWindow {
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let head = Arc::new(raw_args.call_info.args.head.clone());
|
||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||
let (each_args, mut input): (EachWindowArgs, _) = raw_args.process(®istry).await?;
|
||||
let block = Arc::new(each_args.block);
|
||||
|
@ -3,7 +3,7 @@ use crate::commands::WholeStreamCommand;
|
||||
use crate::evaluate::evaluate_baseline_expr;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_protocol::{ReturnSuccess, Scope, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_source::Tagged;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
@ -54,7 +54,7 @@ async fn format_command(
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let scope = Arc::new(args.call_info.scope.clone());
|
||||
let scope = args.call_info.scope.clone();
|
||||
let (FormatArgs { pattern }, input) = args.process(®istry).await?;
|
||||
|
||||
let format_pattern = format(&pattern);
|
||||
@ -83,9 +83,7 @@ async fn format_command(
|
||||
let result = evaluate_baseline_expr(
|
||||
&full_column_path.0,
|
||||
®istry,
|
||||
&value,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
Scope::append_it(scope.clone(), value.clone()),
|
||||
)
|
||||
.await;
|
||||
|
||||
|
@ -96,7 +96,7 @@ pub async fn group_by(
|
||||
let name = args.call_info.name_tag.clone();
|
||||
let registry = registry.clone();
|
||||
let head = Arc::new(args.call_info.args.head.clone());
|
||||
let scope = Arc::new(args.call_info.scope.clone());
|
||||
let scope = args.call_info.scope.clone();
|
||||
let context = Arc::new(EvaluationContext::from_raw(&args, ®istry));
|
||||
let (GroupByArgs { grouper }, input) = args.process(®istry).await?;
|
||||
|
||||
|
@ -4,7 +4,9 @@ use crate::commands::WholeStreamCommand;
|
||||
use crate::evaluate::evaluate_baseline_expr;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::Block, hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue};
|
||||
use nu_protocol::{
|
||||
hir::Block, hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue,
|
||||
};
|
||||
|
||||
pub struct If;
|
||||
|
||||
@ -72,7 +74,7 @@ async fn if_command(
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let tag = raw_args.call_info.name_tag.clone();
|
||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||
|
||||
@ -119,14 +121,12 @@ async fn if_command(
|
||||
let then_case = then_case.clone();
|
||||
let else_case = else_case.clone();
|
||||
let registry = registry.clone();
|
||||
let scope = scope.clone();
|
||||
let scope = Scope::append_it(scope.clone(), input);
|
||||
let mut context = context.clone();
|
||||
|
||||
async move {
|
||||
//FIXME: should we use the scope that's brought in as well?
|
||||
let condition =
|
||||
evaluate_baseline_expr(&condition, &*registry, &input, &scope.vars, &scope.env)
|
||||
.await;
|
||||
let condition = evaluate_baseline_expr(&condition, &*registry, scope.clone()).await;
|
||||
|
||||
match condition {
|
||||
Ok(condition) => match condition.as_bool() {
|
||||
@ -136,9 +136,7 @@ async fn if_command(
|
||||
&then_case,
|
||||
Arc::make_mut(&mut context),
|
||||
InputStream::empty(),
|
||||
&input,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
scope,
|
||||
)
|
||||
.await
|
||||
{
|
||||
@ -151,9 +149,7 @@ async fn if_command(
|
||||
&else_case,
|
||||
Arc::make_mut(&mut context),
|
||||
InputStream::empty(),
|
||||
&input,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
scope,
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
@ -63,15 +63,9 @@ async fn process_row(
|
||||
let for_block = input.clone();
|
||||
let input_stream = once(async { Ok(for_block) }).to_input_stream();
|
||||
|
||||
let result = run_block(
|
||||
&block,
|
||||
Arc::make_mut(&mut context),
|
||||
input_stream,
|
||||
&input,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let scope = Scope::append_it(scope, input.clone());
|
||||
|
||||
let result = run_block(&block, Arc::make_mut(&mut context), input_stream, scope).await;
|
||||
|
||||
match result {
|
||||
Ok(mut stream) => {
|
||||
@ -118,7 +112,11 @@ async fn process_row(
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Nothing),
|
||||
..
|
||||
} => match scope.it.insert_data_at_column_path(&field, value.clone()) {
|
||||
} => match scope
|
||||
.it()
|
||||
.unwrap_or_else(|| UntaggedValue::nothing().into_untagged_value())
|
||||
.insert_data_at_column_path(&field, value.clone())
|
||||
{
|
||||
Ok(v) => OutputStream::one(ReturnSuccess::value(v)),
|
||||
Err(e) => OutputStream::one(Err(e)),
|
||||
},
|
||||
@ -135,7 +133,7 @@ async fn insert(
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||
let (InsertArgs { column, value }, input) = raw_args.process(®istry).await?;
|
||||
let value = Arc::new(value);
|
||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let scope = Arc::new(args.call_info.scope.clone());
|
||||
let scope = args.call_info.scope.clone();
|
||||
|
||||
let call_info = args.evaluate_once(®istry).await?;
|
||||
|
||||
@ -85,19 +85,11 @@ impl WholeStreamCommand for SubCommand {
|
||||
.take_while(move |item| {
|
||||
let condition = condition.clone();
|
||||
let registry = registry.clone();
|
||||
let scope = scope.clone();
|
||||
let item = item.clone();
|
||||
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||
trace!("ITEM = {:?}", item);
|
||||
|
||||
async move {
|
||||
let result = evaluate_baseline_expr(
|
||||
&*condition,
|
||||
®istry,
|
||||
&item,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||
trace!("RESULT = {:?}", result);
|
||||
|
||||
!matches!(result, Ok(ref v) if v.is_true())
|
||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let scope = Arc::new(args.call_info.scope.clone());
|
||||
let scope = args.call_info.scope.clone();
|
||||
let call_info = args.evaluate_once(®istry).await?;
|
||||
|
||||
let block = call_info.args.expect_nth(0)?.clone();
|
||||
@ -84,20 +84,11 @@ impl WholeStreamCommand for SubCommand {
|
||||
.take_while(move |item| {
|
||||
let condition = condition.clone();
|
||||
let registry = registry.clone();
|
||||
let scope = scope.clone();
|
||||
let item = item.clone();
|
||||
|
||||
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||
trace!("ITEM = {:?}", item);
|
||||
|
||||
async move {
|
||||
let result = evaluate_baseline_expr(
|
||||
&*condition,
|
||||
®istry,
|
||||
&item,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||
trace!("RESULT = {:?}", result);
|
||||
|
||||
matches!(result, Ok(ref v) if v.is_true())
|
||||
|
@ -60,21 +60,13 @@ async fn merge(
|
||||
let (merge_args, input): (MergeArgs, _) = raw_args.process(®istry).await?;
|
||||
let block = merge_args.block;
|
||||
|
||||
let table: Option<Vec<Value>> = match run_block(
|
||||
&block,
|
||||
&mut context,
|
||||
InputStream::empty(),
|
||||
&scope.it,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(mut stream) => Some(stream.drain_vec().await),
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
let table: Option<Vec<Value>> =
|
||||
match run_block(&block, &mut context, InputStream::empty(), scope).await {
|
||||
Ok(mut stream) => Some(stream.drain_vec().await),
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
let table = table.unwrap_or_else(|| {
|
||||
vec![Value {
|
||||
|
@ -87,15 +87,9 @@ async fn process_row(
|
||||
let row_clone = row.clone();
|
||||
let input_stream = once(async { Ok(row_clone) }).to_input_stream();
|
||||
|
||||
Ok(run_block(
|
||||
&block,
|
||||
Arc::make_mut(&mut context),
|
||||
input_stream,
|
||||
&row,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await?)
|
||||
let scope = Scope::append_it(scope, row);
|
||||
|
||||
Ok(run_block(&block, Arc::make_mut(&mut context), input_stream, scope).await?)
|
||||
}
|
||||
|
||||
async fn reduce(
|
||||
@ -133,7 +127,7 @@ async fn reduce(
|
||||
.enumerate()
|
||||
.fold(initial, move |acc, input| {
|
||||
let block = Arc::clone(&block);
|
||||
let mut scope = base_scope.clone();
|
||||
let scope = base_scope.clone();
|
||||
let context = Arc::clone(&context);
|
||||
let row = each::make_indexed_item(input.0 + ioffset, input.1);
|
||||
|
||||
@ -151,8 +145,8 @@ async fn reduce(
|
||||
UntaggedValue::table(&values).into_untagged_value()
|
||||
};
|
||||
|
||||
scope.vars.insert(String::from("$acc"), f);
|
||||
process_row(block, Arc::new(scope), context, row).await
|
||||
let scope = Scope::append_var(scope, "$acc".into(), f);
|
||||
process_row(block, scope, context, row).await
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -162,7 +156,7 @@ async fn reduce(
|
||||
Ok(input
|
||||
.fold(initial, move |acc, row| {
|
||||
let block = Arc::clone(&block);
|
||||
let mut scope = base_scope.clone();
|
||||
let scope = base_scope.clone();
|
||||
let context = Arc::clone(&context);
|
||||
|
||||
async {
|
||||
@ -179,8 +173,8 @@ async fn reduce(
|
||||
UntaggedValue::table(&values).into_untagged_value()
|
||||
};
|
||||
|
||||
scope.vars.insert(String::from("$acc"), f);
|
||||
process_row(block, Arc::new(scope), context, row).await
|
||||
let scope = Scope::append_var(scope, "$acc".into(), f);
|
||||
process_row(block, scope, context, row).await
|
||||
}
|
||||
})
|
||||
.await?
|
||||
|
@ -4,7 +4,7 @@ use crate::prelude::*;
|
||||
|
||||
use derive_new::new;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::Block, Signature, SyntaxShape};
|
||||
use nu_protocol::{hir::Block, Scope, Signature, SyntaxShape};
|
||||
|
||||
#[derive(new, Clone)]
|
||||
pub struct AliasCommand {
|
||||
@ -47,26 +47,21 @@ impl WholeStreamCommand for AliasCommand {
|
||||
let mut context = EvaluationContext::from_args(&args, ®istry);
|
||||
let input = args.input;
|
||||
|
||||
let mut scope = call_info.scope.clone();
|
||||
let scope = call_info.scope.clone();
|
||||
let evaluated = call_info.evaluate(®istry).await?;
|
||||
|
||||
let mut vars = IndexMap::new();
|
||||
if let Some(positional) = &evaluated.args.positional {
|
||||
for (pos, arg) in positional.iter().enumerate() {
|
||||
scope
|
||||
.vars
|
||||
.insert(alias_command.args[pos].0.to_string(), arg.clone());
|
||||
vars.insert(alias_command.args[pos].0.to_string(), arg.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let scope = Scope::append_vars(scope, vars);
|
||||
|
||||
// FIXME: we need to patch up the spans to point at the top-level error
|
||||
Ok(run_block(
|
||||
&block,
|
||||
&mut context,
|
||||
input,
|
||||
&scope.it,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await?
|
||||
.to_output_stream())
|
||||
Ok(run_block(&block, &mut context, input, scope)
|
||||
.await?
|
||||
.to_output_stream())
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ impl WholeStreamCommand for RunExternalCommand {
|
||||
command,
|
||||
&mut external_context,
|
||||
input,
|
||||
&scope,
|
||||
scope,
|
||||
external_redirection,
|
||||
)
|
||||
.await;
|
||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let scope = Arc::new(args.call_info.scope.clone());
|
||||
let scope = args.call_info.scope.clone();
|
||||
let call_info = args.evaluate_once(®istry).await?;
|
||||
|
||||
let block = call_info.args.expect_nth(0)?.clone();
|
||||
@ -84,19 +84,11 @@ impl WholeStreamCommand for SubCommand {
|
||||
.skip_while(move |item| {
|
||||
let condition = condition.clone();
|
||||
let registry = registry.clone();
|
||||
let scope = scope.clone();
|
||||
let item = item.clone();
|
||||
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||
trace!("ITEM = {:?}", item);
|
||||
|
||||
async move {
|
||||
let result = evaluate_baseline_expr(
|
||||
&*condition,
|
||||
®istry,
|
||||
&item,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||
trace!("RESULT = {:?}", result);
|
||||
|
||||
!matches!(result, Ok(ref v) if v.is_true())
|
||||
|
@ -3,7 +3,7 @@ use crate::evaluate::evaluate_baseline_expr;
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::ClassifiedCommand, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_protocol::{hir::ClassifiedCommand, Scope, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
@ -33,7 +33,7 @@ impl WholeStreamCommand for SubCommand {
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let scope = Arc::new(args.call_info.scope.clone());
|
||||
let scope = args.call_info.scope.clone();
|
||||
let call_info = args.evaluate_once(®istry).await?;
|
||||
|
||||
let block = call_info.args.expect_nth(0)?.clone();
|
||||
@ -85,18 +85,11 @@ impl WholeStreamCommand for SubCommand {
|
||||
let item = item.clone();
|
||||
let condition = condition.clone();
|
||||
let registry = registry.clone();
|
||||
let scope = scope.clone();
|
||||
let scope = Scope::append_it(scope.clone(), item.clone());
|
||||
trace!("ITEM = {:?}", item);
|
||||
|
||||
async move {
|
||||
let result = evaluate_baseline_expr(
|
||||
&*condition,
|
||||
®istry,
|
||||
&item,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let result = evaluate_baseline_expr(&*condition, ®istry, scope).await;
|
||||
trace!("RESULT = {:?}", result);
|
||||
|
||||
matches!(result, Ok(ref v) if v.is_true())
|
||||
|
@ -70,15 +70,9 @@ async fn process_row(
|
||||
let for_block = input.clone();
|
||||
let input_stream = once(async { Ok(for_block) }).to_input_stream();
|
||||
|
||||
let result = run_block(
|
||||
&block,
|
||||
Arc::make_mut(&mut context),
|
||||
input_stream,
|
||||
&input,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let scope = Scope::append_it(scope, input.clone());
|
||||
|
||||
let result = run_block(&block, Arc::make_mut(&mut context), input_stream, scope).await;
|
||||
|
||||
match result {
|
||||
Ok(mut stream) => {
|
||||
@ -130,7 +124,8 @@ async fn process_row(
|
||||
value: UntaggedValue::Primitive(Primitive::Nothing),
|
||||
..
|
||||
} => match scope
|
||||
.it
|
||||
.it()
|
||||
.unwrap_or_else(|| UntaggedValue::nothing().into_untagged_value())
|
||||
.replace_data_at_column_path(&field, replacement.clone())
|
||||
{
|
||||
Some(v) => OutputStream::one(ReturnSuccess::value(v)),
|
||||
@ -160,7 +155,7 @@ async fn update(
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = registry.clone();
|
||||
let name_tag = Arc::new(raw_args.call_info.name_tag.clone());
|
||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let context = Arc::new(EvaluationContext::from_raw(&raw_args, ®istry));
|
||||
let (UpdateArgs { field, replacement }, input) = raw_args.process(®istry).await?;
|
||||
let replacement = Arc::new(replacement);
|
||||
|
@ -3,7 +3,9 @@ use crate::commands::WholeStreamCommand;
|
||||
use crate::evaluate::evaluate_baseline_expr;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::Block, hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape};
|
||||
use nu_protocol::{
|
||||
hir::Block, hir::ClassifiedCommand, ReturnSuccess, Scope, Signature, SyntaxShape,
|
||||
};
|
||||
|
||||
pub struct Where;
|
||||
|
||||
@ -68,7 +70,7 @@ async fn where_command(
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let registry = Arc::new(registry.clone());
|
||||
let scope = Arc::new(raw_args.call_info.scope.clone());
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let tag = raw_args.call_info.name_tag.clone();
|
||||
let (WhereArgs { block }, input) = raw_args.process(®istry).await?;
|
||||
let condition = {
|
||||
@ -104,13 +106,11 @@ async fn where_command(
|
||||
.filter_map(move |input| {
|
||||
let condition = condition.clone();
|
||||
let registry = registry.clone();
|
||||
let scope = scope.clone();
|
||||
let scope = Scope::append_it(scope.clone(), input.clone());
|
||||
|
||||
async move {
|
||||
//FIXME: should we use the scope that's brought in as well?
|
||||
let condition =
|
||||
evaluate_baseline_expr(&condition, &*registry, &input, &scope.vars, &scope.env)
|
||||
.await;
|
||||
let condition = evaluate_baseline_expr(&condition, &*registry, scope).await;
|
||||
|
||||
match condition {
|
||||
Ok(condition) => match condition.as_bool() {
|
||||
|
@ -2,7 +2,9 @@ use crate::commands::classified::block::run_block;
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir::Block, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_protocol::{
|
||||
hir::Block, Scope, Signature, SpannedTypeName, SyntaxShape, UntaggedValue, Value,
|
||||
};
|
||||
|
||||
pub struct WithEnv;
|
||||
|
||||
@ -77,23 +79,23 @@ async fn with_env(
|
||||
let registry = registry.clone();
|
||||
|
||||
let mut context = EvaluationContext::from_raw(&raw_args, ®istry);
|
||||
let mut scope = raw_args.call_info.scope.clone();
|
||||
let scope = raw_args.call_info.scope.clone();
|
||||
let (WithEnvArgs { variable, block }, input) = raw_args.process(®istry).await?;
|
||||
|
||||
let mut env = IndexMap::new();
|
||||
|
||||
match &variable.value {
|
||||
UntaggedValue::Table(table) => {
|
||||
if table.len() == 1 {
|
||||
// single row([[X W]; [Y Z]])
|
||||
for (k, v) in table[0].row_entries() {
|
||||
scope.env.insert(k.clone(), v.convert_to_string());
|
||||
env.insert(k.clone(), v.convert_to_string());
|
||||
}
|
||||
} else {
|
||||
// primitive values([X Y W Z])
|
||||
for row in table.chunks(2) {
|
||||
if row.len() == 2 && row[0].is_primitive() && row[1].is_primitive() {
|
||||
scope
|
||||
.env
|
||||
.insert(row[0].convert_to_string(), row[1].convert_to_string());
|
||||
env.insert(row[0].convert_to_string(), row[1].convert_to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,7 +103,7 @@ async fn with_env(
|
||||
// when get object by `open x.json` or `from json`
|
||||
UntaggedValue::Row(row) => {
|
||||
for (k, v) in &row.entries {
|
||||
scope.env.insert(k.clone(), v.convert_to_string());
|
||||
env.insert(k.clone(), v.convert_to_string());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -112,15 +114,9 @@ async fn with_env(
|
||||
}
|
||||
};
|
||||
|
||||
let result = run_block(
|
||||
&block,
|
||||
&mut context,
|
||||
input,
|
||||
&scope.it,
|
||||
&scope.vars,
|
||||
&scope.env,
|
||||
)
|
||||
.await;
|
||||
let scope = Scope::append_env(scope, env);
|
||||
|
||||
let result = run_block(&block, &mut context, input, scope).await;
|
||||
|
||||
result.map(|x| x.to_output_stream())
|
||||
}
|
||||
|
@ -4,18 +4,18 @@ use crate::evaluate::evaluate_baseline_expr;
|
||||
use indexmap::IndexMap;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{hir, EvaluatedArgs, Scope, UntaggedValue, Value};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub(crate) async fn evaluate_args(
|
||||
call: &hir::Call,
|
||||
registry: &CommandRegistry,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<EvaluatedArgs, ShellError> {
|
||||
let mut positional_args: Vec<Value> = vec![];
|
||||
|
||||
if let Some(positional) = &call.positional {
|
||||
for pos in positional {
|
||||
let result =
|
||||
evaluate_baseline_expr(pos, registry, &scope.it, &scope.vars, &scope.env).await?;
|
||||
let result = evaluate_baseline_expr(pos, registry, scope.clone()).await?;
|
||||
positional_args.push(result);
|
||||
}
|
||||
}
|
||||
@ -37,8 +37,7 @@ pub(crate) async fn evaluate_args(
|
||||
hir::NamedValue::Value(_, expr) => {
|
||||
named_args.insert(
|
||||
name.clone(),
|
||||
evaluate_baseline_expr(expr, registry, &scope.it, &scope.vars, &scope.env)
|
||||
.await?,
|
||||
evaluate_baseline_expr(expr, registry, scope.clone()).await?,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -7,16 +7,14 @@ use log::trace;
|
||||
use nu_errors::{ArgumentError, ShellError};
|
||||
use nu_protocol::hir::{self, Expression, ExternalRedirection, RangeOperator, SpannedExpression};
|
||||
use nu_protocol::{
|
||||
ColumnPath, Primitive, RangeInclusion, UnspannedPathMember, UntaggedValue, Value,
|
||||
ColumnPath, Primitive, RangeInclusion, Scope, UnspannedPathMember, UntaggedValue, Value,
|
||||
};
|
||||
|
||||
#[async_recursion]
|
||||
pub(crate) async fn evaluate_baseline_expr(
|
||||
expr: &SpannedExpression,
|
||||
registry: &CommandRegistry,
|
||||
it: &Value,
|
||||
vars: &IndexMap<String, Value>,
|
||||
env: &IndexMap<String, String>,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<Value, ShellError> {
|
||||
let tag = Tag {
|
||||
span: expr.span,
|
||||
@ -33,14 +31,14 @@ pub(crate) async fn evaluate_baseline_expr(
|
||||
Expression::Synthetic(hir::Synthetic::String(s)) => {
|
||||
Ok(UntaggedValue::string(s).into_untagged_value())
|
||||
}
|
||||
Expression::Variable(var) => evaluate_reference(&var, it, vars, env, tag),
|
||||
Expression::Variable(var) => evaluate_reference(&var, scope, tag),
|
||||
Expression::Command => unimplemented!(),
|
||||
Expression::Invocation(block) => evaluate_invocation(block, registry, it, vars, env).await,
|
||||
Expression::Invocation(block) => evaluate_invocation(block, registry, scope).await,
|
||||
Expression::ExternalCommand(_) => unimplemented!(),
|
||||
Expression::Binary(binary) => {
|
||||
// TODO: If we want to add short-circuiting, we'll need to move these down
|
||||
let left = evaluate_baseline_expr(&binary.left, registry, it, vars, env).await?;
|
||||
let right = evaluate_baseline_expr(&binary.right, registry, it, vars, env).await?;
|
||||
let left = evaluate_baseline_expr(&binary.left, registry, scope.clone()).await?;
|
||||
let right = evaluate_baseline_expr(&binary.right, registry, scope).await?;
|
||||
|
||||
trace!("left={:?} right={:?}", left.value, right.value);
|
||||
|
||||
@ -62,13 +60,13 @@ pub(crate) async fn evaluate_baseline_expr(
|
||||
}
|
||||
Expression::Range(range) => {
|
||||
let left = if let Some(left) = &range.left {
|
||||
evaluate_baseline_expr(&left, registry, it, vars, env).await?
|
||||
evaluate_baseline_expr(&left, registry, scope.clone()).await?
|
||||
} else {
|
||||
Value::nothing()
|
||||
};
|
||||
|
||||
let right = if let Some(right) = &range.right {
|
||||
evaluate_baseline_expr(&right, registry, it, vars, env).await?
|
||||
evaluate_baseline_expr(&right, registry, scope).await?
|
||||
} else {
|
||||
Value::nothing()
|
||||
};
|
||||
@ -94,7 +92,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
||||
let mut output_headers = vec![];
|
||||
|
||||
for expr in headers {
|
||||
let val = evaluate_baseline_expr(&expr, registry, it, vars, env).await?;
|
||||
let val = evaluate_baseline_expr(&expr, registry, scope.clone()).await?;
|
||||
|
||||
let header = val.as_string()?;
|
||||
output_headers.push(header);
|
||||
@ -122,7 +120,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
||||
|
||||
let mut row_output = IndexMap::new();
|
||||
for cell in output_headers.iter().zip(row.iter()) {
|
||||
let val = evaluate_baseline_expr(&cell.1, registry, it, vars, env).await?;
|
||||
let val = evaluate_baseline_expr(&cell.1, registry, scope.clone()).await?;
|
||||
row_output.insert(cell.0.clone(), val);
|
||||
}
|
||||
output_table.push(UntaggedValue::row(row_output).into_value(tag.clone()));
|
||||
@ -134,7 +132,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
||||
let mut exprs = vec![];
|
||||
|
||||
for expr in list {
|
||||
let expr = evaluate_baseline_expr(&expr, registry, it, vars, env).await?;
|
||||
let expr = evaluate_baseline_expr(&expr, registry, scope.clone()).await?;
|
||||
exprs.push(expr);
|
||||
}
|
||||
|
||||
@ -142,7 +140,7 @@ pub(crate) async fn evaluate_baseline_expr(
|
||||
}
|
||||
Expression::Block(block) => Ok(UntaggedValue::Block(block.clone()).into_value(&tag)),
|
||||
Expression::Path(path) => {
|
||||
let value = evaluate_baseline_expr(&path.head, registry, it, vars, env).await?;
|
||||
let value = evaluate_baseline_expr(&path.head, registry, scope).await?;
|
||||
let mut item = value;
|
||||
|
||||
for member in &path.tail {
|
||||
@ -208,15 +206,20 @@ fn evaluate_literal(literal: &hir::Literal, span: Span) -> Value {
|
||||
|
||||
fn evaluate_reference(
|
||||
name: &hir::Variable,
|
||||
it: &Value,
|
||||
vars: &IndexMap<String, Value>,
|
||||
env: &IndexMap<String, String>,
|
||||
scope: Arc<Scope>,
|
||||
tag: Tag,
|
||||
) -> Result<Value, ShellError> {
|
||||
match name {
|
||||
hir::Variable::It(_) => Ok(it.clone()),
|
||||
hir::Variable::It(_) => match scope.it() {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(ShellError::labeled_error(
|
||||
"$it variable not in scope",
|
||||
"not in scope (are you missing an 'each'?)",
|
||||
tag.span,
|
||||
)),
|
||||
},
|
||||
hir::Variable::Other(name, _) => match name {
|
||||
x if x == "$nu" => crate::evaluate::variables::nu(env, tag),
|
||||
x if x == "$nu" => crate::evaluate::variables::nu(&scope.env(), tag),
|
||||
x if x == "$true" => Ok(Value {
|
||||
value: UntaggedValue::boolean(true),
|
||||
tag,
|
||||
@ -225,10 +228,14 @@ fn evaluate_reference(
|
||||
value: UntaggedValue::boolean(false),
|
||||
tag,
|
||||
}),
|
||||
x => Ok(vars
|
||||
.get(x)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| UntaggedValue::nothing().into_value(tag))),
|
||||
x => match scope.var(x) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(ShellError::labeled_error(
|
||||
"Variable not in scope",
|
||||
"unknown variable",
|
||||
tag.span,
|
||||
)),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -236,20 +243,21 @@ fn evaluate_reference(
|
||||
async fn evaluate_invocation(
|
||||
block: &hir::Block,
|
||||
registry: &CommandRegistry,
|
||||
it: &Value,
|
||||
vars: &IndexMap<String, Value>,
|
||||
env: &IndexMap<String, String>,
|
||||
scope: Arc<Scope>,
|
||||
) -> Result<Value, ShellError> {
|
||||
// FIXME: we should use a real context here
|
||||
let mut context = EvaluationContext::basic()?;
|
||||
context.registry = registry.clone();
|
||||
|
||||
let input = InputStream::one(it.clone());
|
||||
let input = match scope.it() {
|
||||
Some(it) => InputStream::one(it),
|
||||
None => InputStream::empty(),
|
||||
};
|
||||
|
||||
let mut block = block.clone();
|
||||
block.set_redirect(ExternalRedirection::Stdout);
|
||||
|
||||
let result = run_block(&block, &mut context, input, it, vars, env).await?;
|
||||
let result = run_block(&block, &mut context, input, scope).await?;
|
||||
|
||||
let output = result.into_vec().await;
|
||||
|
||||
|
@ -152,18 +152,18 @@ impl EvaluationContext {
|
||||
command: Command,
|
||||
name_tag: Tag,
|
||||
args: hir::Call,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
input: InputStream,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
let command_args = self.command_args(args, input, name_tag, scope);
|
||||
command.run(command_args, self.registry()).await
|
||||
}
|
||||
|
||||
fn call_info(&self, args: hir::Call, name_tag: Tag, scope: &Scope) -> UnevaluatedCallInfo {
|
||||
fn call_info(&self, args: hir::Call, name_tag: Tag, scope: Arc<Scope>) -> UnevaluatedCallInfo {
|
||||
UnevaluatedCallInfo {
|
||||
args,
|
||||
name_tag,
|
||||
scope: scope.clone(),
|
||||
scope,
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ impl EvaluationContext {
|
||||
args: hir::Call,
|
||||
input: InputStream,
|
||||
name_tag: Tag,
|
||||
scope: &Scope,
|
||||
scope: Arc<Scope>,
|
||||
) -> CommandArgs {
|
||||
CommandArgs {
|
||||
host: self.host.clone(),
|
||||
|
@ -1,9 +1,8 @@
|
||||
use futures::executor::block_on;
|
||||
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::hir::ClassifiedBlock;
|
||||
use nu_protocol::{ShellTypeName, Value};
|
||||
use nu_protocol::{Scope, ShellTypeName, Value};
|
||||
|
||||
use crate::commands::classified::block::run_block;
|
||||
use crate::commands::{whole_stream_command, BuildString, Each, Echo, StrCollect};
|
||||
@ -83,17 +82,12 @@ async fn evaluate_block(
|
||||
let input_stream = InputStream::empty();
|
||||
let env = ctx.get_env();
|
||||
|
||||
Ok(run_block(
|
||||
&block.block,
|
||||
ctx,
|
||||
input_stream,
|
||||
&Value::nothing(),
|
||||
&IndexMap::new(),
|
||||
&env,
|
||||
)
|
||||
.await?
|
||||
.into_vec()
|
||||
.await)
|
||||
let scope = Scope::from_env(env);
|
||||
|
||||
Ok(run_block(&block.block, ctx, input_stream, scope)
|
||||
.await?
|
||||
.into_vec()
|
||||
.await)
|
||||
}
|
||||
|
||||
// TODO probably something already available to do this
|
||||
|
@ -2,30 +2,121 @@ use crate::value::Value;
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// An evaluation scope. Scopes map variable names to Values and aid in evaluating blocks and expressions.
|
||||
/// Additionally, holds the value for the special $it variable, a variable used to refer to the value passing
|
||||
/// through the pipeline at that moment
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct Scope {
|
||||
pub it: Value,
|
||||
pub vars: IndexMap<String, Value>,
|
||||
pub env: IndexMap<String, String>,
|
||||
vars: IndexMap<String, Value>,
|
||||
env: IndexMap<String, String>,
|
||||
parent: Option<Arc<Scope>>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
/// Create an empty scope
|
||||
pub fn new() -> Scope {
|
||||
Scope {
|
||||
it: Value::nothing(),
|
||||
vars: IndexMap::new(),
|
||||
env: IndexMap::new(),
|
||||
pub fn vars(&self) -> IndexMap<String, Value> {
|
||||
//FIXME: should this be an interator?
|
||||
|
||||
let mut output = IndexMap::new();
|
||||
|
||||
for v in &self.vars {
|
||||
output.insert(v.0.clone(), v.1.clone());
|
||||
}
|
||||
|
||||
if let Some(parent) = &self.parent {
|
||||
for v in parent.vars() {
|
||||
if !output.contains_key(&v.0) {
|
||||
output.insert(v.0.clone(), v.1.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
pub fn env(&self) -> IndexMap<String, String> {
|
||||
//FIXME: should this be an interator?
|
||||
|
||||
let mut output = IndexMap::new();
|
||||
|
||||
for v in &self.env {
|
||||
output.insert(v.0.clone(), v.1.clone());
|
||||
}
|
||||
|
||||
if let Some(parent) = &self.parent {
|
||||
for v in parent.env() {
|
||||
if !output.contains_key(&v.0) {
|
||||
output.insert(v.0.clone(), v.1.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
pub fn var(&self, name: &str) -> Option<Value> {
|
||||
if let Some(value) = self.vars().get(name) {
|
||||
Some(value.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Scope {
|
||||
fn default() -> Scope {
|
||||
Scope::new()
|
||||
pub fn it(&self) -> Option<Value> {
|
||||
self.var("$it")
|
||||
}
|
||||
|
||||
pub fn from_env(env: IndexMap<String, String>) -> Arc<Scope> {
|
||||
Arc::new(Scope {
|
||||
vars: IndexMap::new(),
|
||||
env,
|
||||
parent: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn append_it(this: Arc<Self>, it: Value) -> Arc<Scope> {
|
||||
let mut vars = IndexMap::new();
|
||||
vars.insert("$it".into(), it);
|
||||
Arc::new(Scope {
|
||||
vars,
|
||||
env: IndexMap::new(),
|
||||
parent: Some(this),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn append_var(this: Arc<Self>, name: String, value: Value) -> Arc<Scope> {
|
||||
let mut vars = IndexMap::new();
|
||||
vars.insert(name, value);
|
||||
Arc::new(Scope {
|
||||
vars,
|
||||
env: IndexMap::new(),
|
||||
parent: Some(this),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn append_vars(this: Arc<Self>, vars: IndexMap<String, Value>) -> Arc<Scope> {
|
||||
Arc::new(Scope {
|
||||
vars,
|
||||
env: IndexMap::new(),
|
||||
parent: Some(this),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn append_env(this: Arc<Self>, env: IndexMap<String, String>) -> Arc<Scope> {
|
||||
Arc::new(Scope {
|
||||
vars: IndexMap::new(),
|
||||
env,
|
||||
parent: Some(this),
|
||||
})
|
||||
}
|
||||
|
||||
/// Create an empty scope
|
||||
pub fn create() -> Arc<Scope> {
|
||||
Arc::new(Scope {
|
||||
vars: IndexMap::new(),
|
||||
env: IndexMap::new(),
|
||||
parent: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user