From b791d1ab0d4cd161b50ab1c07357aad5812b9852 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Fri, 9 Apr 2021 20:12:25 +1200 Subject: [PATCH] Move from using a Block to an Arc'd Block (#3289) --- crates/nu-cli/src/cli.rs | 6 +++- crates/nu-cli/src/completion/engine.rs | 6 ++-- crates/nu-command/src/commands/benchmark.rs | 32 +++++++++++--------- crates/nu-command/src/commands/do_.rs | 4 ++- crates/nu-command/src/commands/with_env.rs | 4 ++- crates/nu-engine/src/evaluate/scope.rs | 8 ++--- crates/nu-engine/src/whole_stream_command.rs | 7 +++-- crates/nu-parser/src/parse.rs | 26 ++++++++-------- crates/nu-parser/src/parse/def.rs | 16 ++++++++-- crates/nu-parser/src/scope.rs | 6 ++-- crates/nu-protocol/src/hir.rs | 20 ++++++------ 11 files changed, 81 insertions(+), 54 deletions(-) diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 322f65c5d..ed69824bc 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -233,7 +233,11 @@ pub fn cli(context: EvaluationContext, options: Options) -> Result<(), Box::get_mut(&mut prompt_block) + { + block.set_redirect(ExternalRedirection::Stdout); + } if err.is_some() { context.scope.exit_scope(); diff --git a/crates/nu-cli/src/completion/engine.rs b/crates/nu-cli/src/completion/engine.rs index fe9160d14..1e0f386cd 100644 --- a/crates/nu-cli/src/completion/engine.rs +++ b/crates/nu-cli/src/completion/engine.rs @@ -254,6 +254,8 @@ pub fn completion_location(line: &str, block: &Block, pos: usize) -> Vec) {} - fn get_definitions(&self) -> Vec { + fn get_definitions(&self) -> Vec> { vec![] } diff --git a/crates/nu-command/src/commands/benchmark.rs b/crates/nu-command/src/commands/benchmark.rs index f84e5857a..190b8450e 100644 --- a/crates/nu-command/src/commands/benchmark.rs +++ b/crates/nu-command/src/commands/benchmark.rs @@ -166,21 +166,23 @@ where } } -fn add_implicit_autoview(mut block: Block) -> Block { - if block.block.is_empty() { - let group = Group::new( - vec![{ - let mut commands = Pipeline::new(block.span); - commands.push(ClassifiedCommand::Internal(InternalCommand::new( - "autoview".to_string(), - block.span, - block.span, - ))); - commands - }], - block.span, - ); - block.push(group); +fn add_implicit_autoview(mut block: Arc) -> Arc { + if let Some(block) = std::sync::Arc::::get_mut(&mut block) { + if block.block.is_empty() { + let group = Group::new( + vec![{ + let mut commands = Pipeline::new(block.span); + commands.push(ClassifiedCommand::Internal(InternalCommand::new( + "autoview".to_string(), + block.span, + block.span, + ))); + commands + }], + block.span, + ); + block.push(group); + } } block } diff --git a/crates/nu-command/src/commands/do_.rs b/crates/nu-command/src/commands/do_.rs index 3ba98b4ae..d4f0ab7de 100644 --- a/crates/nu-command/src/commands/do_.rs +++ b/crates/nu-command/src/commands/do_.rs @@ -81,7 +81,9 @@ fn do_(raw_args: CommandArgs) -> Result { x => x, }; - block.block.set_redirect(block_redirection); + if let Some(block) = std::sync::Arc::::get_mut(&mut block.block) { + block.set_redirect(block_redirection); + } context.scope.enter_scope(); let result = run_block(&block.block, &context, input); context.scope.exit_scope(); diff --git a/crates/nu-command/src/commands/with_env.rs b/crates/nu-command/src/commands/with_env.rs index 68dc4ade0..98bf4d1f0 100644 --- a/crates/nu-command/src/commands/with_env.rs +++ b/crates/nu-command/src/commands/with_env.rs @@ -78,7 +78,9 @@ fn with_env(raw_args: CommandArgs) -> Result { input, ) = raw_args.process()?; - block.block.set_redirect(redirection); + if let Some(block) = std::sync::Arc::::get_mut(&mut block.block) { + block.set_redirect(redirection); + } let mut env = IndexMap::new(); diff --git a/crates/nu-engine/src/evaluate/scope.rs b/crates/nu-engine/src/evaluate/scope.rs index fda0d400a..40d57f0fc 100644 --- a/crates/nu-engine/src/evaluate/scope.rs +++ b/crates/nu-engine/src/evaluate/scope.rs @@ -61,7 +61,7 @@ impl Scope { } } - pub fn get_custom_commands_with_name(&self, name: &str) -> Option> { + pub fn get_custom_commands_with_name(&self, name: &str) -> Option>> { let custom_commands: Vec<_> = self .frames .lock() @@ -307,7 +307,7 @@ impl ParserScope for Scope { self.get_command(name).is_some() } - fn add_definition(&self, block: Block) { + fn add_definition(&self, block: Arc) { if let Some(frame) = self.frames.lock().last_mut() { let name = block.params.name.clone(); frame.custom_commands.insert(name.clone(), block.clone()); @@ -315,7 +315,7 @@ impl ParserScope for Scope { } } - fn get_definitions(&self) -> Vec { + fn get_definitions(&self) -> Vec> { let mut blocks = vec![]; if let Some(frame) = self.frames.lock().last() { for (_, custom_command) in &frame.custom_commands { @@ -356,7 +356,7 @@ pub struct ScopeFrame { pub vars: IndexMap, pub env: IndexMap, pub commands: IndexMap, - pub custom_commands: IndexMap, + pub custom_commands: IndexMap>, pub aliases: IndexMap>>, ///Optional tag to better identify this scope frame later pub tag: Option, diff --git a/crates/nu-engine/src/whole_stream_command.rs b/crates/nu-engine/src/whole_stream_command.rs index 189027b86..873176b16 100644 --- a/crates/nu-engine/src/whole_stream_command.rs +++ b/crates/nu-engine/src/whole_stream_command.rs @@ -44,7 +44,7 @@ pub trait WholeStreamCommand: Send + Sync { // implement a WholeStreamCommand #[allow(clippy::suspicious_else_formatting)] -impl WholeStreamCommand for Block { +impl WholeStreamCommand for Arc { fn name(&self) -> &str { &self.params.name } @@ -61,7 +61,10 @@ impl WholeStreamCommand for Block { let call_info = args.call_info.clone(); let mut block = self.clone(); - block.set_redirect(call_info.args.external_redirection); + + if let Some(block) = std::sync::Arc::::get_mut(&mut block) { + block.set_redirect(call_info.args.external_redirection); + } let ctx = EvaluationContext::from_args(&args); let evaluated = call_info.evaluate(&ctx)?; diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index aad2aee20..b350b877e 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::{path::Path, sync::Arc}; use indexmap::IndexMap; use log::trace; @@ -428,7 +428,9 @@ fn parse_invocation( let (mut classified_block, err) = classify_block(&lite_block, scope); scope.exit_scope(); - classified_block.set_redirect(ExternalRedirection::Stdout); + if let Some(x) = std::sync::Arc::::get_mut(&mut classified_block) { + x.set_redirect(ExternalRedirection::Stdout); + } ( SpannedExpression::new(Expression::Invocation(classified_block), lite_arg.span), @@ -638,12 +640,12 @@ fn parse_interpolated_string( let group = Group::new(pipelines, lite_arg.span); let call = SpannedExpression { - expr: Expression::Invocation(Block::new( + expr: Expression::Invocation(Arc::new(Block::new( Signature::new(""), vec![group], IndexMap::new(), lite_arg.span, - )), + ))), span: lite_arg.span, }; @@ -1286,7 +1288,7 @@ fn parse_positional_argument( span, ); - let arg = SpannedExpression::new(Expression::Block(block), span); + let arg = SpannedExpression::new(Expression::Block(Arc::new(block)), span); idx = new_idx - 1; if error.is_none() { @@ -1329,7 +1331,7 @@ fn parse_positional_argument( span, ); - let arg = SpannedExpression::new(Expression::Block(block), span); + let arg = SpannedExpression::new(Expression::Block(Arc::new(block)), span); idx = new_idx - 1; if error.is_none() { @@ -1948,7 +1950,7 @@ fn parse_alias(call: &LiteCommand, scope: &dyn ParserScope) -> Option (Block, Option) { +) -> (Arc, Option) { let mut output = Block::basic(); let mut error = None; @@ -2012,7 +2014,7 @@ pub fn classify_block( span: Span::new(vars.0.span.start(), vars.1.span.end()), }, SpannedExpression { - expr: Expression::Block(block), + expr: Expression::Block(Arc::new(block)), span, }, ]); @@ -2048,21 +2050,21 @@ pub fn classify_block( } output.infer_params(); - (output, error) + (Arc::new(output), error) } pub fn parse( input: &str, span_offset: usize, scope: &dyn ParserScope, -) -> (Block, Option) { +) -> (Arc, Option) { let (output, error) = lex(input, span_offset); if error.is_some() { - return (Block::basic(), error); + return (Arc::new(Block::basic()), error); } let (lite_block, error) = parse_block(output); if error.is_some() { - return (Block::basic(), error); + return (Arc::new(Block::basic()), error); } classify_block(&lite_block, scope) diff --git a/crates/nu-parser/src/parse/def.rs b/crates/nu-parser/src/parse/def.rs index 68dd3da01..c176e3874 100644 --- a/crates/nu-parser/src/parse/def.rs +++ b/crates/nu-parser/src/parse/def.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crate::{ lex::tokens::LiteCommand, parse::{classify_block, util::trim_quotes}, @@ -64,8 +66,11 @@ pub(crate) fn parse_definition(call: &LiteCommand, scope: &dyn ParserScope) -> O let (mut block, err) = classify_block(&lite_block, scope); scope.exit_scope(); - block.params = signature; - block.params.name = name; + if let Some(block) = std::sync::Arc::::get_mut(&mut block) + { + block.params = signature; + block.params.name = name; + } scope.add_definition(block); @@ -100,7 +105,12 @@ pub(crate) fn parse_definition_prototype( err = error; } - scope.add_definition(Block::new(signature, vec![], IndexMap::new(), call.span())); + scope.add_definition(Arc::new(Block::new( + signature, + vec![], + IndexMap::new(), + call.span(), + ))); err } diff --git a/crates/nu-parser/src/scope.rs b/crates/nu-parser/src/scope.rs index 058966cd9..a112e163c 100644 --- a/crates/nu-parser/src/scope.rs +++ b/crates/nu-parser/src/scope.rs @@ -1,15 +1,15 @@ use nu_protocol::hir::Block; use nu_source::Spanned; -use std::fmt::Debug; +use std::{fmt::Debug, sync::Arc}; pub trait ParserScope: Debug { fn get_signature(&self, name: &str) -> Option; fn has_signature(&self, name: &str) -> bool; - fn add_definition(&self, block: Block); + fn add_definition(&self, block: Arc); - fn get_definitions(&self) -> Vec; + fn get_definitions(&self) -> Vec>; fn get_alias(&self, name: &str) -> Option>>; diff --git a/crates/nu-protocol/src/hir.rs b/crates/nu-protocol/src/hir.rs index 64f9b59bd..8fa090195 100644 --- a/crates/nu-protocol/src/hir.rs +++ b/crates/nu-protocol/src/hir.rs @@ -1,7 +1,7 @@ use std::cmp::{Ord, Ordering, PartialOrd}; -use std::convert::From; use std::hash::{Hash, Hasher}; use std::path::PathBuf; +use std::{convert::From, sync::Arc}; use serde::{Deserialize, Serialize}; @@ -53,14 +53,14 @@ impl InternalCommand { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] pub struct ClassifiedBlock { - pub block: Block, + pub block: Arc, // this is not a Result to make it crystal clear that these shapes // aren't intended to be used directly with `?` pub failed: Option, } impl ClassifiedBlock { - pub fn new(block: Block, failed: Option) -> ClassifiedBlock { + pub fn new(block: Arc, failed: Option) -> ClassifiedBlock { ClassifiedBlock { block, failed } } } @@ -159,12 +159,12 @@ impl Group { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)] pub struct CapturedBlock { - pub block: Block, + pub block: Arc, pub captured: Dictionary, } impl CapturedBlock { - pub fn new(block: Block, captured: Dictionary) -> Self { + pub fn new(block: Arc, captured: Dictionary) -> Self { Self { block, captured } } } @@ -173,7 +173,7 @@ impl CapturedBlock { pub struct Block { pub params: Signature, pub block: Vec, - pub definitions: IndexMap, + pub definitions: IndexMap>, pub span: Span, } @@ -181,7 +181,7 @@ impl Block { pub fn new( params: Signature, block: Vec, - definitions: IndexMap, + definitions: IndexMap>, span: Span, ) -> Block { Block { @@ -632,7 +632,7 @@ pub fn duration(nanos: BigInt) -> UntaggedValue { UntaggedValue::Primitive(Primitive::Duration(nanos)) } -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Deserialize, Serialize)] +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Deserialize, Serialize)] pub struct SpannedExpression { pub expr: Expression, pub span: Span, @@ -1026,7 +1026,7 @@ pub enum Expression { Variable(String, Span), Binary(Box), Range(Box), - Block(hir::Block), + Block(Arc), List(Vec), Table(Vec, Vec>), Path(Box), @@ -1034,7 +1034,7 @@ pub enum Expression { FilePath(PathBuf), ExternalCommand(ExternalStringCommand), Command, - Invocation(hir::Block), + Invocation(Arc), Boolean(bool),