From 840baede170cfbf7893266c834f0621f586a1544 Mon Sep 17 00:00:00 2001 From: Snorre Date: Thu, 20 Mar 2025 14:25:08 +0100 Subject: [PATCH] fixed closures not wroking --- fibonacci | 43 +++++++++++++++ src/lib/node/assign.rs | 2 +- src/lib/node/call.rs | 8 ++- src/lib/node/range.rs | 117 ++++++++++++++++++++++++++++++++++------- src/lib/node/set.rs | 7 ++- src/lib/parser/mod.rs | 31 ++--------- 6 files changed, 156 insertions(+), 52 deletions(-) create mode 100644 fibonacci diff --git a/fibonacci b/fibonacci new file mode 100644 index 0000000..2129ce6 --- /dev/null +++ b/fibonacci @@ -0,0 +1,43 @@ +fib' := a -> n -> target -> + if true then + loop + if n = target then break end + [a1,a2] := a + a <- [a2, a1+a2] + n <- n+1 + end + get(a,1) + end; + +fib := fib'([0,1])(1); + +fib_rec(n) := if n < 2 then n else fib_rec(n-1) + fib_rec(n-2); end; + +concat'(acc,set) := if length(set) = 0 then acc else [h,t] := head(set); concat'(acc+h, t) end +concat := x -> concat'(0,x) +g := i -> set -> get(set,i) + +test := f -> it -> v -> + concat( + map( + g(1), + map( + x -> + benchmark( + [] -> + f(x) + ), + map( + _ -> v, + [0..it] + ) + ) + ) + )/it + +print("Benchmarking fibonacci..."); +print("-------------------------"); +print("Non-recursive implementation"); +print(test(fib)(30)(30)); +print("Recursive implementation"); +print(test(fib_rec)(30)(30)); diff --git a/src/lib/node/assign.rs b/src/lib/node/assign.rs index f7608a8..0f90fb2 100644 --- a/src/lib/node/assign.rs +++ b/src/lib/node/assign.rs @@ -65,12 +65,12 @@ impl Node for Assign { Ok(Empty::new(format!( "[{}] {} {}", - if self.shadow { ":=" } else { "<-" }, symbols .iter() .map(|x| env.id_to_str(&x.get_value()).unwrap().clone()) .reduce(|x, acc| format!("{x}, {acc}")) .unwrap(), + if self.shadow { ":=" } else { "<-" }, right.as_string(Some(env)) ))) } else { diff --git a/src/lib/node/call.rs b/src/lib/node/call.rs index e56fb0d..b9589d5 100644 --- a/src/lib/node/call.rs +++ b/src/lib/node/call.rs @@ -29,11 +29,14 @@ impl Node for Call { env.push_stack()?; + let mut existing_captures = vec![]; + let func = match evaluated.as_ref() { NodeEnum::Function(func) => func, NodeEnum::Closure(closure) => { for (k, v) in closure.get_captured_variables() { env.insert(*k, v.clone(), false); + existing_captures.push((*k,v.clone())); } closure.get_function() } @@ -74,8 +77,9 @@ impl Node for Call { // Return evaluated return value for function Ok(match ev.as_ref() { NodeEnum::Function(hof) => { - let captures = fargs.iter().map(|a| a.get_value()).zip(arguments).collect(); - Closure::new(hof.clone(), captures) + let mut captures = fargs.iter().map(|a| a.get_value()).zip(arguments).collect(); + existing_captures.append(&mut captures); + Closure::new(hof.clone(), existing_captures) } _ => ev, }) diff --git a/src/lib/node/range.rs b/src/lib/node/range.rs index 79a4f11..731d25b 100644 --- a/src/lib/node/range.rs +++ b/src/lib/node/range.rs @@ -1,34 +1,27 @@ use std::rc::Rc; +use rug::ops::{AddFrom, CompleteRound}; + use crate::environment::Environment; use super::{Error, Node, NodeEnum, Precedence, constant::ConstantValue}; #[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct Range { - pub from: ConstantValue, - pub to: ConstantValue, + from: Rc, + to: Rc, } impl Node for Range { - fn evaluate(&self, _: &mut Environment) -> Result, Error> { - Ok(Rc::new(self.clone().into())) + fn evaluate(&self, env: &mut Environment) -> Result, Error> { + let from_evaluated = self.from.evaluate(env)?; + let to_evaluated = self.to.evaluate(env)?; + + Ok(Self::new(from_evaluated, to_evaluated)) } - fn as_string(&self, _: Option<&Environment>) -> String { - format!( - "{}..{}", - self.from - .to_string_radix(10, Some(8)) - .trim_end_matches('0') - .trim_end_matches('.') - .to_string(), - self.to - .to_string_radix(10, Some(8)) - .trim_end_matches('0') - .trim_end_matches('.') - .to_string() - ) + fn as_string(&self, env: Option<&Environment>) -> String { + format!("{}..{}", self.from.as_string(env), self.to.as_string(env)) } fn precedence(&self) -> Precedence { @@ -37,7 +30,93 @@ impl Node for Range { } impl Range { - pub fn new(from: ConstantValue, to: ConstantValue) -> Rc { + pub fn new(from: Rc, to: Rc) -> Rc { Rc::new(Self { from, to }.into()) } + + pub fn min(&self) -> Result<&ConstantValue, Error> { + match self.from.as_ref() { + NodeEnum::Constant(c) => Ok(c.get_value()), + _ => Err(Error::MismatchedType(format!( + "Minimum (from) in range was a {}, but it needs to be a Constant", + self.from.type_str() + ))), + } + } + + pub fn max(&self) -> Result<&ConstantValue, Error> { + match self.to.as_ref() { + NodeEnum::Constant(c) => Ok(c.get_value()), + _ => Err(Error::MismatchedType(format!( + "Maximum (to) in range was a {}, but it needs to be a Constant", + self.to.type_str() + ))), + } + } +} + +// impl Iterator for &Range { +// type Item = ConstantValue; +// +// fn next(&mut self) -> Option { +// if self.it.is_none() { +// return None; +// } +// +// let max = match self.to.as_ref() { +// NodeEnum::Constant(c) => c.get_value(), +// _ => panic!("Max is not a fucking constant dipshit"), +// }; +// +// let result = { +// let added = self.it.clone().unwrap() + 1; +// let comp = added < max.clone(); +// if comp { self.it.clone() } else { None } +// }; +// self.it.as_mut().unwrap().add_from(1); +// result +// } +// } + +pub struct RangeIter { + it: ConstantValue, + start: ConstantValue, + end: ConstantValue, +} + +impl<'a> Iterator for RangeIter { + type Item = ConstantValue; + + fn next(&mut self) -> Option { + let result = { + if self.it < self.end { + Some(self.it.clone()) + } else { + None + } + }; + self.it += 1; + result + } +} + +impl IntoIterator for &Range { + type Item = ConstantValue; + type IntoIter = RangeIter; + + fn into_iter(self) -> Self::IntoIter { + let it = match self.from.as_ref() { + NodeEnum::Constant(c) => c.get_value().clone(), + _ => panic!("This range does not have a defined start"), + }; + let end = match self.to.as_ref() { + NodeEnum::Constant(c) => c.get_value().clone(), + _ => panic!("This range does not have a defined end"), + }; + RangeIter { + start: it.clone(), + end, + it, + } + } } diff --git a/src/lib/node/set.rs b/src/lib/node/set.rs index 74652aa..f5cfe6d 100644 --- a/src/lib/node/set.rs +++ b/src/lib/node/set.rs @@ -15,11 +15,10 @@ impl Node for Set { let evaluated = self.values.first().unwrap().evaluate(env)?; if let NodeEnum::Range(r) = evaluated.as_ref() { - let mut i = r.from.clone(); - while i < r.to { - values.push(Rc::new(Constant::new(i.clone()).into())); - i += 1; + for value in r.into_iter() { + values.push(Rc::new(Constant::new(value.clone()).into())); } + return Ok(Self::new(values)); } } diff --git a/src/lib/parser/mod.rs b/src/lib/parser/mod.rs index caec7c5..8921057 100644 --- a/src/lib/parser/mod.rs +++ b/src/lib/parser/mod.rs @@ -159,8 +159,8 @@ impl<'a> Lexer<'a> { } // tokens.push(Token(i, TokenType::Space)); } - // Comments with // - '/' if self.source.peek() == Some(&'/') => { + // Comments with # + '#' => { while self.source.next() != Some('\n') { i += 1; } @@ -384,10 +384,9 @@ impl<'a> Parser<'a> { loop { expressions.push(self.expression()?); + self.match_type(TokenType::Terminator); - if !self.is_at_end() { - self.match_or_err(TokenType::Terminator)?; - } else { + if self.is_at_end() { break; } } @@ -835,27 +834,7 @@ impl<'a> Parser<'a> { if self.match_type(TokenType::DoubleDot) { let to = self.primary()?; - let from = match exp.as_ref() { - NodeEnum::Constant(c) => c.get_value().clone(), - _ => { - return Err(ParserError::UnexpectedNode( - self.previous.as_ref().unwrap().0, - "Expected a Constant here".to_owned(), - )); - } - }; - - let to = match to.as_ref() { - NodeEnum::Constant(c) => c.get_value().clone(), - _ => { - return Err(ParserError::UnexpectedNode( - self.previous.as_ref().unwrap().0, - "Expected a Constant here".to_owned(), - )); - } - }; - - return Ok(Range::new(from, to)); + return Ok(Range::new(exp, to)); } Ok(exp)