diff --git a/ablescript/src/ast.rs b/ablescript/src/ast.rs index 447fd45..3d82ff9 100644 --- a/ablescript/src/ast.rs +++ b/ablescript/src/ast.rs @@ -8,12 +8,48 @@ //! just plain subroutines and they do not return any value, //! so their calls are statements. -use std::hash::Hash; +use std::{fmt::Debug, hash::Hash}; use crate::variables::Value; type Span = std::ops::Range; +#[derive(Clone)] +pub struct Spanned { + pub item: T, + pub span: Span, +} + +impl Spanned { + pub fn new(item: T, span: Span) -> Self { + Self { item, span } + } +} + +impl Debug for Spanned { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self.item) + } else { + write!(f, "{:?}", self.item) + }?; + + write!(f, " @ {:?}", self.span) + } +} + +impl PartialEq for Spanned { + fn eq(&self, other: &Self) -> bool { + self.item == other.item + } +} + +impl Hash for Spanned { + fn hash(&self, state: &mut H) { + self.item.hash(state); + } +} + #[derive(Debug, Clone)] pub struct Ident { pub ident: String, @@ -47,14 +83,14 @@ pub struct Assignable { #[derive(Debug, PartialEq, Clone, Hash)] pub enum AssignableKind { Variable, - Index { indices: Vec }, + Index { indices: Vec> }, } pub struct InvalidAssignable; impl Assignable { - pub fn from_expr(expr: Expr) -> Result { - match expr.kind { + pub fn from_expr(expr: Spanned) -> Result { + match expr.item { ExprKind::Variable(ident) => Ok(Assignable { ident: Ident::new(ident, expr.span), kind: AssignableKind::Variable, @@ -64,10 +100,10 @@ impl Assignable { } } - fn from_index(mut buf: Expr, index: Expr) -> Result { + fn from_index(mut buf: Spanned, index: Spanned) -> Result { let mut indices = vec![index]; let ident = loop { - match buf.kind { + match buf.item { ExprKind::Variable(ident) => break ident, ExprKind::Index { expr, index } => { indices.push(*index); @@ -87,33 +123,15 @@ impl Assignable { #[derive(Debug, PartialEq, Clone, Hash)] pub struct Block { - pub block: Vec, + pub block: Vec>, } /// A syntactic unit expressing an effect. -#[derive(Debug, Clone)] -pub struct Stmt { - pub kind: StmtKind, - pub span: Span, -} - -impl PartialEq for Stmt { - fn eq(&self, other: &Self) -> bool { - self.kind == other.kind - } -} - -impl Hash for Stmt { - fn hash(&self, state: &mut H) { - self.kind.hash(state) - } -} - #[derive(Debug, PartialEq, Clone, Hash)] pub enum StmtKind { // Control flow If { - cond: Expr, + cond: Spanned, body: Block, }, Loop { @@ -124,11 +142,11 @@ pub enum StmtKind { Var { ident: Ident, - init: Option, + init: Option>, }, Assign { assignable: Assignable, - value: Expr, + value: Spanned, }, Functio { @@ -138,70 +156,40 @@ pub enum StmtKind { }, BfFunctio { ident: Ident, - tape_len: Option, + tape_len: Option>, code: Vec, }, Call { - expr: Expr, - args: Vec, + expr: Spanned, + args: Vec>, }, - Print(Expr), + Print(Spanned), Read(Assignable), Melo(Ident), Rlyeh, Rickroll, } -impl Stmt { - pub fn new(kind: StmtKind, span: Span) -> Self { - Self { kind, span } - } -} - /// Expression is parse unit which do not cause any effect, /// like math and logical operations or values. -#[derive(Debug, Clone)] -pub struct Expr { - pub kind: ExprKind, - pub span: Span, -} - -impl PartialEq for Expr { - fn eq(&self, other: &Self) -> bool { - self.kind == other.kind - } -} - -impl Hash for Expr { - fn hash(&self, state: &mut H) { - self.kind.hash(state) - } -} - #[derive(Debug, PartialEq, Clone, Hash)] pub enum ExprKind { BinOp { - lhs: Box, - rhs: Box, + lhs: Box>, + rhs: Box>, kind: BinOpKind, }, - Not(Box), + Not(Box>), Literal(Value), - Cart(Vec<(Expr, Expr)>), + Cart(Vec<(Spanned, Spanned)>), Index { - expr: Box, - index: Box, + expr: Box>, + index: Box>, }, - Len(Box), + Len(Box>), Variable(String), } -impl Expr { - pub fn new(kind: ExprKind, span: Span) -> Self { - Self { kind, span } - } -} - #[derive(Debug, PartialEq, Clone, Hash)] pub enum BinOpKind { Add, diff --git a/ablescript/src/interpret.rs b/ablescript/src/interpret.rs index caed5f8..f9439b9 100644 --- a/ablescript/src/interpret.rs +++ b/ablescript/src/interpret.rs @@ -19,7 +19,7 @@ use std::{ use rand::random; use crate::{ - ast::{Assignable, AssignableKind, Expr, ExprKind, Ident, Stmt, StmtKind}, + ast::{Assignable, AssignableKind, ExprKind, Ident, Spanned, StmtKind}, base_55, consts::ablescript_consts, error::{Error, ErrorKind}, @@ -108,7 +108,7 @@ impl ExecEnv { /// Execute a set of Statements in the root stack frame. Return an /// error if one or more of the Stmts failed to evaluate, or if a /// `break` or `hopback` statement occurred at the top level. - pub fn eval_stmts(&mut self, stmts: &[Stmt]) -> Result<(), Error> { + pub fn eval_stmts(&mut self, stmts: &[Spanned]) -> Result<(), Error> { match self.eval_stmts_hs(stmts, false)? { HaltStatus::Finished => Ok(()), HaltStatus::Break(span) | HaltStatus::Hopback(span) => Err(Error { @@ -126,7 +126,11 @@ impl ExecEnv { /// /// `interpret`-internal code should typically prefer this /// function over `eval_stmts`. - fn eval_stmts_hs(&mut self, stmts: &[Stmt], stackframe: bool) -> Result { + fn eval_stmts_hs( + &mut self, + stmts: &[Spanned], + stackframe: bool, + ) -> Result { let init_depth = self.stack.len(); if stackframe { @@ -151,11 +155,11 @@ impl ExecEnv { } /// Evaluate an Expr, returning its value or an error. - fn eval_expr(&self, expr: &Expr) -> Result { + fn eval_expr(&self, expr: &Spanned) -> Result { use crate::ast::BinOpKind::*; use crate::ast::ExprKind::*; - Ok(match &expr.kind { + Ok(match &expr.item { BinOp { lhs, rhs, kind } => { let lhs = self.eval_expr(lhs)?; let rhs = self.eval_expr(rhs)?; @@ -204,8 +208,8 @@ impl ExecEnv { } /// Perform the action indicated by a statement. - fn eval_stmt(&mut self, stmt: &Stmt) -> Result { - match &stmt.kind { + fn eval_stmt(&mut self, stmt: &Spanned) -> Result { + match &stmt.item { StmtKind::Print(expr) => { println!("{}", self.eval_expr(expr)?); } @@ -353,13 +357,18 @@ impl ExecEnv { /// Call a function with the given arguments (i.e., actual /// parameters). If the function invocation fails for some reason, /// report the error at `span`. - fn fn_call(&mut self, func: Functio, args: &[Expr], span: &Range) -> Result<(), Error> { + fn fn_call( + &mut self, + func: Functio, + args: &[Spanned], + span: &Range, + ) -> Result<(), Error> { // Arguments that are ExprKind::Variable are pass by // reference; all other expressions are pass by value. let args = args .iter() .map(|arg| { - if let ExprKind::Variable(name) = &arg.kind { + if let ExprKind::Variable(name) = &arg.item { self.get_var_rc(&Ident { ident: name.to_owned(), span: arg.span.clone(), diff --git a/ablescript/src/parser.rs b/ablescript/src/parser.rs index 4b3a070..6e06be6 100644 --- a/ablescript/src/parser.rs +++ b/ablescript/src/parser.rs @@ -29,7 +29,7 @@ impl<'source> Parser<'source> { /// Start parsing tokens /// /// Loops trough lexer, parses statements, returns AST - pub fn init(&mut self) -> Result, Error> { + pub fn init(&mut self) -> Result>, Error> { let mut ast = vec![]; while let Some(token) = self.lexer.next() { match token { @@ -64,32 +64,32 @@ impl<'source> Parser<'source> { /// /// This function will route to corresponding flow functions /// which may advance the lexer iterator - fn parse(&mut self, token: Token) -> Result { + fn parse(&mut self, token: Token) -> Result, Error> { let start = self.lexer.span().start; match token { - Token::If => Ok(Stmt::new(self.if_flow()?, start..self.lexer.span().end)), - Token::Functio => Ok(Stmt::new( + Token::If => Ok(Spanned::new(self.if_flow()?, start..self.lexer.span().end)), + Token::Functio => Ok(Spanned::new( self.functio_flow()?, start..self.lexer.span().end, )), - Token::Bff => Ok(Stmt::new(self.bff_flow()?, start..self.lexer.span().end)), - Token::Var => Ok(Stmt::new(self.var_flow()?, start..self.lexer.span().end)), - Token::Melo => Ok(Stmt::new(self.melo_flow()?, start..self.lexer.span().end)), - Token::Loop => Ok(Stmt::new(self.loop_flow()?, start..self.lexer.span().end)), - Token::Break => Ok(Stmt::new( + Token::Bff => Ok(Spanned::new(self.bff_flow()?, start..self.lexer.span().end)), + Token::Var => Ok(Spanned::new(self.var_flow()?, start..self.lexer.span().end)), + Token::Melo => Ok(Spanned::new(self.melo_flow()?, start..self.lexer.span().end)), + Token::Loop => Ok(Spanned::new(self.loop_flow()?, start..self.lexer.span().end)), + Token::Break => Ok(Spanned::new( self.semicolon_terminated(StmtKind::Break)?, start..self.lexer.span().end, )), - Token::HopBack => Ok(Stmt::new( + Token::HopBack => Ok(Spanned::new( self.semicolon_terminated(StmtKind::HopBack)?, start..self.lexer.span().end, )), - Token::Rlyeh => Ok(Stmt::new( + Token::Rlyeh => Ok(Spanned::new( self.semicolon_terminated(StmtKind::Rlyeh)?, start..self.lexer.span().end, )), - Token::Rickroll => Ok(Stmt::new( + Token::Rickroll => Ok(Spanned::new( self.semicolon_terminated(StmtKind::Rickroll)?, start..self.lexer.span().end, )), @@ -99,7 +99,7 @@ impl<'source> Parser<'source> { | Token::Integer(_) | Token::Not | Token::LeftBracket - | Token::LeftParen => Ok(Stmt::new( + | Token::LeftParen => Ok(Spanned::new( self.value_flow(token)?, start..self.lexer.span().end, )), @@ -147,7 +147,7 @@ impl<'source> Parser<'source> { /// AbleScript strongly separates expressions from statements. /// Expressions do not have any side effects and the are /// only mathematial and logical operations or values. - fn parse_expr(&mut self, token: Token, buf: &mut Option) -> Result { + fn parse_expr(&mut self, token: Token, buf: &mut Option>) -> Result, Error> { let start = match buf { Some(e) => e.span.start, None => self.lexer.span().start, @@ -155,7 +155,7 @@ impl<'source> Parser<'source> { match token { // Values - Token::Identifier(i) => Ok(Expr::new( + Token::Identifier(i) => Ok(Spanned::new( ExprKind::Variable(if self.tdark { i.replace("lang", "script") } else { @@ -163,11 +163,11 @@ impl<'source> Parser<'source> { }), start..self.lexer.span().end, )), - Token::Integer(i) => Ok(Expr::new( + Token::Integer(i) => Ok(Spanned::new( ExprKind::Literal(Value::Int(i)), start..self.lexer.span().end, )), - Token::String(s) => Ok(Expr::new( + Token::String(s) => Ok(Spanned::new( ExprKind::Literal(Value::Str(if self.tdark { s.replace("lang", "script") } else { @@ -177,11 +177,11 @@ impl<'source> Parser<'source> { )), Token::LeftBracket => match buf.take() { - Some(buf) => Ok(Expr::new( + Some(buf) => Ok(Spanned::new( self.index_flow(buf)?, start..self.lexer.span().end, )), - None => Ok(Expr::new(self.cart_flow()?, start..self.lexer.span().end)), + None => Ok(Spanned::new(self.cart_flow()?, start..self.lexer.span().end)), }, // Operations @@ -192,7 +192,7 @@ impl<'source> Parser<'source> { | Token::EqualEqual | Token::NotEqual | Token::LessThan - | Token::GreaterThan => Ok(Expr::new( + | Token::GreaterThan => Ok(Spanned::new( self.binop_flow( BinOpKind::from_token(token).map_err(|e| Error::new(e, self.lexer.span()))?, buf, @@ -200,7 +200,7 @@ impl<'source> Parser<'source> { start..self.lexer.span().end, )), - Token::Not => Ok(Expr::new( + Token::Not => Ok(Spanned::new( { let next = self.checked_next()?; ExprKind::Not(Box::new(self.parse_expr(next, buf)?)) @@ -262,7 +262,7 @@ impl<'source> Parser<'source> { /// Flow for indexing operations /// /// Indexing with empty index resolves to length of expression, else it indexes - fn index_flow(&mut self, expr: Expr) -> Result { + fn index_flow(&mut self, expr: Spanned) -> Result { let mut buf = None; Ok(loop { match self.checked_next()? { @@ -285,7 +285,7 @@ impl<'source> Parser<'source> { /// Generates operation from LHS buffer and next expression as RHS /// /// This is unaware of precedence, as AbleScript do not have it - fn binop_flow(&mut self, kind: BinOpKind, lhs: &mut Option) -> Result { + fn binop_flow(&mut self, kind: BinOpKind, lhs: &mut Option>) -> Result { Ok(ExprKind::BinOp { lhs: Box::new( lhs.take() @@ -303,7 +303,7 @@ impl<'source> Parser<'source> { } /// Parse expressions until terminate token - fn expr_flow(&mut self, terminate: Token) -> Result { + fn expr_flow(&mut self, terminate: Token) -> Result, Error> { let mut buf = None; Ok(loop { match self.checked_next()? { @@ -497,7 +497,7 @@ impl<'source> Parser<'source> { } /// Parse functio call flow - fn functio_call_flow(&mut self, expr: Expr) -> Result { + fn functio_call_flow(&mut self, expr: Spanned) -> Result { let mut args = vec![]; let mut buf = None; loop { diff --git a/ablescript/src/variables.rs b/ablescript/src/variables.rs index 2f93eb5..13c5e97 100644 --- a/ablescript/src/variables.rs +++ b/ablescript/src/variables.rs @@ -12,7 +12,7 @@ use std::{ use rand::Rng; -use crate::{ast::Stmt, brian::INSTRUCTION_MAPPINGS, consts}; +use crate::{brian::INSTRUCTION_MAPPINGS, consts, ast::{Spanned, StmtKind}}; #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub enum Abool { @@ -58,7 +58,7 @@ pub enum Functio { }, Able { params: Vec, - body: Vec, + body: Vec>, }, Builtin(BuiltinFunctio), Chain {