From: Mark Date: Mon, 17 Jul 2023 22:45:03 +0000 (-0600) Subject: remove read/{1,2} as a builtin, write read options upon EOF, throw better domain... X-Git-Tag: v0.9.2~44 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=42a50474daae81bc396f626faade2b77238417d3;p=scryer-prolog.git remove read/{1,2} as a builtin, write read options upon EOF, throw better domain errors in parse_read_term_options/2 --- diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 62dc6146..d97410eb 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -101,8 +101,6 @@ enum BuiltInClauseType { Is(RegType, ArithmeticTerm), #[strum_discriminants(strum(props(Arity = "2", Name = "keysort")))] KeySort, - #[strum_discriminants(strum(props(Arity = "2", Name = "read")))] - Read, #[strum_discriminants(strum(props(Arity = "2", Name = "sort")))] Sort, } @@ -1504,7 +1502,6 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::CallFunctor | &Instruction::CallGround | &Instruction::CallKeySort | - &Instruction::CallRead | &Instruction::CallSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("call"), [atom(name), fixnum(arity)]) @@ -1530,7 +1527,6 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::ExecuteGround | &Instruction::ExecuteIs(..) | &Instruction::ExecuteKeySort | - &Instruction::ExecuteRead | &Instruction::ExecuteSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("execute"), [atom(name), fixnum(arity)]) @@ -1556,7 +1552,6 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::DefaultCallGround | &Instruction::DefaultCallIs(..) | &Instruction::DefaultCallKeySort | - &Instruction::DefaultCallRead | &Instruction::DefaultCallSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("call_default"), [atom(name), fixnum(arity)]) @@ -1582,7 +1577,6 @@ fn generate_instruction_preface() -> TokenStream { &Instruction::DefaultExecuteGround | &Instruction::DefaultExecuteIs(..) | &Instruction::DefaultExecuteKeySort | - &Instruction::DefaultExecuteRead | &Instruction::DefaultExecuteSort => { let (name, arity) = self.to_name_and_arity(); functor!(atom!("execute_default"), [atom(name), fixnum(arity)]) diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index db5282f7..dcc37eb0 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -17,13 +17,13 @@ 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/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, - unify_with_occurs_check/2, write/1, write/2, - write_canonical/1, write_canonical/2, + read/2, 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, unify_with_occurs_check/2, write/1, + write/2, write_canonical/1, write_canonical/2, write_term/2, write_term/3, writeq/1, writeq/2]). /** Builtin predicates @@ -668,9 +668,30 @@ parse_read_term_options(Options, OptionValues, Stub) :- parse_options_list(Options, builtins:parse_read_term_options_, DefaultOptions, OptionValues, Stub). -parse_read_term_options_(singletons(Vars), singletons-Vars) :- !. -parse_read_term_options_(variables(Vars), variables-Vars) :- !. -parse_read_term_options_(variable_names(Vars), variable_names-Vars) :- !. +parse_read_term_options_(singletons(Vars), singletons-Vars) :- + ( ( var(Vars) + ; '$skip_max_list'(_, _, Vars, Rs), + Rs == [] + ) -> + ! + ; throw(error(domain_error(read_option, singletons(Vars)), read_term/2)) + ). +parse_read_term_options_(variables(Vars), variables-Vars) :- + ( ( var(Vars) + ; '$skip_max_list'(_, _, Vars, Rs), + Rs == [] + ) -> + ! + ; throw(error(domain_error(read_option, variables(Vars)), read_term/2)) + ). +parse_read_term_options_(variable_names(Vars), variable_names-Vars) :- + ( ( var(Vars) + ; '$skip_max_list'(_, _, Vars, Rs), + Rs == [] + ) -> + ! + ; throw(error(domain_error(read_option, variable_names(Vars)), read_term/2)) + ). parse_read_term_options_(E,_) :- throw(error(domain_error(read_option, E), _)). @@ -698,7 +719,11 @@ read_term(Term, Options) :- % to read input from a file or the user. Use other predicates like `phrase_from_file/2` for that. read(Term) :- current_input(Stream), - read(Stream, Term). + read_term(Stream, Term, []). + % read(Stream, Term). + +read(Stream, Term) :- + read_term(Stream, Term, []). % ensures List is either a variable or a list. can_be_list(List, _) :- diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index b57e77b9..669b011b 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -309,34 +309,6 @@ impl MachineState { } impl Machine { - fn read(&mut self) -> CallResult { - let stream = self.machine_st.get_stream_or_alias( - self.machine_st.registers[1], - &self.indices.stream_aliases, - atom!("read"), - 2, - )?; - - match self.machine_st.read(stream, &self.indices.op_dir) { - Ok(offset) => { - let value = self.machine_st.registers[2]; - unify_fn!(&mut self.machine_st, value, heap_loc_as_cell!(offset.heap_loc)); - } - Err(CompilationError::ParserError(e)) if e.is_unexpected_eof() => { - let value = self.machine_st.registers[2]; - self.machine_st.unify_atom(atom!("end_of_file"), value); - } - Err(e) => { - let stub = functor_stub(atom!("read"), 2); - let err = self.machine_st.syntax_error(e); - - return Err(self.machine_st.error_form(err, stub)); - } - }; - - Ok(()) - } - pub(super) fn find_living_dynamic_else(&self, mut p: usize) -> Option<(usize, usize)> { loop { match &self.code[p] { @@ -1334,19 +1306,6 @@ impl Machine { } } } - &Instruction::DefaultCallRead => { - try_or_throw!(self.machine_st, self.read()); - step_or_fail!(self, self.machine_st.p += 1); - } - &Instruction::DefaultExecuteRead => { - try_or_throw!(self.machine_st, self.read()); - - if self.machine_st.fail { - self.machine_st.backtrack(); - } else { - self.machine_st.p = self.machine_st.cp; - } - } &Instruction::DefaultCallCopyTerm => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); step_or_fail!(self, self.machine_st.p += 1); @@ -1673,34 +1632,6 @@ impl Machine { } } } - &Instruction::CallRead => { - try_or_throw!(self.machine_st, self.read()); - - if self.machine_st.fail { - self.machine_st.backtrack(); - } else { - try_or_throw!( - self.machine_st, - (self.machine_st.increment_call_count_fn)(&mut self.machine_st) - ); - - self.machine_st.p += 1; - } - } - &Instruction::ExecuteRead => { - try_or_throw!(self.machine_st, self.read()); - - if self.machine_st.fail { - self.machine_st.backtrack(); - } else { - try_or_throw!( - self.machine_st, - (self.machine_st.increment_call_count_fn)(&mut self.machine_st) - ); - - self.machine_st.p = self.machine_st.cp; - } - } &Instruction::CallCopyTerm => { self.machine_st.copy_term(AttrVarPolicy::DeepCopy); diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index d7b66f2e..62663ee2 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -200,6 +200,27 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn ) } +fn push_var_eq_functors<'a>( + heap: &mut Heap, + iter: impl Iterator, + atom_tbl: &mut AtomTable, +) -> Vec { + let mut list_of_var_eqs = vec![]; + + for (var, binding) in iter { + let var_atom = atom_tbl.build_with(&var.to_string()); + let h = heap.len(); + + heap.push(atom_as_cell!(atom!("="), 2)); + heap.push(atom_as_cell!(var_atom)); + heap.push(*binding); + + list_of_var_eqs.push(str_loc_as_cell!(h)); + } + + list_of_var_eqs +} + #[derive(Debug)] pub struct Ball { pub(super) boundary: usize, @@ -489,28 +510,50 @@ impl MachineState { } } - pub fn read_term_body(&mut self, mut term_write_result: TermWriteResult) -> CallResult { - fn push_var_eq_functors<'a>( - heap: &mut Heap, - iter: impl Iterator, - atom_tbl: &mut AtomTable, - ) -> Vec { - let mut list_of_var_eqs = vec![]; - - for (var, binding) in iter { - let var_atom = atom_tbl.build_with(&var.to_string()); - let h = heap.len(); - - heap.push(atom_as_cell!(atom!("="), 2)); - heap.push(atom_as_cell!(var_atom)); - heap.push(*binding); - - list_of_var_eqs.push(str_loc_as_cell!(h)); - } + fn write_read_term_options( + &mut self, + mut var_list: Vec<(VarKey, HeapCellValue, usize)>, + singleton_var_list: Vec, + ) -> CallResult { + var_list.sort_by(|(_,_,idx_1),(_,_,idx_2)| idx_1.cmp(idx_2)); + + let list_of_var_eqs = push_var_eq_functors( + &mut self.heap, + var_list.iter().filter_map(|(var_name, var,_)| if var_name.is_anon() { None } else { Some((var_name,var)) }), + &mut self.atom_tbl, + ); + + let singleton_addr = self.registers[3]; + let singletons_offset = heap_loc_as_cell!( + iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter()) + ); - list_of_var_eqs + unify_fn!(*self, singletons_offset, singleton_addr); + + if self.fail { + return Ok(()); + } + + let vars_addr = self.registers[4]; + let vars_offset = heap_loc_as_cell!( + iter_to_heap_list(&mut self.heap, var_list.into_iter().map(|(_,cell,_)| cell)) + ); + + unify_fn!(*self, vars_offset, vars_addr); + + if self.fail { + return Ok(()); } + let var_names_addr = self.registers[5]; + let var_names_offset = heap_loc_as_cell!( + iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter()) + ); + + Ok(unify_fn!(*self, var_names_offset, var_names_addr)) + } + + pub fn read_term_body(&mut self, mut term_write_result: TermWriteResult) -> CallResult { let heap_loc = read_heap_cell!(self.heap[term_write_result.heap_loc], (HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => { pstr_loc_as_cell!(term_write_result.heap_loc) @@ -542,10 +585,6 @@ impl MachineState { } } - for var in term_write_result.var_dict.values_mut() { - *var = heap_bound_deref(&self.heap, *var); - } - let singleton_var_list = push_var_eq_functors( &mut self.heap, term_write_result.var_dict.iter().filter(|(var_name, binding)| { @@ -562,6 +601,10 @@ impl MachineState { &mut self.atom_tbl, ); + for var in term_write_result.var_dict.values_mut() { + *var = heap_bound_deref(&self.heap, *var); + } + let mut var_list = Vec::with_capacity(singleton_var_set.len()); for (var_name, addr) in term_write_result.var_dict { @@ -571,42 +614,7 @@ impl MachineState { } } - var_list.sort_by(|(_,_,idx_1),(_,_,idx_2)| idx_1.cmp(idx_2)); - - let list_of_var_eqs = push_var_eq_functors( - &mut self.heap, - var_list.iter().filter_map(|(var_name, var,_)| if var_name.is_anon() { None } else { Some((var_name,var)) }), - &mut self.atom_tbl, - ); - - let singleton_addr = self.registers[3]; - let singletons_offset = heap_loc_as_cell!( - iter_to_heap_list(&mut self.heap, singleton_var_list.into_iter()) - ); - - unify_fn!(*self, singletons_offset, singleton_addr); - - if self.fail { - return Ok(()); - } - - let vars_addr = self.registers[4]; - let vars_offset = heap_loc_as_cell!( - iter_to_heap_list(&mut self.heap, var_list.into_iter().map(|(_,cell,_)| cell)) - ); - - unify_fn!(*self, vars_offset, vars_addr); - - if self.fail { - return Ok(()); - } - - let var_names_addr = self.registers[5]; - let var_names_offset = heap_loc_as_cell!( - iter_to_heap_list(&mut self.heap, list_of_var_eqs.into_iter()) - ); - - return Ok(unify_fn!(*self, var_names_offset, var_names_addr)); + self.write_read_term_options(var_list, singleton_var_list) } pub fn read_term_from_user_input_eof_handler(&mut self, stream: Stream) -> Result { @@ -649,6 +657,7 @@ impl MachineState { pub fn read_term_eof_handler(&mut self, mut stream: Stream) -> Result { if stream.at_end_of_stream() { unify!(self, self.registers[2], atom_as_cell!(atom!("end_of_file"))); + stream.set_past_end_of_stream(true); return Ok(OnEOF::Return); } else if stream.past_end_of_stream() { self.eof_action( @@ -697,7 +706,7 @@ impl MachineState { match &err { CompilationError::ParserError(e) if e.is_unexpected_eof() => { match eof_handler(self, stream)? { - OnEOF::Return => return Ok(()), + OnEOF::Return => return self.write_read_term_options(vec![], vec![]), OnEOF::Continue => continue, } } diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 41cc4f39..402c83fb 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -385,7 +385,6 @@ impl Machine { Instruction::ExecuteFunctor, Instruction::ExecuteGround, Instruction::ExecuteKeySort, - Instruction::ExecuteRead, Instruction::ExecuteSort, Instruction::ExecuteN(1), Instruction::ExecuteN(2),