From b21a096516ddf0efe0eb5f44d4badf27f803a073 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 1 May 2021 15:29:41 -0600 Subject: [PATCH] add read/2 and nl/1 (#896) --- src/clause_types.rs | 16 ++- src/lib/builtins.pl | 22 +++-- src/machine/loader.rs | 2 +- src/machine/machine_state.rs | 88 +++++------------ src/machine/machine_state_impl.rs | 6 +- src/machine/streams.rs | 4 +- src/machine/system_calls.rs | 157 ++++++++++++++++++++++-------- tests/scryer/helper.rs | 3 +- 8 files changed, 169 insertions(+), 129 deletions(-) diff --git a/src/clause_types.rs b/src/clause_types.rs index cf327707..7820a9fd 100644 --- a/src/clause_types.rs +++ b/src/clause_types.rs @@ -123,9 +123,8 @@ ref_thread_local! { m.insert(("ground", 1), ClauseType::BuiltIn(BuiltInClauseType::Ground)); m.insert(("is", 2), ClauseType::BuiltIn(BuiltInClauseType::Is(r1, ar_reg!(r2)))); m.insert(("keysort", 2), ClauseType::BuiltIn(BuiltInClauseType::KeySort)); - m.insert(("nl", 0), ClauseType::BuiltIn(BuiltInClauseType::Nl)); m.insert(("\\==", 2), ClauseType::BuiltIn(BuiltInClauseType::NotEq)); - m.insert(("read", 1), ClauseType::BuiltIn(BuiltInClauseType::Read)); + m.insert(("read", 2), ClauseType::BuiltIn(BuiltInClauseType::Read)); m.insert(("sort", 2), ClauseType::BuiltIn(BuiltInClauseType::Sort)); m @@ -592,7 +591,9 @@ impl SystemClauseType { &SystemClauseType::SetSTOAsUnify => clause_name!("$set_sto_as_unify"), &SystemClauseType::SetNSTOAsUnify => clause_name!("$set_nsto_as_unify"), &SystemClauseType::HomeDirectory => clause_name!("$home_directory"), - &SystemClauseType::SetSTOWithErrorAsUnify => clause_name!("$set_sto_with_error_as_unify"), + &SystemClauseType::SetSTOWithErrorAsUnify => { + clause_name!("$set_sto_with_error_as_unify") + } &SystemClauseType::DebugHook => clause_name!("$debug_hook"), } } @@ -834,9 +835,7 @@ impl SystemClauseType { ("$cpp_discontiguous_property", 3) => { Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty)) } - ("$devour_whitespace", 1) => { - Some(SystemClauseType::DevourWhitespace) - } + ("$devour_whitespace", 1) => Some(SystemClauseType::DevourWhitespace), ("$is_sto_enabled", 1) => Some(SystemClauseType::IsSTOEnabled), ("$set_sto_as_unify", 0) => Some(SystemClauseType::SetSTOAsUnify), ("$set_nsto_as_unify", 0) => Some(SystemClauseType::SetNSTOAsUnify), @@ -860,7 +859,6 @@ pub(crate) enum BuiltInClauseType { Ground, Is(RegType, ArithmeticTerm), KeySort, - Nl, NotEq, Read, Sort, @@ -889,7 +887,6 @@ 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"), @@ -909,8 +906,7 @@ impl BuiltInClauseType { &BuiltInClauseType::Is(..) => 2, &BuiltInClauseType::KeySort => 2, &BuiltInClauseType::NotEq => 2, - &BuiltInClauseType::Nl => 0, - &BuiltInClauseType::Read => 1, + &BuiltInClauseType::Read => 2, &BuiltInClauseType::Sort => 2, } } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index c08b4af9..83d248bc 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -13,14 +13,14 @@ fail/0, false/0, findall/3, findall/4, flush_output/0, flush_output/1, get_byte/1, get_byte/2, get_char/1, get_char/2, get_code/1, - get_code/2, halt/0, halt/1, max_arity/1, - number_chars/2, number_codes/2, once/1, op/3, - open/3, open/4, peek_byte/1, peek_byte/2, + get_code/2, halt/0, halt/1, max_arity/1, nl/0, + nl/1, number_chars/2, number_codes/2, once/1, + op/3, open/3, open/4, peek_byte/1, peek_byte/2, peek_char/1, peek_char/2, peek_code/1, peek_code/2, put_byte/1, put_byte/2, put_code/1, - put_code/2, put_char/1, put_char/2, read_term/2, - read_term/3, repeat/0, retract/1, retractall/1, - set_prolog_flag/2, set_input/1, + put_code/2, put_char/1, put_char/2, read/1, + read_term/2, read_term/3, repeat/0, retract/1, + retractall/1, set_prolog_flag/2, set_input/1, set_stream_position/2, set_output/1, setof/3, stream_property/2, sub_atom/5, subsumes_term/2, term_variables/2, throw/1, true/0, @@ -556,6 +556,9 @@ read_term(Term, Options) :- current_input(Stream), read_term(Stream, Term, Options). +read(Term) :- + current_input(Stream), + read(Stream, Term). % term_variables. @@ -1606,3 +1609,10 @@ callable(X) :- true ; false ). + +nl :- + current_output(Stream), + nl(Stream). + +nl(Stream) :- + put_char(Stream, '\n'). diff --git a/src/machine/loader.rs b/src/machine/loader.rs index c33582a7..6f48b1d9 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1586,7 +1586,7 @@ impl Machine { self.machine_st, self.machine_st.get_stream_or_alias( self.machine_st[temp_v!(1)], - &self.indices, + &self.indices.stream_aliases, "$push_load_context", 2, ) diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 2d8e6d47..1d8220e7 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -24,7 +24,6 @@ use indexmap::IndexMap; use std::cmp::Ordering; use std::convert::TryFrom; use std::fmt; -use std::io::Write; use std::mem; use std::ops::{Index, IndexMut}; use std::rc::Rc; @@ -685,8 +684,7 @@ impl MachineState { key: PredicateKey, module_name: ClauseName, _last_call: bool, - current_input_stream: &mut Stream, - current_output_stream: &mut Stream, + stream_aliases: &StreamAliasDir, ) -> CallResult { if module_name.as_str() == "user" { return call_policy.call_clause_type( @@ -694,8 +692,7 @@ impl MachineState { key, &indices.code_dir, &indices.op_dir, - current_input_stream, - current_output_stream, + stream_aliases, ); } else if let Some(module) = indices.modules.get(&module_name) { return call_policy.call_clause_type( @@ -703,8 +700,7 @@ impl MachineState { key, &module.code_dir, &module.op_dir, - current_input_stream, - current_output_stream, + stream_aliases, ); } @@ -1020,8 +1016,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { ct: &BuiltInClauseType, _code_dir: &CodeDir, op_dir: &OpDir, - current_input_stream: &mut Stream, - current_output_stream: &mut Stream, + stream_aliases: &StreamAliasDir, ) -> CallResult { match ct { &BuiltInClauseType::AcyclicTerm => { @@ -1091,24 +1086,21 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { machine_st.compare_term(qt); return_from_clause!(machine_st.last_call, machine_st) } - &BuiltInClauseType::Nl => { - write!(current_output_stream, "\n").unwrap(); - current_output_stream.flush().unwrap(); - - return_from_clause!(machine_st.last_call, machine_st) - } &BuiltInClauseType::Read => { - match machine_st.read( - current_input_stream.clone(), - machine_st.atom_tbl.clone(), - op_dir, - ) { + let stream = machine_st.get_stream_or_alias( + machine_st[temp_v!(1)], + stream_aliases, + "read", + 2, + )?; + + match machine_st.read(stream, machine_st.atom_tbl.clone(), op_dir) { Ok(offset) => { - let addr = machine_st[temp_v!(1)]; + let addr = machine_st[temp_v!(2)]; (machine_st.unify_fn)(machine_st, addr, Addr::HeapCell(offset.heap_loc)); } Err(ParserError::UnexpectedEOF) => { - let addr = machine_st[temp_v!(1)]; + let addr = machine_st[temp_v!(2)]; let eof = clause_name!("end_of_file".to_string(), machine_st.atom_tbl); let atom = machine_st.heap.to_unifiable(HeapCellValue::Atom(eof, None)); @@ -1117,7 +1109,7 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { } Err(e) => { let h = machine_st.heap.h(); - let stub = MachineError::functor_stub(clause_name!("read"), 1); + let stub = MachineError::functor_stub(clause_name!("read"), 2); let err = MachineError::syntax_error(h, e); let err = machine_st.error_form(err, stub); @@ -1225,22 +1217,14 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { key: PredicateKey, code_dir: &CodeDir, op_dir: &OpDir, - current_input_stream: &mut Stream, - current_output_stream: &mut Stream, + stream_aliases: &StreamAliasDir, ) -> CallResult { let (name, arity) = key; match ClauseType::from(name.clone(), arity, None) { ClauseType::BuiltIn(built_in) => { machine_st.setup_built_in_call(built_in.clone()); - self.call_builtin( - machine_st, - &built_in, - code_dir, - op_dir, - current_input_stream, - current_output_stream, - )?; + self.call_builtin(machine_st, &built_in, code_dir, op_dir, stream_aliases)?; } ClauseType::CallN => { machine_st.handle_internal_call_n(arity); @@ -1285,18 +1269,10 @@ pub(crate) trait CallPolicy: Any + fmt::Debug { arity: usize, code_dir: &CodeDir, op_dir: &OpDir, - current_input_stream: &mut Stream, - current_output_stream: &mut Stream, + stream_aliases: &StreamAliasDir, ) -> CallResult { if let Some(key) = machine_st.setup_call_n(arity) { - self.call_clause_type( - machine_st, - key, - code_dir, - op_dir, - current_input_stream, - current_output_stream, - )?; + self.call_clause_type(machine_st, key, code_dir, op_dir, stream_aliases)?; } Ok(()) @@ -1364,17 +1340,10 @@ impl CallPolicy for CWILCallPolicy { ct: &BuiltInClauseType, code_dir: &CodeDir, op_dir: &OpDir, - current_input_stream: &mut Stream, - current_output_stream: &mut Stream, + stream_aliases: &StreamAliasDir, ) -> CallResult { - self.prev_policy.call_builtin( - machine_st, - ct, - code_dir, - op_dir, - current_input_stream, - current_output_stream, - )?; + self.prev_policy + .call_builtin(machine_st, ct, code_dir, op_dir, stream_aliases)?; self.increment(machine_st) } @@ -1385,17 +1354,10 @@ impl CallPolicy for CWILCallPolicy { arity: usize, code_dir: &CodeDir, op_dir: &OpDir, - current_input_stream: &mut Stream, - current_output_stream: &mut Stream, + stream_aliases: &StreamAliasDir, ) -> CallResult { - self.prev_policy.call_n( - machine_st, - arity, - code_dir, - op_dir, - current_input_stream, - current_output_stream, - )?; + self.prev_policy + .call_n(machine_st, arity, code_dir, op_dir, stream_aliases)?; self.increment(machine_st) } diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 946d0945..82aefb13 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -3101,8 +3101,7 @@ impl MachineState { ct, &indices.code_dir, &indices.op_dir, - current_input_stream, - current_output_stream, + &indices.stream_aliases, ) ), &ClauseType::CallN => try_or_fail!( @@ -3112,8 +3111,7 @@ impl MachineState { arity, &indices.code_dir, &indices.op_dir, - current_input_stream, - current_output_stream, + &indices.stream_aliases, ) ), &ClauseType::Inlined(ref ct) => { diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 642bbf17..e8507f13 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -916,14 +916,14 @@ impl MachineState { pub(crate) fn get_stream_or_alias( &mut self, addr: Addr, - indices: &IndexStore, + stream_aliases: &StreamAliasDir, caller: &'static str, arity: usize, ) -> Result { Ok(match self.store(self.deref(addr)) { Addr::Con(h) if self.heap.atom_at(h) => { if let HeapCellValue::Atom(ref atom, ref spec) = self.heap.clone(h) { - match indices.stream_aliases.get(atom) { + match stream_aliases.get(atom) { Some(stream) if !stream.is_null_stream() => stream.clone(), _ => { let stub = MachineError::functor_stub(clause_name!(caller), arity); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 556ad604..6e54145d 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1292,8 +1292,12 @@ impl MachineState { } } &SystemClauseType::PeekByte => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "peek_byte", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "peek_byte", + 2, + )?; self.check_stream_properties( &mut stream, @@ -1390,8 +1394,12 @@ impl MachineState { } } &SystemClauseType::PeekChar => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "peek_char", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "peek_char", + 2, + )?; self.check_stream_properties( &mut stream, @@ -1493,8 +1501,12 @@ impl MachineState { } } &SystemClauseType::PeekCode => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "peek_code", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "peek_code", + 2, + )?; self.check_stream_properties( &mut stream, @@ -1874,8 +1886,12 @@ impl MachineState { }; } &SystemClauseType::PutCode => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "put_code", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "put_code", + 2, + )?; self.check_stream_properties( &mut stream, @@ -1928,8 +1944,12 @@ impl MachineState { } } &SystemClauseType::PutChar => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "put_char", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "put_char", + 2, + )?; self.check_stream_properties( &mut stream, @@ -1975,8 +1995,12 @@ impl MachineState { } } &SystemClauseType::PutChars => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "$put_chars", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "$put_chars", + 2, + )?; let mut bytes = Vec::new(); let string = self.heap_pstr_iter(self[temp_v!(2)]).to_string(); @@ -2023,8 +2047,12 @@ impl MachineState { } } &SystemClauseType::PutByte => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "put_byte", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "put_byte", + 2, + )?; self.check_stream_properties( &mut stream, @@ -2112,8 +2140,12 @@ impl MachineState { } } &SystemClauseType::GetByte => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "get_byte", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "get_byte", + 2, + )?; self.check_stream_properties( &mut stream, @@ -2195,8 +2227,12 @@ impl MachineState { } } &SystemClauseType::GetChar => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "get_char", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "get_char", + 2, + )?; self.check_stream_properties( &mut stream, @@ -2298,8 +2334,12 @@ impl MachineState { } } &SystemClauseType::GetNChars => { - let stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "get_n_chars", 3)?; + let stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "get_n_chars", + 3, + )?; let num = match Number::try_from((self[temp_v!(2)], &self.heap)) { Ok(Number::Fixnum(n)) => usize::try_from(n).unwrap(), @@ -2344,8 +2384,12 @@ impl MachineState { (self.unify_fn)(self, self[temp_v!(3)], string); } &SystemClauseType::GetCode => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "get_code", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "get_code", + 2, + )?; self.check_stream_properties( &mut stream, @@ -2522,8 +2566,12 @@ impl MachineState { } } &SystemClauseType::FlushOutput => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "flush_output", 1)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "flush_output", + 1, + )?; if !stream.is_output_stream() { let stub = MachineError::functor_stub(clause_name!("flush_output"), 1); @@ -2589,7 +2637,12 @@ impl MachineState { }; } &SystemClauseType::Close => { - let mut stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "close", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "close", + 2, + )?; if !stream.is_input_stream() { stream.flush().unwrap(); // 8.11.6.1b) @@ -2737,8 +2790,7 @@ impl MachineState { (name, arity + narity), module_name, true, - current_input_stream, - current_output_stream, + &indices.stream_aliases, ); } else { unreachable!() @@ -2752,8 +2804,7 @@ impl MachineState { (name.clone(), narity), module_name, true, - current_input_stream, - current_output_stream, + &indices.stream_aliases, ); } else { unreachable!() @@ -2766,8 +2817,7 @@ impl MachineState { (clause_name!(c.to_string(), self.atom_tbl), narity), module_name, true, - current_input_stream, - current_output_stream, + &indices.stream_aliases, ); } addr => { @@ -3652,7 +3702,8 @@ impl MachineState { &SystemClauseType::SetCutPointByDefault(r) => deref_cut(self, r), &SystemClauseType::SetInput => { let addr = self.store(self.deref(self[temp_v!(1)])); - let stream = self.get_stream_or_alias(addr, indices, "set_input", 1)?; + let stream = + self.get_stream_or_alias(addr, &indices.stream_aliases, "set_input", 1)?; if !stream.is_input_stream() { let stub = MachineError::functor_stub(clause_name!("set_input"), 1); @@ -3675,7 +3726,8 @@ impl MachineState { } &SystemClauseType::SetOutput => { let addr = self.store(self.deref(self[temp_v!(1)])); - let stream = self.get_stream_or_alias(addr, indices, "set_output", 1)?; + let stream = + self.get_stream_or_alias(addr, &indices.stream_aliases, "set_output", 1)?; if !stream.is_output_stream() { let stub = MachineError::functor_stub(clause_name!("set_input"), 1); @@ -3925,7 +3977,12 @@ impl MachineState { &SystemClauseType::ReadTerm => { readline::set_prompt(false); - let stream = self.get_stream_or_alias(self[temp_v!(1)], indices, "read_term", 3)?; + let stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "read_term", + 3, + )?; self.read_term(stream, indices)?; } @@ -4324,8 +4381,12 @@ impl MachineState { } } &SystemClauseType::SetStreamPosition => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "set_stream_position", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "set_stream_position", + 2, + )?; if !stream.options().reposition { let stub = MachineError::functor_stub(clause_name!("set_stream_position"), 2); @@ -4360,8 +4421,12 @@ impl MachineState { stream.set_position(position); } &SystemClauseType::StreamProperty => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "stream_property", 2)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "stream_property", + 2, + )?; let property = match self.store(self.deref(self[temp_v!(2)])) { Addr::Con(h) if self.heap.atom_at(h) => match &self.heap[h] { @@ -4669,8 +4734,12 @@ impl MachineState { (self.unify_fn)(self, listing, listing_var); } &SystemClauseType::WriteTerm => { - let mut stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "write_term", 3)?; + let mut stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "write_term", + 3, + )?; self.check_stream_properties( &mut stream, @@ -5356,8 +5425,12 @@ impl MachineState { } } &SystemClauseType::DevourWhitespace => { - let stream = - self.get_stream_or_alias(self[temp_v!(1)], indices, "$devour_whitespace", 1)?; + let stream = self.get_stream_or_alias( + self[temp_v!(1)], + &indices.stream_aliases, + "$devour_whitespace", + 1, + )?; match self.devour_whitespace(stream, self.atom_tbl.clone()) { Ok(false) => {} // not at EOF. diff --git a/tests/scryer/helper.rs b/tests/scryer/helper.rs index 5bd498dc..84d59cb5 100644 --- a/tests/scryer/helper.rs +++ b/tests/scryer/helper.rs @@ -33,8 +33,9 @@ pub(crate) fn load_module_test(file: &str, expected: T) { let input = machine::Stream::from(""); let output = machine::Stream::from(String::new()); + let error = machine::Stream::from(String::new()); - let mut wam = machine::Machine::new(input, output.clone()); + let mut wam = machine::Machine::new(input, output.clone(), error); wam.load_file( file.into(), -- 2.54.0