Slightly better ExecEnv::assign

A little more idiomatic, avoid some borrow checker clumsiness, add
comments.
This commit is contained in:
Alex Bethel 2021-11-27 11:02:41 -06:00
parent 8a04d9d1e0
commit 38a3414e88
2 changed files with 28 additions and 15 deletions

View file

@ -11,7 +11,7 @@ use std::{
cell::RefCell, cell::RefCell,
collections::{HashMap, VecDeque}, collections::{HashMap, VecDeque},
io::{stdin, stdout, Read, Write}, io::{stdin, stdout, Read, Write},
mem::swap, mem::take,
ops::Range, ops::Range,
process::exit, process::exit,
rc::Rc, rc::Rc,
@ -292,28 +292,35 @@ impl ExecEnv {
for index in indices { for index in indices {
let index = self.eval_expr(index)?; let index = self.eval_expr(index)?;
let next_cell; let next_cell = match &mut *cell.borrow_mut() {
match &mut *cell.borrow_mut() {
Value::Cart(c) => { Value::Cart(c) => {
// cell is a cart, so we can do simple
// indexing.
if let Some(x) = c.get(&index) { if let Some(x) = c.get(&index) {
next_cell = Rc::clone(x); // cell[index] exists, get a shared
// reference to it.
Rc::clone(x)
} else { } else {
next_cell = Rc::new(RefCell::new(Value::Cart(Default::default()))); // cell[index] does not exist, so we
// insert an empty cart by default
// instead.
let next_cell =
Rc::new(RefCell::new(Value::Cart(Default::default())));
c.insert(index, Rc::clone(&next_cell)); c.insert(index, Rc::clone(&next_cell));
next_cell
} }
} }
x => { x => {
// Annoying borrow checker dance // cell is not a cart; `take` it, convert
// to move *x. // it into a cart, and write the result
let mut tmp = Value::Nul; // back into it.
swap(&mut tmp, x); let mut cart = take(x).into_cart();
let next_cell = Rc::new(RefCell::new(Value::Cart(Default::default())));
let mut c = tmp.into_cart(); cart.insert(index, Rc::clone(&next_cell));
next_cell = Rc::new(RefCell::new(Value::Cart(Default::default()))); *x = Value::Cart(cart);
c.insert(index, Rc::clone(&next_cell)); next_cell
*x = Value::Cart(c);
}
} }
};
cell = next_cell; cell = next_cell;
} }
cell.replace(value); cell.replace(value);

View file

@ -60,6 +60,12 @@ pub enum Value {
Cart(Cart), Cart(Cart),
} }
impl Default for Value {
fn default() -> Self {
Self::Nul
}
}
impl Hash for Value { impl Hash for Value {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
discriminant(self).hash(state); discriminant(self).hash(state);