feat: map function for iterators
This commit is contained in:
parent
a7c6e1a07d
commit
315478826f
6 changed files with 75 additions and 10 deletions
8
mute-interpreter/src/env/core.rs
vendored
8
mute-interpreter/src/env/core.rs
vendored
|
@ -214,7 +214,7 @@ pub(super) fn core() -> HashMap<String, Value> {
|
||||||
.zip(values)
|
.zip(values)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Node::Map(res)
|
Node::Hashmap(res)
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -222,7 +222,7 @@ pub(super) fn core() -> HashMap<String, Value> {
|
||||||
NativeFunc(|args| {
|
NativeFunc(|args| {
|
||||||
arg_count!(1, args.len());
|
arg_count!(1, args.len());
|
||||||
|
|
||||||
if let Node::Map(_map) = args[0].borrow() {
|
if let Node::Hashmap(_map) = args[0].borrow() {
|
||||||
return Node::Boolean(true);
|
return Node::Boolean(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ pub(super) fn core() -> HashMap<String, Value> {
|
||||||
match args.pop_front().expect("argument length checked above") {
|
match args.pop_front().expect("argument length checked above") {
|
||||||
Node::List(list) => Node::Boolean(list.is_empty()),
|
Node::List(list) => Node::Boolean(list.is_empty()),
|
||||||
Node::Vector(vec) => Node::Boolean(vec.is_empty()),
|
Node::Vector(vec) => Node::Boolean(vec.is_empty()),
|
||||||
Node::Map(map) => Node::Boolean(map.is_empty()),
|
Node::Hashmap(map) => Node::Boolean(map.is_empty()),
|
||||||
arg => Node::Error(format!(
|
arg => Node::Error(format!(
|
||||||
"TypeError: expected list, vector, or hashmap, got {}.",
|
"TypeError: expected list, vector, or hashmap, got {}.",
|
||||||
arg.get_type()
|
arg.get_type()
|
||||||
|
@ -253,7 +253,7 @@ pub(super) fn core() -> HashMap<String, Value> {
|
||||||
match args.pop_front().expect("argument length checked above") {
|
match args.pop_front().expect("argument length checked above") {
|
||||||
Node::List(list) => Node::Int(list.len() as i64),
|
Node::List(list) => Node::Int(list.len() as i64),
|
||||||
Node::Vector(vec) => Node::Int(vec.len() as i64),
|
Node::Vector(vec) => Node::Int(vec.len() as i64),
|
||||||
Node::Map(map) => Node::Int(map.len() as i64),
|
Node::Hashmap(map) => Node::Int(map.len() as i64),
|
||||||
arg => Node::Error(format!(
|
arg => Node::Error(format!(
|
||||||
"TypeError: expected list, vector, or hashmap, got {}.",
|
"TypeError: expected list, vector, or hashmap, got {}.",
|
||||||
arg.get_type()
|
arg.get_type()
|
||||||
|
|
|
@ -232,6 +232,36 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
|
||||||
eval_node(env, Node::List(args))?
|
eval_node(env, Node::List(args))?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node::Map(mut body) => {
|
||||||
|
if body.len() != 2 {
|
||||||
|
return Err(Error::MismatchedArgCount(2, body.len()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let list = body.pop_front().expect("arg count verified above");
|
||||||
|
let list = match eval_node(env, list)? {
|
||||||
|
Node::List(list) => list,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let func = match body.pop_front().expect("arg count verified above") {
|
||||||
|
node @ Node::Function(_) => node,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let list = list
|
||||||
|
.into_iter()
|
||||||
|
.map(|node| {
|
||||||
|
let expr = Node::List(vec![func.clone(), node].into());
|
||||||
|
eval_node(env, expr)
|
||||||
|
})
|
||||||
|
.collect::<Result<VecDeque<Node>>>()?;
|
||||||
|
|
||||||
|
Node::List(list)
|
||||||
|
}
|
||||||
|
Node::Filter(mut body) => todo!(),
|
||||||
|
Node::Reduce(mut body) => todo!(),
|
||||||
|
Node::Fold(mut body) => todo!(),
|
||||||
|
|
||||||
Node::Symbol(sym) => env
|
Node::Symbol(sym) => env
|
||||||
.get_node(&sym)
|
.get_node(&sym)
|
||||||
.ok_or_else(|| Error::NotInEnv(sym.clone()))?
|
.ok_or_else(|| Error::NotInEnv(sym.clone()))?
|
||||||
|
@ -246,7 +276,7 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
|
||||||
| Node::Void
|
| Node::Void
|
||||||
| Node::Error(_)
|
| Node::Error(_)
|
||||||
| Node::Vector(_)
|
| Node::Vector(_)
|
||||||
| Node::Map(_)
|
| Node::Hashmap(_)
|
||||||
| Node::Function { .. }
|
| Node::Function { .. }
|
||||||
| Node::Macro { .. } => ast_node,
|
| Node::Macro { .. } => ast_node,
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,7 +32,7 @@ fn format_node(node: Node) -> String {
|
||||||
Node::Error(e) => format!("Node::Error(\"{e}\".to_string())"),
|
Node::Error(e) => format!("Node::Error(\"{e}\".to_string())"),
|
||||||
|
|
||||||
Node::Vector(_) => todo!(),
|
Node::Vector(_) => todo!(),
|
||||||
Node::Map(_) => todo!(),
|
Node::Hashmap(_) => todo!(),
|
||||||
|
|
||||||
// Quoting
|
// Quoting
|
||||||
Node::Quote(node) => format!("Node::Quote(Box::new({}))", format_node(*node)),
|
Node::Quote(node) => format!("Node::Quote(Box::new({}))", format_node(*node)),
|
||||||
|
@ -48,6 +48,11 @@ fn format_node(node: Node) -> String {
|
||||||
Node::Do(body) => format!("Node::Do({})", reduce_list(body)),
|
Node::Do(body) => format!("Node::Do({})", reduce_list(body)),
|
||||||
Node::Eval(body) => format!("Node::Eval({})", reduce_list(body)),
|
Node::Eval(body) => format!("Node::Eval({})", reduce_list(body)),
|
||||||
Node::Apply(body) => format!("Node::Apply({})", reduce_list(body),),
|
Node::Apply(body) => format!("Node::Apply({})", reduce_list(body),),
|
||||||
|
|
||||||
|
Node::Map(body) => format!("Node::Map({})", reduce_list(body)),
|
||||||
|
Node::Filter(body) => format!("Node::Filter({})", reduce_list(body)),
|
||||||
|
Node::Reduce(body) => format!("Node::Reduce({})", reduce_list(body)),
|
||||||
|
Node::Fold(body) => format!("Node::Fold({})", reduce_list(body)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,11 @@ pub enum Token {
|
||||||
If,
|
If,
|
||||||
Do,
|
Do,
|
||||||
|
|
||||||
|
Map,
|
||||||
|
Filter,
|
||||||
|
Reduce,
|
||||||
|
Fold,
|
||||||
|
|
||||||
Quote,
|
Quote,
|
||||||
Quasiquote,
|
Quasiquote,
|
||||||
Unquote,
|
Unquote,
|
||||||
|
@ -219,6 +224,10 @@ fn read_ident(input: &mut Peekable<Chars>, first: char) -> Token {
|
||||||
"apply" => Token::Apply,
|
"apply" => Token::Apply,
|
||||||
"if" => Token::If,
|
"if" => Token::If,
|
||||||
"do" => Token::Do,
|
"do" => Token::Do,
|
||||||
|
"map" => Token::Map,
|
||||||
|
"filter" => Token::Filter,
|
||||||
|
"reduce" => Token::Reduce,
|
||||||
|
"fold" => Token::Fold,
|
||||||
ident => Token::Ident(ident.to_owned()),
|
ident => Token::Ident(ident.to_owned()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ fn next_statement(tokens: &mut TokenIter) -> Result<Option<Node>> {
|
||||||
Token::Apply => Node::Apply(read_body(tokens)?),
|
Token::Apply => Node::Apply(read_body(tokens)?),
|
||||||
Token::If => Node::If(read_body(tokens)?),
|
Token::If => Node::If(read_body(tokens)?),
|
||||||
Token::Do => Node::Do(read_body(tokens)?),
|
Token::Do => Node::Do(read_body(tokens)?),
|
||||||
|
Token::Map => Node::Map(read_body(tokens)?),
|
||||||
|
Token::Filter => Node::Filter(read_body(tokens)?),
|
||||||
|
Token::Reduce => Node::Reduce(read_body(tokens)?),
|
||||||
|
Token::Fold => Node::Fold(read_body(tokens)?),
|
||||||
|
|
||||||
_ => read_list(tokens, Token::RightParen)?,
|
_ => read_list(tokens, Token::RightParen)?,
|
||||||
},
|
},
|
||||||
|
@ -82,7 +86,11 @@ fn next_statement(tokens: &mut TokenIter) -> Result<Option<Node>> {
|
||||||
| Token::Eval
|
| Token::Eval
|
||||||
| Token::Apply
|
| Token::Apply
|
||||||
| Token::If
|
| Token::If
|
||||||
| Token::Do => Err(Error::SpecialNotOperator)?,
|
| Token::Do
|
||||||
|
| Token::Map
|
||||||
|
| Token::Filter
|
||||||
|
| Token::Reduce
|
||||||
|
| Token::Fold => Err(Error::SpecialNotOperator)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(node))
|
Ok(Some(node))
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub enum Node {
|
||||||
Error(String),
|
Error(String),
|
||||||
|
|
||||||
Vector(Vec<Node>),
|
Vector(Vec<Node>),
|
||||||
Map(HashMap<String, Node>),
|
Hashmap(HashMap<String, Node>),
|
||||||
|
|
||||||
// Specials
|
// Specials
|
||||||
// TODO: Specials should point to a LinkedList
|
// TODO: Specials should point to a LinkedList
|
||||||
|
@ -33,6 +33,11 @@ pub enum Node {
|
||||||
Do(VecDeque<Node>),
|
Do(VecDeque<Node>),
|
||||||
Eval(VecDeque<Node>),
|
Eval(VecDeque<Node>),
|
||||||
Apply(VecDeque<Node>),
|
Apply(VecDeque<Node>),
|
||||||
|
|
||||||
|
Map(VecDeque<Node>),
|
||||||
|
Filter(VecDeque<Node>),
|
||||||
|
Reduce(VecDeque<Node>),
|
||||||
|
Fold(VecDeque<Node>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
@ -49,7 +54,7 @@ impl Node {
|
||||||
Node::Void => "void".to_string(),
|
Node::Void => "void".to_string(),
|
||||||
Node::Error(_) => "error".to_string(),
|
Node::Error(_) => "error".to_string(),
|
||||||
Node::Vector(_) => "vector".to_string(),
|
Node::Vector(_) => "vector".to_string(),
|
||||||
Node::Map(_) => "map".to_string(),
|
Node::Hashmap(_) => "hashmap".to_string(),
|
||||||
Node::Define { .. } => "define".to_string(),
|
Node::Define { .. } => "define".to_string(),
|
||||||
Node::Let { .. } => "let".to_string(),
|
Node::Let { .. } => "let".to_string(),
|
||||||
Node::Function { .. } => "function".to_string(),
|
Node::Function { .. } => "function".to_string(),
|
||||||
|
@ -61,6 +66,10 @@ impl Node {
|
||||||
Node::Do { .. } => "do".to_string(),
|
Node::Do { .. } => "do".to_string(),
|
||||||
Node::Eval { .. } => "eval".to_string(),
|
Node::Eval { .. } => "eval".to_string(),
|
||||||
Node::Apply { .. } => "apply".to_string(),
|
Node::Apply { .. } => "apply".to_string(),
|
||||||
|
Node::Map { .. } => "map".to_string(),
|
||||||
|
Node::Filter { .. } => "filter".to_string(),
|
||||||
|
Node::Reduce { .. } => "reduce".to_string(),
|
||||||
|
Node::Fold { .. } => "fold".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +100,7 @@ impl std::fmt::Display for Node {
|
||||||
Node::Error(val) => write!(f, "error: {}", val),
|
Node::Error(val) => write!(f, "error: {}", val),
|
||||||
|
|
||||||
Node::Vector(body) => write!(f, "[{}]", reduce_list(body)),
|
Node::Vector(body) => write!(f, "[{}]", reduce_list(body)),
|
||||||
Node::Map(body) => write!(
|
Node::Hashmap(body) => write!(
|
||||||
f,
|
f,
|
||||||
"{{{}}}",
|
"{{{}}}",
|
||||||
body.iter()
|
body.iter()
|
||||||
|
@ -113,6 +122,10 @@ impl std::fmt::Display for Node {
|
||||||
Node::Do(body) => write!(f, "(do {})", reduce_list(body)),
|
Node::Do(body) => write!(f, "(do {})", reduce_list(body)),
|
||||||
Node::Eval(body) => write!(f, "(eval {})", reduce_list(body)),
|
Node::Eval(body) => write!(f, "(eval {})", reduce_list(body)),
|
||||||
Node::Apply(body) => write!(f, "(apply {})", reduce_list(body)),
|
Node::Apply(body) => write!(f, "(apply {})", reduce_list(body)),
|
||||||
|
Node::Map(body) => write!(f, "(map {})", reduce_list(body)),
|
||||||
|
Node::Filter(body) => write!(f, "(filter {})", reduce_list(body)),
|
||||||
|
Node::Reduce(body) => write!(f, "(reduce {})", reduce_list(body)),
|
||||||
|
Node::Fold(body) => write!(f, "(fold {})", reduce_list(body)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue