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!(
|
Ok(Empty::new(format!(
|
||||||
"[{}] {} {}",
|
"[{}] {} {}",
|
||||||
if self.shadow { ":=" } else { "<-" },
|
|
||||||
symbols
|
symbols
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| env.id_to_str(&x.get_value()).unwrap().clone())
|
.map(|x| env.id_to_str(&x.get_value()).unwrap().clone())
|
||||||
.reduce(|x, acc| format!("{x}, {acc}"))
|
.reduce(|x, acc| format!("{x}, {acc}"))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
if self.shadow { ":=" } else { "<-" },
|
||||||
right.as_string(Some(env))
|
right.as_string(Some(env))
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,11 +29,14 @@ impl Node for Call {
|
||||||
|
|
||||||
env.push_stack()?;
|
env.push_stack()?;
|
||||||
|
|
||||||
|
let mut existing_captures = vec![];
|
||||||
|
|
||||||
let func = match evaluated.as_ref() {
|
let func = match evaluated.as_ref() {
|
||||||
NodeEnum::Function(func) => func,
|
NodeEnum::Function(func) => func,
|
||||||
NodeEnum::Closure(closure) => {
|
NodeEnum::Closure(closure) => {
|
||||||
for (k, v) in closure.get_captured_variables() {
|
for (k, v) in closure.get_captured_variables() {
|
||||||
env.insert(*k, v.clone(), false);
|
env.insert(*k, v.clone(), false);
|
||||||
|
existing_captures.push((*k,v.clone()));
|
||||||
}
|
}
|
||||||
closure.get_function()
|
closure.get_function()
|
||||||
}
|
}
|
||||||
|
@ -74,8 +77,9 @@ impl Node for Call {
|
||||||
// Return evaluated return value for function
|
// Return evaluated return value for function
|
||||||
Ok(match ev.as_ref() {
|
Ok(match ev.as_ref() {
|
||||||
NodeEnum::Function(hof) => {
|
NodeEnum::Function(hof) => {
|
||||||
let captures = fargs.iter().map(|a| a.get_value()).zip(arguments).collect();
|
let mut captures = fargs.iter().map(|a| a.get_value()).zip(arguments).collect();
|
||||||
Closure::new(hof.clone(), captures)
|
existing_captures.append(&mut captures);
|
||||||
|
Closure::new(hof.clone(), existing_captures)
|
||||||
}
|
}
|
||||||
_ => ev,
|
_ => ev,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,34 +1,27 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use rug::ops::{AddFrom, CompleteRound};
|
||||||
|
|
||||||
use crate::environment::Environment;
|
use crate::environment::Environment;
|
||||||
|
|
||||||
use super::{Error, Node, NodeEnum, Precedence, constant::ConstantValue};
|
use super::{Error, Node, NodeEnum, Precedence, constant::ConstantValue};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
pub struct Range {
|
pub struct Range {
|
||||||
pub from: ConstantValue,
|
from: Rc<NodeEnum>,
|
||||||
pub to: ConstantValue,
|
to: Rc<NodeEnum>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for Range {
|
impl Node for Range {
|
||||||
fn evaluate(&self, _: &mut Environment) -> Result<Rc<NodeEnum>, Error> {
|
fn evaluate(&self, env: &mut Environment) -> Result<Rc<NodeEnum>, Error> {
|
||||||
Ok(Rc::new(self.clone().into()))
|
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 {
|
fn as_string(&self, env: Option<&Environment>) -> String {
|
||||||
format!(
|
format!("{}..{}", self.from.as_string(env), self.to.as_string(env))
|
||||||
"{}..{}",
|
|
||||||
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 precedence(&self) -> Precedence {
|
fn precedence(&self) -> Precedence {
|
||||||
|
@ -37,7 +30,93 @@ impl Node for Range {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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())
|
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)?;
|
let evaluated = self.values.first().unwrap().evaluate(env)?;
|
||||||
|
|
||||||
if let NodeEnum::Range(r) = evaluated.as_ref() {
|
if let NodeEnum::Range(r) = evaluated.as_ref() {
|
||||||
let mut i = r.from.clone();
|
for value in r.into_iter() {
|
||||||
while i < r.to {
|
values.push(Rc::new(Constant::new(value.clone()).into()));
|
||||||
values.push(Rc::new(Constant::new(i.clone()).into()));
|
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(Self::new(values));
|
return Ok(Self::new(values));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,8 +159,8 @@ impl<'a> Lexer<'a> {
|
||||||
}
|
}
|
||||||
// tokens.push(Token(i, TokenType::Space));
|
// tokens.push(Token(i, TokenType::Space));
|
||||||
}
|
}
|
||||||
// Comments with //
|
// Comments with #
|
||||||
'/' if self.source.peek() == Some(&'/') => {
|
'#' => {
|
||||||
while self.source.next() != Some('\n') {
|
while self.source.next() != Some('\n') {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -384,10 +384,9 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
expressions.push(self.expression()?);
|
expressions.push(self.expression()?);
|
||||||
|
self.match_type(TokenType::Terminator);
|
||||||
|
|
||||||
if !self.is_at_end() {
|
if self.is_at_end() {
|
||||||
self.match_or_err(TokenType::Terminator)?;
|
|
||||||
} else {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -835,27 +834,7 @@ impl<'a> Parser<'a> {
|
||||||
if self.match_type(TokenType::DoubleDot) {
|
if self.match_type(TokenType::DoubleDot) {
|
||||||
let to = self.primary()?;
|
let to = self.primary()?;
|
||||||
|
|
||||||
let from = match exp.as_ref() {
|
return Ok(Range::new(exp, to));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(exp)
|
Ok(exp)
|
||||||
|
|
Loading…
Reference in a new issue