変数と同じように、関数名とinstructionをhashmapに保存する
/x 2 def /double { x 2 * } fn
"fn" => { let tmp = func(&mut stack, instructions.clone()); for (key, value) in &tmp { funcs.insert(key.to_string(), value.to_vec()); } println!("{:?}", funcs); } // 省略 fn func(stack: &mut Vec<String>, instructions: Vec<String>) -> HashMap<String, Vec<String>> { let mut funcs: HashMap<String, Vec<String>> = HashMap::new(); let name = stack.pop().unwrap(); funcs.insert(name, instructions); funcs }
{“double”: [“x”, “2”, “*”]}
関数名と式をhashmapに保存したので、後は関数名が書かれていた際に、関数の内容を呼び出すだけ
} else if funcs.contains_key(word) { let _ = op_fn(&mut stack, funcs.get(word).unwrap(), vars.clone()); // fn op_fn(stack: &mut Vec<String>, input: &Vec<String>, vars: HashMap<String, String>) { let mut words = input.clone(); while let Some((&ref word, rest)) = words.split_first() { if word.is_empty() { break; } if let Ok(parsed) = word.parse::<i32>() { stack.push(parsed.to_string()); } else if word.starts_with("/") { stack.push((word[1..]).to_string()); } else if vars.contains_key(word) { stack.push(vars.get(word).unwrap().to_string()); } else { match word.as_str() { "+" => add(stack), "-" => sub(stack), "*" => mul(stack), "/" => div(stack), "%" => r#mod(stack), "<" => lt(stack), ">" => rt(stack), "==" => equal(stack), "!=" => nequal(stack), "sqrt" => r#sqrt(stack), "if" => op_if(stack), _ => todo!(), } } words = rest.to_vec(); } }
/x 2 def /double { x 2 * } fn double
=> [“4”]