forked from AbleScript/ablescript
Implemented finally
This commit is contained in:
parent
844ccd731a
commit
472b41cf16
|
@ -142,6 +142,7 @@ pub enum Stmt {
|
|||
},
|
||||
Read(Assignable),
|
||||
Melo(Spanned<String>),
|
||||
Finally(Block),
|
||||
Rlyeh,
|
||||
Rickroll,
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
use crate::{
|
||||
ast::{Assignable, AssignableKind, Expr, Spanned, Stmt},
|
||||
ast::{Assignable, AssignableKind, Block, Expr, Spanned, Stmt},
|
||||
consts::ablescript_consts,
|
||||
error::{Error, ErrorKind},
|
||||
value::{Functio, Value, ValueRef, Variable},
|
||||
|
@ -37,6 +37,9 @@ pub struct ExecEnv {
|
|||
/// (via the `read` statement). We store each of those bits as
|
||||
/// booleans to facilitate easy manipulation.
|
||||
read_buf: VecDeque<bool>,
|
||||
|
||||
/// Vector of blocks to be executed at the end of the program
|
||||
finalisers: Vec<Block>,
|
||||
}
|
||||
|
||||
/// A set of visible variable and function definitions in a single
|
||||
|
@ -51,6 +54,7 @@ impl Default for ExecEnv {
|
|||
Self {
|
||||
stack: vec![Default::default()],
|
||||
read_buf: Default::default(),
|
||||
finalisers: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +103,7 @@ impl ExecEnv {
|
|||
|
||||
Self {
|
||||
stack: vec![scope],
|
||||
read_buf: Default::default(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +119,13 @@ impl ExecEnv {
|
|||
kind: ErrorKind::TopLevelEnough,
|
||||
span,
|
||||
}),
|
||||
}?;
|
||||
|
||||
for block in std::mem::take(&mut self.finalisers) {
|
||||
self.eval_stmts_hs(&block, true)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The same as `eval_stmts`, but report "enough" and "and again"
|
||||
|
@ -302,6 +312,7 @@ impl ExecEnv {
|
|||
}
|
||||
}
|
||||
},
|
||||
Stmt::Finally(block) => self.finalisers.push(block.clone()),
|
||||
Stmt::Rlyeh => {
|
||||
// Maybe print a creepy error message or something
|
||||
// here at some point. ~~Alex
|
||||
|
@ -468,7 +479,9 @@ impl ExecEnv {
|
|||
}
|
||||
};
|
||||
}
|
||||
Functio::Eval(code) => self.eval_stmts(&crate::parser::parse(&code)?)?,
|
||||
Functio::Eval(code) => {
|
||||
self.eval_stmts_hs(&crate::parser::parse(&code)?, false)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -101,6 +101,10 @@ pub enum Token {
|
|||
#[token("and again")]
|
||||
AndAgain,
|
||||
|
||||
/// Run at the end of the program
|
||||
#[token("finally")]
|
||||
Finally,
|
||||
|
||||
/// Crash with random error (see discussion #17)
|
||||
#[token("rlyeh")]
|
||||
Rlyeh,
|
||||
|
|
|
@ -70,9 +70,10 @@ impl<'source> Parser<'source> {
|
|||
Token::Functio => self.functio_flow(),
|
||||
Token::Bff => self.bff_flow(),
|
||||
Token::Melo => self.melo_flow(),
|
||||
Token::Loop => self.loop_flow(),
|
||||
Token::Loop => self.get_block().map(|body| Stmt::Loop { body }),
|
||||
Token::Enough => self.semicolon_terminated(Stmt::Enough),
|
||||
Token::AndAgain => self.semicolon_terminated(Stmt::AndAgain),
|
||||
Token::Finally => self.get_block().map(Stmt::Finally),
|
||||
Token::Rlyeh => self.semicolon_terminated(Stmt::Rlyeh),
|
||||
Token::Rickroll => self.semicolon_terminated(Stmt::Rickroll),
|
||||
|
||||
|
@ -558,15 +559,6 @@ impl<'source> Parser<'source> {
|
|||
self.semicolon_terminated(Stmt::Melo(ident))
|
||||
}
|
||||
|
||||
/// Parse loop flow
|
||||
///
|
||||
/// `loop` is an infinite loop, no condition, only body
|
||||
fn loop_flow(&mut self) -> Result<Stmt, Error> {
|
||||
Ok(Stmt::Loop {
|
||||
body: self.get_block()?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Perform lang -> script substitution if in T-Dark block
|
||||
fn tdark_subst(&self, mut string: String) -> String {
|
||||
if self.tdark {
|
||||
|
|
|
@ -18,8 +18,9 @@ use std::{
|
|||
pub type Cart = HashMap<Value, ValueRef>;
|
||||
|
||||
/// AbleScript Value
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub enum Value {
|
||||
#[default]
|
||||
Nul,
|
||||
Undefined,
|
||||
Str(String),
|
||||
|
@ -29,12 +30,6 @@ pub enum Value {
|
|||
Cart(Cart),
|
||||
}
|
||||
|
||||
impl Default for Value {
|
||||
fn default() -> Self {
|
||||
Self::Nul
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Value {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
discriminant(self).hash(state);
|
||||
|
|
Loading…
Reference in a new issue