fixed closures not wroking

This commit is contained in:
Snorre 2025-03-20 14:25:08 +01:00
parent e5e088c398
commit 840baede17
6 changed files with 156 additions and 52 deletions

43
fibonacci Normal file
View file

@ -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));

View file

@ -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 {

View file

@ -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,
})

View file

@ -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<NodeEnum>,
to: Rc<NodeEnum>,
}
impl Node for Range {
fn evaluate(&self, _: &mut Environment) -> Result<Rc<NodeEnum>, Error> {
Ok(Rc::new(self.clone().into()))
fn evaluate(&self, env: &mut Environment) -> Result<Rc<NodeEnum>, 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<NodeEnum> {
pub fn new(from: Rc<NodeEnum>, to: Rc<NodeEnum>) -> Rc<NodeEnum> {
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<Self::Item> {
// 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<Self::Item> {
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,
}
}
}

View file

@ -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));
}
}

View file

@ -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)