fix more conformity errors
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.45"
|
version = "0.8.46"
|
||||||
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
authors = ["Mark Thom <markjordanthom@gmail.com>"]
|
||||||
repository = "https://github.com/mthom/scryer-prolog"
|
repository = "https://github.com/mthom/scryer-prolog"
|
||||||
description = "A modern Prolog implementation written mostly in Rust."
|
description = "A modern Prolog implementation written mostly in Rust."
|
||||||
@@ -14,7 +14,7 @@ cfg-if = "0.1.7"
|
|||||||
downcast = "0.10.0"
|
downcast = "0.10.0"
|
||||||
num = "0.2"
|
num = "0.2"
|
||||||
ordered-float = "0.5.0"
|
ordered-float = "0.5.0"
|
||||||
prolog_parser = "0.8.16"
|
prolog_parser = "0.8.17"
|
||||||
readline_rs_compat = { version = "0.1.7", optional = true }
|
readline_rs_compat = { version = "0.1.7", optional = true }
|
||||||
ref_thread_local = "0.0.0"
|
ref_thread_local = "0.0.0"
|
||||||
|
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ pub enum SystemClauseType {
|
|||||||
AtomLength,
|
AtomLength,
|
||||||
ModuleAssertDynamicPredicateToFront,
|
ModuleAssertDynamicPredicateToFront,
|
||||||
ModuleAssertDynamicPredicateToBack,
|
ModuleAssertDynamicPredicateToBack,
|
||||||
|
CharCode,
|
||||||
CheckCutPoint,
|
CheckCutPoint,
|
||||||
CopyToLiftedHeap,
|
CopyToLiftedHeap,
|
||||||
DeleteAttribute,
|
DeleteAttribute,
|
||||||
@@ -174,6 +175,7 @@ pub enum SystemClauseType {
|
|||||||
ExpandGoal,
|
ExpandGoal,
|
||||||
ExpandTerm,
|
ExpandTerm,
|
||||||
FetchGlobalVar,
|
FetchGlobalVar,
|
||||||
|
GetChar,
|
||||||
TruncateIfNoLiftedHeapGrowthDiff,
|
TruncateIfNoLiftedHeapGrowthDiff,
|
||||||
TruncateIfNoLiftedHeapGrowth,
|
TruncateIfNoLiftedHeapGrowth,
|
||||||
GetAttributedVariableList,
|
GetAttributedVariableList,
|
||||||
@@ -242,6 +244,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
&SystemClauseType::AtomLength => clause_name!("$atom_length"),
|
||||||
&SystemClauseType::ModuleAssertDynamicPredicateToFront => clause_name!("$module_asserta"),
|
&SystemClauseType::ModuleAssertDynamicPredicateToFront => clause_name!("$module_asserta"),
|
||||||
&SystemClauseType::ModuleAssertDynamicPredicateToBack => clause_name!("$module_assertz"),
|
&SystemClauseType::ModuleAssertDynamicPredicateToBack => clause_name!("$module_assertz"),
|
||||||
|
&SystemClauseType::CharCode => clause_name!("char_code"),
|
||||||
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
||||||
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
&SystemClauseType::CopyToLiftedHeap => clause_name!("$copy_to_lh"),
|
||||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||||
@@ -252,6 +255,7 @@ impl SystemClauseType {
|
|||||||
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
&SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
|
||||||
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
&SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
|
||||||
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
|
&SystemClauseType::FetchGlobalVar => clause_name!("$fetch_global_var"),
|
||||||
|
&SystemClauseType::GetChar => clause_name!("$get_char"),
|
||||||
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => clause_name!("$truncate_if_no_lh_growth"),
|
&SystemClauseType::TruncateIfNoLiftedHeapGrowth => clause_name!("$truncate_if_no_lh_growth"),
|
||||||
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => clause_name!("$truncate_if_no_lh_growth_diff"),
|
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => clause_name!("$truncate_if_no_lh_growth_diff"),
|
||||||
&SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"),
|
&SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"),
|
||||||
@@ -320,6 +324,7 @@ impl SystemClauseType {
|
|||||||
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
|
("$module_assertz", 5) => Some(SystemClauseType::ModuleAssertDynamicPredicateToBack),
|
||||||
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
|
("$asserta", 4) => Some(SystemClauseType::AssertDynamicPredicateToFront),
|
||||||
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
("$assertz", 4) => Some(SystemClauseType::AssertDynamicPredicateToBack),
|
||||||
|
("$char_code", 2) => Some(SystemClauseType::CharCode),
|
||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
|
||||||
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
||||||
@@ -334,6 +339,7 @@ impl SystemClauseType {
|
|||||||
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
|
||||||
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
|
||||||
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
("$fetch_global_var", 2) => Some(SystemClauseType::FetchGlobalVar),
|
||||||
|
("$get_char", 1) => Some(SystemClauseType::GetChar),
|
||||||
("$truncate_if_no_lh_growth", 1) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth),
|
("$truncate_if_no_lh_growth", 1) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth),
|
||||||
("$truncate_if_no_lh_growth_diff", 2) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff),
|
("$truncate_if_no_lh_growth_diff", 2) => Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff),
|
||||||
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
|
||||||
|
|||||||
@@ -59,7 +59,13 @@ fn needs_bracketing(child_spec: &SharedOpDesc, op: &DirectedOp) -> bool
|
|||||||
let (priority, spec) = cell.get();
|
let (priority, spec) = cell.get();
|
||||||
let is_strict_left = is_xfx!(spec) || is_xfy!(spec) || is_xf!(spec);
|
let is_strict_left = is_xfx!(spec) || is_xfy!(spec) || is_xf!(spec);
|
||||||
|
|
||||||
child_spec.prec() > priority || (child_spec.prec() == priority && is_strict_left)
|
if child_spec.prec() > priority || (child_spec.prec() == priority && is_strict_left) {
|
||||||
|
true
|
||||||
|
} else if (is_postfix!(spec) || is_infix!(spec)) && !is_postfix!(child_spec.assoc()) {
|
||||||
|
child_spec.prec() == priority
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,6 +109,20 @@ impl<'a> HCPreOrderIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn char_to_string(c: char) -> String {
|
||||||
|
match c {
|
||||||
|
'\n' => "\\n".to_string(),
|
||||||
|
'\r' => "\\r".to_string(),
|
||||||
|
'\t' => "\\t".to_string(),
|
||||||
|
'\u{0b}' => "\\v".to_string(), // UTF-8 vertical tab
|
||||||
|
'\u{0c}' => "\\f".to_string(), // UTF-8 form feed
|
||||||
|
'\u{08}' => "\\b".to_string(), // UTF-8 backspace
|
||||||
|
'\u{07}' => "\\a".to_string(), // UTF-8 alert
|
||||||
|
'\x20' ... '\x7e' => c.to_string(),
|
||||||
|
_ => format!("\\x{:x}\\", c as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum TokenOrRedirect {
|
pub enum TokenOrRedirect {
|
||||||
Atom(ClauseName),
|
Atom(ClauseName),
|
||||||
@@ -250,12 +270,6 @@ pub struct HCPrinter<'a, Outputter> {
|
|||||||
macro_rules! push_space_if_amb {
|
macro_rules! push_space_if_amb {
|
||||||
($self:expr, $atom:expr, $action:block) => (
|
($self:expr, $atom:expr, $action:block) => (
|
||||||
if $self.ambiguity_check($atom) {
|
if $self.ambiguity_check($atom) {
|
||||||
if $self.last_item_idx > 1 {
|
|
||||||
if !$self.outputter.range(0 .. $self.last_item_idx).ends_with(" ") {
|
|
||||||
$self.outputter.insert($self.last_item_idx, ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$self.outputter.push_char(' ');
|
$self.outputter.push_char(' ');
|
||||||
$action;
|
$action;
|
||||||
} else {
|
} else {
|
||||||
@@ -277,8 +291,10 @@ fn requires_space(atom: &str, op: &str) -> bool {
|
|||||||
alpha_numeric_char!(oc)
|
alpha_numeric_char!(oc)
|
||||||
} else if sign_char!(ac) {
|
} else if sign_char!(ac) {
|
||||||
sign_char!(oc) || decimal_digit_char!(oc)
|
sign_char!(oc) || decimal_digit_char!(oc)
|
||||||
|
} else if single_quote_char!(ac) {
|
||||||
|
single_quote_char!(oc)
|
||||||
} else if ac == '0' {
|
} else if ac == '0' {
|
||||||
!non_quoted_token(op.chars())
|
oc == 'b' || oc == 'x' || oc == 'o' || !non_quoted_token(op.chars())
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -533,7 +549,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
|
|
||||||
if let Some(offset_str) = self.offset_as_string(addr) {
|
if let Some(offset_str) = self.offset_as_string(addr) {
|
||||||
push_space_if_amb!(self, &offset_str, {
|
push_space_if_amb!(self, &offset_str, {
|
||||||
self.append_str(offset_str.as_str());
|
self.append_str(&offset_str);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,53 +571,47 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn print_atom(&mut self, atom: &ClauseName) {
|
fn print_atom(&mut self, atom: &ClauseName) {
|
||||||
push_space_if_amb!(self, atom.as_str(), {
|
let result = self.print_op_addendum(atom.as_str());
|
||||||
self.print_op_addendum(atom.as_str());
|
|
||||||
|
push_space_if_amb!(self, result.as_str(), {
|
||||||
|
self.append_str(&result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_op_addendum(&mut self, atom: &str) {
|
fn print_op_addendum(&mut self, atom: &str) -> String {
|
||||||
if !self.quoted || non_quoted_token(atom.chars()) {
|
if !self.quoted || non_quoted_token(atom.chars()) {
|
||||||
self.append_str(atom);
|
atom.to_string()
|
||||||
} else if atom == "''" {
|
} else if atom == "''" {
|
||||||
self.append_str("''");
|
"''".to_string()
|
||||||
} else {
|
} else {
|
||||||
|
let mut result = String::new();
|
||||||
|
|
||||||
if self.quoted {
|
if self.quoted {
|
||||||
self.push_char('\'');
|
result.push('\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
for c in atom.chars() {
|
for c in atom.chars() {
|
||||||
self.print_char(c);
|
result += &char_to_string(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.quoted {
|
if self.quoted {
|
||||||
self.push_char('\'');
|
result.push('\'');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_op(&mut self, atom: &str) {
|
fn print_op(&mut self, atom: &str) {
|
||||||
push_space_if_amb!(self, atom, {
|
let result = if atom == "," {
|
||||||
if atom == "," {
|
",".to_string()
|
||||||
self.push_char(',');
|
} else {
|
||||||
} else {
|
self.print_op_addendum(atom)
|
||||||
self.print_op_addendum(atom);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_char(&mut self, c: char) {
|
|
||||||
match c {
|
|
||||||
'\n' => self.append_str("\\n"),
|
|
||||||
'\r' => self.append_str("\\r"),
|
|
||||||
'\t' => self.append_str("\\t"),
|
|
||||||
'\u{0b}' => self.append_str("\\v"), // UTF-8 vertical tab
|
|
||||||
'\u{0c}' => self.append_str("\\f"), // UTF-8 form feed
|
|
||||||
'\u{08}' => self.append_str("\\b"), // UTF-8 backspace
|
|
||||||
'\u{07}' => self.append_str("\\a"), // UTF-8 alert
|
|
||||||
'\x20' ... '\x7e' => self.push_char(c),
|
|
||||||
_ => self.append_str(&format!("\\x{:x}\\", c as u32))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
push_space_if_amb!(self, &result, {
|
||||||
|
self.append_str(&result);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_number(&mut self, n: Number, op: &Option<DirectedOp>) {
|
fn print_number(&mut self, n: Number, op: &Option<DirectedOp>) {
|
||||||
@@ -645,7 +655,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
|
|
||||||
fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) {
|
fn print_constant(&mut self, c: Constant, op: &Option<DirectedOp>) {
|
||||||
match c {
|
match c {
|
||||||
Constant::Atom(ref atom, Some(_)) => {
|
Constant::Atom(ref atom, Some(ref spec)) if spec.prec() > 0 => {
|
||||||
if let Some(ref op) = op {
|
if let Some(ref op) = op {
|
||||||
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
if self.outputter.ends_with(&format!(" {}", op.as_str())) {
|
||||||
self.push_char(' ');
|
self.push_char(' ');
|
||||||
@@ -660,20 +670,32 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
self.push_char(')');
|
self.push_char(')');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Constant::Atom(ref atom, None) =>
|
Constant::Atom(ref atom, _) =>
|
||||||
push_space_if_amb!(self, atom.as_str(), {
|
push_space_if_amb!(self, atom.as_str(), {
|
||||||
self.print_atom(atom);
|
self.print_atom(atom);
|
||||||
}),
|
}),
|
||||||
Constant::Char(c) if non_quoted_token(once(c)) =>
|
Constant::Char(c) if non_quoted_token(once(c)) => {
|
||||||
self.print_char(c),
|
let c = char_to_string(c);
|
||||||
Constant::Char(c) =>
|
|
||||||
|
push_space_if_amb!(self, &c, {
|
||||||
|
self.append_str(c.as_str());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Constant::Char(c) => {
|
||||||
|
let mut result = String::new();
|
||||||
|
|
||||||
if self.quoted {
|
if self.quoted {
|
||||||
self.push_char('\'');
|
result.push('\'');
|
||||||
self.print_char(c);
|
result += &char_to_string(c);
|
||||||
self.push_char('\'');
|
result.push('\'');
|
||||||
} else {
|
} else {
|
||||||
self.print_char(c);
|
result += &char_to_string(c);
|
||||||
},
|
}
|
||||||
|
|
||||||
|
push_space_if_amb!(self, &result, {
|
||||||
|
self.append_str(result.as_str());
|
||||||
|
});
|
||||||
|
},
|
||||||
Constant::CharCode(c) =>
|
Constant::CharCode(c) =>
|
||||||
self.append_str(&format!("{}", c)),
|
self.append_str(&format!("{}", c)),
|
||||||
Constant::EmptyList =>
|
Constant::EmptyList =>
|
||||||
|
|||||||
@@ -9,12 +9,12 @@
|
|||||||
abolish/1, asserta/1, assertz/1, atom_chars/2, atom_codes/2,
|
abolish/1, asserta/1, assertz/1, atom_chars/2, atom_codes/2,
|
||||||
atom_length/2, bagof/3, bb_b_put/2, bb_get/2, bb_put/2,
|
atom_length/2, bagof/3, bb_b_put/2, bb_get/2, bb_put/2,
|
||||||
call_cleanup/2, call_with_inference_limit/3, catch/3,
|
call_cleanup/2, call_with_inference_limit/3, catch/3,
|
||||||
clause/2, current_predicate/1, current_op/3,
|
char_code/2, clause/2, current_predicate/1, current_op/3,
|
||||||
current_prolog_flag/2, expand_goal/2, expand_term/2,
|
current_prolog_flag/2, expand_goal/2, expand_term/2,
|
||||||
findall/3, findall/4, halt/0, once/1, op/3, repeat/0,
|
findall/3, findall/4, get_char/1, halt/0, once/1, op/3,
|
||||||
retract/1, set_prolog_flag/2, setof/3, setup_call_cleanup/3,
|
repeat/0, retract/1, set_prolog_flag/2, setof/3,
|
||||||
term_variables/2, throw/1, true/0, false/0, write/1,
|
setup_call_cleanup/3, term_variables/2, throw/1, true/0,
|
||||||
write_canonical/1, writeq/1, write_term/2]).
|
false/0, write/1, write_canonical/1, writeq/1, write_term/2]).
|
||||||
|
|
||||||
/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
|
/* this is an implementation specific declarative operator used to implement call_with_inference_limit/3
|
||||||
and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
|
and setup_call_cleanup/3. switches to the default trust_me and retry_me_else. Indexing choice
|
||||||
@@ -833,3 +833,19 @@ atom_codes(Atom, List) :-
|
|||||||
; atom(Atom) -> '$atom_codes'(Atom, List)
|
; atom(Atom) -> '$atom_codes'(Atom, List)
|
||||||
; throw(error(type_error(atom, Atom), atom_codes/2))
|
; throw(error(type_error(atom, Atom), atom_codes/2))
|
||||||
).
|
).
|
||||||
|
|
||||||
|
char_code(Char, Code) :-
|
||||||
|
( var(Char) ->
|
||||||
|
( var(Code) -> throw(error(instantiation_error, char_code/2))
|
||||||
|
; integer(Code) -> '$char_code'(Char, Code)
|
||||||
|
; throw(error(type_error(integer, Code), char_code/2))
|
||||||
|
)
|
||||||
|
; atom_length(Char, 1) -> '$char_code'(Char, Code)
|
||||||
|
; throw(error(type_error(character, Char), char_code/2))
|
||||||
|
).
|
||||||
|
|
||||||
|
get_char(C) :-
|
||||||
|
( var(C) -> '$get_char'(C)
|
||||||
|
; atom_length(C, 1) -> '$get_char'(C)
|
||||||
|
; throw(error(type_error(in_character, C), get_char/1))
|
||||||
|
).
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ impl DomainError {
|
|||||||
// from 7.12.2 f) of 13211-1:1995
|
// from 7.12.2 f) of 13211-1:1995
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum RepFlag {
|
pub enum RepFlag {
|
||||||
// Character,
|
Character,
|
||||||
CharacterCode,
|
CharacterCode,
|
||||||
// InCharacterCode,
|
// InCharacterCode,
|
||||||
MaxArity,
|
MaxArity,
|
||||||
@@ -235,7 +235,7 @@ pub enum RepFlag {
|
|||||||
impl RepFlag {
|
impl RepFlag {
|
||||||
pub fn as_str(self) -> &'static str {
|
pub fn as_str(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
// RepFlag::Character => "character",
|
RepFlag::Character => "character",
|
||||||
RepFlag::CharacterCode => "character_code",
|
RepFlag::CharacterCode => "character_code",
|
||||||
// RepFlag::InCharacterCode => "in_character_code",
|
// RepFlag::InCharacterCode => "in_character_code",
|
||||||
RepFlag::MaxArity => "max_arity",
|
RepFlag::MaxArity => "max_arity",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use prolog::num::bigint::{BigInt};
|
|||||||
use ref_thread_local::RefThreadLocal;
|
use ref_thread_local::RefThreadLocal;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Read, Write};
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -452,6 +452,8 @@ impl MachineState {
|
|||||||
|
|
||||||
let atom = match self.store(self.deref(a1)) {
|
let atom = match self.store(self.deref(a1)) {
|
||||||
Addr::Con(Constant::Atom(name, _)) => name,
|
Addr::Con(Constant::Atom(name, _)) => name,
|
||||||
|
Addr::Con(Constant::EmptyList) => clause_name!("[]"),
|
||||||
|
Addr::Con(Constant::Char(c)) => clause_name!(c.to_string(), indices.atom_tbl),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -480,6 +482,42 @@ impl MachineState {
|
|||||||
|
|
||||||
self.unify(a1, lh_len);
|
self.unify(a1, lh_len);
|
||||||
},
|
},
|
||||||
|
&SystemClauseType::CharCode => {
|
||||||
|
let a1 = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
|
match self.store(self.deref(a1)) {
|
||||||
|
Addr::Con(Constant::Atom(name, _)) => {
|
||||||
|
let c = name.as_str().chars().next().unwrap();
|
||||||
|
let a2 = self[temp_v!(2)].clone();
|
||||||
|
|
||||||
|
self.unify(Addr::Con(Constant::CharCode(c as u8)), a2);
|
||||||
|
},
|
||||||
|
Addr::Con(Constant::Char(c)) => {
|
||||||
|
let a2 = self[temp_v!(2)].clone();
|
||||||
|
self.unify(Addr::Con(Constant::CharCode(c as u8)), a2);
|
||||||
|
},
|
||||||
|
ref addr if addr.is_ref() => {
|
||||||
|
let a2 = self[temp_v!(2)].clone();
|
||||||
|
|
||||||
|
match self.store(self.deref(a2)) {
|
||||||
|
Addr::Con(Constant::CharCode(code)) =>
|
||||||
|
self.unify(Addr::Con(Constant::Char(code as char)), addr.clone()),
|
||||||
|
Addr::Con(Constant::Number(Number::Integer(n))) =>
|
||||||
|
if let Some(c) = n.to_u8() {
|
||||||
|
self.unify(Addr::Con(Constant::Char(c as char)), addr.clone());
|
||||||
|
} else {
|
||||||
|
let stub = MachineError::functor_stub(clause_name!("char_code"), 2);
|
||||||
|
let err = MachineError::representation_error(RepFlag::CharacterCode);
|
||||||
|
let err = self.error_form(err, stub);
|
||||||
|
|
||||||
|
return Err(err);
|
||||||
|
},
|
||||||
|
_ => self.fail = true
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
},
|
||||||
&SystemClauseType::CheckCutPoint => {
|
&SystemClauseType::CheckCutPoint => {
|
||||||
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
let addr = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
|
|
||||||
@@ -503,6 +541,25 @@ impl MachineState {
|
|||||||
None => self.fail = true
|
None => self.fail = true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
&SystemClauseType::GetChar => {
|
||||||
|
let c = std::io::stdin()
|
||||||
|
.bytes()
|
||||||
|
.next()
|
||||||
|
.and_then(|result| result.ok());
|
||||||
|
|
||||||
|
let a1 = self[temp_v!(1)].clone();
|
||||||
|
|
||||||
|
match c {
|
||||||
|
Some(c) => self.unify(Addr::Con(Constant::Char(c as char)), a1),
|
||||||
|
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 => {
|
&SystemClauseType::GetModuleClause => {
|
||||||
let module = self[temp_v!(3)].clone();
|
let module = self[temp_v!(3)].clone();
|
||||||
let head = self[temp_v!(1)].clone();
|
let head = self[temp_v!(1)].clone();
|
||||||
|
|||||||
Reference in New Issue
Block a user