2021-06-06 16:13:48 -05:00
|
|
|
//! AbleScript's Abstract Syntax tree
|
|
|
|
//!
|
|
|
|
//! Statements are the type which is AST made of, as they
|
|
|
|
//! express an effect.
|
|
|
|
//!
|
|
|
|
//! Expressions are just operations and they cannot be
|
|
|
|
//! used as statements. Functions in AbleScript are in fact
|
2021-06-06 17:09:45 -05:00
|
|
|
//! just plain subroutines and they do not return any value,
|
2021-06-06 16:13:48 -05:00
|
|
|
//! so their calls are statements.
|
|
|
|
|
2021-06-06 14:09:18 -05:00
|
|
|
use crate::variables::Value;
|
2022-04-02 07:13:49 -05:00
|
|
|
use std::{fmt::Debug, hash::Hash};
|
2021-06-06 14:09:18 -05:00
|
|
|
|
|
|
|
type Span = std::ops::Range<usize>;
|
|
|
|
|
2022-04-01 18:22:46 -05:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Spanned<T> {
|
|
|
|
pub item: T,
|
|
|
|
pub span: Span,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Spanned<T> {
|
|
|
|
pub fn new(item: T, span: Span) -> Self {
|
|
|
|
Self { item, span }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Debug> Debug for Spanned<T> {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
if f.alternate() {
|
2022-04-01 18:42:13 -05:00
|
|
|
write!(f, "{:#?} @ {:?}", self.item, self.span)
|
2022-04-01 18:22:46 -05:00
|
|
|
} else {
|
2022-04-01 18:42:13 -05:00
|
|
|
write!(f, "{:?} @ {:?}", self.item, self.span)
|
|
|
|
}
|
2022-04-01 18:22:46 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: PartialEq> PartialEq for Spanned<T> {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self.item == other.item
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Hash> Hash for Spanned<T> {
|
|
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
|
|
self.item.hash(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-12 15:14:20 -05:00
|
|
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
|
|
|
pub struct Assignable {
|
2022-04-01 18:34:25 -05:00
|
|
|
pub ident: Spanned<String>,
|
2021-10-12 15:14:20 -05:00
|
|
|
pub kind: AssignableKind,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
|
|
|
pub enum AssignableKind {
|
|
|
|
Variable,
|
2022-04-01 18:34:25 -05:00
|
|
|
Index { indices: Vec<Spanned<Expr>> },
|
2021-10-12 15:14:20 -05:00
|
|
|
}
|
|
|
|
|
2022-03-01 14:53:58 -06:00
|
|
|
pub struct InvalidAssignable;
|
|
|
|
|
2021-10-21 13:51:24 -05:00
|
|
|
impl Assignable {
|
2022-04-01 18:34:25 -05:00
|
|
|
pub fn from_expr(expr: Spanned<Expr>) -> Result<Assignable, InvalidAssignable> {
|
2022-04-01 18:22:46 -05:00
|
|
|
match expr.item {
|
2022-04-01 18:34:25 -05:00
|
|
|
Expr::Variable(ident) => Ok(Assignable {
|
|
|
|
ident: Spanned::new(ident, expr.span),
|
2021-10-21 13:51:24 -05:00
|
|
|
kind: AssignableKind::Variable,
|
|
|
|
}),
|
2022-04-01 18:34:25 -05:00
|
|
|
Expr::Index { expr, index } => Self::from_index(*expr, *index),
|
2022-03-01 14:53:58 -06:00
|
|
|
_ => Err(InvalidAssignable),
|
2021-10-21 13:51:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-02 07:13:49 -05:00
|
|
|
fn from_index(
|
|
|
|
mut buf: Spanned<Expr>,
|
|
|
|
index: Spanned<Expr>,
|
|
|
|
) -> Result<Assignable, InvalidAssignable> {
|
2021-10-21 13:51:24 -05:00
|
|
|
let mut indices = vec![index];
|
|
|
|
let ident = loop {
|
2022-04-01 18:22:46 -05:00
|
|
|
match buf.item {
|
2022-04-01 18:34:25 -05:00
|
|
|
Expr::Variable(ident) => break ident,
|
|
|
|
Expr::Index { expr, index } => {
|
2021-10-21 13:51:24 -05:00
|
|
|
indices.push(*index);
|
|
|
|
buf = *expr;
|
|
|
|
}
|
2022-03-01 14:53:58 -06:00
|
|
|
_ => return Err(InvalidAssignable),
|
2021-10-21 13:51:24 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
indices.reverse();
|
|
|
|
Ok(Assignable {
|
2022-04-01 18:34:25 -05:00
|
|
|
ident: Spanned::new(ident, buf.span),
|
2021-10-21 13:51:24 -05:00
|
|
|
kind: AssignableKind::Index { indices },
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-01 18:34:25 -05:00
|
|
|
pub type Block = Vec<Spanned<Stmt>>;
|
2021-06-06 14:09:18 -05:00
|
|
|
|
|
|
|
/// A syntactic unit expressing an effect.
|
2021-08-07 17:33:28 -05:00
|
|
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
2022-04-01 18:34:25 -05:00
|
|
|
pub enum Stmt {
|
2021-06-06 14:09:18 -05:00
|
|
|
// Control flow
|
|
|
|
If {
|
2022-04-01 18:34:25 -05:00
|
|
|
cond: Spanned<Expr>,
|
2021-06-06 14:09:18 -05:00
|
|
|
body: Block,
|
|
|
|
},
|
|
|
|
Loop {
|
|
|
|
body: Block,
|
|
|
|
},
|
|
|
|
Break,
|
|
|
|
HopBack,
|
|
|
|
|
|
|
|
Var {
|
2022-04-01 18:34:25 -05:00
|
|
|
ident: Spanned<String>,
|
|
|
|
init: Option<Spanned<Expr>>,
|
2021-06-06 14:09:18 -05:00
|
|
|
},
|
2021-06-11 09:59:40 -05:00
|
|
|
Assign {
|
2021-10-12 15:14:20 -05:00
|
|
|
assignable: Assignable,
|
2022-04-01 18:34:25 -05:00
|
|
|
value: Spanned<Expr>,
|
2021-06-11 09:59:40 -05:00
|
|
|
},
|
2021-06-06 14:09:18 -05:00
|
|
|
|
|
|
|
Functio {
|
2022-04-01 18:34:25 -05:00
|
|
|
ident: Spanned<String>,
|
|
|
|
params: Vec<Spanned<String>>,
|
2021-06-06 14:09:18 -05:00
|
|
|
body: Block,
|
|
|
|
},
|
2021-06-11 10:52:47 -05:00
|
|
|
BfFunctio {
|
2022-04-01 18:34:25 -05:00
|
|
|
ident: Spanned<String>,
|
|
|
|
tape_len: Option<Spanned<Expr>>,
|
2021-06-11 11:10:11 -05:00
|
|
|
code: Vec<u8>,
|
2021-06-11 10:52:47 -05:00
|
|
|
},
|
2021-06-06 14:09:18 -05:00
|
|
|
Call {
|
2022-04-01 18:34:25 -05:00
|
|
|
expr: Spanned<Expr>,
|
|
|
|
args: Vec<Spanned<Expr>>,
|
2021-06-06 14:09:18 -05:00
|
|
|
},
|
2022-04-01 18:34:25 -05:00
|
|
|
Print(Spanned<Expr>),
|
2021-10-23 14:53:21 -05:00
|
|
|
Read(Assignable),
|
2022-04-01 18:34:25 -05:00
|
|
|
Melo(Spanned<String>),
|
2021-06-07 04:07:50 -05:00
|
|
|
Rlyeh,
|
2021-06-13 20:40:42 -05:00
|
|
|
Rickroll,
|
2021-06-06 14:09:18 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Expression is parse unit which do not cause any effect,
|
|
|
|
/// like math and logical operations or values.
|
2021-08-07 17:33:28 -05:00
|
|
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
2022-04-01 18:34:25 -05:00
|
|
|
pub enum Expr {
|
2021-06-06 16:13:48 -05:00
|
|
|
BinOp {
|
2022-04-01 18:34:25 -05:00
|
|
|
lhs: Box<Spanned<Expr>>,
|
|
|
|
rhs: Box<Spanned<Expr>>,
|
2021-06-06 14:09:18 -05:00
|
|
|
kind: BinOpKind,
|
|
|
|
},
|
2022-04-08 10:39:14 -05:00
|
|
|
Aint(Box<Spanned<Expr>>),
|
2021-06-06 14:09:18 -05:00
|
|
|
Literal(Value),
|
2022-04-01 18:34:25 -05:00
|
|
|
Cart(Vec<(Spanned<Expr>, Spanned<Expr>)>),
|
2021-07-27 04:51:05 -05:00
|
|
|
Index {
|
2022-04-01 18:34:25 -05:00
|
|
|
expr: Box<Spanned<Expr>>,
|
|
|
|
index: Box<Spanned<Expr>>,
|
2021-07-27 04:51:05 -05:00
|
|
|
},
|
2022-04-01 18:34:25 -05:00
|
|
|
Len(Box<Spanned<Expr>>),
|
2021-06-06 16:13:48 -05:00
|
|
|
Variable(String),
|
2021-06-06 14:09:18 -05:00
|
|
|
}
|
|
|
|
|
2021-08-07 17:33:28 -05:00
|
|
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
2021-06-06 14:09:18 -05:00
|
|
|
pub enum BinOpKind {
|
|
|
|
Add,
|
|
|
|
Subtract,
|
|
|
|
Multiply,
|
|
|
|
Divide,
|
|
|
|
Greater,
|
|
|
|
Less,
|
|
|
|
Equal,
|
|
|
|
NotEqual,
|
|
|
|
}
|
2021-06-07 02:17:18 -05:00
|
|
|
|
|
|
|
impl BinOpKind {
|
|
|
|
pub fn from_token(t: crate::lexer::Token) -> Result<Self, crate::error::ErrorKind> {
|
|
|
|
use crate::lexer::Token;
|
|
|
|
|
|
|
|
match t {
|
|
|
|
Token::Plus => Ok(Self::Add),
|
|
|
|
Token::Minus => Ok(Self::Subtract),
|
|
|
|
Token::Star => Ok(Self::Multiply),
|
|
|
|
Token::FwdSlash => Ok(Self::Divide),
|
|
|
|
Token::GreaterThan => Ok(Self::Greater),
|
|
|
|
Token::LessThan => Ok(Self::Less),
|
|
|
|
Token::EqualEqual => Ok(Self::Equal),
|
|
|
|
Token::NotEqual => Ok(Self::NotEqual),
|
2021-06-07 04:00:06 -05:00
|
|
|
t => Err(crate::error::ErrorKind::UnexpectedToken(t)),
|
2021-06-07 02:17:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|