destructuring assignment
This commit is contained in:
parent
bb1b051598
commit
9da6f7d302
|
@ -1,4 +1,3 @@
|
||||||
use std::f32::consts;
|
|
||||||
use std::f64;
|
use std::f64;
|
||||||
use std::io::{self, StdoutLock, Write, stdout};
|
use std::io::{self, StdoutLock, Write, stdout};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -12,7 +11,6 @@ use libopenbirch::node::set::Set;
|
||||||
use libopenbirch::node::string_node::StringNode;
|
use libopenbirch::node::string_node::StringNode;
|
||||||
use libopenbirch::node::{Node, NodeEnum};
|
use libopenbirch::node::{Node, NodeEnum};
|
||||||
use libopenbirch::parser::{Lexer, LexerError, Parser, ParserError};
|
use libopenbirch::parser::{Lexer, LexerError, Parser, ParserError};
|
||||||
use raylib::ease::elastic_in;
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
use termion::AsyncReader;
|
use termion::AsyncReader;
|
||||||
use termion::color;
|
use termion::color;
|
||||||
|
@ -382,6 +380,31 @@ fn benchmark(args: &Vec<Rc<NodeEnum>>, env: &mut Environment) -> Result<Rc<NodeE
|
||||||
Ok(Set::new(vec![time_str, time_const, result]))
|
Ok(Set::new(vec![time_str, time_const, result]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn head(args: &Vec<Rc<NodeEnum>>, env: &mut Environment) -> Result<Rc<NodeEnum>, String> {
|
||||||
|
if args.len() != 1 {
|
||||||
|
Err(format!("Expected 1 argument but got {}", args.len()))?
|
||||||
|
}
|
||||||
|
|
||||||
|
let set = if let NodeEnum::Set(set) = args.first().unwrap().as_ref() {
|
||||||
|
set.get_values()
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"Expected a Set but got a {}",
|
||||||
|
args.first().unwrap().type_str()
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
let head = set.first().cloned().unwrap_or(Set::new(vec![]));
|
||||||
|
let len = set.len();
|
||||||
|
let tail = if len > 1 {
|
||||||
|
set[1..len].to_vec()
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Set::new(vec![head, Set::new(tail)]))
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), io::Error> {
|
fn main() -> Result<(), io::Error> {
|
||||||
let mut input = Input::new();
|
let mut input = Input::new();
|
||||||
|
|
||||||
|
@ -394,6 +417,7 @@ fn main() -> Result<(), io::Error> {
|
||||||
env.define_native_function("get_float_precision", get_float_precision);
|
env.define_native_function("get_float_precision", get_float_precision);
|
||||||
env.define_native_function("set_float_precision", set_float_precision);
|
env.define_native_function("set_float_precision", set_float_precision);
|
||||||
env.define_native_function("map", map);
|
env.define_native_function("map", map);
|
||||||
|
env.define_native_function("head", head);
|
||||||
env.define_native_function("get", get);
|
env.define_native_function("get", get);
|
||||||
env.define_native_function("length", length);
|
env.define_native_function("length", length);
|
||||||
env.define_native_function("benchmark", benchmark);
|
env.define_native_function("benchmark", benchmark);
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use raylib::ffi::StopAutomationEventRecording;
|
||||||
use rug::Float;
|
use rug::Float;
|
||||||
|
|
||||||
use super::{Environment, Node, NodeEnum, Precedence, constant::Constant, set::Set};
|
use super::{
|
||||||
|
Environment, Node, NodeEnum, Precedence, constant::Constant, set::Set, string_node::StringNode,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
pub struct Add {
|
pub struct Add {
|
||||||
|
@ -44,6 +47,11 @@ impl Node for Add {
|
||||||
Ok(Set::new(values))
|
Ok(Set::new(values))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Concatenate strings
|
||||||
|
(NodeEnum::StringNode(s1), NodeEnum::StringNode(s2)) => {
|
||||||
|
Ok(StringNode::new(s1.get_value().clone() + s2.get_value()))
|
||||||
|
}
|
||||||
|
|
||||||
_ => Ok(Rc::new(Add::new(evaluated_left, evaluated_right).into())),
|
_ => Ok(Rc::new(Add::new(evaluated_left, evaluated_right).into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use super::{Environment, Node, NodeEnum, Precedence, empty::Empty};
|
use super::{Environment, Node, NodeEnum, Precedence, empty::Empty, symbol};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct Assign {
|
pub struct Assign {
|
||||||
|
@ -10,23 +10,70 @@ pub struct Assign {
|
||||||
|
|
||||||
impl Node for Assign {
|
impl Node for Assign {
|
||||||
fn evaluate(&self, env: &mut Environment) -> Result<Rc<NodeEnum>, String> {
|
fn evaluate(&self, env: &mut Environment) -> Result<Rc<NodeEnum>, String> {
|
||||||
if let NodeEnum::Symbol(symbol) = self.left.as_ref() {
|
match self.left.as_ref() {
|
||||||
let name = env
|
NodeEnum::Symbol(symbol) => {
|
||||||
.id_to_str(&symbol.get_value())
|
let name = env
|
||||||
.expect("Unknown symbol")
|
.id_to_str(&symbol.get_value())
|
||||||
.clone();
|
.expect("Unknown symbol")
|
||||||
let right = self.right.evaluate(env)?;
|
.clone();
|
||||||
|
let right = self.right.evaluate(env)?;
|
||||||
|
|
||||||
env.insert(symbol.get_value(), right.clone());
|
env.insert(symbol.get_value(), right.clone());
|
||||||
Ok(Empty::new(format!(
|
Ok(Empty::new(format!(
|
||||||
"{name} := {}",
|
"{name} := {}",
|
||||||
right.as_string(Some(env))
|
right.as_string(Some(env))
|
||||||
)))
|
)))
|
||||||
} else {
|
}
|
||||||
Err(format!(
|
|
||||||
"Cannot assign to a {}",
|
NodeEnum::Set(set) => {
|
||||||
self.left.as_string(Some(env))
|
// Check if every element of the set is a symbol
|
||||||
))
|
let values = set.get_values();
|
||||||
|
|
||||||
|
if values.len() == 0 {
|
||||||
|
return Err(format!("Cannot assign to an empty Set"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut symbols = Vec::with_capacity(values.len());
|
||||||
|
for node in values {
|
||||||
|
if let NodeEnum::Symbol(symbol) = node.as_ref() {
|
||||||
|
symbols.push(symbol);
|
||||||
|
} else {
|
||||||
|
return Err(format!("Cannot assign to a {}", node.type_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate right hand side and check that it is a set of the same size
|
||||||
|
let right = self.right.evaluate(env)?;
|
||||||
|
|
||||||
|
if let NodeEnum::Set(set) = right.as_ref() {
|
||||||
|
let values = set.get_values();
|
||||||
|
if values.len() != symbols.len() {
|
||||||
|
return Err(format!(
|
||||||
|
"Expected rhs with {} elements but got {}",
|
||||||
|
symbols.len(),
|
||||||
|
values.len()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (symbol,value) in symbols.iter().zip(values.into_iter()) {
|
||||||
|
env.insert(symbol.get_value(), value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Empty::new(format!(
|
||||||
|
"[{}] := {}",
|
||||||
|
symbols
|
||||||
|
.iter()
|
||||||
|
.map(|x| env.id_to_str(&x.get_value()).unwrap().clone())
|
||||||
|
.reduce(|x, acc| format!("{x}, {acc}"))
|
||||||
|
.unwrap(),
|
||||||
|
right.as_string(Some(env))
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
return Err(format!("Cannot unpack {} for assignment", right.type_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => Err(format!("Cannot assign to a {}", self.left.type_str())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,14 @@ impl Node for Call {
|
||||||
fargs.iter().zip(&arguments).for_each(|(symbol, value)| {
|
fargs.iter().zip(&arguments).for_each(|(symbol, value)| {
|
||||||
env.insert(symbol.get_value(), value.clone());
|
env.insert(symbol.get_value(), value.clone());
|
||||||
});
|
});
|
||||||
let ev = body.evaluate(env)?;
|
let ev = body.evaluate(env);
|
||||||
|
|
||||||
|
if ev.is_err() {
|
||||||
|
env.pop_stack()?;
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ev = ev?;
|
||||||
|
|
||||||
// Return evaluated return value for function
|
// Return evaluated return value for function
|
||||||
Ok(match ev.as_ref() {
|
Ok(match ev.as_ref() {
|
||||||
|
|
Loading…
Reference in a new issue