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