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] 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() }