add remaining atomic term processing builtins, rename (=@=)/2 to variant/2, address issue #133

This commit is contained in:
Mark Thom
2019-04-30 20:55:53 -06:00
parent fb023c99c1
commit 3fd274c583
11 changed files with 246 additions and 110 deletions

View File

@@ -11,7 +11,7 @@ use prolog::machine::machine_errors::*;
use prolog::machine::machine_indices::*;
use prolog::machine::modules::*;
use prolog::machine::or_stack::*;
use prolog::num::{BigInt, BigUint, Zero, One};
use prolog::num::{BigInt, BigUint, One, ToPrimitive, Zero};
use prolog::read::PrologStream;
use downcast::Any;
@@ -244,7 +244,7 @@ impl MachineState {
{
let mut chars = String::new();
let mut iter = addrs.iter();
while let Some(addr) = iter.next() {
match addr {
&Addr::Con(Constant::String(ref s))
@@ -269,6 +269,38 @@ impl MachineState {
Ok(chars)
}
pub(super)
fn try_code_list(&self, addrs: Vec<Addr>) -> Result<Vec<u8>, MachineError>
{
let mut codes = vec![];
let mut iter = addrs.iter();
while let Some(addr) = iter.next() {
match addr {
&Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_codes() => {
codes.extend(s.borrow().chars().map(|c| c as u8));
if iter.next().is_some() {
return Err(MachineError::representation_error(RepFlag::CharacterCode));
}
},
&Addr::Con(Constant::CharCode(c)) =>
codes.push(c),
&Addr::Con(Constant::Number(Number::Integer(ref n))) =>
if let Some(c) = n.to_u8() {
codes.push(c);
} else {
return Err(MachineError::representation_error(RepFlag::CharacterCode));
},
_ =>
return Err(MachineError::representation_error(RepFlag::CharacterCode))
}
}
Ok(codes)
}
fn call_at_index(&mut self, arity: usize, p: usize)
{
self.cp.assign_if_local(self.p.clone() + 1);
@@ -596,14 +628,7 @@ pub(crate) trait CallPolicy: Any {
return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::CompareTerm(qt) => {
match qt {
CompareTermQT::Equal =>
machine_st.fail = machine_st.structural_eq_test(),
CompareTermQT::NotEqual =>
machine_st.fail = !machine_st.structural_eq_test(),
_ => machine_st.compare_term(qt)
};
machine_st.compare_term(qt);
return_from_clause!(machine_st.last_call, machine_st)
},
&BuiltInClauseType::CyclicTerm => {

View File

@@ -1815,11 +1815,15 @@ impl MachineState {
self.fail = true;
},
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() && !s.is_empty() => {
if !self.flags.double_quotes.is_atom() && !s.is_empty() => {
if n == 1 || n == 2 {
let a3 = self[temp_v!(3)].clone();
let h_a = if n == 1 {
Addr::Con(Constant::Char(s.head().unwrap()))
if self.flags.double_quotes.is_chars() {
Addr::Con(Constant::Char(s.head().unwrap()))
} else {
Addr::Con(Constant::CharCode(s.head().unwrap() as u8))
}
} else {
Addr::Con(Constant::String(s.tail()))
};
@@ -2228,7 +2232,7 @@ impl MachineState {
Addr::DBRef(_) =>
self.fail = true,
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() && !s.is_empty() => {
if !self.flags.double_quotes.is_atom() && !s.is_empty() => {
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)
},
@@ -2362,7 +2366,7 @@ impl MachineState {
l = hcp + 1;
},
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() => {
if !self.flags.double_quotes.is_atom() => {
result.push(Addr::Con(Constant::String(s.clone())));
break;
},
@@ -2382,7 +2386,7 @@ impl MachineState {
Ok(result)
},
Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_chars() =>
Addr::Con(Constant::String(ref s)) if !self.flags.double_quotes.is_atom() =>
Ok(vec![Addr::Con(Constant::String(s.clone()))]),
Addr::HeapCell(_) | Addr::StackCell(..) =>
Err(self.error_form(MachineError::instantiation_error(), caller)),

View File

@@ -80,7 +80,7 @@ impl MachineState {
Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset),
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() =>
if !self.flags.double_quotes.is_atom() =>
return CycleSearchResult::String(0, s.clone()),
_ => return CycleSearchResult::NotList
};
@@ -105,7 +105,7 @@ impl MachineState {
Addr::Lis(offset) => offset + 1,
Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList,
Addr::Con(Constant::String(ref s))
if self.flags.double_quotes.is_chars() =>
if !self.flags.double_quotes.is_atom() =>
return CycleSearchResult::String(0, s.clone()),
_ => return CycleSearchResult::NotList
};
@@ -158,7 +158,7 @@ impl MachineState {
};
match search_result {
CycleSearchResult::String(n, s) =>
CycleSearchResult::String(n, s) =>
if max_steps == -1 {
self.finalize_skip_max_list(n + s.len(),
Addr::Con(Constant::EmptyList))
@@ -352,6 +352,52 @@ impl MachineState {
}
}
fn parse_number_from_string(&mut self, mut string: String, indices: &IndexStore, stub: MachineStub)
-> CallResult
{
let nx = self[temp_v!(2)].clone();
if let Some(c) = string.chars().last() {
if layout_char!(c) {
let err = ParserError::UnexpectedChar(c);
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);
return Err(self.error_form(err, stub));
}
}
string.push('.');
let mut stream = parsing_stream(std::io::Cursor::new(string));
let mut parser = Parser::new(&mut stream, indices.atom_tbl.clone(),
self.machine_flags());
match parser.read_term(composite_op!(&indices.op_dir)) {
Err(err) => {
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);
return Err(self.error_form(err, stub));
},
Ok(Term::Constant(_, Constant::Number(n))) =>
self.unify(nx, Addr::Con(Constant::Number(n))),
Ok(Term::Constant(_, Constant::CharCode(c))) =>
self.unify(nx, Addr::Con(Constant::CharCode(c))),
_ => {
let err = ParserError::ParseBigInt;
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);
return Err(self.error_form(err, stub));
}
}
Ok(())
}
pub(super) fn system_call(&mut self,
ct: &SystemClauseType,
indices: &mut IndexStore,
@@ -509,53 +555,15 @@ impl MachineState {
self.unify(a2, Addr::Con(Constant::Number(len)));
},
&SystemClauseType::CharsToNumber => {
let nx = self[temp_v!(2)].clone();
&SystemClauseType::CharsToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
match self.try_from_list(temp_v!(1), stub.clone()) {
Err(e) => return Err(e),
Ok(addrs) =>
match self.try_char_list(addrs) {
Ok(mut string) => {
if let Some(c) = string.chars().last() {
if layout_char!(c) {
let err = ParserError::UnexpectedChar(c);
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);
return Err(self.error_form(err, stub));
}
}
string.push('.');
let mut stream = parsing_stream(std::io::Cursor::new(string));
let mut parser = Parser::new(&mut stream, indices.atom_tbl.clone(),
self.machine_flags());
match parser.read_term(composite_op!(&indices.op_dir)) {
Err(err) => {
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);
return Err(self.error_form(err, stub));
},
Ok(Term::Constant(_, Constant::Number(n))) =>
self.unify(nx, Addr::Con(Constant::Number(n))),
Ok(Term::Constant(_, Constant::CharCode(c))) =>
self.unify(nx, Addr::Con(Constant::CharCode(c))),
_ => {
let err = ParserError::ParseBigInt;
let h = self.heap.h;
let err = MachineError::syntax_error(h, err);
return Err(self.error_form(err, stub));
}
}
},
Ok(string) =>
self.parse_number_from_string(string, indices, stub)?,
Err(err) =>
return Err(self.error_form(err, stub))
}
@@ -577,6 +585,39 @@ impl MachineState {
let char_list = Addr::HeapCell(self.heap.to_list(chars));
self.unify(char_list, chs);
},
&SystemClauseType::NumberToCodes => {
let n = self[temp_v!(1)].clone();
let chs = self[temp_v!(2)].clone();
let string = match self.store(self.deref(n)) {
Addr::Con(Constant::Number(Number::Float(OrderedFloat(n)))) =>
format!("{0:<20?}", n),
Addr::Con(Constant::Number(Number::Integer(n))) =>
n.to_string(),
_ => unreachable!()
};
let codes = string.trim().chars().map(|c| Addr::Con(Constant::CharCode(c as u8)));
let codes_list = Addr::HeapCell(self.heap.to_list(codes));
self.unify(codes_list, chs);
},
&SystemClauseType::CodesToNumber => {
let stub = MachineError::functor_stub(clause_name!("number_codes"), 2);
match self.try_from_list(temp_v!(1), stub.clone()) {
Err(e) => return Err(e),
Ok(addrs) =>
match self.try_code_list(addrs) {
Ok(codes) => {
let string = codes.iter().map(|c| *c as char).collect();
self.parse_number_from_string(string, indices, stub)?
},
Err(err) =>
return Err(self.error_form(err, stub))
}
}
},
&SystemClauseType::ModuleAssertDynamicPredicateToFront => {
let p = self.cp;
@@ -1600,7 +1641,10 @@ impl MachineState {
self.unify_with_occurs_check(a1, a2);
},
&SystemClauseType::UnwindStack => self.unwind_stack(),
&SystemClauseType::UnwindStack =>
self.unwind_stack(),
&SystemClauseType::Variant =>
self.fail = self.structural_eq_test(),
&SystemClauseType::WriteTerm => {
let addr = self[temp_v!(1)].clone();