]> Repositorios git - scryer-prolog.git/commitdiff
add double_quotes write option for printing to strings, enable it at toplevel
authorMark <[email protected]>
Mon, 3 Jul 2023 17:35:07 +0000 (11:35 -0600)
committerMark <[email protected]>
Mon, 3 Jul 2023 18:09:05 +0000 (12:09 -0600)
build/instructions_template.rs
src/heap_print.rs
src/lib/builtins.pl
src/lib/charsio.pl
src/machine/machine_state.rs
src/machine/mock_wam.rs
src/parser/ast.rs
src/toplevel.pl

index 7f559b8e287043d140aa3ad279d8e7a8acda7236..dc88a827e0de7bd5cec764a19b8dd5f9d151a6bc 100644 (file)
@@ -472,9 +472,9 @@ enum SystemClauseType {
     WAMInstructions,
     #[strum_discriminants(strum(props(Arity = "2", Name = "$inlined_instructions")))]
     InlinedInstructions,
-    #[strum_discriminants(strum(props(Arity = "7", Name = "$write_term")))]
+    #[strum_discriminants(strum(props(Arity = "8", Name = "$write_term")))]
     WriteTerm,
-    #[strum_discriminants(strum(props(Arity = "7", Name = "$write_term_to_chars")))]
+    #[strum_discriminants(strum(props(Arity = "8", Name = "$write_term_to_chars")))]
     WriteTermToChars,
     #[strum_discriminants(strum(props(Arity = "1", Name = "$scryer_prolog_version")))]
     ScryerPrologVersion,
index 4025339cef51b154bd5d2b75300acc20cc83a301..4aef1ab1bb3599a20a0ca802fcd058937fcfa8ba 100644 (file)
@@ -478,6 +478,7 @@ pub struct HCPrinter<'a, Outputter> {
     iter: StackfulPreOrderHeapIter<'a>,
     atom_tbl: &'a mut AtomTable,
     op_dir: &'a OpDir,
+    flags: MachineFlags,
     state_stack: Vec<TokenOrRedirect>,
     toplevel_spec: Option<DirectedOp>,
     last_item_idx: usize,
@@ -488,6 +489,7 @@ pub struct HCPrinter<'a, Outputter> {
     pub ignore_ops: bool,
     pub print_strings_as_strs: bool,
     pub max_depth: usize,
+    pub double_quotes: bool,
 }
 
 macro_rules! push_space_if_amb {
@@ -544,6 +546,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         atom_tbl: &'a mut AtomTable,
         stack: &'a mut Stack,
         op_dir: &'a OpDir,
+        flags: MachineFlags,
         output: Outputter,
         cell: HeapCellValue,
     ) -> Self {
@@ -552,6 +555,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             iter: stackful_preorder_iter(heap, stack, cell),
             atom_tbl,
             op_dir,
+            flags,
             state_stack: vec![],
             toplevel_spec: None,
             last_item_idx: 0,
@@ -562,6 +566,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             var_names: IndexMap::new(),
             print_strings_as_strs: false,
             max_depth: 0,
+            double_quotes: false,
         }
     }
 
@@ -1164,9 +1169,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
 
         let at_cdr = self.outputter.ends_with("|");
 
-        if !at_cdr && !self.ignore_ops && end_cell.is_string_terminator(&self.iter.heap) {
-            self.remove_list_children(focus.value() as usize);
-            return self.print_proper_string(focus.value() as usize, max_depth);
+        if self.double_quotes && self.flags.double_quotes == DoubleQuotes::Chars {
+            if !at_cdr && !self.ignore_ops && end_cell.is_string_terminator(&self.iter.heap) {
+                self.remove_list_children(focus.value() as usize);
+                return self.print_proper_string(focus.value() as usize, max_depth);
+            }
         }
 
         if self.ignore_ops {
index 904d2f690cc31d67d6310e0485dda69f887a7c2d..4794c60353c5acc5b311cc1d6e1e1e07b9e32041 100644 (file)
@@ -528,30 +528,34 @@ parse_options_list(Options, Selector, DefaultPairs, OptionValues, Stub) :-
 
 
 parse_write_options(Options, OptionValues, Stub) :-
-    DefaultOptions = [ignore_ops-false, max_depth-0, numbervars-false,
+    DefaultOptions = [double_quotes-false, ignore_ops-false, max_depth-0, numbervars-false,
                       quoted-false, variable_names-[]],
     parse_options_list(Options, builtins:parse_write_options_, DefaultOptions, OptionValues, Stub).
 
+
+parse_write_options_(double_quotes(DoubleQuotes), double_quotes-DoubleQuotes) :-
+    (  nonvar(DoubleQuotes),
+       lists:member(DoubleQuotes, [true, false]),
+       !
+    ;  throw(error(domain_error(write_option, double_quotes(DoubleQuotes)), _))
+    ).
 parse_write_options_(ignore_ops(IgnoreOps), ignore_ops-IgnoreOps) :-
     (  nonvar(IgnoreOps),
        lists:member(IgnoreOps, [true, false]),
        !
-    ;
-       throw(error(domain_error(write_option, ignore_ops(IgnoreOps)), _))
+    ;  throw(error(domain_error(write_option, ignore_ops(IgnoreOps)), _))
     ).
 parse_write_options_(quoted(Quoted), quoted-Quoted) :-
     (  nonvar(Quoted),
        lists:member(Quoted, [true, false]),
        !
-    ;
-       throw(error(domain_error(write_option, quoted(Quoted)), _))
+    ;  throw(error(domain_error(write_option, quoted(Quoted)), _))
     ).
 parse_write_options_(numbervars(NumberVars), numbervars-NumberVars) :-
     (  nonvar(NumberVars),
        lists:member(NumberVars, [true, false]),
        !
-    ;
-       throw(error(domain_error(write_option, numbervars(NumberVars)), _))
+    ;  throw(error(domain_error(write_option, numbervars(NumberVars)), _))
     ).
 parse_write_options_(variable_names(VNNames), variable_names-VNNames) :-
     must_be_var_names_list(VNNames),
@@ -560,8 +564,7 @@ parse_write_options_(max_depth(MaxDepth), max_depth-MaxDepth) :-
     (  integer(MaxDepth),
        MaxDepth >= 0,
        !
-    ;
-       throw(error(domain_error(write_option, max_depth(MaxDepth)), _))
+    ;  throw(error(domain_error(write_option, max_depth(MaxDepth)), _))
     ).
 parse_write_options_(E, _) :-
     throw(error(domain_error(write_option, E), _)).
@@ -607,11 +610,12 @@ write_term(Term, Options) :-
 %  * `max_depth(+N)` if the term is nested deeper than N, print the reminder as ellipses.
 %    If N = 0 (default), there's no limit.
 %  * `numbervars(+Boolean)` if true, replaces `$VAR(N)` variables with letters, in order. Default is false.
-%  * `quoted(+Boolean)` if true, strings and atoms that need quotes to be valid Prolog synytax, are quoted. Default is false.
+%  * `quoted(+Boolean)` if true, strings and atoms that need quotes to be valid Prolog syntax, are quoted. Default is false.
 %  * `variable_names(+List)` assign names to variables in term. List should be a list of terms of format `Name=Var`.
+%  * `double_quotes(+Boolean)` if true, strings are printed in double quotes rather than with list notation. Default is false.
 write_term(Stream, Term, Options) :-
-    parse_write_options(Options, [IgnoreOps, MaxDepth, NumberVars, Quoted, VNNames], write_term/3),
-    '$write_term'(Stream, Term, IgnoreOps, NumberVars, Quoted, VNNames, MaxDepth).
+    parse_write_options(Options, [DoubleQuotes, IgnoreOps, MaxDepth, NumberVars, Quoted, VNNames], write_term/3),
+    '$write_term'(Stream, Term, IgnoreOps, NumberVars, Quoted, VNNames, MaxDepth, DoubleQuotes).
 
 
 %% write(+Term).
@@ -619,26 +623,26 @@ write_term(Stream, Term, Options) :-
 % Write Term to the current output stream using a syntax similar to Prolog
 write(Term) :-
     current_output(Stream),
-    '$write_term'(Stream, Term, false, true, false, [], 0).
+    '$write_term'(Stream, Term, false, true, false, [], 0, false).
 
 %% write(+Stream, +Term).
 %
 % Write Term to the stream Stream using a syntax similar to Prolog
 write(Stream, Term) :-
-    '$write_term'(Stream, Term, false, true, false, [], 0).
+    '$write_term'(Stream, Term, false, true, false, [], 0, false).
 
 %% write_canonical(+Term).
 %
 % Write Term to the current output stream using canonical Prolog syntax. Can be read back as Prolog terms.
 write_canonical(Term) :-
     current_output(Stream),
-    '$write_term'(Stream, Term, true, false, true, [], 0).
+    '$write_term'(Stream, Term, true, false, true, [], 0, false).
 
 %% write_canonical(+Stream, +Term).
 %
 % Write Term to the stream Stream using canonical Prolog syntax. Can be read back as Prolog terms.
 write_canonical(Stream, Term) :-
-    '$write_term'(Stream, Term, true, false, true, [], 0).
+    '$write_term'(Stream, Term, true, false, true, [], 0, false).
 
 %% writeq(+Term).
 %
@@ -646,14 +650,14 @@ write_canonical(Stream, Term) :-
 % quoted according to Prolog syntax.
 writeq(Term) :-
     current_output(Stream),
-    '$write_term'(Stream, Term, false, true, true, [], 0).
+    '$write_term'(Stream, Term, false, true, true, [], 0, false).
 
 %% writeq(+Stream, +Term).
 %
 % Write Term to the stream Stream using a syntax similar to `write/1` but quoting the atoms that need to be
 % quoted according to Prolog syntax.
 writeq(Stream, Term) :-
-    '$write_term'(Stream, Term, false, true, true, [], 0).
+    '$write_term'(Stream, Term, false, true, true, [], 0, false).
 
 select_rightmost_options([Option-Value | OptionPairs], OptionValues) :-
     (  pairs:same_key(Option, OptionPairs, OtherValues, _),
index 99b5c281188f7b3b63a75fd44c3476269f993f1b..128a6c5004c6c9fbee7e8189d6c453e788d15023 100644 (file)
@@ -206,13 +206,14 @@ read_from_chars(Chars, Term) :-
 %  * `max_depth(+N)` if the term is nested deeper than N, print the reminder as ellipses.
 %    If N = 0 (default), there's no limit.
 %  * `numbervars(+Boolean)` if true, replaces `$VAR(N)` variables with letters, in order. Default is false.
-%  * `quoted(+Boolean)` if true, strings and atoms that need quotes to be valid Prolog synytax, are quoted. Default is false.
+%  * `quoted(+Boolean)` if true, strings and atoms that need quotes to be valid Prolog syntax, are quoted. Default is false.
 %  * `variable_names(+List)` assign names to variables in term. List should be a list of terms of format `Name=Var`.
+%  * `double_quotes(+Boolean)` if true, strings are printed in double quotes rather than with list notation. Default is false.
 write_term_to_chars(_, Options, _) :-
     var(Options), instantiation_error(write_term_to_chars/3).
 write_term_to_chars(Term, Options, Chars) :-
     builtins:parse_write_options(Options,
-                                 [IgnoreOps, MaxDepth, NumberVars, Quoted, VNNames],
+                                 [DoubleQuotes, IgnoreOps, MaxDepth, NumberVars, Quoted, VNNames],
                                  write_term_to_chars/3),
     (  nonvar(Chars)  ->
        throw(error(uninstantiation_error(Chars), write_term_to_chars/3))
@@ -221,7 +222,7 @@ write_term_to_chars(Term, Options, Chars) :-
     ),
     term_variables(Term, Vars),
     extend_var_list(Vars, VNNames, NewVarNames, numbervars),
-    '$write_term_to_chars'(Chars, Term, IgnoreOps, NumberVars, Quoted, NewVarNames, MaxDepth).
+    '$write_term_to_chars'(Chars, Term, IgnoreOps, NumberVars, Quoted, NewVarNames, MaxDepth, DoubleQuotes).
 
 % Encodes Ch character to list of Bytes.
 char_utf8bytes(Ch, Bytes) :-
index 29702c4affc736f20d6e21b2d5cd36896002738d..78b1a7f57f118597e570c18c9e22bb9de3a7e7de 100644 (file)
@@ -666,6 +666,7 @@ impl MachineState {
         let numbervars = self.store(self.deref(self.registers[4]));
         let quoted = self.store(self.deref(self.registers[5]));
         let max_depth = self.store(self.deref(self.registers[7]));
+        let double_quotes = self.store(self.deref(self.registers[8]));
 
         let term_to_be_printed = self.store(self.deref(self.registers[2]));
         let stub_gen = || functor_stub(atom!("write_term"), 2);
@@ -747,7 +748,25 @@ impl MachineState {
                 );
 
                 let quoted = read_heap_cell!(quoted,
-                    (HeapCellValueTag::Atom, (name, _arity)) => {
+                    (HeapCellValueTag::Atom, (name, arity)) => {
+                        debug_assert_eq!(arity, 0);
+                        name == atom!("true")
+                    }
+                    (HeapCellValueTag::Str, s) => {
+                        let (name, arity) = cell_as_atom_cell!(self.heap[s])
+                            .get_name_and_arity();
+
+                        debug_assert_eq!(arity, 0);
+                        name == atom!("true")
+                    }
+                    _ => {
+                        unreachable!()
+                    }
+                );
+
+                let double_quotes = read_heap_cell!(double_quotes,
+                    (HeapCellValueTag::Atom, (name, arity)) => {
+                        debug_assert_eq!(arity, 0);
                         name == atom!("true")
                     }
                     (HeapCellValueTag::Str, s) => {
@@ -767,6 +786,7 @@ impl MachineState {
                     &mut self.atom_tbl,
                     &mut self.stack,
                     op_dir,
+                    self.flags,
                     PrinterOutputter::new(),
                     term_to_be_printed,
                 );
@@ -774,6 +794,7 @@ impl MachineState {
                 printer.ignore_ops = ignore_ops;
                 printer.numbervars = numbervars;
                 printer.quoted = quoted;
+                printer.double_quotes = double_quotes;
 
                 match Number::try_from(max_depth) {
                     Ok(Number::Fixnum(n)) => {
index 70264ac9a6f62718d0b74597854b3b2a123a647e..a4aad74c611362c440d9e45d7b0a4ed42b205ec9 100644 (file)
@@ -64,6 +64,7 @@ impl MockWAM {
             &mut self.machine_st.atom_tbl,
             &mut self.machine_st.stack,
             &self.op_dir,
+            self.machine_st.flags,
             PrinterOutputter::new(),
             heap_loc_as_cell!(term_write_result.heap_loc),
         );
index 31f1a702b15864d5d207f824dd7d2962edb1acbf..272d5b7eb01fdd83ca739eda1a97584a6e766b14 100644 (file)
@@ -313,7 +313,7 @@ impl Default for MachineFlags {
     }
 }
 
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq)]
 pub enum DoubleQuotes {
     Atom,
     Chars,
index 30de5227b128d6513c058b00a151785c64625789..2df6d3601eff84cb09bcd11d9b7fc5c246c18bcd 100644 (file)
@@ -231,13 +231,13 @@ write_goal(G, VarList, MaxDepth) :-
        write(' = '),
        (  needs_bracketing(Value, =) ->
           write('('),
-          write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth)]),
+          write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(true)]),
           write(')')
-       ;  write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth)])
+       ;  write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(true)])
        )
     ;  G == [] ->
        write('true')
-    ;  write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth)])
+    ;  write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth), double_quotes(true)])
     ).
 
 write_last_goal(G, VarList, MaxDepth) :-
@@ -250,9 +250,9 @@ write_last_goal(G, VarList, MaxDepth) :-
        write(' = '),
        (  needs_bracketing(Value, =) ->
           write('('),
-          write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth)]),
+          write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(true)]),
           write(')')
-       ;  write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth)]),
+       ;  write_term(Value, [quoted(true), variable_names(NewVarList), max_depth(MaxDepth), double_quotes(true)]),
           (  trailing_period_is_ambiguous(Value) ->
              write(' ')
           ;  true
@@ -260,7 +260,7 @@ write_last_goal(G, VarList, MaxDepth) :-
        )
     ;  G == [] ->
        write('true')
-    ;  write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth)])
+    ;  write_term(G, [quoted(true), variable_names(VarList), max_depth(MaxDepth), double_quotes(true)])
     ).
 
 write_eq((G1, G2), VarList, MaxDepth) :-