diff --git a/ablescript/src/ast.rs b/ablescript/src/ast.rs index 447fd45..7bec17a 100644 --- a/ablescript/src/ast.rs +++ b/ablescript/src/ast.rs @@ -8,68 +8,80 @@ //! 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(Debug, Clone)] -pub struct Ident { - pub ident: String, +#[derive(Clone)] +pub struct Spanned { + pub item: T, pub span: Span, } -impl Ident { - pub fn new(ident: String, span: Span) -> Self { - Self { ident, span } +impl Spanned { + pub fn new(item: T, span: Span) -> Self { + Self { item, span } } } -impl PartialEq for Ident { +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.ident == other.ident + self.item == other.item } } -impl Hash for Ident { +impl Hash for Spanned { fn hash(&self, state: &mut H) { - self.ident.hash(state) + self.item.hash(state); } } #[derive(Debug, PartialEq, Clone, Hash)] pub struct Assignable { - pub ident: Ident, + pub ident: Spanned, pub kind: AssignableKind, } #[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 { - ExprKind::Variable(ident) => Ok(Assignable { - ident: Ident::new(ident, expr.span), + pub fn from_expr(expr: Spanned) -> Result { + match expr.item { + Expr::Variable(ident) => Ok(Assignable { + ident: Spanned::new(ident, expr.span), kind: AssignableKind::Variable, }), - ExprKind::Index { expr, index } => Self::from_index(*expr, *index), + Expr::Index { expr, index } => Self::from_index(*expr, *index), _ => Err(InvalidAssignable), } } - 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 { - ExprKind::Variable(ident) => break ident, - ExprKind::Index { expr, index } => { + match buf.item { + Expr::Variable(ident) => break ident, + Expr::Index { expr, index } => { indices.push(*index); buf = *expr; } @@ -79,41 +91,20 @@ impl Assignable { indices.reverse(); Ok(Assignable { - ident: Ident::new(ident, buf.span), + ident: Spanned::new(ident, buf.span), kind: AssignableKind::Index { indices }, }) } } -#[derive(Debug, PartialEq, Clone, Hash)] -pub struct Block { - pub block: Vec, -} +pub type 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 { +pub enum Stmt { // Control flow If { - cond: Expr, + cond: Spanned, body: Block, }, Loop { @@ -123,85 +114,55 @@ pub enum StmtKind { HopBack, Var { - ident: Ident, - init: Option, + ident: Spanned, + init: Option>, }, Assign { assignable: Assignable, - value: Expr, + value: Spanned, }, Functio { - ident: Ident, - params: Vec, + ident: Spanned, + params: Vec>, body: Block, }, BfFunctio { - ident: Ident, - tape_len: Option, + ident: Spanned, + tape_len: Option>, code: Vec, }, Call { - expr: Expr, - args: Vec, + expr: Spanned, + args: Vec>, }, - Print(Expr), + Print(Spanned), Read(Assignable), - Melo(Ident), + Melo(Spanned), 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 { +pub enum Expr { 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..aa2a41a 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, Expr, Spanned, Stmt}, 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::*; + use crate::ast::Expr::*; - Ok(match &expr.kind { + Ok(match &expr.item { BinOp { lhs, rhs, kind } => { let lhs = self.eval_expr(lhs)?; let rhs = self.eval_expr(rhs)?; @@ -172,7 +176,7 @@ impl ExecEnv { } Not(expr) => !self.eval_expr(expr)?, Literal(value) => value.clone(), - ExprKind::Cart(members) => Value::Cart( + Expr::Cart(members) => Value::Cart( members .iter() .map(|(value, key)| { @@ -196,47 +200,44 @@ impl ExecEnv { // TODO: not too happy with constructing an artificial // Ident here. - Variable(name) => self.get_var(&Ident { - ident: name.to_owned(), - span: expr.span.clone(), - })?, + Variable(name) => self.get_var(&Spanned::new(name.to_owned(), expr.span.clone()))?, }) } /// Perform the action indicated by a statement. - fn eval_stmt(&mut self, stmt: &Stmt) -> Result { - match &stmt.kind { - StmtKind::Print(expr) => { + fn eval_stmt(&mut self, stmt: &Spanned) -> Result { + match &stmt.item { + Stmt::Print(expr) => { println!("{}", self.eval_expr(expr)?); } - StmtKind::Var { ident, init } => { + Stmt::Var { ident, init } => { let init = match init { Some(e) => self.eval_expr(e)?, None => Value::Nul, }; - self.decl_var(&ident.ident, init); + self.decl_var(&ident.item, init); } - StmtKind::Functio { + Stmt::Functio { ident, params, body, } => { self.decl_var( - &ident.ident, + &ident.item, Value::Functio(Functio::Able { - params: params.iter().map(|ident| ident.ident.to_owned()).collect(), - body: body.block.to_owned(), + params: params.iter().map(|ident| ident.item.to_owned()).collect(), + body: body.to_owned(), }), ); } - StmtKind::BfFunctio { + Stmt::BfFunctio { ident, tape_len, code, } => { self.decl_var( - &ident.ident, + &ident.item, Value::Functio(Functio::Bf { instructions: code.to_owned(), tape_len: tape_len @@ -248,47 +249,47 @@ impl ExecEnv { }), ); } - StmtKind::If { cond, body } => { + Stmt::If { cond, body } => { if self.eval_expr(cond)?.into_abool().to_bool() { - return self.eval_stmts_hs(&body.block, true); + return self.eval_stmts_hs(body, true); } } - StmtKind::Call { expr, args } => { + Stmt::Call { expr, args } => { let func = self.eval_expr(expr)?.into_functio(); self.fn_call(func, args, &stmt.span)?; } - StmtKind::Loop { body } => loop { - let res = self.eval_stmts_hs(&body.block, true)?; + Stmt::Loop { body } => loop { + let res = self.eval_stmts_hs(body, true)?; match res { HaltStatus::Finished => {} HaltStatus::Break(_) => break, HaltStatus::Hopback(_) => continue, } }, - StmtKind::Assign { assignable, value } => { + Stmt::Assign { assignable, value } => { self.assign(assignable, self.eval_expr(value)?)?; } - StmtKind::Break => { + Stmt::Break => { return Ok(HaltStatus::Break(stmt.span.clone())); } - StmtKind::HopBack => { + Stmt::HopBack => { return Ok(HaltStatus::Hopback(stmt.span.clone())); } - StmtKind::Melo(ident) => { + Stmt::Melo(ident) => { self.get_var_mut(ident)?.melo = true; } - StmtKind::Rlyeh => { + Stmt::Rlyeh => { // Maybe print a creepy error message or something // here at some point. ~~Alex exit(random()); } - StmtKind::Rickroll => { + Stmt::Rickroll => { stdout() .write_all(include_str!("rickroll").as_bytes()) .expect("Failed to write to stdout"); } - StmtKind::Read(assignable) => { + Stmt::Read(assignable) => { let mut value = 0; for _ in 0..READ_BITS { value <<= 1; @@ -353,17 +354,19 @@ 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 { - self.get_var_rc(&Ident { - ident: name.to_owned(), - span: arg.span.clone(), - }) + if let Expr::Variable(name) = &arg.item { + self.get_var_rc(&Spanned::new(name.to_owned(), arg.span.clone())) } else { self.eval_expr(arg).map(ValueRef::new) } @@ -513,9 +516,9 @@ impl ExecEnv { /// Get the value of a variable. Throw an error if the variable is /// inaccessible or banned. - fn get_var(&self, name: &Ident) -> Result { + fn get_var(&self, name: &Spanned) -> Result { // One-letter names are reserved as base55 numbers. - let mut chars = name.ident.chars(); + let mut chars = name.item.chars(); if let (Some(first), None) = (chars.next(), chars.next()) { return Ok(Value::Int(base_55::char2num(first))); } @@ -526,20 +529,20 @@ impl ExecEnv { .stack .iter() .rev() - .find_map(|scope| scope.variables.get(&name.ident)) + .find_map(|scope| scope.variables.get(&name.item)) { Some(var) => { if !var.melo { Ok(var.value.borrow().clone()) } else { Err(Error { - kind: ErrorKind::MeloVariable(name.ident.to_owned()), + kind: ErrorKind::MeloVariable(name.item.to_owned()), span: name.span.clone(), }) } } None => Err(Error { - kind: ErrorKind::UnknownVariable(name.ident.to_owned()), + kind: ErrorKind::UnknownVariable(name.item.to_owned()), span: name.span.clone(), }), } @@ -547,27 +550,27 @@ impl ExecEnv { /// Get a mutable reference to a variable. Throw an error if the /// variable is inaccessible or banned. - fn get_var_mut(&mut self, name: &Ident) -> Result<&mut Variable, Error> { + fn get_var_mut(&mut self, name: &Spanned) -> Result<&mut Variable, Error> { // This function has a lot of duplicated code with `get_var`, // which I feel like is a bad sign... match self .stack .iter_mut() .rev() - .find_map(|scope| scope.variables.get_mut(&name.ident)) + .find_map(|scope| scope.variables.get_mut(&name.item)) { Some(var) => { if !var.melo { Ok(var) } else { Err(Error { - kind: ErrorKind::MeloVariable(name.ident.to_owned()), + kind: ErrorKind::MeloVariable(name.item.to_owned()), span: name.span.clone(), }) } } None => Err(Error { - kind: ErrorKind::UnknownVariable(name.ident.to_owned()), + kind: ErrorKind::UnknownVariable(name.item.to_owned()), span: name.span.clone(), }), } @@ -575,7 +578,7 @@ impl ExecEnv { /// Get an Rc'd pointer to the value of a variable. Throw an error /// if the variable is inaccessible or banned. - fn get_var_rc(&mut self, name: &Ident) -> Result { + fn get_var_rc(&mut self, name: &Spanned) -> Result { Ok(self.get_var_mut(name)?.value.clone()) } @@ -597,7 +600,7 @@ impl ExecEnv { #[cfg(test)] mod tests { - use crate::ast::ExprKind; + use crate::ast::Expr; use super::*; @@ -606,14 +609,14 @@ mod tests { // Check that 2 + 2 = 4. let env = ExecEnv::new(); assert_eq!( - env.eval_expr(&Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(2)), + env.eval_expr(&Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(2)), span: 1..1, }), - rhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(2)), + rhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(2)), span: 1..1, }), kind: crate::ast::BinOpKind::Add, @@ -633,14 +636,14 @@ mod tests { let env = ExecEnv::new(); assert_eq!( - env.eval_expr(&Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(2)), + env.eval_expr(&Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(2)), span: 1..1, }), - rhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Abool(Abool::Always)), + rhs: Box::new(Spanned { + item: Expr::Literal(Value::Abool(Abool::Always)), span: 1..1, }), kind: crate::ast::BinOpKind::Add, @@ -658,14 +661,14 @@ mod tests { // of panicking. let env = ExecEnv::new(); assert_eq!( - env.eval_expr(&Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(isize::MAX)), + env.eval_expr(&Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(isize::MAX)), span: 1..1, }), - rhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(1)), + rhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(1)), span: 1..1, }), kind: crate::ast::BinOpKind::Add, @@ -678,14 +681,14 @@ mod tests { // And the same for divide by zero. assert_eq!( - env.eval_expr(&Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(84)), + env.eval_expr(&Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(84)), span: 1..1, }), - rhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(0)), + rhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(0)), span: 1..1, }), kind: crate::ast::BinOpKind::Divide, @@ -719,8 +722,8 @@ mod tests { // Declaring and reading from a variable. eval(&mut env, "var foo = 32; var bar = foo + 1;").unwrap(); assert_eq!( - env.get_var(&Ident { - ident: "bar".to_owned(), + env.get_var(&Spanned { + item: "bar".to_owned(), span: 1..1, }) .unwrap(), @@ -730,8 +733,8 @@ mod tests { // Assigning an existing variable. eval(&mut env, "foo = /*hi*/;").unwrap(); assert_eq!( - env.get_var(&Ident { - ident: "foo".to_owned(), + env.get_var(&Spanned { + item: "foo".to_owned(), span: 1..1, }) .unwrap(), @@ -756,8 +759,8 @@ mod tests { .unwrap(); assert_eq!( - env.get_var(&Ident { - ident: "foo".to_owned(), + env.get_var(&Spanned { + item: "foo".to_owned(), span: 1..1, }) .unwrap(), diff --git a/ablescript/src/parser.rs b/ablescript/src/parser.rs index 4b3a070..7b200ae 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 { let mut ast = vec![]; while let Some(token) = self.lexer.next() { match token { @@ -37,7 +37,7 @@ impl<'source> Parser<'source> { Token::Comment => continue, // T-Dark block (replace `lang` with `script`) - Token::TDark => ast.extend(self.tdark_flow()?.block), + Token::TDark => ast.extend(self.tdark_flow()?), token => ast.push(self.parse(token)?), } } @@ -64,33 +64,39 @@ 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( - self.semicolon_terminated(StmtKind::Break)?, + 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::HopBack => Ok(Stmt::new( - self.semicolon_terminated(StmtKind::HopBack)?, + Token::Loop => Ok(Spanned::new( + self.loop_flow()?, start..self.lexer.span().end, )), - Token::Rlyeh => Ok(Stmt::new( - self.semicolon_terminated(StmtKind::Rlyeh)?, + Token::Break => Ok(Spanned::new( + self.semicolon_terminated(Stmt::Break)?, start..self.lexer.span().end, )), - Token::Rickroll => Ok(Stmt::new( - self.semicolon_terminated(StmtKind::Rickroll)?, + Token::HopBack => Ok(Spanned::new( + self.semicolon_terminated(Stmt::HopBack)?, + start..self.lexer.span().end, + )), + Token::Rlyeh => Ok(Spanned::new( + self.semicolon_terminated(Stmt::Rlyeh)?, + start..self.lexer.span().end, + )), + Token::Rickroll => Ok(Spanned::new( + self.semicolon_terminated(Stmt::Rickroll)?, start..self.lexer.span().end, )), @@ -99,7 +105,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, )), @@ -114,7 +120,7 @@ impl<'source> Parser<'source> { /// Require statement to be semicolon terminated /// /// Utility function for short statements - fn semicolon_terminated(&mut self, stmt_kind: StmtKind) -> Result { + fn semicolon_terminated(&mut self, stmt_kind: Stmt) -> Result { self.require(Token::Semicolon)?; Ok(stmt_kind) } @@ -128,16 +134,16 @@ impl<'source> Parser<'source> { } /// Get an Identifier - fn get_ident(&mut self) -> Result { + fn get_ident(&mut self) -> Result, Error> { match self.checked_next()? { - Token::Identifier(ident) => Ok(Ident { - ident: if self.tdark { + Token::Identifier(ident) => Ok(Spanned::new( + if self.tdark { ident.replace("lang", "script") } else { ident }, - span: self.lexer.span(), - }), + self.lexer.span(), + )), t => Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())), } } @@ -147,7 +153,11 @@ 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,20 +165,20 @@ impl<'source> Parser<'source> { match token { // Values - Token::Identifier(i) => Ok(Expr::new( - ExprKind::Variable(if self.tdark { + Token::Identifier(i) => Ok(Spanned::new( + Expr::Variable(if self.tdark { i.replace("lang", "script") } else { i }), start..self.lexer.span().end, )), - Token::Integer(i) => Ok(Expr::new( - ExprKind::Literal(Value::Int(i)), + Token::Integer(i) => Ok(Spanned::new( + Expr::Literal(Value::Int(i)), start..self.lexer.span().end, )), - Token::String(s) => Ok(Expr::new( - ExprKind::Literal(Value::Str(if self.tdark { + Token::String(s) => Ok(Spanned::new( + Expr::Literal(Value::Str(if self.tdark { s.replace("lang", "script") } else { s @@ -177,11 +187,14 @@ 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 +205,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,10 +213,10 @@ 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)?)) + Expr::Not(Box::new(self.parse_expr(next, buf)?)) }, start..self.lexer.span().end, )), @@ -214,7 +227,7 @@ impl<'source> Parser<'source> { } /// Flow for creating carts - fn cart_flow(&mut self) -> Result { + fn cart_flow(&mut self) -> Result { let mut cart = vec![]; let mut buf = None; @@ -256,24 +269,24 @@ impl<'source> Parser<'source> { } } - Ok(ExprKind::Cart(cart)) + Ok(Expr::Cart(cart)) } /// 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()? { Token::RightBracket => match buf { Some(index) => { - break ExprKind::Index { + break Expr::Index { expr: Box::new(expr), index: Box::new(index), } } - None => break ExprKind::Len(Box::new(expr)), + None => break Expr::Len(Box::new(expr)), }, token => buf = Some(self.parse_expr(token, &mut buf)?), } @@ -285,8 +298,12 @@ 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 { - Ok(ExprKind::BinOp { + fn binop_flow( + &mut self, + kind: BinOpKind, + lhs: &mut Option>, + ) -> Result { + Ok(Expr::BinOp { lhs: Box::new( lhs.take() .ok_or_else(|| Error::new(ErrorKind::MissingLhs, self.lexer.span()))?, @@ -303,7 +320,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()? { @@ -325,11 +342,11 @@ impl<'source> Parser<'source> { loop { match self.checked_next()? { Token::RightCurly => break, - Token::TDark => block.extend(self.tdark_flow()?.block), + Token::TDark => block.extend(self.tdark_flow()?), t => block.push(self.parse(t)?), } } - Ok(Block { block }) + Ok(block) } /// Parse T-Dark block @@ -343,13 +360,13 @@ impl<'source> Parser<'source> { /// If Statement parser gets any kind of value (Identifier or Literal) /// It cannot parse it as it do not parse expressions. Instead of it it /// will parse it to function call or print statement. - fn value_flow(&mut self, init: Token) -> Result { + fn value_flow(&mut self, init: Token) -> Result { let mut buf = Some(self.parse_expr(init, &mut None)?); let r = loop { match self.checked_next()? { // Print to stdout Token::Print => { - let stmt = StmtKind::Print(buf.take().ok_or_else(|| { + let stmt = Stmt::Print(buf.take().ok_or_else(|| { Error::new(ErrorKind::UnexpectedToken(Token::Print), self.lexer.span()) })?); break self.semicolon_terminated(stmt)?; @@ -368,7 +385,7 @@ impl<'source> Parser<'source> { // Variable Assignment Token::Equal => { if let Some(Ok(assignable)) = buf.take().map(Assignable::from_expr) { - break StmtKind::Assign { + break Stmt::Assign { assignable, value: self.expr_flow(Token::Semicolon)?, }; @@ -384,7 +401,7 @@ impl<'source> Parser<'source> { Token::Read => { if let Some(Ok(assignable)) = buf.take().map(Assignable::from_expr) { self.require(Token::Semicolon)?; - break StmtKind::Read(assignable); + break Stmt::Read(assignable); } else { return Err(Error::new( ErrorKind::UnexpectedToken(Token::Read), @@ -403,20 +420,20 @@ impl<'source> Parser<'source> { /// Parse If flow /// /// Consists of condition and block, there is no else - fn if_flow(&mut self) -> Result { + fn if_flow(&mut self) -> Result { self.require(Token::LeftParen)?; let cond = self.expr_flow(Token::RightParen)?; let body = self.get_block()?; - Ok(StmtKind::If { cond, body }) + Ok(Stmt::If { cond, body }) } /// Parse functio flow /// /// functio $ident (a, b, c) { ... } - fn functio_flow(&mut self) -> Result { + fn functio_flow(&mut self) -> Result { let ident = self.get_ident()?; self.require(Token::LeftParen)?; @@ -426,7 +443,7 @@ impl<'source> Parser<'source> { match self.checked_next()? { Token::RightParen => break, Token::Identifier(i) => { - params.push(Ident::new(i, self.lexer.span())); + params.push(Spanned::new(i, self.lexer.span())); // Require comma (next) or right paren (end) after identifier match self.checked_next()? { @@ -446,7 +463,7 @@ impl<'source> Parser<'source> { let body = self.get_block()?; - Ok(StmtKind::Functio { + Ok(Stmt::Functio { ident, params, body, @@ -456,7 +473,7 @@ impl<'source> Parser<'source> { /// Parse BF function declaration /// /// `bff $ident ([tapelen]) { ... }` - fn bff_flow(&mut self) -> Result { + fn bff_flow(&mut self) -> Result { let ident = self.get_ident()?; let tape_len = match self.checked_next()? { @@ -489,7 +506,7 @@ impl<'source> Parser<'source> { } } - Ok(StmtKind::BfFunctio { + Ok(Stmt::BfFunctio { ident, tape_len, code, @@ -497,7 +514,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 { @@ -526,11 +543,11 @@ impl<'source> Parser<'source> { } self.require(Token::Semicolon)?; - Ok(StmtKind::Call { expr, args }) + Ok(Stmt::Call { expr, args }) } /// Parse variable declaration - fn var_flow(&mut self) -> Result { + fn var_flow(&mut self) -> Result { let ident = self.get_ident()?; let init = match self.checked_next()? { Token::Equal => Some(self.expr_flow(Token::Semicolon)?), @@ -538,20 +555,20 @@ impl<'source> Parser<'source> { t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())), }; - Ok(StmtKind::Var { ident, init }) + Ok(Stmt::Var { ident, init }) } /// Parse Melo flow - fn melo_flow(&mut self) -> Result { + fn melo_flow(&mut self) -> Result { let ident = self.get_ident()?; - self.semicolon_terminated(StmtKind::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 { - Ok(StmtKind::Loop { + fn loop_flow(&mut self) -> Result { + Ok(Stmt::Loop { body: self.get_block()?, }) } @@ -564,23 +581,23 @@ mod tests { #[test] fn simple_math() { let code = "1 * (a + 3) / 666 print;"; - let expected = &[Stmt { - kind: StmtKind::Print(Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(1)), + let expected = &[Spanned { + item: Stmt::Print(Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(1)), span: 0..1, }), - rhs: Box::new(Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Variable("a".to_owned()), + rhs: Box::new(Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Variable("a".to_owned()), span: 5..6, }), - rhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(3)), + rhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(3)), span: 9..10, }), kind: BinOpKind::Add, @@ -591,8 +608,8 @@ mod tests { }, span: 0..11, }), - rhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(666)), + rhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(666)), span: 14..17, }), kind: BinOpKind::Divide, @@ -609,14 +626,14 @@ mod tests { #[test] fn variable_declaration() { let code = "var a = 42;"; - let expected = &[Stmt { - kind: StmtKind::Var { - ident: Ident { - ident: "a".to_owned(), + let expected = &[Spanned { + item: Stmt::Var { + ident: Spanned { + item: "a".to_owned(), span: 4..5, }, - init: Some(Expr { - kind: ExprKind::Literal(Value::Int(42)), + init: Some(Spanned { + item: Expr::Literal(Value::Int(42)), span: 8..10, }), }, @@ -630,31 +647,29 @@ mod tests { #[test] fn if_flow() { let code = "if (a == always) { /*Buy Able products!*/ print; }"; - let expected = &[Stmt { - kind: StmtKind::If { - cond: Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Variable("a".to_owned()), + let expected = &[Spanned { + item: Stmt::If { + cond: Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Variable("a".to_owned()), span: 4..5, }), - rhs: Box::new(Expr { - kind: ExprKind::Variable("always".to_owned()), + rhs: Box::new(Spanned { + item: Expr::Variable("always".to_owned()), span: 9..15, }), kind: BinOpKind::Equal, }, span: 4..15, }, - body: Block { - block: vec![Stmt { - kind: StmtKind::Print(Expr { - kind: ExprKind::Literal(Value::Str("Buy Able products!".to_owned())), - span: 19..39, - }), - span: 19..46, - }], - }, + body: vec![Spanned { + item: Stmt::Print(Spanned { + item: Expr::Literal(Value::Str("Buy Able products!".to_owned())), + span: 19..39, + }), + span: 19..46, + }], }, span: 0..48, }]; @@ -666,20 +681,20 @@ mod tests { #[test] fn tdark() { let code = "T-Dark { var lang = /*lang*/ + lang; }"; - let expected = &[Stmt { - kind: StmtKind::Var { - ident: Ident { - ident: "script".to_owned(), + let expected = &[Spanned { + item: Stmt::Var { + ident: Spanned { + item: "script".to_owned(), span: 13..17, }, - init: Some(Expr { - kind: ExprKind::BinOp { - lhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Str("script".to_owned())), + init: Some(Spanned { + item: Expr::BinOp { + lhs: Box::new(Spanned { + item: Expr::Literal(Value::Str("script".to_owned())), span: 20..26, }), - rhs: Box::new(Expr { - kind: ExprKind::Variable("script".to_owned()), + rhs: Box::new(Spanned { + item: Expr::Variable("script".to_owned()), span: 29..33, }), kind: BinOpKind::Add, @@ -697,33 +712,33 @@ mod tests { #[test] fn cart_construction() { let code = "[/*able*/ <= 1, /*script*/ <= 3 - 1] print;"; - let expected = &[Stmt { - kind: StmtKind::Print(Expr { - kind: ExprKind::Cart(vec![ + let expected = &[Spanned { + item: Stmt::Print(Spanned { + item: Expr::Cart(vec![ ( - Expr { - kind: ExprKind::Literal(Value::Str("able".to_owned())), + Spanned { + item: Expr::Literal(Value::Str("able".to_owned())), span: 1..7, }, - Expr { - kind: ExprKind::Literal(Value::Int(1)), + Spanned { + item: Expr::Literal(Value::Int(1)), span: 11..12, }, ), ( - Expr { - kind: ExprKind::Literal(Value::Str("script".to_owned())), + Spanned { + item: Expr::Literal(Value::Str("script".to_owned())), span: 14..22, }, - Expr { - kind: ExprKind::BinOp { + Spanned { + item: Expr::BinOp { kind: BinOpKind::Subtract, - lhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(3)), + lhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(3)), span: 26..27, }), - rhs: Box::new(Expr { - kind: ExprKind::Literal(Value::Int(1)), + rhs: Box::new(Spanned { + item: Expr::Literal(Value::Int(1)), span: 30..31, }), }, @@ -743,24 +758,24 @@ mod tests { #[test] fn cart_index() { let code = "[/*able*/ <= /*ablecorp*/][/*ablecorp*/] print;"; - let expected = &[Stmt { - kind: StmtKind::Print(Expr { - kind: ExprKind::Index { - expr: Box::new(Expr { - kind: ExprKind::Cart(vec![( - Expr { - kind: ExprKind::Literal(Value::Str("able".to_owned())), + let expected = &[Spanned { + item: Stmt::Print(Spanned { + item: Expr::Index { + expr: Box::new(Spanned { + item: Expr::Cart(vec![( + Spanned { + item: Expr::Literal(Value::Str("able".to_owned())), span: 1..7, }, - Expr { - kind: ExprKind::Literal(Value::Str("ablecorp".to_owned())), + Spanned { + item: Expr::Literal(Value::Str("ablecorp".to_owned())), span: 11..21, }, )]), span: 0..22, }), - index: Box::new(Expr { - kind: ExprKind::Literal(Value::Str("ablecorp".to_owned())), + index: Box::new(Spanned { + item: Expr::Literal(Value::Str("ablecorp".to_owned())), span: 23..33, }), }, diff --git a/ablescript/src/variables.rs b/ablescript/src/variables.rs index 2f93eb5..09572ad 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::{ast::Block, brian::INSTRUCTION_MAPPINGS, consts}; #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] pub enum Abool { @@ -58,7 +58,7 @@ pub enum Functio { }, Able { params: Vec, - body: Vec, + body: Block, }, Builtin(BuiltinFunctio), Chain {