aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/builtins.rs44
-rw-r--r--src/eval.rs12
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! {
39 // list 39 // list
40 length, 40 length,
41 member, 41 member,
42 push,
43 pop,
42} 44}
43 45
44fn print(ctx: &mut Context, args: &[ast::Expr]) -> Result { 46fn print(ctx: &mut Context, args: &[ast::Expr]) -> Result {
@@ -152,6 +154,48 @@ fn member(ctx: &mut Context, args: &[ast::Expr]) -> Result {
152 .wrap(Ok) 154 .wrap(Ok)
153} 155}
154 156
157fn 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
179fn 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 })
197}
198
155fn get_args<const N: usize>(args: &[ast::Expr]) -> std::result::Result<&[ast::Expr; N], Error> { 199fn get_args<const N: usize>(args: &[ast::Expr]) -> std::result::Result<&[ast::Expr; N], Error> {
156 args.try_into().map_err(|_| Error::IncorrectArgFormat { 200 args.try_into().map_err(|_| Error::IncorrectArgFormat {
157 wanted: N, 201 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 {
15 &self.value 15 &self.value
16 } 16 }
17 17
18 fn ty(&self) -> &ast::Type { 18 pub(crate) fn ty(&self) -> &ast::Type {
19 &self.ty 19 &self.ty
20 } 20 }
21 21
@@ -30,6 +30,10 @@ impl Variable {
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#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] 39#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
@@ -45,7 +49,7 @@ pub enum Value {
45type NodeId = usize; 49type NodeId = usize;
46 50
47impl Value { 51impl Value {
48 fn ty(&self) -> ast::Type { 52 pub(crate) fn ty(&self) -> ast::Type {
49 match self { 53 match self {
50 Self::Unit => ast::Type::Unit, 54 Self::Unit => ast::Type::Unit,
51 Self::Integer(_) => ast::Type::Integer, 55 Self::Integer(_) => ast::Type::Integer,
@@ -562,13 +566,13 @@ impl Context {
562 .wrap_ok() 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 self.variables 570 self.variables
567 .get(ident) 571 .get(ident)
568 .ok_or_else(|| Error::FailedLookup(ident.to_owned())) 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 self.variables 576 self.variables
573 .get_mut(ident) 577 .get_mut(ident)
574 .ok_or_else(|| Error::FailedLookup(ident.to_owned())) 578 .ok_or_else(|| Error::FailedLookup(ident.to_owned()))