From a176f12c9e3ba98fdb0be9b4988e69f0c68e7a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Fri, 24 Sep 2021 21:12:30 +0300 Subject: [PATCH 1/7] Start simple module parsing --- crates/nu-parser/src/parser.rs | 118 +++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 71b2005fa7..9869936a36 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2649,6 +2649,123 @@ pub fn parse_alias( ) } +pub fn parse_module( + working_set: &mut StateWorkingSet, + spans: &[Span], +) -> (Statement, Option) { + let mut error = None; + let bytes = working_set.get_span_contents(spans[0]); + + // parse_def() equivalent + if bytes == b"module" && spans.len() >= 3 { + let (name_expr, err) = parse_string(working_set, spans[1]); + error = error.or(err); + + // parse_block_expression() equivalent + let block_span = spans[2]; + let block_bytes = working_set.get_span_contents(block_span); + let mut start = block_span.start; + let mut end = block_span.end; + + if block_bytes.starts_with(b"{") { + start += 1; + } else { + return ( + garbage_statement(spans), + Some(ParseError::Expected("block".into(), block_span)), + ); + } + + if block_bytes.ends_with(b"}") { + end -= 1; + } else { + error = error.or_else(|| { + Some(ParseError::Unclosed( + "}".into(), + Span { + start: end, + end: end + 1, + }, + )) + }); + } + + let block_span = Span { start, end }; + + let source = working_set.get_span_contents(block_span); + + let (output, err) = lex(source, start, &[], &[]); + error = error.or(err); + + working_set.enter_scope(); + + // Do we need block parameters? + + let (output, err) = lite_parse(&output); + error = error.or(err); + + // We probably don't need $it + + // we're doing parse_block() equivalent + // let (mut output, err) = parse_block(working_set, &output, false); + + for pipeline in &output.block { + if pipeline.commands.len() == 1 { + parse_def_predecl(working_set, &pipeline.commands[0].parts); + } + } + + let block: Block = output + .block + .iter() + .map(|pipeline| { + if pipeline.commands.len() == 1 { + // this one here is doing parse_statement() equivalent + // let (stmt, err) = parse_statement(working_set, &pipeline.commands[0].parts); + let name = working_set.get_span_contents(pipeline.commands[0].parts[0]); + + let (stmt, err) = match name { + // TODO: Here we can add other stuff that's alowed for modules + b"def" => parse_def(working_set, &pipeline.commands[0].parts), + _ => ( + garbage_statement(&pipeline.commands[0].parts), + Some(ParseError::Expected("def".into(), block_span)), + ) + }; + + if error.is_none() { + error = err; + } + + stmt + } else { + error = Some(ParseError::Expected("not a pipeline".into(), block_span)); + garbage_statement(spans) + } + }) + .into(); + + working_set.exit_scope(); + + // WIP error: + ( + garbage_statement(spans), + Some(ParseError::UnknownState( + "This is OK module".into(), + span(spans), + )), + ) + } else { + ( + garbage_statement(spans), + Some(ParseError::UnknownState( + "Expected structure: module {}".into(), + span(spans), + )), + ) + } +} + pub fn parse_let( working_set: &mut StateWorkingSet, spans: &[Span], @@ -2707,6 +2824,7 @@ pub fn parse_statement( b"def" => parse_def(working_set, spans), b"let" => parse_let(working_set, spans), b"alias" => parse_alias(working_set, spans), + b"module" => parse_module(working_set, spans), _ => { let (expr, err) = parse_expression(working_set, spans); (Statement::Pipeline(Pipeline::from_vec(vec![expr])), err) From e9f1575924475ac8da93a9f7624fb0c7b479105f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Sun, 26 Sep 2021 01:59:18 +0300 Subject: [PATCH 2/7] Add a module command --- crates/nu-command/src/default_context.rs | 4 ++- crates/nu-command/src/lib.rs | 2 ++ crates/nu-parser/src/parser.rs | 33 +++++++++++++++++++----- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 5890d791cb..43f68d27e4 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -7,7 +7,7 @@ use nu_protocol::{ use crate::{ where_::Where, Alias, Benchmark, BuildString, Def, Do, Each, External, For, Git, GitCheckout, - If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Table, + If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Table, }; pub fn create_default_context() -> Rc> { @@ -46,6 +46,8 @@ pub fn create_default_context() -> Rc> { working_set.add_decl(Box::new(Ls)); + working_set.add_decl(Box::new(Module)); + working_set.add_decl(Box::new(Table)); working_set.add_decl(Box::new(External)); diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index 1f150c2c65..a788812025 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -16,6 +16,7 @@ mod lines; mod list_git_branches; mod ls; mod run_external; +mod module; mod table; mod where_; @@ -37,4 +38,5 @@ pub use lines::Lines; pub use list_git_branches::ListGitBranches; pub use ls::Ls; pub use run_external::External; +pub use module::Module; pub use table::Table; diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 9869936a36..012addf4b2 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2747,13 +2747,34 @@ pub fn parse_module( working_set.exit_scope(); - // WIP error: + let block_id = working_set.add_block(block); + + let block_expr = Expression { + expr: Expr::Block(block_id), + span: block_span, + ty: Type::Block, + custom_completion: None, + }; + + let module_decl_id = working_set + .find_decl(b"module") + .expect("internal error: missing module command"); + + let call = Box::new(Call { + head: spans[0], + decl_id: module_decl_id, + positional: vec![name_expr, block_expr], + named: vec![], + }); + ( - garbage_statement(spans), - Some(ParseError::UnknownState( - "This is OK module".into(), - span(spans), - )), + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Call(call), + span: span(spans), + ty: Type::Unknown, + custom_completion: None, + }])), + error, ) } else { ( From 12cf1a8f830680d304e9d18c37bc52cb369ad105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Sun, 26 Sep 2021 15:00:03 +0300 Subject: [PATCH 3/7] Allow adding module blocks to engine state --- crates/nu-command/src/lib.rs | 4 +-- crates/nu-parser/src/parser.rs | 29 +++++++++++++++---- crates/nu-protocol/src/ast/block.rs | 11 +++++++ crates/nu-protocol/src/engine/engine_state.rs | 19 ++++++++++++ 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index a788812025..86142f32b0 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -15,8 +15,8 @@ mod let_env; mod lines; mod list_git_branches; mod ls; -mod run_external; mod module; +mod run_external; mod table; mod where_; @@ -37,6 +37,6 @@ pub use let_env::LetEnv; pub use lines::Lines; pub use list_git_branches::ListGitBranches; pub use ls::Ls; -pub use run_external::External; pub use module::Module; +pub use run_external::External; pub use table::Table; diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 012addf4b2..5fbebc4ebd 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2658,9 +2658,13 @@ pub fn parse_module( // parse_def() equivalent if bytes == b"module" && spans.len() >= 3 { - let (name_expr, err) = parse_string(working_set, spans[1]); + let (module_name_expr, err) = parse_string(working_set, spans[1]); error = error.or(err); + let module_name = module_name_expr + .as_string() + .expect("internal error: module name is not a string"); + // parse_block_expression() equivalent let block_span = spans[2]; let block_bytes = working_set.get_span_contents(block_span); @@ -2715,6 +2719,8 @@ pub fn parse_module( } } + let mut exports: Vec> = vec![]; + let block: Block = output .block .iter() @@ -2726,11 +2732,22 @@ pub fn parse_module( let (stmt, err) = match name { // TODO: Here we can add other stuff that's alowed for modules - b"def" => parse_def(working_set, &pipeline.commands[0].parts), + b"def" => { + let (stmt, err) = parse_def(working_set, &pipeline.commands[0].parts); + + if err.is_none() { + let def_name = + working_set.get_span_contents(pipeline.commands[0].parts[1]); + // TODO: Later, we want to put this behind 'export' + exports.push(def_name.into()); + } + + (stmt, err) + } _ => ( garbage_statement(&pipeline.commands[0].parts), Some(ParseError::Expected("def".into(), block_span)), - ) + ), }; if error.is_none() { @@ -2745,9 +2762,11 @@ pub fn parse_module( }) .into(); + let block = block.with_exports(exports); + working_set.exit_scope(); - let block_id = working_set.add_block(block); + let block_id = working_set.add_module(&module_name, block); let block_expr = Expression { expr: Expr::Block(block_id), @@ -2763,7 +2782,7 @@ pub fn parse_module( let call = Box::new(Call { head: spans[0], decl_id: module_decl_id, - positional: vec![name_expr, block_expr], + positional: vec![module_name_expr, block_expr], named: vec![], }); diff --git a/crates/nu-protocol/src/ast/block.rs b/crates/nu-protocol/src/ast/block.rs index e5db26da36..33de58ca84 100644 --- a/crates/nu-protocol/src/ast/block.rs +++ b/crates/nu-protocol/src/ast/block.rs @@ -8,6 +8,7 @@ use super::Statement; pub struct Block { pub signature: Box, pub stmts: Vec, + pub exports: Vec>, // Assuming just defs for now } impl Block { @@ -45,6 +46,15 @@ impl Block { Self { signature: Box::new(Signature::new("")), stmts: vec![], + exports: vec![], + } + } + + pub fn with_exports(self, exports: Vec>) -> Self { + Self { + signature: self.signature, + stmts: self.stmts, + exports, } } } @@ -57,6 +67,7 @@ where Self { signature: Box::new(Signature::new("")), stmts: stmts.collect(), + exports: vec![], } } } diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 6a75884289..7108225312 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -17,6 +17,7 @@ pub struct ScopeFrame { vars: HashMap, VarId>, decls: HashMap, DeclId>, aliases: HashMap, Vec>, + modules: HashMap, BlockId>, } impl ScopeFrame { @@ -25,6 +26,7 @@ impl ScopeFrame { vars: HashMap::new(), decls: HashMap::new(), aliases: HashMap::new(), + modules: HashMap::new(), } } @@ -290,6 +292,23 @@ impl<'a> StateWorkingSet<'a> { self.num_blocks() - 1 } + pub fn add_module(&mut self, name: &str, block: Block) -> BlockId { + let name = name.as_bytes().to_vec(); + + self.delta.blocks.push(block); + let block_id = self.num_blocks() - 1; + + let scope_frame = self + .delta + .scope + .last_mut() + .expect("internal error: missing required scope frame"); + + scope_frame.modules.insert(name, block_id); + + block_id + } + pub fn next_span_start(&self) -> usize { self.permanent_state.next_span_start() + self.delta.file_contents.len() } From 57a07385ace6b9b42a5c60613753698c63f61795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Sun, 26 Sep 2021 13:25:37 +0300 Subject: [PATCH 4/7] Add leftover Module command file --- crates/nu-command/src/module.rs | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 crates/nu-command/src/module.rs diff --git a/crates/nu-command/src/module.rs b/crates/nu-command/src/module.rs new file mode 100644 index 0000000000..e2cec960d8 --- /dev/null +++ b/crates/nu-command/src/module.rs @@ -0,0 +1,34 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::{Signature, SyntaxShape, Value}; + +pub struct Module; + +impl Command for Module { + fn name(&self) -> &str { + "module" + } + + fn usage(&self) -> &str { + "Define a custom module" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("module") + .required("module_name", SyntaxShape::String, "module name") + .required( + "block", + SyntaxShape::Block(Some(vec![])), + "body of the module", + ) + } + + fn run( + &self, + _context: &EvaluationContext, + call: &Call, + _input: Value, + ) -> Result { + Ok(Value::Nothing { span: call.head }) + } +} From 9e176674a5b08d7af63bc78db21ce3351e9b64a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Sun, 26 Sep 2021 13:25:52 +0300 Subject: [PATCH 5/7] Start parsing 'use'; Add Use command --- crates/nu-command/src/default_context.rs | 4 +- crates/nu-command/src/lib.rs | 2 + crates/nu-command/src/use_.rs | 29 +++++++++ crates/nu-parser/src/errors.rs | 4 ++ crates/nu-parser/src/parser.rs | 60 +++++++++++++++++++ crates/nu-protocol/src/engine/engine_state.rs | 19 ++++++ 6 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 crates/nu-command/src/use_.rs diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index 43f68d27e4..4c793baa4c 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -7,7 +7,7 @@ use nu_protocol::{ use crate::{ where_::Where, Alias, Benchmark, BuildString, Def, Do, Each, External, For, Git, GitCheckout, - If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Table, + If, Length, Let, LetEnv, Lines, ListGitBranches, Ls, Module, Table, Use, }; pub fn create_default_context() -> Rc> { @@ -48,6 +48,8 @@ pub fn create_default_context() -> Rc> { working_set.add_decl(Box::new(Module)); + working_set.add_decl(Box::new(Use)); + working_set.add_decl(Box::new(Table)); working_set.add_decl(Box::new(External)); diff --git a/crates/nu-command/src/lib.rs b/crates/nu-command/src/lib.rs index 86142f32b0..a96a41ec3b 100644 --- a/crates/nu-command/src/lib.rs +++ b/crates/nu-command/src/lib.rs @@ -18,6 +18,7 @@ mod ls; mod module; mod run_external; mod table; +mod use_; mod where_; pub use alias::Alias; @@ -40,3 +41,4 @@ pub use ls::Ls; pub use module::Module; pub use run_external::External; pub use table::Table; +pub use use_::Use; diff --git a/crates/nu-command/src/use_.rs b/crates/nu-command/src/use_.rs new file mode 100644 index 0000000000..e317adbffb --- /dev/null +++ b/crates/nu-command/src/use_.rs @@ -0,0 +1,29 @@ +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EvaluationContext}; +use nu_protocol::{Signature, SyntaxShape, Value}; + +pub struct Use; + +impl Command for Use { + fn name(&self) -> &str { + "use" + } + + fn usage(&self) -> &str { + "Use definitions from a module" + } + + fn signature(&self) -> nu_protocol::Signature { + Signature::build("use") + .required("module_name", SyntaxShape::String, "module name") + } + + fn run( + &self, + _context: &EvaluationContext, + call: &Call, + _input: Value, + ) -> Result { + Ok(Value::Nothing { span: call.head }) + } +} diff --git a/crates/nu-parser/src/errors.rs b/crates/nu-parser/src/errors.rs index 6d400f67b4..52f3983c1f 100644 --- a/crates/nu-parser/src/errors.rs +++ b/crates/nu-parser/src/errors.rs @@ -65,6 +65,10 @@ pub enum ParseError { #[diagnostic(code(nu::parser::variable_not_found), url(docsrs))] VariableNotFound(#[label = "variable not found"] Span), + #[error("Module not found.")] + #[diagnostic(code(nu::parser::module_not_found), url(docsrs))] + ModuleNotFound(#[label = "module not found"] Span), + #[error("Unknown command.")] #[diagnostic( code(nu::parser::unknown_command), diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 5fbebc4ebd..822fd2f403 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -2806,6 +2806,65 @@ pub fn parse_module( } } +pub fn parse_use( + working_set: &mut StateWorkingSet, + spans: &[Span], +) -> (Statement, Option) { + let mut error = None; + let bytes = working_set.get_span_contents(spans[0]); + + // TODO: Currently, this directly imports the module's definitions into the current scope. + // Later, we want to put them behind the module's name and add selective importing + if bytes == b"use" && spans.len() >= 2 { + let (module_name_expr, err) = parse_string(working_set, spans[1]); + error = error.or(err); + + let module_name = module_name_expr + .as_string() + .expect("internal error: module name is not a string"); + + let module_name_bytes = module_name.as_bytes().to_vec(); + + let block = if let Some(block_id) = working_set.find_module(&module_name_bytes) { + working_set.get_block(block_id) + } else { + return ( + garbage_statement(spans), + Some(ParseError::ModuleNotFound(spans[1])), + ); + }; + + let use_decl_id = working_set + .find_decl(b"use") + .expect("internal error: missing use command"); + + let call = Box::new(Call { + head: spans[0], + decl_id: use_decl_id, + positional: vec![module_name_expr], + named: vec![], + }); + + ( + Statement::Pipeline(Pipeline::from_vec(vec![Expression { + expr: Expr::Call(call), + span: span(spans), + ty: Type::Unknown, + custom_completion: None, + }])), + error, + ) + } else { + ( + garbage_statement(spans), + Some(ParseError::UnknownState( + "Expected structure: use ".into(), + span(spans), + )), + ) + } +} + pub fn parse_let( working_set: &mut StateWorkingSet, spans: &[Span], @@ -2865,6 +2924,7 @@ pub fn parse_statement( b"let" => parse_let(working_set, spans), b"alias" => parse_alias(working_set, spans), b"module" => parse_module(working_set, spans), + b"use" => parse_use(working_set, spans), _ => { let (expr, err) = parse_expression(working_set, spans); (Statement::Pipeline(Pipeline::from_vec(vec![expr])), err) diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 7108225312..bd51f47647 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -78,6 +78,9 @@ impl EngineState { for item in first.aliases.into_iter() { last.aliases.insert(item.0, item.1); } + for item in first.modules.into_iter() { + last.modules.insert(item.0, item.1); + } } } @@ -394,6 +397,22 @@ impl<'a> StateWorkingSet<'a> { None } + pub fn find_module(&self, name: &[u8]) -> Option { + for scope in self.delta.scope.iter().rev() { + if let Some(block_id) = scope.modules.get(name) { + return Some(*block_id); + } + } + + for scope in self.permanent_state.scope.iter().rev() { + if let Some(block_id) = scope.modules.get(name) { + return Some(*block_id); + } + } + + None + } + // pub fn update_decl(&mut self, decl_id: usize, block: Option) { // let decl = self.get_decl_mut(decl_id); // decl.body = block; From f57f7b2defa985dc1fc6f521947bfc6549659c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Sun, 26 Sep 2021 13:53:52 +0300 Subject: [PATCH 6/7] Allow adding definitions from module into scope --- crates/nu-parser/src/parser.rs | 26 ++++++++++++++----- crates/nu-protocol/src/ast/block.rs | 6 ++--- crates/nu-protocol/src/engine/engine_state.rs | 14 ++++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 822fd2f403..805c637484 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -10,7 +10,7 @@ use nu_protocol::{ RangeInclusion, RangeOperator, Statement, }, engine::StateWorkingSet, - span, Flag, PositionalArg, Signature, Span, SyntaxShape, Type, VarId, + span, DeclId, Flag, PositionalArg, Signature, Span, SyntaxShape, Type, VarId, }; #[derive(Debug, Clone)] @@ -2653,6 +2653,9 @@ pub fn parse_module( working_set: &mut StateWorkingSet, spans: &[Span], ) -> (Statement, Option) { + // TODO: Currently, module is closing over its parent scope (i.e., defs in the parent scope are + // visible and usable in this module's scope). We might want to disable that. How? + let mut error = None; let bytes = working_set.get_span_contents(spans[0]); @@ -2719,7 +2722,7 @@ pub fn parse_module( } } - let mut exports: Vec> = vec![]; + let mut exports: Vec<(Vec, DeclId)> = vec![]; let block: Block = output .block @@ -2736,10 +2739,15 @@ pub fn parse_module( let (stmt, err) = parse_def(working_set, &pipeline.commands[0].parts); if err.is_none() { - let def_name = + let decl_name = working_set.get_span_contents(pipeline.commands[0].parts[1]); + + let decl_id = working_set + .find_decl(decl_name) + .expect("internal error: failed to find added declaration"); + // TODO: Later, we want to put this behind 'export' - exports.push(def_name.into()); + exports.push((decl_name.into(), decl_id)); } (stmt, err) @@ -2825,8 +2833,10 @@ pub fn parse_use( let module_name_bytes = module_name.as_bytes().to_vec(); - let block = if let Some(block_id) = working_set.find_module(&module_name_bytes) { - working_set.get_block(block_id) + let exports = if let Some(block_id) = working_set.find_module(&module_name_bytes) { + // TODO: Since we don't use the Block at all, we might just as well create a separate + // Module that holds only the exports, without having Blocks in the way. + working_set.get_block(block_id).exports.clone() } else { return ( garbage_statement(spans), @@ -2834,6 +2844,10 @@ pub fn parse_use( ); }; + // Extend the current scope with the module's exports + working_set.activate_overlay(exports); + + // Create the Use command call let use_decl_id = working_set .find_decl(b"use") .expect("internal error: missing use command"); diff --git a/crates/nu-protocol/src/ast/block.rs b/crates/nu-protocol/src/ast/block.rs index 33de58ca84..a5ea245664 100644 --- a/crates/nu-protocol/src/ast/block.rs +++ b/crates/nu-protocol/src/ast/block.rs @@ -1,6 +1,6 @@ use std::ops::{Index, IndexMut}; -use crate::Signature; +use crate::{Signature, DeclId}; use super::Statement; @@ -8,7 +8,7 @@ use super::Statement; pub struct Block { pub signature: Box, pub stmts: Vec, - pub exports: Vec>, // Assuming just defs for now + pub exports: Vec<(Vec, DeclId)>, // Assuming just defs for now } impl Block { @@ -50,7 +50,7 @@ impl Block { } } - pub fn with_exports(self, exports: Vec>) -> Self { + pub fn with_exports(self, exports: Vec<(Vec, DeclId)>) -> Self { Self { signature: self.signature, stmts: self.stmts, diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index bd51f47647..ede56b40c1 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -312,6 +312,20 @@ impl<'a> StateWorkingSet<'a> { block_id } + pub fn activate_overlay(&mut self, overlay: Vec<(Vec, DeclId)>) { + // TODO: This will overwrite all existing definitions in a scope. When we add deactivate, + // we need to re-think how make it recoverable. + let scope_frame = self + .delta + .scope + .last_mut() + .expect("internal error: missing required scope frame"); + + for (name, decl_id) in overlay { + scope_frame.decls.insert(name, decl_id); + } + } + pub fn next_span_start(&self) -> usize { self.permanent_state.next_span_start() + self.delta.file_contents.len() } From 3f8f3ecf9ae4c16f29a85fe5a5d4046756507373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Sun, 26 Sep 2021 14:12:39 +0300 Subject: [PATCH 7/7] Fmt --- crates/nu-command/src/use_.rs | 3 +-- crates/nu-protocol/src/ast/block.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/nu-command/src/use_.rs b/crates/nu-command/src/use_.rs index e317adbffb..30b5e3d0b0 100644 --- a/crates/nu-command/src/use_.rs +++ b/crates/nu-command/src/use_.rs @@ -14,8 +14,7 @@ impl Command for Use { } fn signature(&self) -> nu_protocol::Signature { - Signature::build("use") - .required("module_name", SyntaxShape::String, "module name") + Signature::build("use").required("module_name", SyntaxShape::String, "module name") } fn run( diff --git a/crates/nu-protocol/src/ast/block.rs b/crates/nu-protocol/src/ast/block.rs index a5ea245664..70273816b5 100644 --- a/crates/nu-protocol/src/ast/block.rs +++ b/crates/nu-protocol/src/ast/block.rs @@ -1,6 +1,6 @@ use std::ops::{Index, IndexMut}; -use crate::{Signature, DeclId}; +use crate::{DeclId, Signature}; use super::Statement;