better syntax for exporting
This commit is contained in:
@@ -1,6 +1,3 @@
|
|||||||
|
|
||||||
use crate::executor::Executor;
|
|
||||||
|
|
||||||
use super::{Value, Type, Function, FunctionType};
|
use super::{Value, Type, Function, FunctionType};
|
||||||
use super::tokenizer::{Token, TokenType, Op};
|
use super::tokenizer::{Token, TokenType, Op};
|
||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
@@ -388,21 +385,26 @@ impl Parser {
|
|||||||
Box::new(cond), Box::new(truebranch), Box::new(falsebranch))))
|
Box::new(cond), Box::new(truebranch), Box::new(falsebranch))))
|
||||||
},
|
},
|
||||||
Op::Export => {
|
Op::Export => {
|
||||||
let list = self.parse(tokens)?.ok_or(
|
let token = tokens.next()
|
||||||
Error::new("export expects one argument of [String], but found nothing".into())
|
.ok_or(Error::new("export expects one argument of [String], but found nothing".into())
|
||||||
.location(token.line, token.location.clone())
|
.location(token.line, token.location.clone()))??;
|
||||||
)?;
|
|
||||||
|
|
||||||
let list = Executor::new().exec(list)?;
|
let names = match token.token() {
|
||||||
|
TokenType::Identifier(ident) => vec![ident],
|
||||||
|
TokenType::Operator(Op::OpenStatement) => {
|
||||||
|
tokens
|
||||||
|
.take_while(|token| !matches!(token.clone().map(|token| token.token()), Ok(TokenType::Operator(Op::CloseStatement))))
|
||||||
|
.map(|token| token.map(|token| match token.token() {
|
||||||
|
TokenType::Identifier(ident) => Ok(ident),
|
||||||
|
_ => Err(Error::new(format!("expected an identifier")).location(token.line, token.location))
|
||||||
|
})?)
|
||||||
|
.collect::<Result<_, Error>>()?
|
||||||
|
}
|
||||||
|
_ => return Err(Error::new("export expects one or more identifiers".into()).location(token.line, token.location)),
|
||||||
|
};
|
||||||
|
|
||||||
if let Value::Array(Type::String, items) = list {
|
for name in &names {
|
||||||
let names = items.into_iter().map(|x| match x {
|
let (name, t) = self.locals.remove_entry(name)
|
||||||
Value::String(s) => s,
|
|
||||||
_ => unreachable!(),
|
|
||||||
});
|
|
||||||
|
|
||||||
for name in names.clone() {
|
|
||||||
let t = self.locals.remove(&name)
|
|
||||||
.ok_or(
|
.ok_or(
|
||||||
Error::new(format!("attempt to export {name}, which is not in local scope"))
|
Error::new(format!("attempt to export {name}, which is not in local scope"))
|
||||||
.location(token.line, token.location.clone())
|
.location(token.line, token.location.clone())
|
||||||
@@ -411,13 +413,7 @@ impl Parser {
|
|||||||
self.globals.insert(name, t);
|
self.globals.insert(name, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(ParseTree::Export(names.collect())))
|
Ok(Some(ParseTree::Export(names)))
|
||||||
} else {
|
|
||||||
Err(
|
|
||||||
Error::new(format!("export expects one argument of [String], but found {}", list.get_type()))
|
|
||||||
.location(token.line, token.location)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
op => self.parse_operator(tokens, op).map(|x| Some(x)),
|
op => self.parse_operator(tokens, op).map(|x| Some(x)),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user