Add export statement.
This commit is contained in:
parent
89d75b1b11
commit
eb52bfa28a
26
README.md
26
README.md
@ -2044,10 +2044,30 @@ Using external modules
|
|||||||
[module]: #using-external-modules
|
[module]: #using-external-modules
|
||||||
[modules]: #using-external-modules
|
[modules]: #using-external-modules
|
||||||
|
|
||||||
Rhai allows organizing code (functions and variables) into _modules_. A module is a single script file
|
Rhai allows organizing code (functions and variables) into _modules_.
|
||||||
with `export` statements that _exports_ certain global variables and functions as contents of the module.
|
Modules can be disabled via the [`no_module`] feature.
|
||||||
|
|
||||||
Everything exported as part of a module is constant and read-only.
|
### Exporting variables and functions
|
||||||
|
|
||||||
|
A module is a single script (or pre-compiled `AST`) containing global variables and functions.
|
||||||
|
The `export` statement, which can only be at global level, exposes selected variables as members of a module.
|
||||||
|
Variables not exported are private and invisible to the outside.
|
||||||
|
|
||||||
|
All functions are automatically exported. Everything exported from a module is **constant** (**read-only**).
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// This is a module script.
|
||||||
|
|
||||||
|
fn inc(x) { x + 1 } // function
|
||||||
|
|
||||||
|
let private = 123; // variable not exported - invisible to outside
|
||||||
|
let x = 42; // this will be exported below
|
||||||
|
|
||||||
|
export x; // the variable 'x' is exported under its own name
|
||||||
|
|
||||||
|
export x as answer; // the variable 'x' is exported under the alias 'answer'
|
||||||
|
// another script can load this module and access 'x' as 'module::answer'
|
||||||
|
```
|
||||||
|
|
||||||
### Importing modules
|
### Importing modules
|
||||||
|
|
||||||
|
@ -1622,7 +1622,10 @@ impl Engine {
|
|||||||
.try_cast::<String>()
|
.try_cast::<String>()
|
||||||
{
|
{
|
||||||
if let Some(resolver) = self.module_resolver.as_ref() {
|
if let Some(resolver) = self.module_resolver.as_ref() {
|
||||||
let module = resolver.resolve(self, &path, expr.position())?;
|
// Use an empty scope to create a module
|
||||||
|
let mut mod_scope = Scope::new();
|
||||||
|
let module =
|
||||||
|
resolver.resolve(self, mod_scope, &path, expr.position())?;
|
||||||
|
|
||||||
// TODO - avoid copying module name in inner block?
|
// TODO - avoid copying module name in inner block?
|
||||||
let mod_name = name.as_ref().clone();
|
let mod_name = name.as_ref().clone();
|
||||||
@ -1639,6 +1642,36 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Export statement
|
||||||
|
Stmt::Export(list) => {
|
||||||
|
for (id, id_pos, rename) in list {
|
||||||
|
let mut found = false;
|
||||||
|
|
||||||
|
// Mark scope variables as public
|
||||||
|
match scope.get_index(id) {
|
||||||
|
Some((index, ScopeEntryType::Normal))
|
||||||
|
| Some((index, ScopeEntryType::Constant)) => {
|
||||||
|
let alias = rename
|
||||||
|
.as_ref()
|
||||||
|
.map(|(n, _)| n.clone())
|
||||||
|
.unwrap_or_else(|| id.clone());
|
||||||
|
scope.set_entry_alias(index, alias);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
Some((_, ScopeEntryType::Module)) => unreachable!(),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return Err(Box::new(EvalAltResult::ErrorVariableNotFound(
|
||||||
|
id.into(),
|
||||||
|
*id_pos,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Default::default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
src/error.rs
16
src/error.rs
@ -98,6 +98,14 @@ pub enum ParseErrorType {
|
|||||||
///
|
///
|
||||||
/// Never appears under the `no_function` feature.
|
/// Never appears under the `no_function` feature.
|
||||||
FnMissingBody(String),
|
FnMissingBody(String),
|
||||||
|
/// An export statement has duplicated names.
|
||||||
|
///
|
||||||
|
/// Never appears under the `no_module` feature.
|
||||||
|
DuplicatedExport(String),
|
||||||
|
/// Export statement not at global level.
|
||||||
|
///
|
||||||
|
/// Never appears under the `no_module` feature.
|
||||||
|
WrongExport,
|
||||||
/// Assignment to a copy of a value.
|
/// Assignment to a copy of a value.
|
||||||
AssignmentToCopy,
|
AssignmentToCopy,
|
||||||
/// Assignment to an a constant variable.
|
/// Assignment to an a constant variable.
|
||||||
@ -147,6 +155,8 @@ impl ParseError {
|
|||||||
ParseErrorType::FnDuplicatedParam(_,_) => "Duplicated parameters in function declaration",
|
ParseErrorType::FnDuplicatedParam(_,_) => "Duplicated parameters in function declaration",
|
||||||
ParseErrorType::FnMissingBody(_) => "Expecting body statement block for function declaration",
|
ParseErrorType::FnMissingBody(_) => "Expecting body statement block for function declaration",
|
||||||
ParseErrorType::WrongFnDefinition => "Function definitions must be at global level and cannot be inside a block or another function",
|
ParseErrorType::WrongFnDefinition => "Function definitions must be at global level and cannot be inside a block or another function",
|
||||||
|
ParseErrorType::DuplicatedExport(_) => "Duplicated variable/function in export statement",
|
||||||
|
ParseErrorType::WrongExport => "Export statement can only appear at global level",
|
||||||
ParseErrorType::AssignmentToCopy => "Only a copy of the value is change with this assignment",
|
ParseErrorType::AssignmentToCopy => "Only a copy of the value is change with this assignment",
|
||||||
ParseErrorType::AssignmentToConstant(_) => "Cannot assign to a constant value.",
|
ParseErrorType::AssignmentToConstant(_) => "Cannot assign to a constant value.",
|
||||||
ParseErrorType::LoopBreak => "Break statement should only be used inside a loop"
|
ParseErrorType::LoopBreak => "Break statement should only be used inside a loop"
|
||||||
@ -193,6 +203,12 @@ impl fmt::Display for ParseError {
|
|||||||
write!(f, "Duplicated parameter '{}' for function '{}'", arg, s)?
|
write!(f, "Duplicated parameter '{}' for function '{}'", arg, s)?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParseErrorType::DuplicatedExport(s) => write!(
|
||||||
|
f,
|
||||||
|
"Duplicated variable/function '{}' in export statement",
|
||||||
|
s
|
||||||
|
)?,
|
||||||
|
|
||||||
ParseErrorType::MissingToken(token, s) => write!(f, "Expecting '{}' {}", token, s)?,
|
ParseErrorType::MissingToken(token, s) => write!(f, "Expecting '{}' {}", token, s)?,
|
||||||
|
|
||||||
ParseErrorType::AssignmentToConstant(s) if s.is_empty() => {
|
ParseErrorType::AssignmentToConstant(s) if s.is_empty() => {
|
||||||
|
@ -31,6 +31,7 @@ pub trait ModuleResolver {
|
|||||||
fn resolve(
|
fn resolve(
|
||||||
&self,
|
&self,
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
|
scope: Scope,
|
||||||
path: &str,
|
path: &str,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Module, Box<EvalAltResult>>;
|
) -> Result<Module, Box<EvalAltResult>>;
|
||||||
@ -570,17 +571,15 @@ impl Module {
|
|||||||
/// use rhai::{Engine, Module};
|
/// use rhai::{Engine, Module};
|
||||||
///
|
///
|
||||||
/// let engine = Engine::new();
|
/// let engine = Engine::new();
|
||||||
|
/// let mut scope = Scope::new();
|
||||||
/// let ast = engine.compile("let answer = 42;")?;
|
/// let ast = engine.compile("let answer = 42;")?;
|
||||||
/// let module = Module::eval_ast_as_new(&ast, &engine)?;
|
/// let module = Module::eval_ast_as_new(scope, &ast, &engine)?;
|
||||||
/// assert!(module.contains_var("answer"));
|
/// assert!(module.contains_var("answer"));
|
||||||
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
|
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval_ast_as_new(ast: &AST, engine: &Engine) -> FuncReturn<Self> {
|
pub fn eval_ast_as_new(mut scope: Scope, ast: &AST, engine: &Engine) -> FuncReturn<Self> {
|
||||||
// Use new scope
|
|
||||||
let mut scope = Scope::new();
|
|
||||||
|
|
||||||
// Run the script
|
// Run the script
|
||||||
engine.eval_ast_with_scope_raw(&mut scope, &ast)?;
|
engine.eval_ast_with_scope_raw(&mut scope, &ast)?;
|
||||||
|
|
||||||
@ -589,13 +588,19 @@ impl Module {
|
|||||||
|
|
||||||
scope.into_iter().for_each(
|
scope.into_iter().for_each(
|
||||||
|ScopeEntry {
|
|ScopeEntry {
|
||||||
name, typ, value, ..
|
name,
|
||||||
|
typ,
|
||||||
|
value,
|
||||||
|
alias,
|
||||||
|
..
|
||||||
}| {
|
}| {
|
||||||
match typ {
|
match typ {
|
||||||
// Variables left in the scope become module variables
|
// Variables with an alias left in the scope become module variables
|
||||||
ScopeEntryType::Normal | ScopeEntryType::Constant => {
|
ScopeEntryType::Normal | ScopeEntryType::Constant if alias.is_some() => {
|
||||||
module.variables.insert(name.into_owned(), value);
|
module.variables.insert(*alias.unwrap(), value);
|
||||||
}
|
}
|
||||||
|
// Variables with no alias are private and not exported
|
||||||
|
ScopeEntryType::Normal | ScopeEntryType::Constant => (),
|
||||||
// Modules left in the scope become sub-modules
|
// Modules left in the scope become sub-modules
|
||||||
ScopeEntryType::Module => {
|
ScopeEntryType::Module => {
|
||||||
module
|
module
|
||||||
@ -788,9 +793,10 @@ mod file {
|
|||||||
pub fn create_module<P: Into<PathBuf>>(
|
pub fn create_module<P: Into<PathBuf>>(
|
||||||
&self,
|
&self,
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
|
scope: Scope,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<Module, Box<EvalAltResult>> {
|
) -> Result<Module, Box<EvalAltResult>> {
|
||||||
self.resolve(engine, path, Default::default())
|
self.resolve(engine, scope, path, Default::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,6 +804,7 @@ mod file {
|
|||||||
fn resolve(
|
fn resolve(
|
||||||
&self,
|
&self,
|
||||||
engine: &Engine,
|
engine: &Engine,
|
||||||
|
scope: Scope,
|
||||||
path: &str,
|
path: &str,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Module, Box<EvalAltResult>> {
|
) -> Result<Module, Box<EvalAltResult>> {
|
||||||
@ -811,7 +818,7 @@ mod file {
|
|||||||
.compile_file(file_path)
|
.compile_file(file_path)
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))?;
|
.map_err(|err| EvalAltResult::set_position(err, pos))?;
|
||||||
|
|
||||||
Module::eval_ast_as_new(&ast, engine)
|
Module::eval_ast_as_new(scope, &ast, engine)
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
.map_err(|err| EvalAltResult::set_position(err, pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -938,6 +945,7 @@ mod stat {
|
|||||||
fn resolve(
|
fn resolve(
|
||||||
&self,
|
&self,
|
||||||
_: &Engine,
|
_: &Engine,
|
||||||
|
_: Scope,
|
||||||
path: &str,
|
path: &str,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Module, Box<EvalAltResult>> {
|
) -> Result<Module, Box<EvalAltResult>> {
|
||||||
|
@ -284,6 +284,8 @@ pub enum Stmt {
|
|||||||
ReturnWithVal(Option<Box<Expr>>, ReturnType, Position),
|
ReturnWithVal(Option<Box<Expr>>, ReturnType, Position),
|
||||||
/// import expr as module
|
/// import expr as module
|
||||||
Import(Box<Expr>, Box<String>, Position),
|
Import(Box<Expr>, Box<String>, Position),
|
||||||
|
/// expr id as name, ...
|
||||||
|
Export(Vec<(String, Position, Option<(String, Position)>)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stmt {
|
impl Stmt {
|
||||||
@ -302,6 +304,8 @@ impl Stmt {
|
|||||||
Stmt::IfThenElse(expr, _, _) | Stmt::Expr(expr) => expr.position(),
|
Stmt::IfThenElse(expr, _, _) | Stmt::Expr(expr) => expr.position(),
|
||||||
|
|
||||||
Stmt::While(_, stmt) | Stmt::Loop(stmt) | Stmt::For(_, _, stmt) => stmt.position(),
|
Stmt::While(_, stmt) | Stmt::Loop(stmt) | Stmt::For(_, _, stmt) => stmt.position(),
|
||||||
|
|
||||||
|
Stmt::Export(list) => list.get(0).unwrap().1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,6 +324,7 @@ impl Stmt {
|
|||||||
Stmt::Let(_, _, _)
|
Stmt::Let(_, _, _)
|
||||||
| Stmt::Const(_, _, _)
|
| Stmt::Const(_, _, _)
|
||||||
| Stmt::Import(_, _, _)
|
| Stmt::Import(_, _, _)
|
||||||
|
| Stmt::Export(_)
|
||||||
| Stmt::Expr(_)
|
| Stmt::Expr(_)
|
||||||
| Stmt::Continue(_)
|
| Stmt::Continue(_)
|
||||||
| Stmt::Break(_)
|
| Stmt::Break(_)
|
||||||
@ -344,6 +349,7 @@ impl Stmt {
|
|||||||
Stmt::Block(statements, _) => statements.iter().all(Stmt::is_pure),
|
Stmt::Block(statements, _) => statements.iter().all(Stmt::is_pure),
|
||||||
Stmt::Continue(_) | Stmt::Break(_) | Stmt::ReturnWithVal(_, _, _) => false,
|
Stmt::Continue(_) | Stmt::Break(_) | Stmt::ReturnWithVal(_, _, _) => false,
|
||||||
Stmt::Import(_, _, _) => false,
|
Stmt::Import(_, _, _) => false,
|
||||||
|
Stmt::Export(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1970,6 +1976,63 @@ fn parse_import<'a>(
|
|||||||
Ok(Stmt::Import(Box::new(expr), Box::new(name), pos))
|
Ok(Stmt::Import(Box::new(expr), Box::new(name), pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse an export statement.
|
||||||
|
fn parse_export<'a>(input: &mut Peekable<TokenIterator<'a>>) -> Result<Stmt, Box<ParseError>> {
|
||||||
|
eat_token(input, Token::Export);
|
||||||
|
|
||||||
|
let mut exports = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (id, id_pos) = match input.next().unwrap() {
|
||||||
|
(Token::Identifier(s), pos) => (s.clone(), pos),
|
||||||
|
(Token::LexError(err), pos) => {
|
||||||
|
return Err(PERR::BadInput(err.to_string()).into_err(pos))
|
||||||
|
}
|
||||||
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rename = if match_token(input, Token::As)? {
|
||||||
|
match input.next().unwrap() {
|
||||||
|
(Token::Identifier(s), pos) => Some((s.clone(), pos)),
|
||||||
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.push((id, id_pos, rename));
|
||||||
|
|
||||||
|
match input.peek().unwrap() {
|
||||||
|
(Token::Comma, _) => {
|
||||||
|
eat_token(input, Token::Comma);
|
||||||
|
}
|
||||||
|
(Token::Identifier(_), pos) => {
|
||||||
|
return Err(PERR::MissingToken(
|
||||||
|
Token::Comma.into(),
|
||||||
|
"to separate the list of exports".into(),
|
||||||
|
)
|
||||||
|
.into_err(*pos))
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicating parameters
|
||||||
|
exports
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.try_for_each(|(i, (p1, _, _))| {
|
||||||
|
exports
|
||||||
|
.iter()
|
||||||
|
.skip(i + 1)
|
||||||
|
.find(|(p2, _, _)| p2 == p1)
|
||||||
|
.map_or_else(|| Ok(()), |(p2, pos, _)| Err((p2, *pos)))
|
||||||
|
})
|
||||||
|
.map_err(|(p, pos)| PERR::DuplicatedExport(p.to_string()).into_err(pos))?;
|
||||||
|
|
||||||
|
Ok(Stmt::Export(exports))
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a statement block.
|
/// Parse a statement block.
|
||||||
fn parse_block<'a>(
|
fn parse_block<'a>(
|
||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
@ -1995,7 +2058,7 @@ fn parse_block<'a>(
|
|||||||
|
|
||||||
while !match_token(input, Token::RightBrace)? {
|
while !match_token(input, Token::RightBrace)? {
|
||||||
// Parse statements inside the block
|
// Parse statements inside the block
|
||||||
let stmt = parse_stmt(input, stack, breakable, allow_stmt_expr)?;
|
let stmt = parse_stmt(input, stack, breakable, false, allow_stmt_expr)?;
|
||||||
|
|
||||||
// See if it needs a terminating semicolon
|
// See if it needs a terminating semicolon
|
||||||
let need_semicolon = !stmt.is_self_terminated();
|
let need_semicolon = !stmt.is_self_terminated();
|
||||||
@ -2053,6 +2116,7 @@ fn parse_stmt<'a>(
|
|||||||
input: &mut Peekable<TokenIterator<'a>>,
|
input: &mut Peekable<TokenIterator<'a>>,
|
||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
breakable: bool,
|
breakable: bool,
|
||||||
|
is_global: bool,
|
||||||
allow_stmt_expr: bool,
|
allow_stmt_expr: bool,
|
||||||
) -> Result<Stmt, Box<ParseError>> {
|
) -> Result<Stmt, Box<ParseError>> {
|
||||||
let (token, pos) = match input.peek().unwrap() {
|
let (token, pos) = match input.peek().unwrap() {
|
||||||
@ -2113,6 +2177,12 @@ fn parse_stmt<'a>(
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
Token::Import => parse_import(input, stack, allow_stmt_expr),
|
Token::Import => parse_import(input, stack, allow_stmt_expr),
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
Token::Export if !is_global => Err(PERR::WrongExport.into_err(*pos)),
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
Token::Export => parse_export(input),
|
||||||
|
|
||||||
_ => parse_expr_stmt(input, stack, allow_stmt_expr),
|
_ => parse_expr_stmt(input, stack, allow_stmt_expr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2123,7 +2193,7 @@ fn parse_fn<'a>(
|
|||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
allow_stmt_expr: bool,
|
allow_stmt_expr: bool,
|
||||||
) -> Result<FnDef, Box<ParseError>> {
|
) -> Result<FnDef, Box<ParseError>> {
|
||||||
let pos = input.next().expect("should be fn").1;
|
let pos = eat_token(input, Token::Fn);
|
||||||
|
|
||||||
let name = match input.next().unwrap() {
|
let name = match input.next().unwrap() {
|
||||||
(Token::Identifier(s), _) => s,
|
(Token::Identifier(s), _) => s,
|
||||||
@ -2258,7 +2328,7 @@ fn parse_global_level<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Actual statement
|
// Actual statement
|
||||||
let stmt = parse_stmt(input, &mut stack, false, true)?;
|
let stmt = parse_stmt(input, &mut stack, false, true, true)?;
|
||||||
|
|
||||||
let need_semicolon = !stmt.is_self_terminated();
|
let need_semicolon = !stmt.is_self_terminated();
|
||||||
|
|
||||||
|
17
src/scope.rs
17
src/scope.rs
@ -30,6 +30,8 @@ pub struct Entry<'a> {
|
|||||||
pub typ: EntryType,
|
pub typ: EntryType,
|
||||||
/// Current value of the entry.
|
/// Current value of the entry.
|
||||||
pub value: Dynamic,
|
pub value: Dynamic,
|
||||||
|
/// Alias of the entry.
|
||||||
|
pub alias: Option<Box<String>>,
|
||||||
/// A constant expression if the initial value matches one of the recognized types.
|
/// A constant expression if the initial value matches one of the recognized types.
|
||||||
pub expr: Option<Box<Expr>>,
|
pub expr: Option<Box<Expr>>,
|
||||||
}
|
}
|
||||||
@ -248,6 +250,7 @@ impl<'a> Scope<'a> {
|
|||||||
self.0.push(Entry {
|
self.0.push(Entry {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
typ: entry_type,
|
typ: entry_type,
|
||||||
|
alias: None,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
expr,
|
expr,
|
||||||
});
|
});
|
||||||
@ -412,16 +415,15 @@ impl<'a> Scope<'a> {
|
|||||||
/// Get a mutable reference to an entry in the Scope.
|
/// Get a mutable reference to an entry in the Scope.
|
||||||
pub(crate) fn get_mut(&mut self, index: usize) -> (&mut Dynamic, EntryType) {
|
pub(crate) fn get_mut(&mut self, index: usize) -> (&mut Dynamic, EntryType) {
|
||||||
let entry = self.0.get_mut(index).expect("invalid index in Scope");
|
let entry = self.0.get_mut(index).expect("invalid index in Scope");
|
||||||
|
|
||||||
// assert_ne!(
|
|
||||||
// entry.typ,
|
|
||||||
// EntryType::Constant,
|
|
||||||
// "get mut of constant entry"
|
|
||||||
// );
|
|
||||||
|
|
||||||
(&mut entry.value, entry.typ)
|
(&mut entry.value, entry.typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the access type of an entry in the Scope.
|
||||||
|
pub(crate) fn set_entry_alias(&mut self, index: usize, alias: String) {
|
||||||
|
let entry = self.0.get_mut(index).expect("invalid index in Scope");
|
||||||
|
entry.alias = Some(Box::new(alias));
|
||||||
|
}
|
||||||
|
|
||||||
/// Get an iterator to entries in the Scope.
|
/// Get an iterator to entries in the Scope.
|
||||||
pub(crate) fn into_iter(self) -> impl Iterator<Item = Entry<'a>> {
|
pub(crate) fn into_iter(self) -> impl Iterator<Item = Entry<'a>> {
|
||||||
self.0.into_iter()
|
self.0.into_iter()
|
||||||
@ -439,6 +441,7 @@ impl<'a, K: Into<Cow<'a, str>>> iter::Extend<(K, EntryType, Dynamic)> for Scope<
|
|||||||
.extend(iter.into_iter().map(|(name, typ, value)| Entry {
|
.extend(iter.into_iter().map(|(name, typ, value)| Entry {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
typ,
|
typ,
|
||||||
|
alias: None,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
expr: None,
|
expr: None,
|
||||||
}));
|
}));
|
||||||
|
Loading…
Reference in New Issue
Block a user