Implemented finally

trunk
ondra05 2022-07-01 22:56:22 +02:00
parent 7e31c857bf
commit 4a2674a035
5 changed files with 26 additions and 21 deletions

View File

@ -142,6 +142,7 @@ pub enum Stmt {
},
Read(Assignable),
Melo(Spanned<String>),
Finally(Block),
Rlyeh,
Rickroll,
}

View File

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

View File

@ -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,

View File

@ -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),
@ -149,7 +150,7 @@ impl<'source> Parser<'source> {
let next = self.checked_next()?;
Ok(Expr::Aint(Box::new(self.parse_expr(next, buf)?)))
}
Token::Plus
| Token::Minus
| Token::Star
@ -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 {

View File

@ -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);