From aabe7b26230e9ce5b66dcd0629dcc643f1dff592 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sat, 11 Sep 2021 02:53:32 +0200 Subject: [PATCH] Repair reading of simple but compound types within a simple dictionary pattern --- .../preserves-schema/src/compiler/context.rs | 10 +++ .../preserves-schema/src/compiler/readers.rs | 78 +++++++++++-------- 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/implementations/rust/preserves-schema/src/compiler/context.rs b/implementations/rust/preserves-schema/src/compiler/context.rs index 3f22563..aefb4f1 100644 --- a/implementations/rust/preserves-schema/src/compiler/context.rs +++ b/implementations/rust/preserves-schema/src/compiler/context.rs @@ -177,6 +177,16 @@ impl<'a, 'm> FunctionContext<'a, 'm> { }) } + pub fn with_definite_mode 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 ()>(&mut self, f: F) -> Vec { let saved_mode = std::mem::replace(&mut self.capture_mode, CaptureMode::Indefinite(Vec::new())); f(self); diff --git a/implementations/rust/preserves-schema/src/compiler/readers.rs b/implementations/rust/preserves-schema/src/compiler/readers.rs index 31b7460..5040d1e 100644 --- a/implementations/rust/preserves-schema/src/compiler/readers.rs +++ b/implementations/rust/preserves-schema/src/compiler/readers.rs @@ -357,45 +357,57 @@ fn simple_pattern_reader( dest }, SimplePattern::Seqof { pattern } => { - let boundary_tracker = BoundaryTracker::unwrap( - ctxt, body, "r.open_sequence()?;", boundary_tracker); - let mut inner = Vec::new(); - boundary_tracker.emit_boundary(&mut inner); - let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); - inner.push(item(seq![dest.to_owned(), ".push(", - store_wrap(true, &field_type(pattern), &item_dest), ");"])); - ctxt.declare_compound(body, &dest, item("std::vec::Vec::new()")); - boundary_tracker.emit_loop(body, inner); + let compound_dest = ctxt.gentempname(); + ctxt.with_definite_mode(|ctxt| { + let boundary_tracker = BoundaryTracker::unwrap( + ctxt, body, "r.open_sequence()?;", boundary_tracker); + let mut inner = Vec::new(); + boundary_tracker.emit_boundary(&mut inner); + let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); + inner.push(item(seq![compound_dest.to_owned(), ".push(", + 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 }, SimplePattern::Setof { pattern } => { - let boundary_tracker = BoundaryTracker::new( - ctxt, body, "r.open_set()?;", "_support::B::Item::SetValue"); - let mut inner = Vec::new(); - boundary_tracker.emit_boundary(&mut inner); - let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); - inner.push(item(seq![dest.to_owned(), ".insert(", - store_wrap(true, &field_type(pattern), &item_dest), ");"])); - ctxt.declare_compound(body, &dest, item("preserves::value::Set::new()")); - boundary_tracker.emit_loop(body, inner); + let compound_dest = ctxt.gentempname(); + ctxt.with_definite_mode(|ctxt| { + let boundary_tracker = BoundaryTracker::new( + ctxt, body, "r.open_set()?;", "_support::B::Item::SetValue"); + let mut inner = Vec::new(); + boundary_tracker.emit_boundary(&mut inner); + let item_dest = simple_pattern_reader(ctxt, pattern, None, &mut inner); + inner.push(item(seq![compound_dest.to_owned(), ".insert(", + 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 }, SimplePattern::Dictof { key, value } => { - let mut boundary_tracker = BoundaryTracker::new( - ctxt, body, "r.open_dictionary()?;", "_support::B::Item::DictionaryKey"); - let mut inner = Vec::new(); - boundary_tracker.emit_boundary(&mut inner); - let key_dest = simple_pattern_reader(ctxt, key, None, &mut inner); - boundary_tracker.item_expr = "_support::B::Item::DictionaryValue"; - boundary_tracker.emit_boundary(&mut inner); - let value_dest = simple_pattern_reader(ctxt, value, None, &mut inner); - inner.push(item(seq![ - dest.to_owned(), ".insert(", - store_wrap(true, &field_type(key), &key_dest), ", ", - store_wrap(true, &field_type(value), &value_dest), ");"])); - ctxt.declare_compound(body, &dest, item("preserves::value::Map::new()")); - boundary_tracker.item_expr = "_support::B::Item::DictionaryKey"; - boundary_tracker.emit_loop(body, inner); + let compound_dest = ctxt.gentempname(); + ctxt.with_definite_mode(|ctxt| { + let mut boundary_tracker = BoundaryTracker::new( + ctxt, body, "r.open_dictionary()?;", "_support::B::Item::DictionaryKey"); + let mut inner = Vec::new(); + boundary_tracker.emit_boundary(&mut inner); + let key_dest = simple_pattern_reader(ctxt, key, None, &mut inner); + boundary_tracker.item_expr = "_support::B::Item::DictionaryValue"; + boundary_tracker.emit_boundary(&mut inner); + let value_dest = simple_pattern_reader(ctxt, value, None, &mut inner); + inner.push(item(seq![ + compound_dest.to_owned(), ".insert(", + store_wrap(true, &field_type(key), &key_dest), ", ", + store_wrap(true, &field_type(value), &value_dest), ");"])); + 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 }, SimplePattern::Ref(r) => {