diff --git a/ablescript/src/ast.rs b/ablescript/src/ast.rs index 3d82ff9b..7bec17a7 100644 --- a/ablescript/src/ast.rs +++ b/ablescript/src/ast.rs @@ -50,62 +50,38 @@ impl Hash for Spanned { } } -#[derive(Debug, Clone)] -pub struct Ident { - pub ident: String, - pub span: Span, -} - -impl Ident { - pub fn new(ident: String, span: Span) -> Self { - Self { ident, span } - } -} - -impl PartialEq for Ident { - fn eq(&self, other: &Self) -> bool { - self.ident == other.ident - } -} - -impl Hash for Ident { - fn hash(&self, state: &mut H) { - self.ident.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: Spanned) -> Result { + pub fn from_expr(expr: Spanned) -> Result { match expr.item { - ExprKind::Variable(ident) => Ok(Assignable { - ident: Ident::new(ident, expr.span), + 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: Spanned, index: Spanned) -> Result { + fn from_index(mut buf: Spanned, index: Spanned) -> Result { let mut indices = vec![index]; let ident = loop { match buf.item { - ExprKind::Variable(ident) => break ident, - ExprKind::Index { expr, index } => { + Expr::Variable(ident) => break ident, + Expr::Index { expr, index } => { indices.push(*index); buf = *expr; } @@ -115,23 +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, PartialEq, Clone, Hash)] -pub enum StmtKind { +pub enum Stmt { // Control flow If { - cond: Spanned, + cond: Spanned, body: Block, }, Loop { @@ -141,31 +114,31 @@ pub enum StmtKind { HopBack, Var { - ident: Ident, - init: Option>, + ident: Spanned, + init: Option>, }, Assign { assignable: Assignable, - value: Spanned, + 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: Spanned, - args: Vec>, + expr: Spanned, + args: Vec>, }, - Print(Spanned), + Print(Spanned), Read(Assignable), - Melo(Ident), + Melo(Spanned), Rlyeh, Rickroll, } @@ -173,20 +146,20 @@ pub enum StmtKind { /// Expression is parse unit which do not cause any effect, /// like math and logical operations or values. #[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<(Spanned, Spanned)>), + Cart(Vec<(Spanned, Spanned)>), Index { - expr: Box>, - index: Box>, + expr: Box>, + index: Box>, }, - Len(Box>), + Len(Box>), Variable(String), } diff --git a/ablescript/src/interpret.rs b/ablescript/src/interpret.rs index f9439b9d..aa2a41ab 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, ExprKind, Ident, Spanned, 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: &[Spanned]) -> 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 { @@ -128,7 +128,7 @@ impl ExecEnv { /// function over `eval_stmts`. fn eval_stmts_hs( &mut self, - stmts: &[Spanned], + stmts: &[Spanned], stackframe: bool, ) -> Result { let init_depth = self.stack.len(); @@ -155,9 +155,9 @@ impl ExecEnv { } /// Evaluate an Expr, returning its value or an error. - fn eval_expr(&self, expr: &Spanned) -> Result { + fn eval_expr(&self, expr: &Spanned) -> Result { use crate::ast::BinOpKind::*; - use crate::ast::ExprKind::*; + use crate::ast::Expr::*; Ok(match &expr.item { BinOp { lhs, rhs, kind } => { @@ -176,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)| { @@ -200,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: &Spanned) -> Result { + fn eval_stmt(&mut self, stmt: &Spanned) -> Result { match &stmt.item { - StmtKind::Print(expr) => { + 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 @@ -252,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; @@ -360,7 +357,7 @@ impl ExecEnv { fn fn_call( &mut self, func: Functio, - args: &[Spanned], + args: &[Spanned], span: &Range, ) -> Result<(), Error> { // Arguments that are ExprKind::Variable are pass by @@ -368,11 +365,8 @@ impl ExecEnv { let args = args .iter() .map(|arg| { - if let ExprKind::Variable(name) = &arg.item { - 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) } @@ -522,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))); } @@ -535,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(), }), } @@ -556,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(), }), } @@ -584,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()) } @@ -606,7 +600,7 @@ impl ExecEnv { #[cfg(test)] mod tests { - use crate::ast::ExprKind; + use crate::ast::Expr; use super::*; @@ -615,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, @@ -642,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, @@ -667,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, @@ -687,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, @@ -728,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(), @@ -739,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(), @@ -765,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 6e06be6b..7b200aee 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,7 +64,7 @@ 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, Error> { + fn parse(&mut self, token: Token) -> Result, Error> { let start = self.lexer.span().start; match token { @@ -75,22 +75,28 @@ impl<'source> Parser<'source> { )), 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::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)?, + self.semicolon_terminated(Stmt::Break)?, start..self.lexer.span().end, )), Token::HopBack => Ok(Spanned::new( - self.semicolon_terminated(StmtKind::HopBack)?, + self.semicolon_terminated(Stmt::HopBack)?, start..self.lexer.span().end, )), Token::Rlyeh => Ok(Spanned::new( - self.semicolon_terminated(StmtKind::Rlyeh)?, + self.semicolon_terminated(Stmt::Rlyeh)?, start..self.lexer.span().end, )), Token::Rickroll => Ok(Spanned::new( - self.semicolon_terminated(StmtKind::Rickroll)?, + self.semicolon_terminated(Stmt::Rickroll)?, 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, Error> { + 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, @@ -156,7 +166,7 @@ impl<'source> Parser<'source> { match token { // Values Token::Identifier(i) => Ok(Spanned::new( - ExprKind::Variable(if self.tdark { + Expr::Variable(if self.tdark { i.replace("lang", "script") } else { i @@ -164,11 +174,11 @@ impl<'source> Parser<'source> { start..self.lexer.span().end, )), Token::Integer(i) => Ok(Spanned::new( - ExprKind::Literal(Value::Int(i)), + Expr::Literal(Value::Int(i)), start..self.lexer.span().end, )), Token::String(s) => Ok(Spanned::new( - ExprKind::Literal(Value::Str(if self.tdark { + Expr::Literal(Value::Str(if self.tdark { s.replace("lang", "script") } else { s @@ -181,7 +191,10 @@ impl<'source> Parser<'source> { self.index_flow(buf)?, start..self.lexer.span().end, )), - None => Ok(Spanned::new(self.cart_flow()?, start..self.lexer.span().end)), + None => Ok(Spanned::new( + self.cart_flow()?, + start..self.lexer.span().end, + )), }, // Operations @@ -203,7 +216,7 @@ impl<'source> Parser<'source> { 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: Spanned) -> 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, Error> { + 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: Spanned) -> 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 13c5e979..09572ad6 100644 --- a/ablescript/src/variables.rs +++ b/ablescript/src/variables.rs @@ -12,7 +12,7 @@ use std::{ use rand::Rng; -use crate::{brian::INSTRUCTION_MAPPINGS, consts, ast::{Spanned, StmtKind}}; +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 {