destructuring assignment
This commit is contained in:
parent
bb1b051598
commit
9da6f7d302
|
@ -1,4 +1,3 @@
|
|||
use std::f32::consts;
|
||||
use std::f64;
|
||||
use std::io::{self, StdoutLock, Write, stdout};
|
||||
use std::rc::Rc;
|
||||
|
@ -12,7 +11,6 @@ use libopenbirch::node::set::Set;
|
|||
use libopenbirch::node::string_node::StringNode;
|
||||
use libopenbirch::node::{Node, NodeEnum};
|
||||
use libopenbirch::parser::{Lexer, LexerError, Parser, ParserError};
|
||||
use raylib::ease::elastic_in;
|
||||
#[cfg(feature = "async")]
|
||||
use termion::AsyncReader;
|
||||
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]))
|
||||
}
|
||||
|
||||
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> {
|
||||
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("set_float_precision", set_float_precision);
|
||||
env.define_native_function("map", map);
|
||||
env.define_native_function("head", head);
|
||||
env.define_native_function("get", get);
|
||||
env.define_native_function("length", length);
|
||||
env.define_native_function("benchmark", benchmark);
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use raylib::ffi::StopAutomationEventRecording;
|
||||
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)]
|
||||
pub struct Add {
|
||||
|
@ -44,6 +47,11 @@ impl Node for Add {
|
|||
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())),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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)]
|
||||
pub struct Assign {
|
||||
|
@ -10,23 +10,70 @@ pub struct Assign {
|
|||
|
||||
impl Node for Assign {
|
||||
fn evaluate(&self, env: &mut Environment) -> Result<Rc<NodeEnum>, String> {
|
||||
if let NodeEnum::Symbol(symbol) = self.left.as_ref() {
|
||||
let name = env
|
||||
.id_to_str(&symbol.get_value())
|
||||
.expect("Unknown symbol")
|
||||
.clone();
|
||||
let right = self.right.evaluate(env)?;
|
||||
match self.left.as_ref() {
|
||||
NodeEnum::Symbol(symbol) => {
|
||||
let name = env
|
||||
.id_to_str(&symbol.get_value())
|
||||
.expect("Unknown symbol")
|
||||
.clone();
|
||||
let right = self.right.evaluate(env)?;
|
||||
|
||||
env.insert(symbol.get_value(), right.clone());
|
||||
Ok(Empty::new(format!(
|
||||
"{name} := {}",
|
||||
right.as_string(Some(env))
|
||||
)))
|
||||
} else {
|
||||
Err(format!(
|
||||
"Cannot assign to a {}",
|
||||
self.left.as_string(Some(env))
|
||||
))
|
||||
env.insert(symbol.get_value(), right.clone());
|
||||
Ok(Empty::new(format!(
|
||||
"{name} := {}",
|
||||
right.as_string(Some(env))
|
||||
)))
|
||||
}
|
||||
|
||||
NodeEnum::Set(set) => {
|
||||
// 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)| {
|
||||
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
|
||||
Ok(match ev.as_ref() {
|
||||
|
|
Loading…
Reference in a new issue