From d19ece6df8b066f8b7db4b721ab4a9ed39e9bcff Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sat, 18 Aug 2018 18:03:28 -0600 Subject: [PATCH] add some prolog flags, tabled strings --- src/prolog/ast.rs | 8 +++- src/prolog/lib/builtins.pl | 48 ++++++++++++++++++++++++ src/prolog/machine/machine_state.rs | 25 +++++++++++- src/prolog/machine/machine_state_impl.rs | 3 +- src/prolog/machine/system_calls.rs | 18 +++++++++ src/prolog/parser | 2 +- 6 files changed, 100 insertions(+), 4 deletions(-) diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 7c5bc6e1..b67c3391 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -531,7 +531,7 @@ pub enum Constant { Atom(ClauseName), Char(char), Number(Number), - String(Rc), + String(TabledRc), Usize(usize), EmptyList } @@ -725,10 +725,12 @@ pub enum SystemClauseType { GetBall, GetCurrentBlock, GetCutPoint, + GetDoubleQuotes, InstallNewBlock, ResetBlock, SetBall, SetCutPointByDefault(RegType), + SetDoubleQuotes, SkipMaxList, Succeed, UnwindStack @@ -743,6 +745,7 @@ impl SystemClauseType { match self { &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"), &SystemClauseType::GetBValue => clause_name!("$get_b_value"), + &SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"), &SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"), &SystemClauseType::InstallSCCCleaner => clause_name!("$install_scc_cleaner"), &SystemClauseType::InstallInferenceCounter => @@ -764,6 +767,7 @@ impl SystemClauseType { &SystemClauseType::ResetBlock => clause_name!("$reset_block"), &SystemClauseType::SetBall => clause_name!("$set_ball"), &SystemClauseType::SetCutPointByDefault(_) => clause_name!("$set_cp_by_default"), + &SystemClauseType::SetDoubleQuotes => clause_name!("$set_double_quotes"), &SystemClauseType::SkipMaxList => clause_name!("$skip_max_list"), &SystemClauseType::Succeed => clause_name!("$succeed"), &SystemClauseType::UnwindStack => clause_name!("$unwind_stack"), @@ -774,6 +778,7 @@ impl SystemClauseType { match (name, arity) { ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint), ("$get_b_value", 1) => Some(SystemClauseType::GetBValue), + ("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes), ("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner), ("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner), @@ -796,6 +801,7 @@ impl SystemClauseType { ("$reset_block", 1) => Some(SystemClauseType::ResetBlock), ("$set_ball", 1) => Some(SystemClauseType::SetBall), ("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))), + ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), _ => None diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index ace096a0..d15b3f25 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -6,6 +6,7 @@ (-)/1, (>=)/2, (=<)/2, (,)/2, (->)/2, (;)/2, (=..)/2, (==)/2, (\==)/2, (@=<)/2, (@>=)/2, (@<)/2, (@>)/2, (=@=)/2, (\=@=)/2, (:)/2, call_with_inference_limit/3, catch/3, + current_prolog_flag/2, set_prolog_flag/2, setup_call_cleanup/3, throw/1, true/0, false/0]). /* this is an implementation specific declarative operator used to implement call_with_inference_limit/3 @@ -70,6 +71,53 @@ true. false :- '$fail'. +% flags. + +current_prolog_flag(Flag, false) :- Flag == bounded, !. +current_prolog_flag(bounded, false). +current_prolog_flag(Flag, down) :- Flag == integer_rounding_function, !. +current_prolog_flag(integer_rounding_function, down). +current_prolog_flag(Flag, Value) :- Flag == double_quotes, !, '$get_double_quotes'(Value). +current_prolog_flag(double_quotes, Value) :- '$get_double_quotes'(Value). +current_prolog_flag(Flag, _) :- Flag == max_integer, !, '$fail'. +current_prolog_flag(Flag, _) :- Flag == min_integer, !, '$fail'. +current_prolog_flag(Flag, _) :- + atom(Flag), + throw(error(domain_error(prolog_flag, Flag), current_prolog_flag/2)). % 8.17.2.3 b +current_prolog_flag(Flag, _) :- + nonvar(Flag), + throw(error(type_error(atom, Flag), current_prolog_flag/2)). % 8.17.2.3 a + +set_prolog_flag(Flag, Value) :- + (var(Flag) ; var(Value)), + throw(error(instantiation_error, set_prolog_flag/2)). % 8.17.1.3 a, b +set_prolog_flag(bounded, false) :- !. % 7.11.1.1 +set_prolog_flag(bounded, true) :- !, '$fail'. % 7.11.1.1 +set_prolog_flag(bounded, Value) :- + throw(error(domain_error(flag_value, bounded + Value), set_prolog_flag/2)). % 8.17.1.3 e +set_prolog_flag(max_integer, Value) :- integer(Value), !, '$fail'. % 7.11.1.2 +set_prolog_flag(max_integer, Value) :- + throw(error(domain_error(flag_value, max_integer + Value), set_prolog_flag/2)). % 8.17.1.3 e +set_prolog_flag(min_integer, Value) :- integer(Value), !, '$fail'. % 7.11.1.3 +set_prolog_flag(min_integer, Value) :- + throw(error(domain_error(flag_value, min_integer + Value), set_prolog_flag/2)). % 8.17.1.3 e +set_prolog_flag(integer_rounding_function, down) :- !. % 7.11.1.4 +set_prolog_flag(integer_rounding_function, Value) :- + throw(error(domain_error(flag_value, integer_rounding_function + Value), + set_prolog_flag/2)). % 8.17.1.3 e +set_prolog_flag(double_quotes, chars) :- + !, '$set_double_quotes'(chars). % 7.11.2.5, list of one-char atoms. +set_prolog_flag(double_quotes, atom) :- + !, '$set_double_quotes'(atom). % 7.11.2.5, list of one-char atoms. +set_prolog_flag(double_quotes, Value) :- + throw(error(domain_error(flag_value, double_quotes + Value), + set_prolog_flag/2)). % 8.17.1.3 e +set_prolog_flag(Flag, _) :- + atom(Flag), + throw(error(domain_error(prolog_flag, Flag), set_prolog_flag/2)). % 8.17.1.3 d +set_prolog_flag(Flag, _) :- + throw(error(type_error(atom, Flag), set_prolog_flag/2)). % 8.17.1.3 c + % control operators. ','(G1, G2) :- '$get_b_value'(B), ','(G1, G2, B). diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 73be6ceb..6403de19 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -264,6 +264,28 @@ pub(super) enum MachineMode { Write } +#[derive(Clone, Copy)] +pub(super) enum DoubleQuotes { + Atom, Chars, // Codes +} + +impl Default for DoubleQuotes { + fn default() -> Self { + DoubleQuotes::Chars + } +} + +#[derive(Clone, Copy)] +pub(super) struct MachineFlags { + pub(super) double_quotes: DoubleQuotes +} + +impl Default for MachineFlags { + fn default() -> Self { + MachineFlags { double_quotes: DoubleQuotes::default() } + } +} + pub struct MachineState { pub(crate) atom_tbl: TabledData, pub(super) s: usize, @@ -285,7 +307,8 @@ pub struct MachineState { pub(super) block: usize, // an offset into the OR stack. pub(super) ball: Ball, pub(super) interms: Vec, // intermediate numbers. - pub(super) last_call: bool + pub(super) last_call: bool, + pub(super) flags: MachineFlags } fn call_at_index(machine_st: &mut MachineState, module_name: ClauseName, arity: usize, idx: usize) diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index f199f058..a0101fd5 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -50,7 +50,8 @@ impl MachineState { block: 0, ball: Ball::new(), interms: vec![Number::default(); 256], - last_call: false + last_call: false, + flags: MachineFlags::default() } } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index d4eec167..e99d7001 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -195,6 +195,16 @@ impl MachineState { _ => self.fail = true }; }, + &SystemClauseType::GetDoubleQuotes => { + let a1 = self[temp_v!(1)].clone(); + + match self.flags.double_quotes { + DoubleQuotes::Chars => + self.unify(a1, Addr::Con(atom!("chars"))), + DoubleQuotes::Atom => + self.unify(a1, Addr::Con(atom!("atom"))) + } + }, &SystemClauseType::GetSCCCleaner => { let dest = self[temp_v!(1)].clone(); @@ -330,6 +340,14 @@ impl MachineState { }, &SystemClauseType::SetCutPointByDefault(r) => deref_cut(self, r), + &SystemClauseType::SetDoubleQuotes => + match self[temp_v!(1)].clone() { + Addr::Con(Constant::Atom(ref atom)) if atom.as_str() == "chars" => + self.flags.double_quotes = DoubleQuotes::Chars, + Addr::Con(Constant::Atom(ref atom)) if atom.as_str() == "atom" => + self.flags.double_quotes = DoubleQuotes::Atom, + _ => self.fail = true + }, &SystemClauseType::InferenceLevel => { let a1 = self[temp_v!(1)].clone(); let a2 = self.store(self.deref(self[temp_v!(2)].clone())); diff --git a/src/prolog/parser b/src/prolog/parser index 6a754525..0d10b8e4 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit 6a7545257bbfc660b37a0bc3d7a72edb244dda86 +Subproject commit 0d10b8e4b736f54940b58cf111ac1f3290b29340 -- 2.54.0