tree-based source processing language

add list::push and list::pop

+52 -4
+44
src/builtins.rs
··· 39 39 // list 40 40 length, 41 41 member, 42 + push, 43 + pop, 42 44 } 43 45 44 46 fn print(ctx: &mut Context, args: &[ast::Expr]) -> Result { ··· 150 152 .any(|item| item == &element) 151 153 .wrap(Value::Boolean) 152 154 .wrap(Ok) 155 + } 156 + 157 + fn push(ctx: &mut Context, args: &[ast::Expr]) -> Result { 158 + let [lhs, rhs] = get_args::<2>(args)?; 159 + let ast::Expr::Ident(ident) = lhs else { 160 + return Err(Error::MalformedExpr(format!( 161 + "malformed assigment, lhs: {:?}", 162 + lhs 163 + ))); 164 + }; 165 + let element = ctx.eval_expr(&rhs)?; 166 + let variable = ctx.lookup_mut(ident)?; 167 + variable.mutate(|v| match &mut v.value { 168 + Value::List(l) => { 169 + l.push(element); 170 + Ok(Value::Unit) 171 + } 172 + _ => Err(Error::TypeMismatch { 173 + expected: ast::Type::List, 174 + got: v.ty().clone(), 175 + }), 176 + }) 177 + } 178 + 179 + fn pop(ctx: &mut Context, args: &[ast::Expr]) -> Result { 180 + let [lhs] = get_args::<1>(args)?; 181 + let ast::Expr::Ident(ident) = lhs else { 182 + return Err(Error::MalformedExpr(format!( 183 + "malformed assigment, lhs: {:?}", 184 + lhs 185 + ))); 186 + }; 187 + let variable = ctx.lookup_mut(ident)?; 188 + variable.mutate(|v| match &mut v.value { 189 + Value::List(l) => l 190 + .pop() 191 + .ok_or_else(|| Error::ArrayOutOfBounds { idx: 0, len: 0 }), 192 + _ => Err(Error::TypeMismatch { 193 + expected: ast::Type::List, 194 + got: v.ty().clone(), 195 + }), 196 + }) 153 197 } 154 198 155 199 fn get_args<const N: usize>(args: &[ast::Expr]) -> std::result::Result<&[ast::Expr; N], Error> {
+8 -4
src/eval.rs
··· 15 15 &self.value 16 16 } 17 17 18 - fn ty(&self) -> &ast::Type { 18 + pub(crate) fn ty(&self) -> &ast::Type { 19 19 &self.ty 20 20 } 21 21 ··· 30 30 }) 31 31 } 32 32 } 33 + 34 + pub(crate) fn mutate(&mut self, f: impl FnOnce(&mut Self) -> Result) -> Result { 35 + f(self) 36 + } 33 37 } 34 38 35 39 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] ··· 45 49 type NodeId = usize; 46 50 47 51 impl Value { 48 - fn ty(&self) -> ast::Type { 52 + pub(crate) fn ty(&self) -> ast::Type { 49 53 match self { 50 54 Self::Unit => ast::Type::Unit, 51 55 Self::Integer(_) => ast::Type::Integer, ··· 562 566 .wrap_ok() 563 567 } 564 568 565 - fn lookup(&mut self, ident: &ast::Identifier) -> std::result::Result<&Variable, Error> { 569 + pub(crate) fn lookup(&mut self, ident: &ast::Identifier) -> std::result::Result<&Variable, Error> { 566 570 self.variables 567 571 .get(ident) 568 572 .ok_or_else(|| Error::FailedLookup(ident.to_owned())) 569 573 } 570 574 571 - fn lookup_mut(&mut self, ident: &ast::Identifier) -> std::result::Result<&mut Variable, Error> { 575 + pub(crate) fn lookup_mut(&mut self, ident: &ast::Identifier) -> std::result::Result<&mut Variable, Error> { 572 576 self.variables 573 577 .get_mut(ident) 574 578 .ok_or_else(|| Error::FailedLookup(ident.to_owned()))