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)
|
||||
.collect();
|
||||
|
||||
Node::Map(res)
|
||||
Node::Hashmap(res)
|
||||
}),
|
||||
),
|
||||
(
|
||||
|
@ -222,7 +222,7 @@ pub(super) fn core() -> HashMap<String, Value> {
|
|||
NativeFunc(|args| {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ pub(super) fn core() -> HashMap<String, Value> {
|
|||
match args.pop_front().expect("argument length checked above") {
|
||||
Node::List(list) => Node::Boolean(list.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!(
|
||||
"TypeError: expected list, vector, or hashmap, got {}.",
|
||||
arg.get_type()
|
||||
|
@ -253,7 +253,7 @@ pub(super) fn core() -> HashMap<String, Value> {
|
|||
match args.pop_front().expect("argument length checked above") {
|
||||
Node::List(list) => Node::Int(list.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!(
|
||||
"TypeError: expected list, vector, or hashmap, got {}.",
|
||||
arg.get_type()
|
||||
|
|
|
@ -232,6 +232,36 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
|
|||
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
|
||||
.get_node(&sym)
|
||||
.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::Error(_)
|
||||
| Node::Vector(_)
|
||||
| Node::Map(_)
|
||||
| Node::Hashmap(_)
|
||||
| Node::Function { .. }
|
||||
| Node::Macro { .. } => ast_node,
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@ fn format_node(node: Node) -> String {
|
|||
Node::Error(e) => format!("Node::Error(\"{e}\".to_string())"),
|
||||
|
||||
Node::Vector(_) => todo!(),
|
||||
Node::Map(_) => todo!(),
|
||||
Node::Hashmap(_) => todo!(),
|
||||
|
||||
// Quoting
|
||||
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::Eval(body) => format!("Node::Eval({})", 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,
|
||||
Do,
|
||||
|
||||
Map,
|
||||
Filter,
|
||||
Reduce,
|
||||
Fold,
|
||||
|
||||
Quote,
|
||||
Quasiquote,
|
||||
Unquote,
|
||||
|
@ -219,6 +224,10 @@ fn read_ident(input: &mut Peekable<Chars>, first: char) -> Token {
|
|||
"apply" => Token::Apply,
|
||||
"if" => Token::If,
|
||||
"do" => Token::Do,
|
||||
"map" => Token::Map,
|
||||
"filter" => Token::Filter,
|
||||
"reduce" => Token::Reduce,
|
||||
"fold" => Token::Fold,
|
||||
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::If => Node::If(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)?,
|
||||
},
|
||||
|
@ -82,7 +86,11 @@ fn next_statement(tokens: &mut TokenIter) -> Result<Option<Node>> {
|
|||
| Token::Eval
|
||||
| Token::Apply
|
||||
| Token::If
|
||||
| Token::Do => Err(Error::SpecialNotOperator)?,
|
||||
| Token::Do
|
||||
| Token::Map
|
||||
| Token::Filter
|
||||
| Token::Reduce
|
||||
| Token::Fold => Err(Error::SpecialNotOperator)?,
|
||||
};
|
||||
|
||||
Ok(Some(node))
|
||||
|
|
|
@ -16,7 +16,7 @@ pub enum Node {
|
|||
Error(String),
|
||||
|
||||
Vector(Vec<Node>),
|
||||
Map(HashMap<String, Node>),
|
||||
Hashmap(HashMap<String, Node>),
|
||||
|
||||
// Specials
|
||||
// TODO: Specials should point to a LinkedList
|
||||
|
@ -33,6 +33,11 @@ pub enum Node {
|
|||
Do(VecDeque<Node>),
|
||||
Eval(VecDeque<Node>),
|
||||
Apply(VecDeque<Node>),
|
||||
|
||||
Map(VecDeque<Node>),
|
||||
Filter(VecDeque<Node>),
|
||||
Reduce(VecDeque<Node>),
|
||||
Fold(VecDeque<Node>),
|
||||
}
|
||||
|
||||
impl Node {
|
||||
|
@ -49,7 +54,7 @@ impl Node {
|
|||
Node::Void => "void".to_string(),
|
||||
Node::Error(_) => "error".to_string(),
|
||||
Node::Vector(_) => "vector".to_string(),
|
||||
Node::Map(_) => "map".to_string(),
|
||||
Node::Hashmap(_) => "hashmap".to_string(),
|
||||
Node::Define { .. } => "define".to_string(),
|
||||
Node::Let { .. } => "let".to_string(),
|
||||
Node::Function { .. } => "function".to_string(),
|
||||
|
@ -61,6 +66,10 @@ impl Node {
|
|||
Node::Do { .. } => "do".to_string(),
|
||||
Node::Eval { .. } => "eval".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::Vector(body) => write!(f, "[{}]", reduce_list(body)),
|
||||
Node::Map(body) => write!(
|
||||
Node::Hashmap(body) => write!(
|
||||
f,
|
||||
"{{{}}}",
|
||||
body.iter()
|
||||
|
@ -113,6 +122,10 @@ impl std::fmt::Display for Node {
|
|||
Node::Do(body) => write!(f, "(do {})", reduce_list(body)),
|
||||
Node::Eval(body) => write!(f, "(eval {})", 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