]> Repositorios git - scryer-prolog.git/commitdiff
fix attribute_goals/2 display bugs, cycle detection bug
authorMark Thom <[email protected]>
Thu, 14 Feb 2019 08:12:52 +0000 (01:12 -0700)
committerMark Thom <[email protected]>
Thu, 14 Feb 2019 08:12:52 +0000 (01:12 -0700)
12 files changed:
README.md
src/prolog/compile.rs
src/prolog/heap_print.rs
src/prolog/instructions.rs
src/prolog/lib/dif.pl
src/prolog/machine/attributed_variables.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/project_attributes.pl
src/prolog/machine/system_calls.rs
src/prolog/write.rs

index 620dfecdc5bed9e07445fecbae00a7239fb3f3da..e4517e85ae9cda3536726ab987a19eef626fc391 100644 (file)
--- a/README.md
+++ b/README.md
@@ -163,6 +163,7 @@ The following predicates are built-in to rusty-wam.
 * `member/2`
 * `memberchk/2`
 * `must_be/2`
+* `nl/0`
 * `nonvar/1`
 * `numbervars/2`
 * `once/1`
index 3e70a381c381b6f94e3904ab4c26fc47b2420784..21ea358574a94a917994c03bcfb76763cd021fcd 100644 (file)
@@ -118,7 +118,6 @@ fn compile_query(terms: Vec<QueryTerm>, queue: VecDeque<TopLevel>, flags: Machin
     let mut code = try!(cg.compile_query(&terms));
 
     compile_appendix(&mut code, &queue, false, flags)?;
-
     Ok((code, cg.take_vars()))
 }
 
index 76ec3b0186eee116c79feb7ffaf0a75bc25c4932..4ca1cf267fc105b6f7d2f5540aadd56497408eda 100644 (file)
@@ -630,7 +630,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
 
     pub fn print(mut self, addr: Addr) -> Outputter {
         let mut iter = self.machine_st.pre_order_iter(addr);
-        
+
         loop {
             if let Some(loc_data) = self.state_stack.pop() {
                 match loc_data {
index a39cd1db7eb1209d5d85ccff733804545cd7b71d..d44fbdd03a3cbcce16a7a629de651d06948bdccd 100644 (file)
@@ -238,6 +238,7 @@ pub struct Module {
 #[derive(Copy, Clone, PartialEq)]
 pub enum SystemClauseType {
     CheckCutPoint,
+    Deallocate,
     DeleteAttribute,
     DeleteHeadAttribute,
     DynamicModuleResolution,
@@ -279,6 +280,7 @@ impl SystemClauseType {
     pub fn name(&self) -> ClauseName {
         match self {
             &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
+            &SystemClauseType::Deallocate => clause_name!("$deallocate"),
             &SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
             &SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
             &SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
@@ -320,6 +322,7 @@ impl SystemClauseType {
     pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
         match (name, arity) {
             ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
+            ("$deallocate", 0) => Some(SystemClauseType::Deallocate),
             ("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
             ("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
             ("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
@@ -372,6 +375,7 @@ pub enum BuiltInClauseType {
     Ground,
     Is(RegType, ArithmeticTerm),
     KeySort,
+    Nl,
     NotEq,
     PartialString,
     Read,
@@ -450,6 +454,7 @@ impl BuiltInClauseType {
             &BuiltInClauseType::Ground  => clause_name!("ground"),
             &BuiltInClauseType::Is(..)  => clause_name!("is"),
             &BuiltInClauseType::KeySort => clause_name!("keysort"),
+            &BuiltInClauseType::Nl => clause_name!("nl"),
             &BuiltInClauseType::NotEq => clause_name!("\\=="),
             &BuiltInClauseType::Read => clause_name!("read"),
             &BuiltInClauseType::Sort => clause_name!("sort"),
@@ -471,6 +476,7 @@ impl BuiltInClauseType {
             &BuiltInClauseType::Is(..) => 2,
             &BuiltInClauseType::KeySort => 2,
             &BuiltInClauseType::NotEq => 2,
+            &BuiltInClauseType::Nl => 0,
             &BuiltInClauseType::Read => 1,
             &BuiltInClauseType::Sort => 2,
             &BuiltInClauseType::PartialString => 1,
@@ -495,6 +501,7 @@ impl BuiltInClauseType {
             ("ground", 1) => Some(BuiltInClauseType::Ground),
             ("is", 2) => Some(BuiltInClauseType::Is(temp_v!(1), ArithmeticTerm::Reg(temp_v!(2)))),
             ("keysort", 2) => Some(BuiltInClauseType::KeySort),
+            ("nl", 0) => Some(BuiltInClauseType::Nl),
             ("\\==", 2) => Some(BuiltInClauseType::NotEq),
             ("sort", 2) => Some(BuiltInClauseType::Sort),
             ("read", 1) => Some(BuiltInClauseType::Read),
@@ -927,7 +934,7 @@ pub enum CodePtr {
     BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
     CallN(usize, LocalCodePtr), // arity, local.
     Local(LocalCodePtr),
-    VerifyAttrInterrupt(usize) // location of the verify attribute interrupt code in the CodeDir.
+    VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
 }
 
 impl CodePtr {
@@ -936,7 +943,7 @@ impl CodePtr {
             &CodePtr::BuiltInClause(_, ref local)
           | &CodePtr::CallN(_, ref local)
           | &CodePtr::Local(ref local) => local.clone(),
-            &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p)
+            &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
         }
     }
 }
index fadf9fea1b653c45b5fac6e4b145671875588edc..5b6ba1c3605d3d114e98453cc3acdc8a6af03249 100644 (file)
@@ -36,22 +36,23 @@ verify_attributes(Var, Value, Goals) :-
 % suggestions for improvement.
 
 dif(X, Y) :- (   X \= Y -> true
-            ;   term_variables(X, XVars), term_variables(Y, YVars),
-                (   XVars == [], YVars == [] -> false
+             ;   term_variables(X, XVars), term_variables(Y, YVars),
+                (   XVars == [], YVars == [] -> true
                 ;   dif_set_variables(XVars, X, Y),
                     dif_set_variables(YVars, X, Y)
                 )
             ).
 
-gather_dif_goals(Attrs, Goal, Goal) :-
+gather_dif_goals(Attrs, _) :-
     var(Attrs), !.
-gather_dif_goals([dif(X, Y)|Attrs], OldGoal, Goal) :-
-    (   var(OldGoal), !, gather_dif_goals(Attrs, dif(X, Y), Goal)
-    ;   !, gather_dif_goals(Attrs, (dif(X, Y), OldGoal), Goal)
-    ).
-gather_dif_goals([_|Attrs], OldGoal, Goal) :-
-    gather_dif_goals(Attrs, OldGoal, Goal).
+gather_dif_goals([dif(X, Y) | Attrs], Goal) :-
+    gather_dif_goals(Attrs, OldGoal),
+    (   var(OldGoal), !, Goal = dif(X, Y)
+    ;   !, Goal = (dif(X, Y), OldGoal)
+    ). 
+gather_dif_goals([_ | Attrs], Goal) :-
+    gather_dif_goals(Attrs, Goal).
 
 attribute_goals(X, Goal) :-
     '$get_attr_list'(X, Attrs),
-    gather_dif_goals(Attrs, _, Goal).
+    gather_dif_goals(Attrs, Goal).
index 75ec9db258492c7f4a84ee258b24f072d15949ae..b1b56fc7fd07cf038f28bfc90df5ddfe30288bfb 100644 (file)
@@ -1,11 +1,14 @@
+use prolog::heap_iter::*;
 use prolog::machine::*;
 
+use std::collections::HashSet;
+
 pub static VERIFY_ATTRS: &str  = include_str!("attributed_variables.pl");
 pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
 
 pub(super) type Bindings = Vec<(usize, Addr)>;
 
-pub(super) struct AttrVarInitializer {    
+pub(super) struct AttrVarInitializer {
     pub(super) bindings: Bindings,
     pub(super) cp: LocalCodePtr,
     pub(super) verify_attrs_loc: usize,
@@ -52,7 +55,7 @@ impl MachineState {
     pub(super)
     fn calculate_register_threshold(&self) -> usize {
         let mut count = 0;
-        
+
         for r in 1 .. MAX_ARITY + 1 {
             if let &Addr::HeapCell(0) = &self[RegType::Temp(r)] {
                 break;
@@ -63,7 +66,7 @@ impl MachineState {
 
         count
     }
-    
+
     pub(super)
     fn verify_attributes(&mut self)
     {
@@ -89,4 +92,79 @@ impl MachineState {
         self[temp_v!(1)] = var_list_addr;
         self[temp_v!(2)] = value_list_addr;
     }
+
+    fn populate_project_attr_lists(&mut self, var_dict: &HeapVarDict) -> (Addr, Addr)
+    {
+        let mut query_vars = HashSet::new();
+        let mut attr_vars  = HashSet::new();
+
+        for (_, addr) in var_dict {
+            let iter = HCPreOrderIterator::new(&self, addr.clone());
+
+            for value in iter {
+                match value {
+                    HeapCellValue::Addr(Addr::HeapCell(h)) => {
+                        query_vars.insert(Addr::HeapCell(h));
+                    },
+                    HeapCellValue::Addr(Addr::StackCell(fr, sc)) => {
+                        query_vars.insert(Addr::StackCell(fr, sc));
+                    },
+                    HeapCellValue::Addr(Addr::AttrVar(h)) => {
+                        attr_vars.insert(Addr::AttrVar(h));
+                    },
+                    _ => {}
+                };
+            }
+        }
+
+        let query_var_list = Addr::HeapCell(self.heap.to_list(query_vars.into_iter()));
+        let attr_var_list  = Addr::HeapCell(self.heap.to_list(attr_vars.into_iter()));
+
+        (query_var_list, attr_var_list)
+    }
+
+    pub(super)
+    fn verify_attr_interrupt(&mut self, p: usize) {
+        let rs = self.calculate_register_threshold();
+
+        // store temp vars in perm vars slots along with
+        // self.b0 and self.num_of_args. why self.bo? if we return to a
+        // NeckCut after finishing the interrupt, it won't
+        // work correctly if self.b == self.b0. we must
+        // change it back when we return, as if nothing happened.
+        self.allocate(rs + 2);
+
+        let e = self.e;
+        self.and_stack[e].special_form_cp = self.attr_var_init.cp;
+
+        for i in 1 .. rs + 1 {
+            self.and_stack[e][i] = self[RegType::Temp(i)].clone();
+        }
+
+        self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0));
+        self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args));
+
+        self.verify_attributes();
+
+        self.num_of_args = 2;
+        self.b0 = self.b;
+        self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
+    }
+}
+
+impl Machine {    
+    pub
+    fn attribute_goals(&mut self, var_dict: &HeapVarDict)
+    {
+        let p = self.machine_st.attr_var_init.project_attrs_loc;
+        let (query_vars, attr_vars) = self.machine_st.populate_project_attr_lists(var_dict);
+
+        self.machine_st.allocate(0);
+
+        self.machine_st[temp_v!(1)] = query_vars;
+        self.machine_st[temp_v!(2)] = attr_vars;
+
+        self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
+        self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo);
+    }
 }
index ffa6da8644debea8626b4cf577d6d56b54afcfa3..ec979842072888cd83c5deeda13732200d304073 100644 (file)
@@ -12,13 +12,13 @@ use prolog::or_stack::*;
 use downcast::Any;
 
 use std::cmp::Ordering;
-use std::io::stdin;
+use std::io::{Write, stdin, stdout};
 use std::mem::swap;
 use std::ops::{Index, IndexMut};
 use std::rc::Rc;
 
 pub(super) struct Ball {
-    pub(super) boundary: usize, // ball.0
+    pub(super) boundary: usize,   // ball.0
     pub(super) stub: MachineStub, // ball.1
 }
 
@@ -378,7 +378,7 @@ pub(crate) trait CallPolicy: Any {
         machine_st.pstr_trail.truncate(machine_st.pstr_tr);
 
         machine_st.heap.truncate(machine_st.or_stack[b].h);
-        
+
         machine_st.hb = machine_st.heap.h;
         machine_st.p += offset;
 
@@ -547,6 +547,13 @@ pub(crate) trait CallPolicy: Any {
                 machine_st.fail = !machine_st.is_cyclic_term(addr);
                 return_from_clause!(machine_st.last_call, machine_st)
             },
+            &BuiltInClauseType::Nl => {
+                let mut stdout = stdout();
+
+                write!(stdout, "\n\r").unwrap();
+                stdout.flush().unwrap();
+                return_from_clause!(machine_st.last_call, machine_st)
+            },
             &BuiltInClauseType::Read => {
                 match machine_st.read(stdin(), indices.atom_tbl.clone(), &indices.op_dir) {
                     Ok(offset) => {
index 4299c5656ba51e28eb736c625ee6dc2cc7205777..e9feda1a922027c7f65403861e7020dd04973c3d 100644 (file)
@@ -152,7 +152,7 @@ impl MachineState {
     fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict,
                                mut output: Outputter)
                                -> Outputter
-    where Outputter: HCValueOutputter
+      where Outputter: HCValueOutputter
     {
         let orig_len = output.len();
 
@@ -180,7 +180,7 @@ impl MachineState {
     pub(super)
     fn print_exception<Outputter>(&self, addr: Addr, var_dir: &HeapVarDict, output: Outputter)
                                   -> Outputter
-    where Outputter: HCValueOutputter
+      where Outputter: HCValueOutputter
     {
         let printer = HCPrinter::from_heap_locs(&self, output, var_dir);
         printer.print(addr)
@@ -1626,7 +1626,7 @@ impl MachineState {
               | (HeapCellValue::Addr(Addr::HeapCell(hc1)),
                  HeapCellValue::Addr(Addr::AttrVar(hc2)))
               | (HeapCellValue::Addr(Addr::AttrVar(hc1)),
-                 HeapCellValue::Addr(Addr::AttrVar(hc2))) =>                    
+                 HeapCellValue::Addr(Addr::AttrVar(hc2))) =>
                     if hc1 != hc2 {
                         return hc1.cmp(&hc2);
                     },
@@ -2260,7 +2260,7 @@ impl MachineState {
                                    self.tr,
                                    self.pstr_tr,
                                    self.heap.h,
-                                   self.b0,                                   
+                                   self.b0,
                                    self.num_of_args);
 
                 self.b = self.or_stack.len();
index aa69368593bbb8040f15d81af4e578986122385c..1b6ac2a58380036c78ecda8800f27b4ce4720532 100644 (file)
@@ -502,7 +502,7 @@ impl Machine {
         for (var, addr) in sorted_vars {
             output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, output);
         }
-
+        
         output
     }
 
@@ -604,34 +604,7 @@ impl MachineState {
                 _ => {}
             };
         }
-    }
-
-    fn verify_attr_interrupt(&mut self, p: usize) {
-        let rs = self.calculate_register_threshold();
-
-        // store temp vars in perm vars slots along with
-        // self.b0 and self.num_of_args. why self.bo? if we return to a
-        // NeckCut after finishing the interrupt, it won't
-        // work correctly if self.b == self.b0. we must
-        // change it back when we return, as if nothing happened.
-        self.allocate(rs + 2);
-
-        let e = self.e;
-        self.and_stack[e].special_form_cp = self.attr_var_init.cp;
-
-        for i in 1 .. rs + 1 {
-            self.and_stack[e][i] = self[RegType::Temp(i)].clone();
-        }
-
-        self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0));
-        self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args));
-
-        self.verify_attributes();
-
-        self.num_of_args = 2;
-        self.b0 = self.b;
-        self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
-    }
+    }    
 
     fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
                          heap_locs: &mut HeapVarDict)
index d876e5b551e801830a001f8ae4949608ecca7f30..d163aa27087efb3066ed15f51d2adf5cf449a122 100644 (file)
@@ -1,46 +1,43 @@
-:- use_module(library(dcgs)).
-
 driver(QueryVars, AttrVars) :-
-    phrase(gather_modules(AttrVars), Modules0),
+    gather_modules(AttrVars, Modules0, _),
     sort(Modules0, Modules),
     call_project_attributes(Modules, QueryVars, AttrVars),
-    call_attribute_goals(QueryVars),
-    call_attribute_goals(AttrVars).
+    call_attribute_goals(Modules, QueryVars),
+    call_attribute_goals(Modules, AttrVars),
+    '$deallocate'.
 
 call_project_attributes([], _, _).
 call_project_attributes([Module|Modules], QueryVars, AttrVars) :-
     (   catch(Module:project_attributes(QueryVars, AttrVars),
-             error(evaluation_error((Module:project_attributes/2), project_attributes/2)),
+             error(evaluation_error((Module:project_attributes)/2), project_attributes/2),
              true) -> true
     ;   true
     ),
     call_project_attributes(Modules, QueryVars, AttrVars).
 
-call_attribute_goals([]).
-call_attribute_goals([AttrVar | AttrVars]) :-
-    (   '$get_attr_list'(AttrVar, Ls) -> call_goals(Ls, AttrVar)
-    ;   true
-    ),
-    call_attribute_goals(AttrVars).
+call_attribute_goals([], _).
+call_attribute_goals([Module | Modules], AttrVars) :-
+    call_goals(AttrVars, Module),
+    call_attribute_goals(Modules, AttrVars).
 
-call_goals(Ls, _) :- var(Ls), !.
-call_goals([Attr|Attrs], X) :-
-    '$module_of'(Module, Attr),
-    (   catch(Module:attribute_goals(X, Goal),
-             error(evaluation_error((Module:attribute_goals/2), attribute_goals/2)),
-             writeq(Goal)) -> true
+call_goals([], _).
+call_goals([AttrVar|AttrVars], Module) :-
+    (   catch(Module:attribute_goals(AttrVar, Goal),
+             error(evaluation_error((Module:attribute_goals)/2), attribute_goals/2),
+             true),
+       nonvar(Goal) -> nl, writeq(Goal)
     ;   true
     ),
-    call_goals(Attrs, X).
+    call_goals(AttrVars, Module).
 
-gather_modules([]) --> [].
-gather_modules([AttrVar|AttrVars]) -->
-    { '$get_attr_list'(AttrVar, Attrs) },
-    gather_modules_for_attrs(Attrs),
-    gather_modules(AttrVars).
+gather_modules([], [], _).
+gather_modules([AttrVar|AttrVars], Modules, Modules0) :-
+    '$get_attr_list'(AttrVar, Attrs),
+    gather_modules_for_attrs(Attrs, Modules, Modules0),
+    gather_modules(AttrVars, Modules0, _).
 
-gather_modules_for_attrs(Attrs) --> { var(Attrs), ! }.
-gather_modules_for_attrs([Attr|Attrs]) -->
-    { '$module_of'(Module, Attr) },
-    [Module],
-    gather_modules_for_attrs(Attrs).
+gather_modules_for_attrs(Attrs, Modules, Modules) :-
+    var(Attrs), !.
+gather_modules_for_attrs([Attr|Attrs], [Module|Modules], Modules0) :-
+    '$module_of'(Module, Attr),
+    gather_modules_for_attrs(Attrs, Modules, Modules0).
index 6a96180a7f8c5bfd281736df520b85c71154ac28..5dec796294515aeeb07ccfe08258baf8d2f19151 100644 (file)
@@ -30,20 +30,7 @@ impl MachineState {
     // a step in Brent's algorithm.
     fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
     {
-        match self.heap[brent_st.hare].clone() {
-            HeapCellValue::Addr(Addr::Lis(l)) => {
-                brent_st.hare = l + 1;
-                brent_st.steps += 1;
-
-                if brent_st.tortoise == brent_st.hare {
-                    return Some(CycleSearchResult::NotList);
-                } else if brent_st.steps == brent_st.power {
-                    brent_st.tortoise = brent_st.hare;
-                    brent_st.power <<= 1;
-                }
-
-                None
-            },
+        match self.heap[brent_st.hare].clone() {            
             HeapCellValue::NamedStr(..) =>
                 Some(CycleSearchResult::NotList),
             HeapCellValue::Addr(addr) =>
@@ -52,6 +39,19 @@ impl MachineState {
                         Some(CycleSearchResult::ProperList(brent_st.steps)),
                     Addr::HeapCell(_) | Addr::StackCell(..) =>
                         Some(CycleSearchResult::PartialList(brent_st.steps, brent_st.hare)),
+                    Addr::Lis(l) => {
+                        brent_st.hare = l + 1;
+                        brent_st.steps += 1;
+                        
+                        if brent_st.tortoise == brent_st.hare {
+                            return Some(CycleSearchResult::NotList);
+                        } else if brent_st.steps == brent_st.power {
+                            brent_st.tortoise = brent_st.hare;
+                            brent_st.power <<= 1;
+                        }
+                        
+                        None
+                    },
                     _ =>
                         Some(CycleSearchResult::NotList)
                 }
@@ -204,6 +204,10 @@ impl MachineState {
                     _ => self.fail = true
                 };
             },
+            &SystemClauseType::Deallocate => {
+                self.deallocate();
+                return Ok(());
+            },
             &SystemClauseType::DeleteAttribute => {
                 let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
 
@@ -453,11 +457,11 @@ impl MachineState {
                 let e = self.e;
 
                 let frame_len = self.and_stack[e].len();
-                
-                for i in 1 .. frame_len - 1 { 
+
+                for i in 1 .. frame_len - 1 {
                     self[RegType::Temp(i)] = self.and_stack[e][i].clone();
-                }                
-                
+                }
+
                 if let &Addr::Con(Constant::Usize(b0)) = &self.and_stack[e][frame_len - 1] {
                     self.b0 = b0;
                 }
@@ -468,7 +472,7 @@ impl MachineState {
 
                 self.p = CodePtr::Local(self.and_stack[e].special_form_cp);
                 self.deallocate();
-                
+
                 return Ok(());
             },
             &SystemClauseType::RestoreCutPolicy => {
@@ -643,7 +647,7 @@ impl MachineState {
                 }
 
                 let mut output  = printer.print(addr);
-                println!("{}", output.result());
+                print!("{}", output.result());
             }
         };
 
index 239feb4f2bd50acc0f4fe26e437eeac5b6d183a6..aae16284f6311983a4ba2de431400b7cf72de21c 100644 (file)
@@ -360,18 +360,20 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
                 write!(stdout, "{}", bindings).unwrap();
                 stdout.flush().unwrap();
 
+                wam.attribute_goals(&heap_locs);
+
                 if !wam.or_stack_is_empty() {
                     stdout.flush().unwrap();
 
                     for c in stdin.keys() {
                         match c.unwrap() {
                             Key::Char(' ') | Key::Char(';') => {
-                                write!(stdout, " ;\n\r").unwrap();
+                                write!(stdout, " ;\r\n").unwrap();
                                 result = wam.continue_query(&alloc_locs, &mut heap_locs);
                                 break;
                             },
                             Key::Char('.') => {
-                                write!(stdout, " .\n\r").unwrap();
+                                write!(stdout, " .\r\n").unwrap();
                                 return;
                             },
                             _ => {}
@@ -380,14 +382,14 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
 
                     if let &EvalSession::Error(SessionError::QueryFailure) = &result
                     {
-                        write!(stdout, "false.\n\r").unwrap();
+                        write!(stdout, "false.\r\n").unwrap();
                         stdout.flush().unwrap();
                         return;
                     }
 
                     if let &EvalSession::Error(SessionError::QueryFailureWithException(ref e)) = &result
                     {
-                        write!(stdout, "{}\n\r", error_string(e)).unwrap();
+                        write!(stdout, "{}\r\n", error_string(e)).unwrap();
                         stdout.flush().unwrap();
                         return;
                     }