Repair reading of simple but compound types within a simple dictionary pattern

This commit is contained in:
Tony Garnock-Jones 2021-09-11 02:53:32 +02:00
parent e43e85ce8e
commit aabe7b2623
2 changed files with 55 additions and 33 deletions

View File

@ -177,6 +177,16 @@ impl<'a, 'm> FunctionContext<'a, 'm> {
}) })
} }
pub fn with_definite_mode<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
let saved_mode = std::mem::replace(&mut self.capture_mode, CaptureMode::Definite);
let result = f(self);
match std::mem::replace(&mut self.capture_mode, saved_mode) {
CaptureMode::Definite => (),
CaptureMode::Indefinite(_) => panic!("corrupt capture_mode"),
}
result
}
pub fn with_indefinite_mode<F: FnOnce(&mut Self) -> ()>(&mut self, f: F) -> Vec<Item> { pub fn with_indefinite_mode<F: FnOnce(&mut Self) -> ()>(&mut self, f: F) -> Vec<Item> {
let saved_mode = std::mem::replace(&mut self.capture_mode, CaptureMode::Indefinite(Vec::new())); let saved_mode = std::mem::replace(&mut self.capture_mode, CaptureMode::Indefinite(Vec::new()));
f(self); f(self);

View File

@ -357,45 +357,57 @@ fn simple_pattern_reader(
dest dest
}, },
SimplePattern::Seqof { pattern } => { SimplePattern::Seqof { pattern } => {
let boundary_tracker = BoundaryTracker::unwrap( let compound_dest = ctxt.gentempname();
ctxt, body, "r.open_sequence()?;", boundary_tracker); ctxt.with_definite_mode(|ctxt| {
let mut inner = Vec::new(); let boundary_tracker = BoundaryTracker::unwrap(
boundary_tracker.emit_boundary(&mut inner); ctxt, body, "r.open_sequence()?;", boundary_tracker);
let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); let mut inner = Vec::new();
inner.push(item(seq![dest.to_owned(), ".push(", boundary_tracker.emit_boundary(&mut inner);
store_wrap(true, &field_type(pattern), &item_dest), ");"])); let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner);
ctxt.declare_compound(body, &dest, item("std::vec::Vec::new()")); inner.push(item(seq![compound_dest.to_owned(), ".push(",
boundary_tracker.emit_loop(body, inner); store_wrap(true, &field_type(pattern), &item_dest), ");"]));
ctxt.declare_compound(body, &compound_dest, item("std::vec::Vec::new()"));
boundary_tracker.emit_loop(body, inner);
});
ctxt.define_atom(body, &dest, item(compound_dest));
dest dest
}, },
SimplePattern::Setof { pattern } => { SimplePattern::Setof { pattern } => {
let boundary_tracker = BoundaryTracker::new( let compound_dest = ctxt.gentempname();
ctxt, body, "r.open_set()?;", "_support::B::Item::SetValue"); ctxt.with_definite_mode(|ctxt| {
let mut inner = Vec::new(); let boundary_tracker = BoundaryTracker::new(
boundary_tracker.emit_boundary(&mut inner); ctxt, body, "r.open_set()?;", "_support::B::Item::SetValue");
let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); let mut inner = Vec::new();
inner.push(item(seq![dest.to_owned(), ".insert(", boundary_tracker.emit_boundary(&mut inner);
store_wrap(true, &field_type(pattern), &item_dest), ");"])); let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner);
ctxt.declare_compound(body, &dest, item("preserves::value::Set::new()")); inner.push(item(seq![compound_dest.to_owned(), ".insert(",
boundary_tracker.emit_loop(body, inner); store_wrap(true, &field_type(pattern), &item_dest), ");"]));
ctxt.declare_compound(body, &compound_dest, item("preserves::value::Set::new()"));
boundary_tracker.emit_loop(body, inner);
});
ctxt.define_atom(body, &dest, item(compound_dest));
dest dest
}, },
SimplePattern::Dictof { key, value } => { SimplePattern::Dictof { key, value } => {
let mut boundary_tracker = BoundaryTracker::new( let compound_dest = ctxt.gentempname();
ctxt, body, "r.open_dictionary()?;", "_support::B::Item::DictionaryKey"); ctxt.with_definite_mode(|ctxt| {
let mut inner = Vec::new(); let mut boundary_tracker = BoundaryTracker::new(
boundary_tracker.emit_boundary(&mut inner); ctxt, body, "r.open_dictionary()?;", "_support::B::Item::DictionaryKey");
let key_dest = simple_pattern_reader(ctxt, key, None, &mut inner); let mut inner = Vec::new();
boundary_tracker.item_expr = "_support::B::Item::DictionaryValue"; boundary_tracker.emit_boundary(&mut inner);
boundary_tracker.emit_boundary(&mut inner); let key_dest = simple_pattern_reader(ctxt, key, None, &mut inner);
let value_dest = simple_pattern_reader(ctxt, value, None, &mut inner); boundary_tracker.item_expr = "_support::B::Item::DictionaryValue";
inner.push(item(seq![ boundary_tracker.emit_boundary(&mut inner);
dest.to_owned(), ".insert(", let value_dest = simple_pattern_reader(ctxt, value, None, &mut inner);
store_wrap(true, &field_type(key), &key_dest), ", ", inner.push(item(seq![
store_wrap(true, &field_type(value), &value_dest), ");"])); compound_dest.to_owned(), ".insert(",
ctxt.declare_compound(body, &dest, item("preserves::value::Map::new()")); store_wrap(true, &field_type(key), &key_dest), ", ",
boundary_tracker.item_expr = "_support::B::Item::DictionaryKey"; store_wrap(true, &field_type(value), &value_dest), ");"]));
boundary_tracker.emit_loop(body, inner); ctxt.declare_compound(body, &compound_dest, item("preserves::value::Map::new()"));
boundary_tracker.item_expr = "_support::B::Item::DictionaryKey";
boundary_tracker.emit_loop(body, inner);
});
ctxt.define_atom(body, &dest, item(compound_dest));
dest dest
}, },
SimplePattern::Ref(r) => { SimplePattern::Ref(r) => {