fixed closures not wroking
This commit is contained in:
parent
e5e088c398
commit
840baede17
43
fibonacci
Normal file
43
fibonacci
Normal 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));
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue