diff --git a/ablescript/src/ast.rs b/ablescript/src/ast.rs index 8e654ed..e11cb33 100644 --- a/ablescript/src/ast.rs +++ b/ablescript/src/ast.rs @@ -38,6 +38,18 @@ impl Hash for Ident { } } +#[derive(Debug, PartialEq, Clone, Hash)] +pub struct Assignable { + pub ident: Ident, + pub kind: AssignableKind, +} + +#[derive(Debug, PartialEq, Clone, Hash)] +pub enum AssignableKind { + Variable, + Cart { indices: Vec }, +} + #[derive(Debug, PartialEq, Clone, Hash)] pub struct Block { pub block: Vec, @@ -80,7 +92,7 @@ pub enum StmtKind { init: Option, }, Assign { - ident: Ident, + assignable: Assignable, value: Expr, }, diff --git a/ablescript/src/interpret.rs b/ablescript/src/interpret.rs index ab58a7e..f9b10e7 100644 --- a/ablescript/src/interpret.rs +++ b/ablescript/src/interpret.rs @@ -197,7 +197,11 @@ impl ExecEnv { self.decl_var(&ident.ident, init); } - StmtKind::Functio { ident, params, body } => { + StmtKind::Functio { + ident, + params, + body, + } => { self.decl_var( &ident.ident, Value::Functio(Functio::AbleFunctio { @@ -240,9 +244,10 @@ impl ExecEnv { HaltStatus::Hopback(_) => continue, } }, - StmtKind::Assign { ident, value } => { + StmtKind::Assign { assignable, value } => { + // TODO: Assigning to carts let value = self.eval_expr(value)?; - self.get_var_mut(ident)?.value.replace(value); + self.get_var_mut(&assignable.ident)?.value.replace(value); } StmtKind::Break => { return Ok(HaltStatus::Break(stmt.span.clone())); diff --git a/ablescript/src/parser.rs b/ablescript/src/parser.rs index f07039d..f01a9da 100644 --- a/ablescript/src/parser.rs +++ b/ablescript/src/parser.rs @@ -355,15 +355,25 @@ impl<'source> Parser<'source> { // Variable Assignment Token::Equal => { - if let Some(Expr { - kind: ExprKind::Variable(ident), - span, - }) = buf - { + let assignable = buf.take().and_then(|buf| match buf.kind { + ExprKind::Variable(ident) => Some(Assignable { + ident: Ident::new(ident, buf.span), + kind: AssignableKind::Variable, + }), + ExprKind::Index { expr, index } => self.cart_assignable_flow(*expr, *index), + _ => None, + }); + + if let Some(assignable) = assignable { break StmtKind::Assign { - ident: Ident::new(ident, span), + assignable, value: self.expr_flow(Token::Semicolon)?, }; + } else { + return Err(Error::new( + ErrorKind::UnexpectedToken(Token::Equal), + self.lexer.span(), + )); } } @@ -385,6 +395,27 @@ impl<'source> Parser<'source> { Ok(r) } + /// Parse Cart Assignable flow + fn cart_assignable_flow(&mut self, mut buf: Expr, index: Expr) -> Option { + let mut indices = vec![index]; + let ident = loop { + match buf.kind { + ExprKind::Variable(ident) => break ident, + ExprKind::Index { expr, index } => { + indices.push(*index); + buf = *expr; + } + _ => return None, + } + }; + + indices.reverse(); + Some(Assignable { + ident: Ident::new(ident, buf.span), + kind: AssignableKind::Cart { indices }, + }) + } + /// Parse If flow /// /// Consists of condition and block, there is no else @@ -431,7 +462,11 @@ impl<'source> Parser<'source> { let body = self.get_block()?; - Ok(StmtKind::Functio { ident, params, body }) + Ok(StmtKind::Functio { + ident, + params, + body, + }) } /// Parse BF function declaration