add remaining atomic term processing builtins, rename (=@=)/2 to variant/2, address issue #133
This commit is contained in:
@@ -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 => {
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user