From 90473b06eda85ec0e01c8ddc48ff7c82bab3f066 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sun, 15 Sep 2024 13:20:38 +0100 Subject: add list::push and list::pop --- src/builtins.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/eval.rs | 12 ++++++++---- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/builtins.rs b/src/builtins.rs index 6fa1110..0c9dbf3 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -39,6 +39,8 @@ builtins! { // list length, member, + push, + pop, } fn print(ctx: &mut Context, args: &[ast::Expr]) -> Result { @@ -152,6 +154,48 @@ fn member(ctx: &mut Context, args: &[ast::Expr]) -> Result { .wrap(Ok) } +fn push(ctx: &mut Context, args: &[ast::Expr]) -> Result { + let [lhs, rhs] = get_args::<2>(args)?; + let ast::Expr::Ident(ident) = lhs else { + return Err(Error::MalformedExpr(format!( + "malformed assigment, lhs: {:?}", + lhs + ))); + }; + let element = ctx.eval_expr(&rhs)?; + let variable = ctx.lookup_mut(ident)?; + variable.mutate(|v| match &mut v.value { + Value::List(l) => { + l.push(element); + Ok(Value::Unit) + } + _ => Err(Error::TypeMismatch { + expected: ast::Type::List, + got: v.ty().clone(), + }), + }) +} + +fn pop(ctx: &mut Context, args: &[ast::Expr]) -> Result { + let [lhs] = get_args::<1>(args)?; + let ast::Expr::Ident(ident) = lhs else { + return Err(Error::MalformedExpr(format!( + "malformed assigment, lhs: {:?}", + lhs + ))); + }; + let variable = ctx.lookup_mut(ident)?; + variable.mutate(|v| match &mut v.value { + Value::List(l) => l + .pop() + .ok_or_else(|| Error::ArrayOutOfBounds { idx: 0, len: 0 }), + _ => Err(Error::TypeMismatch { + expected: ast::Type::List, + got: v.ty().clone(), + }), + }) +} + fn get_args(args: &[ast::Expr]) -> std::result::Result<&[ast::Expr; N], Error> { args.try_into().map_err(|_| Error::IncorrectArgFormat { wanted: N, diff --git a/src/eval.rs b/src/eval.rs index b92bf97..7d6c64e 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -15,7 +15,7 @@ impl Variable { &self.value } - fn ty(&self) -> &ast::Type { + pub(crate) fn ty(&self) -> &ast::Type { &self.ty } @@ -30,6 +30,10 @@ impl Variable { }) } } + + pub(crate) fn mutate(&mut self, f: impl FnOnce(&mut Self) -> Result) -> Result { + f(self) + } } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] @@ -45,7 +49,7 @@ pub enum Value { type NodeId = usize; impl Value { - fn ty(&self) -> ast::Type { + pub(crate) fn ty(&self) -> ast::Type { match self { Self::Unit => ast::Type::Unit, Self::Integer(_) => ast::Type::Integer, @@ -562,13 +566,13 @@ impl Context { .wrap_ok() } - fn lookup(&mut self, ident: &ast::Identifier) -> std::result::Result<&Variable, Error> { + pub(crate) fn lookup(&mut self, ident: &ast::Identifier) -> std::result::Result<&Variable, Error> { self.variables .get(ident) .ok_or_else(|| Error::FailedLookup(ident.to_owned())) } - fn lookup_mut(&mut self, ident: &ast::Identifier) -> std::result::Result<&mut Variable, Error> { + pub(crate) fn lookup_mut(&mut self, ident: &ast::Identifier) -> std::result::Result<&mut Variable, Error> { self.variables .get_mut(ident) .ok_or_else(|| Error::FailedLookup(ident.to_owned())) -- cgit v1.2.3