diff --git a/src/heap_print.rs b/src/heap_print.rs index 3c22f0ae..f6f0c8f3 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -874,12 +874,16 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { None => { if self.max_depth == 0 || *max_depth == 0 { // otherwise, contract it to an ellipsis. - push_space_if_amb!(self, "...", { - append_str!(self, "..."); - }); + self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); } else { debug_assert!(cell.is_ref()); + let h = cell.get_value() as usize; + self.iter.push_stack(IterStackLoc::iterable_loc( + h, + HeapOrStackTag::Heap, + )); + // as usual, the WAM's // optimization of the Lis tag // (conflating the location of @@ -889,15 +893,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { // lest we find ourselves in // an infinite loop. if cell.get_tag() == HeapCellValueTag::Lis { - *max_depth -= 1; + if self.iter.heap[cell.get_value() as usize] + .get_forwarding_bit() + { + self.state_stack + .push(TokenOrRedirect::Atom(atom!("..."))); + return None; + } else { + *max_depth -= 1; + } } - let h = cell.get_value() as usize; - self.iter.push_stack(IterStackLoc::iterable_loc( - h, - HeapOrStackTag::Heap, - )); - if let Some(cell) = self.iter.next() { orig_cell = cell; continue; diff --git a/src/lib/charsio.pl b/src/lib/charsio.pl index 2204d80d..536aeac6 100644 --- a/src/lib/charsio.pl +++ b/src/lib/charsio.pl @@ -195,7 +195,7 @@ get_single_char(C) :- ; type_error(in_character, C, get_single_char/1) ). -%% read_from_chars(+Chars, -Term). +%% read_from_chars(+Chars, ?Term). % % Given a string made of chars which contains a representation of % a Prolog term, Term is the Prolog term represented. Example: @@ -206,10 +206,10 @@ get_single_char(C) :- % ``` read_from_chars(Chars, Term) :- must_be(chars, Chars), - must_be(var, Term), - '$read_from_chars'(Chars, Term). + '$read_from_chars'(Chars, Term0), + Term = Term0. -%% read_term_from_chars(+Chars, -Term, +Options). +%% read_term_from_chars(+Chars, ?Term, +Options). % % Like `read_from_chars`, except the reader is configured according to % `Options` which are those of `read_term`. @@ -220,9 +220,9 @@ read_from_chars(Chars, Term) :- % ``` read_term_from_chars(Chars, Term, Options) :- must_be(chars, Chars), - must_be(var, Term), builtins:parse_read_term_options(Options, [Singletons, VariableNames, Variables], read_term_from_chars/3), - '$read_term_from_chars'(Chars, Term, Singletons, Variables, VariableNames). + '$read_term_from_chars'(Chars, Term0, Singletons, Variables, VariableNames), + Term = Term0. %% write_term_to_chars(+Term, +Options, -Chars). % diff --git a/src/wasm.rs b/src/wasm.rs index 10430677..22234e16 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -78,6 +78,7 @@ impl WasmMachine { ), } .into(); + self_iterable(&query_state); Ok(query_state) } @@ -174,6 +175,21 @@ impl WasmQueryState { } } +/// Sets a [JsValue] as the `Symbol.iterator` property of the [JsValue]. +/// +/// If the [JsValue] conforms to the [JavaScript iterator interface](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators), +/// this function will make the [JsValue] iterable. +#[wasm_bindgen(inline_js = " + export function self_iterable(obj) { + obj[Symbol.iterator] = function () { + return this; + }; + } +")] +extern "C" { + fn self_iterable(obj: &JsValue); +} + impl From for JsValue { fn from(leaf_answer: LeafAnswer) -> JsValue { match leaf_answer {