From: Mark Thom Date: Thu, 25 Apr 2019 15:10:52 +0000 (-0600) Subject: address issues #114, #115 X-Git-Tag: v0.8.110~85 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=b07a19fc4721094c1cf446f14aba62ede22a5aa6;p=scryer-prolog.git address issues #114, #115 --- diff --git a/Cargo.toml b/Cargo.toml index 5522e1c9..9d113c5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scryer-prolog" -version = "0.8.63" +version = "0.8.64" authors = ["Mark Thom "] repository = "https://github.com/mthom/scryer-prolog" description = "A modern Prolog implementation written mostly in Rust." diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index b13fcf5a..207b8e98 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -769,6 +769,7 @@ char_code(Char, Code) :- get_char(C) :- ( var(C) -> '$get_char'(C) + ; C == end_of_file -> '$get_char'(C) ; atom_length(C, 1) -> '$get_char'(C) ; throw(error(type_error(in_character, C), get_char/1)) ). diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 05ac8513..4e064c61 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -619,7 +619,7 @@ pub(crate) trait CallPolicy: Any { return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::Functor => { - machine_st.try_functor(&indices.op_dir)?; + machine_st.try_functor(&indices)?; return_from_clause!(machine_st.last_call, machine_st) }, &BuiltInClauseType::NotEq => { diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 5b7645c9..33d862a0 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -1,5 +1,6 @@ use prolog_parser::ast::*; use prolog_parser::string_list::StringList; +use prolog_parser::tabled_rc::*; use prolog::clause_types::*; use prolog::forms::*; @@ -191,7 +192,7 @@ impl MachineState { -> Outputter where Outputter: HCValueOutputter { - let orig_len = output.len(); + let orig_len = output.len(); output.begin_new_var(); @@ -204,7 +205,7 @@ impl MachineState { printer.quoted = true; let mut output = printer.print(addr); - + let bad_ending = format!("= {}", &var); if output.ends_with(&bad_ending) { @@ -702,7 +703,7 @@ impl MachineState { Ok(Rc::new(Ratio::from_integer((*bi).clone()))) } } - + fn get_rational(&mut self, at: &ArithmeticTerm, caller: &MachineStub) -> Result>, MachineStub> { @@ -857,12 +858,12 @@ impl MachineState { (Number::Integer(_), n) | (n, _) => { let n = Addr::Con(Constant::Number(n)); let stub = MachineError::functor_stub(clause_name!("^"), 2); - - Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub)) + + Err(self.error_form(MachineError::type_error(ValidType::Integer, n), stub)) } } } - + fn pow(&self, n1: Number, n2: Number) -> Result { match n1.pow(n2) { @@ -2049,7 +2050,29 @@ impl MachineState { self.try_functor_unify_components(name, arity); } - pub(super) fn try_functor(&mut self, op_dir: &OpDir) -> CallResult { + fn try_functor_fabricate_struct(&mut self, name: ClauseName, arity: isize, + spec: Option, op_dir: &OpDir, + r: Ref) + { + let spec = fetch_atom_op_spec(name.clone(), spec, op_dir); + + let f_a = if name.as_str() == "." && arity == 2 { + Addr::Lis(self.heap.h) + } else { + let h = self.heap.h; + self.heap.push(HeapCellValue::NamedStr(arity as usize, name, spec)); + Addr::Str(h) + }; + + for _ in 0 .. arity { + let h = self.heap.h; + self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); + } + + self.bind(r, f_a); + } + + pub(super) fn try_functor(&mut self, indices: &IndexStore) -> CallResult { let stub = MachineError::functor_stub(clause_name!("functor"), 3); let a1 = self.store(self.deref(self[temp_v!(1)].clone())); @@ -2061,13 +2084,13 @@ impl MachineState { Addr::Str(o) => match self.heap[o].clone() { HeapCellValue::NamedStr(arity, name, spec) => { - let spec = fetch_op_spec(name.clone(), arity, spec, op_dir); + let spec = fetch_op_spec(name.clone(), arity, spec, &indices.op_dir); self.try_functor_compound_case(name, arity, spec) - }, + }, _ => self.fail = true }, Addr::Lis(_) => { - let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, op_dir); + let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir); self.try_functor_compound_case(clause_name!("."), 2, shared_op_desc) }, Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(..) => { @@ -2101,23 +2124,13 @@ impl MachineState { match name { Addr::Con(_) if arity == 0 => self.unify(a1, name), - Addr::Con(Constant::Atom(name, spec)) => { - let spec = fetch_atom_op_spec(name.clone(), spec, op_dir); - - let f_a = if name.as_str() == "." && arity == 2 { - Addr::Lis(self.heap.h) - } else { - let h = self.heap.h; - self.heap.push(HeapCellValue::NamedStr(arity as usize, name, spec)); - Addr::Str(h) - }; - - for _ in 0 .. arity { - let h = self.heap.h; - self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); - } - - self.unify(a1, f_a); + Addr::Con(Constant::Atom(name, spec)) => + self.try_functor_fabricate_struct(name, arity, spec, &indices.op_dir, + a1.as_var().unwrap()), + Addr::Con(Constant::Char(c)) => { + let name = clause_name!(c.to_string(), indices.atom_tbl); + self.try_functor_fabricate_struct(name, arity, None, &indices.op_dir, + a1.as_var().unwrap()); }, Addr::Con(_) => return Err(self.error_form(MachineError::type_error(ValidType::Atom, name), @@ -2621,7 +2634,7 @@ impl MachineState { pub(super) fn sink_to_snapshot(&mut self) -> MachineState { let mut snapshot = MachineState::with_capacity(0); - + snapshot.hb = self.hb; snapshot.e = self.e; snapshot.b = self.b; @@ -2634,7 +2647,7 @@ impl MachineState { snapshot.fail = self.fail; snapshot.trail = mem::replace(&mut self.trail, vec![]); snapshot.pstr_trail = mem::replace(&mut self.pstr_trail, vec![]); - snapshot.heap = self.heap.take(); + snapshot.heap = self.heap.take(); snapshot.mode = self.mode; snapshot.and_stack = self.and_stack.take(); snapshot.or_stack = self.or_stack.take(); diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 31ecdb68..a0f8b042 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -323,7 +323,7 @@ impl MachineState { Err(err) } } - + pub(super) fn system_call(&mut self, ct: &SystemClauseType, indices: &mut IndexStore, @@ -573,13 +573,17 @@ impl MachineState { match result { Some(Ok(b)) => self.unify(Addr::Con(Constant::Char(b as char)), a1), - _ => { + Some(Err(_)) => { + let end_of_file = clause_name!("end_of_file"); + self.unify(a1, Addr::Con(Constant::Atom(end_of_file, None))); + }, + None => { let stub = MachineError::functor_stub(clause_name!("get_char"), 1); let err = MachineError::representation_error(RepFlag::Character); let err = self.error_form(err, stub); return Err(err); - } + }, } }, &SystemClauseType::GetModuleClause => {