diff options
-rw-r--r-- | src/builtins.rs | 44 | ||||
-rw-r--r-- | 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! { | |||
39 | // list | 39 | // list |
40 | length, | 40 | length, |
41 | member, | 41 | member, |
42 | push, | ||
43 | pop, | ||
42 | } | 44 | } |
43 | 45 | ||
44 | fn print(ctx: &mut Context, args: &[ast::Expr]) -> Result { | 46 | fn 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 | ||
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 | }) | ||
197 | } | ||
198 | |||
155 | fn get_args<const N: usize>(args: &[ast::Expr]) -> std::result::Result<&[ast::Expr; N], Error> { | 199 | fn 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 { | |||
45 | type NodeId = usize; | 49 | type NodeId = usize; |
46 | 50 | ||
47 | impl Value { | 51 | impl 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())) |