From: Mark Date: Sat, 15 Jul 2023 17:20:20 +0000 (-0600) Subject: add read_term_from_chars/3 (#637) X-Git-Tag: v0.9.2~51 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=5a7da721cd9f1ae02df9c515e4a9384ebb5d9f8c;p=scryer-prolog.git add read_term_from_chars/3 (#637) --- diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 5eaa542b..62dc6146 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -418,7 +418,9 @@ enum SystemClauseType { CurrentTime, #[strum_discriminants(strum(props(Arity = "1", Name = "$quoted_token")))] QuotedToken, - #[strum_discriminants(strum(props(Arity = "2", Name = "$read_term_from_chars")))] + #[strum_discriminants(strum(props(Arity = "2", Name = "$read_from_chars")))] + ReadFromChars, + #[strum_discriminants(strum(props(Arity = "5", Name = "$read_term_from_chars")))] ReadTermFromChars, #[strum_discriminants(strum(props(Arity = "1", Name = "$reset_block")))] ResetBlock, @@ -1735,6 +1737,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::CallStripModule | &Instruction::CallCurrentTime | &Instruction::CallQuotedToken | + &Instruction::CallReadFromChars | &Instruction::CallReadTermFromChars | &Instruction::CallResetBlock | &Instruction::CallResetSCCBlock | @@ -1959,6 +1962,7 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::ExecuteStripModule | &Instruction::ExecuteCurrentTime | &Instruction::ExecuteQuotedToken | + &Instruction::ExecuteReadFromChars | &Instruction::ExecuteReadTermFromChars | &Instruction::ExecuteResetBlock | &Instruction::ExecuteResetSCCBlock | diff --git a/src/lib/charsio.pl b/src/lib/charsio.pl index 128a6c50..618416f1 100644 --- a/src/lib/charsio.pl +++ b/src/lib/charsio.pl @@ -12,6 +12,7 @@ read and write chars. get_n_chars/3, get_line_to_chars/3, read_from_chars/2, + read_term_from_chars/3, write_term_to_chars/3, chars_base64/3]). @@ -194,7 +195,22 @@ get_single_char(C) :- read_from_chars(Chars, Term) :- must_be(chars, Chars), must_be(var, Term), - '$read_term_from_chars'(Chars, Term). + '$read_from_chars'(Chars, Term). + +%% 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`. +% +% ``` +% ?- read_term_from_chars("f(X,y).", T, [variable_names(['X'=X])]). +% T = f(X,y). +% ``` +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). %% write_term_to_chars(+Term, +Options, -Chars). % diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index afe67fb9..b57e77b9 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -4270,6 +4270,14 @@ impl Machine { self.quoted_token(); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } + &Instruction::CallReadFromChars => { + try_or_throw!(self.machine_st, self.read_from_chars()); + step_or_fail!(self, self.machine_st.p += 1); + } + &Instruction::ExecuteReadFromChars => { + try_or_throw!(self.machine_st, self.read_from_chars()); + step_or_fail!(self, self.machine_st.p = self.machine_st.cp); + } &Instruction::CallReadTermFromChars => { try_or_throw!(self.machine_st, self.read_term_from_chars()); step_or_fail!(self, self.machine_st.p += 1); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index d53ef79f..35e019ff 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -5792,7 +5792,7 @@ impl Machine { } #[inline(always)] - pub(crate) fn read_term_from_chars(&mut self) -> CallResult { + pub(crate) fn read_from_chars(&mut self) -> CallResult { if let Some(atom_or_string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) { let chars = CharReader::new(ByteStream::from_string(atom_or_string.to_string())); let mut parser = Parser::new(chars, &mut self.machine_st); @@ -5829,6 +5829,16 @@ impl Machine { Ok(()) } + #[inline(always)] + pub(crate) fn read_term_from_chars(&mut self) -> CallResult { + if let Some(atom_or_string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) { + let stream = Stream::from_owned_string(atom_or_string.to_string(), &mut self.machine_st.arena); + self.machine_st.read_term(stream, &mut self.indices) + } else { + unreachable!() + } + } + #[inline(always)] pub(crate) fn reset_block(&mut self) { let addr = self.deref_register(1);