From: Mark Thom Date: Tue, 4 Sep 2018 03:58:07 +0000 (-0600) Subject: farm parser out to a crate, remove it as a git submodule. X-Git-Tag: v0.8.110~398 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=ff9d2662e62c466cd653e8cdb1da6a2979c4890e;p=scryer-prolog.git farm parser out to a crate, remove it as a git submodule. --- diff --git a/.gitmodules b/.gitmodules index ca057cc1..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +0,0 @@ -[submodule "src/prolog/parser"] - path = src/prolog/parser - url = http://github.com/mthom/prolog-parser - branch = rusty-wam_branch diff --git a/Cargo.lock b/Cargo.lock index 3626ee47..a33c62b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,6 +84,14 @@ dependencies = [ "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "prolog_parser" +version = "0.7.9" +dependencies = [ + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.32" @@ -104,6 +112,7 @@ dependencies = [ "downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "prolog_parser 0.7.9", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 6c9f0e0a..4cafa599 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,16 @@ [package] name = "rusty-wam" version = "0.7.9" -authors = ["Mark Thom"] +authors = ["Mark Thom "] +repository = "https://github.com/mthom/rusty-wam" +description = "The Warren Abstract Machine in Rust." +license = "BSD-3-Clause" [dependencies] downcast = "0.9.1" num = "0.2" ordered-float = "0.5.0" +prolog_parser = "0.7.9" [dependencies.termion] version = "1.4.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ddc82b10..2c53b5ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,11 @@ #[macro_use] extern crate downcast; +#[macro_use] extern crate prolog_parser; extern crate termion; -#[macro_use] +use prolog::ast::*; + mod prolog; -use prolog::ast::*; use prolog::compile::*; use prolog::io::*; use prolog::machine::*; diff --git a/src/prolog/allocator.rs b/src/prolog/allocator.rs index b075b5c1..cf645681 100644 --- a/src/prolog/allocator.rs +++ b/src/prolog/allocator.rs @@ -1,3 +1,5 @@ +use prolog_parser::ast::*; + use prolog::ast::*; use prolog::fixtures::*; use prolog::targets::*; diff --git a/src/prolog/arithmetic.rs b/src/prolog/arithmetic.rs index 72f5c562..b91df8f0 100644 --- a/src/prolog/arithmetic.rs +++ b/src/prolog/arithmetic.rs @@ -1,5 +1,6 @@ -use prolog::ast::*; +use prolog_parser::ast::*; +use prolog::ast::*; use std::cell::Cell; use std::cmp::{min, max}; use std::rc::Rc; diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 3a51a086..9a7fbf59 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -1,106 +1,160 @@ -use prolog::num::bigint::{BigInt, BigUint}; -use prolog::num::{Float, Integer, One, Signed, ToPrimitive, Zero}; -use prolog::num::rational::{BigRational, Ratio}; -use prolog::ordered_float::*; -use prolog::string_list::*; -use prolog::tabled_rc::*; +use prolog_parser::ast::*; use std::cell::{Cell, RefCell}; -use std::cmp::Ordering; use std::collections::{BTreeSet, HashMap, VecDeque}; -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::io::Error as IOError; -use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, MulAssign, Neg}; +use std::cmp::Ordering; +use std::ops::{Add, AddAssign, Index, IndexMut, Sub}; use std::rc::Rc; -use std::str::Utf8Error; -use std::vec::Vec; - -pub type Atom = String; - -pub type Var = String; - -pub type Specifier = u32; - -pub const MAX_ARITY: usize = 63; - -pub const XFX: u32 = 0x0001; -pub const XFY: u32 = 0x0002; -pub const YFX: u32 = 0x0004; -pub const XF: u32 = 0x0010; -pub const YF: u32 = 0x0020; -pub const FX: u32 = 0x0040; -pub const FY: u32 = 0x0080; -pub const DELIMITER: u32 = 0x0100; -pub const TERM: u32 = 0x1000; -pub const LTERM: u32 = 0x3000; - -macro_rules! is_term { - ($x:expr) => ( ($x & TERM) != 0 ) -} - -macro_rules! is_lterm { - ($x:expr) => ( ($x & LTERM) != 0 ) -} -macro_rules! is_op { - ($x:expr) => ( $x & (XF | YF | FX | FY | XFX | XFY | YFX) != 0 ) +#[derive(Clone, PartialEq)] +pub enum InlinedClauseType { + CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm), + IsAtom(RegType), + IsAtomic(RegType), + IsCompound(RegType), + IsInteger(RegType), + IsRational(RegType), + IsString(RegType), + IsFloat(RegType), + IsNonVar(RegType), + IsPartialString(RegType), + IsVar(RegType) } -macro_rules! is_postfix { - ($x:expr) => ( $x & (XF | YF) != 0 ) -} +impl InlinedClauseType { + pub fn name(&self) -> &'static str { + match self { + &InlinedClauseType::CompareNumber(qt, ..) => qt.name(), + &InlinedClauseType::IsAtom(..) => "atom", + &InlinedClauseType::IsAtomic(..) => "atomic", + &InlinedClauseType::IsCompound(..) => "compound", + &InlinedClauseType::IsInteger (..) => "integer", + &InlinedClauseType::IsRational(..) => "rational", + &InlinedClauseType::IsString(..) => "string", + &InlinedClauseType::IsFloat (..) => "float", + &InlinedClauseType::IsNonVar(..) => "nonvar", + &InlinedClauseType::IsPartialString(..) => "partial_string", + &InlinedClauseType::IsVar(..) => "var", + } + } -macro_rules! is_infix { - ($x:expr) => ( ($x & (XFX | XFY | YFX)) != 0 ) -} + pub fn from(name: &str, arity: usize) -> Option { + let r1 = temp_v!(1); + let r2 = temp_v!(2); -macro_rules! is_xfx { - ($x:expr) => ( ($x & XFX) != 0 ) -} + let a1 = ArithmeticTerm::Reg(r1); + let a2 = ArithmeticTerm::Reg(r2); -macro_rules! is_xfy { - ($x:expr) => ( ($x & XFY) != 0 ) + match (name, arity) { + (">", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, a1, a2)), + ("<", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, a1, a2)), + (">=", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,a1, a2)), + ("=<", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, a1, a2)), + ("=\\=", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, a1, a2)), + ("=:=", 2) => + Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, a1, a2)), + ("atom", 1) => Some(InlinedClauseType::IsAtom(r1)), + ("atomic", 1) => Some(InlinedClauseType::IsAtomic(r1)), + ("compound", 1) => Some(InlinedClauseType::IsCompound(r1)), + ("integer", 1) => Some(InlinedClauseType::IsInteger(r1)), + ("rational", 1) => Some(InlinedClauseType::IsRational(r1)), + ("string", 1) => Some(InlinedClauseType::IsString(r1)), + ("float", 1) => Some(InlinedClauseType::IsFloat(r1)), + ("nonvar", 1) => Some(InlinedClauseType::IsNonVar(r1)), + ("var", 1) => Some(InlinedClauseType::IsVar(r1)), + ("is_partial_string", 1) => Some(InlinedClauseType::IsPartialString(r1)), + _ => None + } + } } -macro_rules! is_yfx { - ($x:expr) => ( ($x & YFX) != 0 ) +#[derive(Clone, Copy, PartialEq)] +pub enum CompareNumberQT { + GreaterThan, + LessThan, + GreaterThanOrEqual, + LessThanOrEqual, + NotEqual, + Equal } -macro_rules! is_yf { - ($x:expr) => ( ($x & YF) != 0 ) +impl CompareNumberQT { + fn name(self) -> &'static str { + match self { + CompareNumberQT::GreaterThan => ">", + CompareNumberQT::LessThan => "<", + CompareNumberQT::GreaterThanOrEqual => ">=", + CompareNumberQT::LessThanOrEqual => "=<", + CompareNumberQT::NotEqual => "=\\=", + CompareNumberQT::Equal => "=:=" + } + } } -macro_rules! is_xf { - ($x:expr) => ( ($x & XF) != 0 ) +#[derive(Clone, Copy, PartialEq)] +pub enum CompareTermQT { + LessThan, + LessThanOrEqual, + Equal, + GreaterThanOrEqual, + GreaterThan, + NotEqual, } -macro_rules! is_fx { - ($x:expr) => ( ($x & FX) != 0 ) +impl CompareTermQT { + fn name<'a>(self) -> &'a str { + match self { + CompareTermQT::GreaterThan => "@>", + CompareTermQT::LessThan => "@<", + CompareTermQT::GreaterThanOrEqual => "@>=", + CompareTermQT::LessThanOrEqual => "@=<", + CompareTermQT::NotEqual => "\\=@=", + CompareTermQT::Equal => "=@=" + } + } } -macro_rules! is_fy { - ($x:expr) => ( ($x & FY) != 0 ) -} +// vars of predicate, toplevel offset. Vec is always a vector +// of vars (we get their adjoining cells this way). +pub type JumpStub = Vec; -macro_rules! prefix { - ($x:expr) => ($x & (FX | FY)) +pub enum QueryTerm { + // register, clause type, subterms, use default call policy. + Clause(Cell, ClauseType, Vec>, bool), + BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. + UnblockedCut(Cell), + GetLevelAndUnify(Cell, Rc), + Jump(JumpStub) } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum GenContext { - Head, Mid(usize), Last(usize) // Mid & Last: chunk_num -} +impl QueryTerm { + pub fn set_default_caller(&mut self) { + match self { + &mut QueryTerm::Clause(_, _, _, ref mut use_default_cp) => *use_default_cp = true, + _ => {} + }; + } -impl GenContext { - pub fn chunk_num(self) -> usize { + pub fn arity(&self) -> usize { match self { - GenContext::Head => 0, - GenContext::Mid(cn) | GenContext::Last(cn) => cn + &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), + &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0, + &QueryTerm::Jump(ref vars) => vars.len(), + &QueryTerm::GetLevelAndUnify(..) => 1, } } } +pub struct Rule { + pub head: (ClauseName, Vec>, QueryTerm), + pub clauses: Vec +} + pub struct Predicate(pub Vec); impl Predicate { @@ -137,11 +191,6 @@ impl PredicateClause { } } -pub type OpDirKey = (ClauseName, Fixity); - -// name and fixity -> operator type and precedence. -pub type OpDir = HashMap; - pub type ModuleCodeDir = HashMap; pub type CodeDir = HashMap; @@ -163,683 +212,106 @@ pub struct Module { pub op_dir: OpDir } -pub fn default_op_dir() -> OpDir { - let module_name = clause_name!("builtins"); - let mut op_dir = OpDir::new(); - - op_dir.insert((clause_name!(":-"), Fixity::In), (XFX, 1200, module_name.clone())); - op_dir.insert((clause_name!(":-"), Fixity::Pre), (FX, 1200, module_name.clone())); - op_dir.insert((clause_name!("?-"), Fixity::Pre), (FX, 1200, module_name.clone())); - - op_dir +#[derive(Copy, Clone, PartialEq)] +pub enum SystemClauseType { + CheckCutPoint, + GetBValue, + GetSCCCleaner, + InstallSCCCleaner, + InstallInferenceCounter, + RemoveCallPolicyCheck, + RemoveInferenceCounter, + RestoreCutPolicy, + SetCutPoint(RegType), + InferenceLevel, + CleanUpBlock, + EraseBall, + Fail, + GetBall, + GetCurrentBlock, + GetCutPoint, + GetDoubleQuotes, + InstallNewBlock, + ResetBlock, + SetBall, + SetCutPointByDefault(RegType), + SetDoubleQuotes, + SkipMaxList, + Succeed, + UnwindStack } -pub static BUILTINS: &str = include_str!("./lib/builtins.pl"); +impl SystemClauseType { + pub fn fixity(&self) -> Option { + None + } -impl Module { - pub fn new(module_decl: ModuleDecl) -> Self { - Module { module_decl, - code_dir: ModuleCodeDir::new(), - op_dir: default_op_dir() } + pub fn name(&self) -> ClauseName { + 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 => + clause_name!("$install_inference_counter"), + &SystemClauseType::RemoveCallPolicyCheck => + clause_name!("$remove_call_policy_check"), + &SystemClauseType::RemoveInferenceCounter => + clause_name!("$remove_inference_counter"), + &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"), + &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"), + &SystemClauseType::InferenceLevel => clause_name!("$inference_level"), + &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), + &SystemClauseType::EraseBall => clause_name!("$erase_ball"), + &SystemClauseType::Fail => clause_name!("$fail"), + &SystemClauseType::GetBall => clause_name!("$get_ball"), + &SystemClauseType::GetCutPoint => clause_name!("$get_cp"), + &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), + &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), + &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"), + } } -} -pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir { - code_dir.into_iter() - .map(|(k, code_idx)| { - let (idx, module_name) = code_idx.0.borrow().clone(); - (k, ModuleCodeIndex(idx, module_name)) - }) - .collect() -} - -impl SubModuleUser for Module { - fn op_dir(&mut self) -> &mut OpDir { - &mut self.op_dir - } - - fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) { - self.code_dir.insert((name, arity), idx); - } -} - -pub trait SubModuleUser { - fn op_dir(&mut self) -> &mut OpDir; - fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex); - - // returns true on successful import. - fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool { - let name = name.defrock_brackets(); - let mut found_op = false; - - { - let mut insert_op_dir = |fix| { - if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) { - self.op_dir().insert((name.clone(), fix), op_data.clone()); - found_op = true; - } - }; - - if arity == 1 { - insert_op_dir(Fixity::Pre); - insert_op_dir(Fixity::Post); - } else if arity == 2 { - insert_op_dir(Fixity::In); - } - } - - if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) { - self.insert_dir_entry(name, arity, code_data.clone()); - true - } else { - found_op - } - } - - fn use_qualified_module(&mut self, submodule: &Module, exports: &Vec) -> EvalSession - { - for (name, arity) in exports.iter().cloned() { - if !submodule.module_decl.exports.contains(&(name.clone(), arity)) { - continue; - } - - if !self.import_decl(name, arity, submodule) { - return EvalSession::from(SessionError::ModuleDoesNotContainExport); - } - } - - EvalSession::EntrySuccess - } - - fn use_module(&mut self, submodule: &Module) -> EvalSession { - for (name, arity) in submodule.module_decl.exports.iter().cloned() { - if !self.import_decl(name, arity, submodule) { - return EvalSession::from(SessionError::ModuleDoesNotContainExport); - } - } - - EvalSession::EntrySuccess - } -} - -pub enum Declaration { - NonCountedBacktracking(ClauseName, usize), // name, arity - Module(ModuleDecl), - Op(OpDecl), - UseModule(ClauseName), - UseQualifiedModule(ClauseName, Vec) -} - -pub enum TopLevel { - Declaration(Declaration), - Fact(Term), - Predicate(Predicate), - Query(Vec), - Rule(Rule) -} - -impl TopLevel { - pub fn name(&self) -> Option { - match self { - &TopLevel::Declaration(_) => None, - &TopLevel::Fact(ref term) => term.name(), - &TopLevel::Predicate(ref clauses) => - clauses.0.first().and_then(|ref term| term.name()), - &TopLevel::Query(_) => None, - &TopLevel::Rule(Rule { ref head, .. }) => - Some(head.0.clone()) - } - } - - pub fn arity(&self) -> usize { - match self { - &TopLevel::Declaration(_) => 0, - &TopLevel::Fact(ref term) => term.arity(), - &TopLevel::Predicate(ref clauses) => - clauses.0.first().map(|t| t.arity()).unwrap_or(0), - &TopLevel::Query(_) => 0, - &TopLevel::Rule(Rule { ref head, .. }) => head.1.len() - } - } - - pub fn as_predicate(self) -> Result { - match self { - TopLevel::Fact(term) => Ok(Predicate(vec![PredicateClause::Fact(term)])), - TopLevel::Rule(rule) => Ok(Predicate(vec![PredicateClause::Rule(rule)])), - TopLevel::Predicate(pred) => Ok(pred), - _ => Err(self) - } - } -} - -#[derive(Clone, Copy)] -pub enum Level { - Deep, Root, Shallow -} - -impl Level { - pub fn child_level(self) -> Level { - match self { - Level::Root => Level::Shallow, - _ => Level::Deep - } - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub enum RegType { - Perm(usize), - Temp(usize) -} - -impl Default for RegType { - fn default() -> Self { - RegType::Temp(0) - } -} - -impl RegType { - pub fn reg_num(self) -> usize { - match self { - RegType::Perm(reg_num) | RegType::Temp(reg_num) => reg_num - } - } - - pub fn is_perm(self) -> bool { - match self { - RegType::Perm(_) => true, - _ => false - } - } -} - -#[derive(PartialEq, Eq, Clone, Copy)] -pub enum VarReg { - ArgAndNorm(RegType, usize), - Norm(RegType) -} - -impl VarReg { - pub fn norm(self) -> RegType { - match self { - VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg - } - } -} - -impl Default for VarReg { - fn default() -> Self { - VarReg::Norm(RegType::default()) - } -} - -// labeled with chunk numbers. -pub enum VarStatus { - Perm(usize), Temp(usize, TempVarData) // Perm(chunk_num) | Temp(chunk_num, _) -} - -pub type OccurrenceSet = BTreeSet<(GenContext, usize)>; - -// Perm: 0 initially, a stack register once processed. -// Temp: labeled with chunk_num and temp offset (unassigned if 0). -pub enum VarData { - Perm(usize), Temp(usize, usize, TempVarData) -} - -pub struct TempVarData { - pub last_term_arity: usize, - pub use_set: OccurrenceSet, - pub no_use_set: BTreeSet, - pub conflict_set: BTreeSet -} - -pub type HeapVarDict = HashMap, Addr>; -pub type AllocVarDict = HashMap, VarData>; - -pub enum SessionError { - ImpermissibleEntry(String), - ModuleDoesNotContainExport, - ModuleNotFound, - NamelessEntry, - OpIsInfixAndPostFix, - ParserError(ParserError), - QueryFailure, - QueryFailureWithException(String) -} - -pub enum EvalSession { - EntrySuccess, - Error(SessionError), - InitialQuerySuccess(AllocVarDict, HeapVarDict), - SubsequentQuerySuccess, -} - -impl From for EvalSession { - fn from(err: SessionError) -> Self { - EvalSession::Error(err) - } -} - -impl From for SessionError { - fn from(err: ParserError) -> Self { - SessionError::ParserError(err) - } -} - -impl From for EvalSession { - fn from(err: ParserError) -> Self { - EvalSession::from(SessionError::ParserError(err)) - } -} - -pub struct OpDecl(pub usize, pub Specifier, pub ClauseName); - -impl OpDecl { - pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), SessionError> - { - let (prec, spec, name) = (self.0, self.1, self.2.clone()); - - if is_infix!(spec) { - match op_dir.get(&(name.clone(), Fixity::Post)) { - Some(_) => return Err(SessionError::OpIsInfixAndPostFix), - _ => {} - }; - } - - if is_postfix!(spec) { - match op_dir.get(&(name.clone(), Fixity::In)) { - Some(_) => return Err(SessionError::OpIsInfixAndPostFix), - _ => {} - }; - } - - if prec > 0 { - match spec { - XFY | XFX | YFX => op_dir.insert((name.clone(), Fixity::In), - (spec, prec, module.clone())), - XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec, module.clone())), - FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec, prec, module.clone())), - _ => None - }; - } else { - op_dir.remove(&(name.clone(), Fixity::Pre)); - op_dir.remove(&(name.clone(), Fixity::In)); - op_dir.remove(&(name.clone(), Fixity::Post)); - } - - Ok(()) - } -} - -#[derive(Debug, Clone, Copy)] -pub enum ArithmeticError { - InvalidAtom, - InvalidOp, - InvalidTerm, - NoRoots, - UninstantiatedVar -} - -#[derive(Debug)] -pub enum ParserError -{ - Arithmetic(ArithmeticError), - BackQuotedString, - // BuiltInArityMismatch(&'static str), - UnexpectedChar(char), - UnexpectedEOF, - IO(IOError), - ExpectedRel, - InadmissibleFact, - InadmissibleQueryTerm, - IncompleteReduction, - InconsistentEntry, - InvalidModuleDecl, - InvalidModuleExport, - InvalidRuleHead, - InvalidUseModuleDecl, - InvalidModuleResolution, - MissingQuote, - NonPrologChar, - ParseBigInt, - ParseFloat, - Utf8Conversion(Utf8Error) -} - -impl From for ParserError { - fn from(err: ArithmeticError) -> ParserError { - ParserError::Arithmetic(err) - } -} - -impl From for ParserError { - fn from(err: IOError) -> ParserError { - ParserError::IO(err) - } -} - -impl From for ParserError { - fn from(err: Utf8Error) -> ParserError { - ParserError::Utf8Conversion(err) - } -} - -#[derive(Clone, Copy, Eq, Hash, PartialEq)] -pub enum Fixity { - In, Post, Pre -} - -#[derive(Clone, Hash)] -pub enum Constant { - Atom(ClauseName), - Char(char), - Number(Number), - String(StringList), - Usize(usize), - EmptyList -} - -impl PartialEq for Constant { - fn eq(&self, other: &Constant) -> bool { - match (self, other) { - (&Constant::Atom(ref atom), &Constant::Char(c)) - | (&Constant::Char(c), &Constant::Atom(ref atom)) => { - let s = atom.as_str(); - c.len_utf8() == s.len() && Some(c) == s.chars().next() - }, - (&Constant::Atom(ref a1), &Constant::Atom(ref a2)) => - a1.as_str() == a2.as_str(), - (&Constant::Char(c1), &Constant::Char(c2)) => - c1 == c2, - (&Constant::Number(ref n1), &Constant::Number(ref n2)) => - n1 == n2, - (&Constant::String(ref s1), &Constant::String(ref s2)) => - s1 == s2, - (&Constant::EmptyList, &Constant::EmptyList) => - true, - (&Constant::Usize(u1), &Constant::Usize(u2)) => - u1 == u2, - _ => false - } - } -} - -impl Eq for Constant {} - -impl Constant { - pub fn to_atom(self) -> Option { - match self { - Constant::Atom(a) => Some(a.defrock_brackets()), - _ => None - } - } - - pub fn to_integer(self) -> Option> { - match self { - Constant::Number(Number::Integer(b)) => Some(b), - _ => None - } - } -} - -#[derive(PartialEq, Eq, Clone)] -pub enum Term { - AnonVar, - Clause(Cell, ClauseName, Vec>, Option), - Cons(Cell, Box, Box), - Constant(Cell, Constant), - Var(Cell, Rc) -} - -#[derive(Clone, PartialEq)] -pub enum InlinedClauseType { - CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm), - IsAtom(RegType), - IsAtomic(RegType), - IsCompound(RegType), - IsInteger(RegType), - IsRational(RegType), - IsString(RegType), - IsFloat(RegType), - IsNonVar(RegType), - IsPartialString(RegType), - IsVar(RegType) -} - -impl InlinedClauseType { - pub fn name(&self) -> &'static str { - match self { - &InlinedClauseType::CompareNumber(qt, ..) => qt.name(), - &InlinedClauseType::IsAtom(..) => "atom", - &InlinedClauseType::IsAtomic(..) => "atomic", - &InlinedClauseType::IsCompound(..) => "compound", - &InlinedClauseType::IsInteger (..) => "integer", - &InlinedClauseType::IsRational(..) => "rational", - &InlinedClauseType::IsString(..) => "string", - &InlinedClauseType::IsFloat (..) => "float", - &InlinedClauseType::IsNonVar(..) => "nonvar", - &InlinedClauseType::IsPartialString(..) => "partial_string", - &InlinedClauseType::IsVar(..) => "var", - } - } - - pub fn from(name: &str, arity: usize) -> Option { - let r1 = temp_v!(1); - let r2 = temp_v!(2); - - let a1 = ArithmeticTerm::Reg(r1); - let a2 = ArithmeticTerm::Reg(r2); - - match (name, arity) { - (">", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThan, a1, a2)), - ("<", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThan, a1, a2)), - (">=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::GreaterThanOrEqual,a1, a2)), - ("=<", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::LessThanOrEqual, a1, a2)), - ("=\\=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::NotEqual, a1, a2)), - ("=:=", 2) => - Some(InlinedClauseType::CompareNumber(CompareNumberQT::Equal, a1, a2)), - ("atom", 1) => Some(InlinedClauseType::IsAtom(r1)), - ("atomic", 1) => Some(InlinedClauseType::IsAtomic(r1)), - ("compound", 1) => Some(InlinedClauseType::IsCompound(r1)), - ("integer", 1) => Some(InlinedClauseType::IsInteger(r1)), - ("rational", 1) => Some(InlinedClauseType::IsRational(r1)), - ("string", 1) => Some(InlinedClauseType::IsString(r1)), - ("float", 1) => Some(InlinedClauseType::IsFloat(r1)), - ("nonvar", 1) => Some(InlinedClauseType::IsNonVar(r1)), - ("var", 1) => Some(InlinedClauseType::IsVar(r1)), - ("is_partial_string", 1) => Some(InlinedClauseType::IsPartialString(r1)), - _ => None - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum CompareNumberQT { - GreaterThan, - LessThan, - GreaterThanOrEqual, - LessThanOrEqual, - NotEqual, - Equal -} - -impl CompareNumberQT { - fn name(self) -> &'static str { - match self { - CompareNumberQT::GreaterThan => ">", - CompareNumberQT::LessThan => "<", - CompareNumberQT::GreaterThanOrEqual => ">=", - CompareNumberQT::LessThanOrEqual => "=<", - CompareNumberQT::NotEqual => "=\\=", - CompareNumberQT::Equal => "=:=" - } - } -} - -#[derive(Clone, Copy, PartialEq)] -pub enum CompareTermQT { - LessThan, - LessThanOrEqual, - Equal, - GreaterThanOrEqual, - GreaterThan, - NotEqual, -} - -impl CompareTermQT { - fn name<'a>(self) -> &'a str { - match self { - CompareTermQT::GreaterThan => "@>", - CompareTermQT::LessThan => "@<", - CompareTermQT::GreaterThanOrEqual => "@>=", - CompareTermQT::LessThanOrEqual => "@=<", - CompareTermQT::NotEqual => "\\=@=", - CompareTermQT::Equal => "=@=" - } - } -} - -// vars of predicate, toplevel offset. Vec is always a vector -// of vars (we get their adjoining cells this way). -pub type JumpStub = Vec; - -pub enum QueryTerm { - // register, clause type, subterms, use default call policy. - Clause(Cell, ClauseType, Vec>, bool), - BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q. - UnblockedCut(Cell), - GetLevelAndUnify(Cell, Rc), - Jump(JumpStub) -} - -impl QueryTerm { - pub fn set_default_caller(&mut self) { - match self { - &mut QueryTerm::Clause(_, _, _, ref mut use_default_cp) => *use_default_cp = true, - _ => {} - }; - } - - pub fn arity(&self) -> usize { - match self { - &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(), - &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => 0, - &QueryTerm::Jump(ref vars) => vars.len(), - &QueryTerm::GetLevelAndUnify(..) => 1, - } - } -} - -pub struct Rule { - pub head: (ClauseName, Vec>, QueryTerm), - pub clauses: Vec -} - -#[derive(Copy, Clone, PartialEq)] -pub enum SystemClauseType { - CheckCutPoint, - GetBValue, - GetSCCCleaner, - InstallSCCCleaner, - InstallInferenceCounter, - RemoveCallPolicyCheck, - RemoveInferenceCounter, - RestoreCutPolicy, - SetCutPoint(RegType), - InferenceLevel, - CleanUpBlock, - EraseBall, - Fail, - GetBall, - GetCurrentBlock, - GetCutPoint, - GetDoubleQuotes, - InstallNewBlock, - ResetBlock, - SetBall, - SetCutPointByDefault(RegType), - SetDoubleQuotes, - SkipMaxList, - Succeed, - UnwindStack -} - -impl SystemClauseType { - pub fn fixity(&self) -> Option { - None - } - - pub fn name(&self) -> ClauseName { - 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 => - clause_name!("$install_inference_counter"), - &SystemClauseType::RemoveCallPolicyCheck => - clause_name!("$remove_call_policy_check"), - &SystemClauseType::RemoveInferenceCounter => - clause_name!("$remove_inference_counter"), - &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"), - &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"), - &SystemClauseType::InferenceLevel => clause_name!("$inference_level"), - &SystemClauseType::CleanUpBlock => clause_name!("$clean_up_block"), - &SystemClauseType::EraseBall => clause_name!("$erase_ball"), - &SystemClauseType::Fail => clause_name!("$fail"), - &SystemClauseType::GetBall => clause_name!("$get_ball"), - &SystemClauseType::GetCutPoint => clause_name!("$get_cp"), - &SystemClauseType::GetCurrentBlock => clause_name!("$get_current_block"), - &SystemClauseType::InstallNewBlock => clause_name!("$install_new_block"), - &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"), - } - } - - pub fn from(name: &str, arity: usize) -> Option { - 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), - ("$install_inference_counter", 3) => - Some(SystemClauseType::InstallInferenceCounter), - ("$remove_call_policy_check", 1) => - Some(SystemClauseType::RemoveCallPolicyCheck), - ("$remove_inference_counter", 2) => - Some(SystemClauseType::RemoveInferenceCounter), - ("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy), - ("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))), - ("$inference_level", 2) => Some(SystemClauseType::InferenceLevel), - ("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock), - ("$erase_ball", 0) => Some(SystemClauseType::EraseBall), - ("$fail", 0) => Some(SystemClauseType::Fail), - ("$get_ball", 1) => Some(SystemClauseType::GetBall), - ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), - ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), - ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), - ("$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 - } - } + pub fn from(name: &str, arity: usize) -> Option { + 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), + ("$install_inference_counter", 3) => + Some(SystemClauseType::InstallInferenceCounter), + ("$remove_call_policy_check", 1) => + Some(SystemClauseType::RemoveCallPolicyCheck), + ("$remove_inference_counter", 2) => + Some(SystemClauseType::RemoveInferenceCounter), + ("$restore_cut_policy", 0) => Some(SystemClauseType::RestoreCutPolicy), + ("$set_cp", 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))), + ("$inference_level", 2) => Some(SystemClauseType::InferenceLevel), + ("$clean_up_block", 1) => Some(SystemClauseType::CleanUpBlock), + ("$erase_ball", 0) => Some(SystemClauseType::EraseBall), + ("$fail", 0) => Some(SystemClauseType::Fail), + ("$get_ball", 1) => Some(SystemClauseType::GetBall), + ("$get_current_block", 1) => Some(SystemClauseType::GetCurrentBlock), + ("$get_cp", 1) => Some(SystemClauseType::GetCutPoint), + ("$install_new_block", 1) => Some(SystemClauseType::InstallNewBlock), + ("$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 + } + } } #[derive(Clone, PartialEq)] @@ -872,70 +344,6 @@ pub enum ClauseType { System(SystemClauseType) } -#[derive(Clone)] -pub enum ClauseName { - BuiltIn(&'static str), - User(TabledRc) -} - -impl Hash for ClauseName { - fn hash(&self, state: &mut H) { - (*self.as_str()).hash(state) - } -} - -impl PartialEq for ClauseName { - fn eq(&self, other: &ClauseName) -> bool { - *self.as_str() == *other.as_str() - } -} - -impl Eq for ClauseName {} - -impl Ord for ClauseName { - fn cmp(&self, other: &ClauseName) -> Ordering { - (*self.as_str()).cmp(other.as_str()) - } -} - -impl PartialOrd for ClauseName { - fn partial_cmp(&self, other: &ClauseName) -> Option { - Some(self.cmp(other)) - } -} - -impl<'a> From<&'a TabledRc> for ClauseName { - fn from(name: &'a TabledRc) -> ClauseName { - ClauseName::User(name.clone()) - } -} - -impl ClauseName { - pub fn as_str(&self) -> &str { - match self { - &ClauseName::BuiltIn(s) => s, - &ClauseName::User(ref name) => name.as_ref() - } - } - - pub fn defrock_brackets(self) -> Self { - fn defrock_brackets(s: &str) -> &str { - if s.starts_with('(') && s.ends_with(')') { - &s[1 .. s.len() - 1] - } else { - s - } - } - - match self { - ClauseName::BuiltIn(s) => - ClauseName::BuiltIn(defrock_brackets(s)), - ClauseName::User(s) => - ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), s.table())) - } - } -} - impl BuiltInClauseType { fn fixity(&self) -> Option { match self { @@ -1061,428 +469,50 @@ impl ClauseType { } impl From for ClauseType { - fn from(inlined_ct: InlinedClauseType) -> Self { - ClauseType::Inlined(inlined_ct) - } -} - -#[derive(Clone)] -pub enum TermRef<'a> { - AnonVar(Level), - Cons(Level, &'a Cell, &'a Term, &'a Term), - Constant(Level, &'a Cell, &'a Constant), - Clause(Level, &'a Cell, ClauseType, &'a Vec>), - Var(Level, &'a Cell, Rc) -} - -impl<'a> TermRef<'a> { - pub fn level(self) -> Level { - match self { - TermRef::AnonVar(lvl) - | TermRef::Cons(lvl, ..) - | TermRef::Constant(lvl, ..) - | TermRef::Var(lvl, ..) - | TermRef::Clause(lvl, ..) => lvl - } - } -} - -#[derive(Clone)] -pub enum ChoiceInstruction { - DefaultRetryMeElse(usize), - DefaultTrustMe, - RetryMeElse(usize), - TrustMe, - TryMeElse(usize) -} - -#[derive(Clone)] -pub enum CutInstruction { - Cut(RegType), - GetLevel(RegType), - GetLevelAndUnify(RegType), - NeckCut -} - -#[derive(Clone)] -pub enum IndexedChoiceInstruction { - Retry(usize), - Trust(usize), - Try(usize) -} - -impl From for Line { - fn from(i: IndexedChoiceInstruction) -> Self { - Line::IndexedChoice(i) - } -} - -impl IndexedChoiceInstruction { - pub fn offset(&self) -> usize { - match self { - &IndexedChoiceInstruction::Retry(offset) => offset, - &IndexedChoiceInstruction::Trust(offset) => offset, - &IndexedChoiceInstruction::Try(offset) => offset - } - } -} - -#[derive(Clone, PartialEq, Eq, Hash)] -pub enum Number { - Float(OrderedFloat), - Integer(Rc), - Rational(Rc>) -} - -impl PartialOrd for Number { - fn partial_cmp(&self, other: &Number) -> Option { - match NumberPair::from(self.clone(), other.clone()) { - NumberPair::Integer(n1, n2) => - Some(n1.cmp(&n2)), - NumberPair::Float(n1, n2) => - Some(n1.cmp(&n2)), - NumberPair::Rational(n1, n2) => - Some(n1.cmp(&n2)) - } - } -} - -impl Ord for Number { - fn cmp(&self, other: &Number) -> Ordering { - match NumberPair::from(self.clone(), other.clone()) { - NumberPair::Integer(n1, n2) => - n1.cmp(&n2), - NumberPair::Float(n1, n2) => - n1.cmp(&n2), - NumberPair::Rational(n1, n2) => - n1.cmp(&n2) - } - } -} - -impl fmt::Display for Number { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &Number::Float(fl) => write!(f, "{}", fl), - &Number::Integer(ref bi) => write!(f, "{}", bi), - &Number::Rational(ref r) => write!(f, "{}", r) - } - } -} - -impl Default for Number { - fn default() -> Self { - Number::Float(OrderedFloat(0f64)) - } -} - -fn binary_pow(mut n: T, mut power: BigUint) -> T - where T: Clone + Mul + One, - for<'a> T: MulAssign<&'a T> -{ - if power.is_zero() { - return T::one(); - } - - let mut oddand = T::one(); - let one = BigUint::one(); - - while power > one { - if power.is_odd() { - oddand *= &n; - } - - n = n.clone() * n; - power >>= 1; - } - - n * oddand -} - -fn rational_pow(r1: BigRational, r2: BigRational) -> Result -{ - #[inline] - fn to_unsigned(n: &BigInt) -> Result { - n.abs().to_biguint().ok_or(ArithmeticError::NoRoots) - }; - - #[inline] - fn to_big_rational(n: BigUint) -> BigRational { - BigRational::from_integer(BigInt::from(n)) - }; - - let r2 = r2.reduced(); // so that gcd(numer, denom) = 1 - let n = to_unsigned(r2.denom())?; - - if n == BigUint::one() { - return if r2.is_positive() { - Ok(binary_pow(r1, to_unsigned(&r2.numer())?)) - } else if r2.is_negative() { - Ok(binary_pow(r1, to_unsigned(&r2.numer())?).recip()) - } else { - Ok(BigRational::one()) - }; - } - - if (n.is_even() && r1.is_negative()) || (r2.is_negative() && r1.is_zero()) { - return Err(ArithmeticError::NoRoots); - } - - let sgn = r1.signum(); - let r1 = r1 * &sgn; // set r1 to its absolute value. - - let epsilon = BigRational::new_raw(BigInt::one(), BigInt::from(10000)); - let n1 = n.clone() - BigUint::one(); // n -1 - - // 1 + r1 / (n-1) is a good initial point. - let mut x_i = BigRational::one() + r1.clone() / to_big_rational(n1.clone()); - let mut x_i_n1 = binary_pow(x_i.clone(), n1.clone()); // x_i^{n-1} - let mut delta_x_i = BigRational::one(); - - while delta_x_i.abs() > epsilon { - x_i = x_i.reduced(); - x_i_n1 = x_i_n1.reduced(); - - let r_quot = r1.clone() / &x_i_n1; // r1 / x_i^{n-1} - let r_n = to_big_rational(n.clone()); - - delta_x_i = ( r_quot - &x_i ) / &r_n; - - x_i += &delta_x_i; - x_i_n1 = binary_pow(x_i.clone(), n1.clone()); - } - - if r2.is_positive() { - Ok(binary_pow(sgn * x_i, to_unsigned(r2.numer())?)) - } else { - Ok(binary_pow(sgn * x_i, to_unsigned(r2.numer())?).recip()) - } -} - -fn pow_float(f1: f64, f2: f64) -> Result { - let result = OrderedFloat(f1.powf(f2)); - - if result.is_finite() { - Ok(Number::Float(result)) - } else { - Err(ArithmeticError::NoRoots) - } -} - -fn rational_to_f64(r: &BigRational) -> Option { - match (r.numer().to_f64(), r.denom().to_f64()) { - (Some(ref f1), Some(ref f2)) if f2.is_normal() => Some(*f1 / *f2), - _ => None - } -} - -impl Number { - pub fn pow(self, other: Number) -> Result { - match NumberPair::from(self, other) { - NumberPair::Integer(n1, n2) => - if let Some(n2) = n2.to_biguint() { - Ok(Number::Integer(Rc::new(binary_pow((*n1).clone(), n2)))) - } else if n1.is_zero() { - Err(ArithmeticError::NoRoots) - } else { - let r1 = Ratio::new(BigInt::one(), (*n1).clone()); - let n2 = n2.abs().to_biguint().unwrap(); - - Ok(Number::Rational(Rc::new(binary_pow(r1, n2)))) - }, - NumberPair::Float(n1, n2) => - pow_float(n1.into_inner(), n2.into_inner()), - NumberPair::Rational(r1, r2) => { - if let (Some(f1), Some(f2)) = (rational_to_f64(&r1), rational_to_f64(&r2)) { - if let Ok(result) = pow_float(f1, f2) { - return Ok(result); - } - } - - let root = rational_pow((*r1).clone(), (*r2).clone())?; - Ok(Number::Rational(Rc::new(root))) - } - } - } - - #[inline] - pub fn is_zero(&self) -> bool { - match self { - &Number::Float(fl) => fl.into_inner().is_zero(), - &Number::Integer(ref bi) => bi.is_zero(), - &Number::Rational(ref r) => r.is_zero() - } - } - - #[inline] - pub fn abs(&self) -> Self { - match self { - &Number::Float(ref fl) => Number::Float(OrderedFloat(fl.into_inner().abs())), - &Number::Integer(ref n) => Number::Integer(Rc::new((*n).clone().abs())), - &Number::Rational(ref r) => Number::Rational(Rc::new((*r).clone().abs())) - } - } -} - -pub enum NumberPair { - Float(OrderedFloat, OrderedFloat), - Integer(Rc, Rc), - Rational(Rc>, Rc>) -} - -impl NumberPair { - fn flip(self) -> NumberPair { - match self { - NumberPair::Float(f1, f2) => NumberPair::Float(f2, f1), - NumberPair::Integer(n1, n2) => NumberPair::Integer(n2, n1), - NumberPair::Rational(r1, r2) => NumberPair::Rational(r2, r1) - } - } - - fn integer_float_pair(n1: Rc, n2: OrderedFloat) -> NumberPair { - match n1.to_f64() { - Some(f1) => NumberPair::Float(OrderedFloat(f1), n2), - None => if let Some(r) = Ratio::from_float(n2.into_inner()) { - NumberPair::Rational(Rc::new(Ratio::from_integer((*n1).clone())), - Rc::new(r)) - } else if n2.into_inner().is_sign_positive() { - NumberPair::Float(OrderedFloat(f64::infinity()), - OrderedFloat(f64::infinity())) - } else { - NumberPair::Float(OrderedFloat(f64::neg_infinity()), - OrderedFloat(f64::neg_infinity())) - } - } - } - - fn float_rational_pair(n1: OrderedFloat, n2: Rc>) -> NumberPair { - match (n2.numer().to_f64(), n2.denom().to_f64()) { - (Some(num), Some(denom)) => - NumberPair::Float(n1, OrderedFloat(num / denom)), - _ => if let Some(r) = Ratio::from_float(n1.into_inner()) { - NumberPair::Rational(Rc::new(r), n2) - } else if n1.into_inner().is_sign_positive() { - NumberPair::Float(OrderedFloat(f64::infinity()), - OrderedFloat(f64::infinity())) - } else { - NumberPair::Float(OrderedFloat(f64::neg_infinity()), - OrderedFloat(f64::neg_infinity())) - } - } - } - - pub fn from(n1: Number, n2: Number) -> NumberPair - { - match (n1, n2) { - (Number::Integer(n1), Number::Integer(n2)) => - NumberPair::Integer(n1, n2), - (Number::Float(n1), Number::Float(n2)) => - NumberPair::Float(n1, n2), - (Number::Rational(n1), Number::Rational(n2)) => - NumberPair::Rational(n1, n2), - (Number::Integer(n1), Number::Float(n2)) => - Self::integer_float_pair(n1, n2), - (Number::Float(n1), Number::Integer(n2)) => - Self::integer_float_pair(n2, n1).flip(), - (Number::Float(n1), Number::Rational(n2)) => - Self::float_rational_pair(n1, n2), - (Number::Rational(n1), Number::Float(n2)) => - Self::float_rational_pair(n2, n1).flip(), - (Number::Rational(n1), Number::Integer(n2)) => - NumberPair::Rational(n1, Rc::new(Ratio::from_integer((*n2).clone()))), - (Number::Integer(n1), Number::Rational(n2)) => - NumberPair::Rational(Rc::new(Ratio::from_integer((*n1).clone())), n2) - } - } -} - -impl Add for Number { - type Output = Number; - - fn add(self, rhs: Number) -> Self::Output { - match NumberPair::from(self, rhs) { - NumberPair::Float(f1, f2) => - Number::Float(OrderedFloat(f1.into_inner() + f2.into_inner())), - NumberPair::Integer(n1, n2) => - Number::Integer(Rc::new(&*n1 + &*n2)), - NumberPair::Rational(r1, r2) => - Number::Rational(Rc::new(&*r1 + &*r2)) - } - } -} - -impl Sub for Number { - type Output = Number; - - fn sub(self, rhs: Number) -> Self::Output { - match NumberPair::from(self, rhs) { - NumberPair::Float(f1, f2) => - Number::Float(OrderedFloat(f1.into_inner() - f2.into_inner())), - NumberPair::Integer(n1, n2) => - Number::Integer(Rc::new(&*n1 - &*n2)), - NumberPair::Rational(r1, r2) => - Number::Rational(Rc::new(&*r1 - &*r2)) - } - } -} - -impl Mul for Number { - type Output = Number; - - fn mul(self, rhs: Number) -> Self::Output { - match NumberPair::from(self, rhs) { - NumberPair::Float(f1, f2) => - Number::Float(OrderedFloat(f1.into_inner() * f2.into_inner())), - NumberPair::Integer(n1, n2) => - Number::Integer(Rc::new(&*n1 * &*n2)), - NumberPair::Rational(r1, r2) => - Number::Rational(Rc::new(&*r1 * &*r2)) - } + fn from(inlined_ct: InlinedClauseType) -> Self { + ClauseType::Inlined(inlined_ct) } } -impl Div for Number { - type Output = Number; +#[derive(Clone)] +pub enum ChoiceInstruction { + DefaultRetryMeElse(usize), + DefaultTrustMe, + RetryMeElse(usize), + TrustMe, + TryMeElse(usize) +} - fn div(self, rhs: Number) -> Self::Output { - match NumberPair::from(self, rhs) { - NumberPair::Float(f1, f2) => - Number::Float(OrderedFloat(f1.into_inner() / f2.into_inner())), - NumberPair::Integer(n1, n2) => - match n1.to_f64() { - Some(f1) => if let Some(f2) = n2.to_f64() { - Number::Float(OrderedFloat(f1 / f2)) - } else { - let r1 = Ratio::from_integer((*n1).clone()); - let r2 = Ratio::from_integer((*n2).clone()); +#[derive(Clone)] +pub enum CutInstruction { + Cut(RegType), + GetLevel(RegType), + GetLevelAndUnify(RegType), + NeckCut +} - Number::Rational(Rc::new(r1 / r2)) - }, - None => { - let r1 = Ratio::from_integer((*n1).clone()); - let r2 = Ratio::from_integer((*n2).clone()); +#[derive(Clone)] +pub enum IndexedChoiceInstruction { + Retry(usize), + Trust(usize), + Try(usize) +} - Number::Rational(Rc::new(r1 / r2)) - }, - }, - NumberPair::Rational(r1, r2) => - Number::Rational(Rc::new(&*r1 / &*r2)) - } +impl From for Line { + fn from(i: IndexedChoiceInstruction) -> Self { + Line::IndexedChoice(i) } } -impl Neg for Number { - type Output = Number; - - fn neg(self) -> Self::Output { +impl IndexedChoiceInstruction { + pub fn offset(&self) -> usize { match self { - Number::Integer(n) => Number::Integer(Rc::new(-&*n)), - Number::Float(f) => Number::Float(OrderedFloat(-1.0 * f.into_inner())), - Number::Rational(r) => Number::Rational(Rc::new(- &*r)) + &IndexedChoiceInstruction::Retry(offset) => offset, + &IndexedChoiceInstruction::Trust(offset) => offset, + &IndexedChoiceInstruction::Try(offset) => offset } } } - #[derive(Clone, PartialEq)] pub enum ArithmeticTerm { Reg(RegType), @@ -1827,188 +857,447 @@ impl PartialOrd for CodePtr { _ => Some(Ordering::Greater) } } -} +} + +impl PartialOrd for LocalCodePtr { + fn partial_cmp(&self, other: &LocalCodePtr) -> Option { + match (self, other) { + (&LocalCodePtr::DirEntry(p1, _), &LocalCodePtr::DirEntry(p2, _)) => + p1.partial_cmp(&p2), + (&LocalCodePtr::DirEntry(..), &LocalCodePtr::TopLevel(_, _)) => + Some(Ordering::Less), + (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => + p1.partial_cmp(p2), + _ => Some(Ordering::Greater) + } + } +} + +impl Default for CodePtr { + fn default() -> Self { + CodePtr::Local(LocalCodePtr::default()) + } +} + +impl Default for LocalCodePtr { + fn default() -> Self { + LocalCodePtr::TopLevel(0, 0) + } +} + +impl Add for LocalCodePtr { + type Output = LocalCodePtr; + + fn add(self, rhs: usize) -> Self::Output { + match self { + LocalCodePtr::DirEntry(p, name) => LocalCodePtr::DirEntry(p + rhs, name), + LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs) + } + } +} + +impl AddAssign for LocalCodePtr { + fn add_assign(&mut self, rhs: usize) { + match self { + &mut LocalCodePtr::DirEntry(ref mut p, _) | + &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs + } + } +} + +impl Add for CodePtr { + type Output = CodePtr; + + fn add(self, rhs: usize) -> Self::Output { + match self { + CodePtr::Local(local) => CodePtr::Local(local + rhs), + CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs), + } + } +} + +impl AddAssign for CodePtr { + fn add_assign(&mut self, rhs: usize) { + match self { + &mut CodePtr::Local(ref mut local) => *local += rhs, + _ => *self = CodePtr::Local(self.local() + rhs) + } + } +} + +pub struct Heap { + heap: Vec, + pub h: usize +} + +impl Heap { + pub fn with_capacity(cap: usize) -> Self { + Heap { heap: Vec::with_capacity(cap), h: 0 } + } + + pub fn push(&mut self, val: HeapCellValue) { + self.heap.push(val); + self.h += 1; + } + + pub fn truncate(&mut self, h: usize) { + self.h = h; + self.heap.truncate(h); + } + + pub fn len(&self) -> usize { + self.heap.len() + } + + pub fn append(&mut self, vals: Vec) { + let n = vals.len(); + + self.heap.extend(vals.into_iter()); + self.h += n; + } + + pub fn clear(&mut self) { + self.heap.clear(); + self.h = 0; + } +} + +impl Index for Heap { + type Output = HeapCellValue; + + fn index(&self, index: usize) -> &Self::Output { + &self.heap[index] + } +} + +impl IndexMut for Heap { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.heap[index] + } +} + +pub type Registers = Vec; + +pub enum TermIterState<'a> { + AnonVar(Level), + Constant(Level, &'a Cell, &'a Constant), + Clause(Level, usize, &'a Cell, ClauseType, &'a Vec>), + InitialCons(Level, &'a Cell, &'a Term, &'a Term), + FinalCons(Level, &'a Cell, &'a Term, &'a Term), + Var(Level, &'a Cell, Rc) +} + +impl<'a> TermIterState<'a> { + pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { + match term { + &Term::AnonVar => + TermIterState::AnonVar(lvl), + &Term::Clause(ref cell, ref name, ref subterms, fixity) => { + let ct = if let Some(fixity) = fixity { + ClauseType::Op(name.clone(), fixity, CodeIndex::default()) + } else { + ClauseType::Named(name.clone(), CodeIndex::default()) + }; + + TermIterState::Clause(lvl, 0, cell, ct, subterms) + }, + &Term::Cons(ref cell, ref head, ref tail) => + TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()), + &Term::Constant(ref cell, ref constant) => + TermIterState::Constant(lvl, cell, constant), + &Term::Var(ref cell, ref var) => + TermIterState::Var(lvl, cell, var.clone()) + } + } +} + +impl Module { + pub fn new(module_decl: ModuleDecl) -> Self { + Module { module_decl, + code_dir: ModuleCodeDir::new(), + op_dir: default_op_dir() } + } +} + +pub fn as_module_code_dir(code_dir: CodeDir) -> ModuleCodeDir { + code_dir.into_iter() + .map(|(k, code_idx)| { + let (idx, module_name) = code_idx.0.borrow().clone(); + (k, ModuleCodeIndex(idx, module_name)) + }) + .collect() +} + +impl SubModuleUser for Module { + fn op_dir(&mut self) -> &mut OpDir { + &mut self.op_dir + } + + fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: ModuleCodeIndex) { + self.code_dir.insert((name, arity), idx); + } +} + +pub trait SubModuleUser { + fn op_dir(&mut self) -> &mut OpDir; + fn insert_dir_entry(&mut self, ClauseName, usize, ModuleCodeIndex); + + // returns true on successful import. + fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool { + let name = name.defrock_brackets(); + let mut found_op = false; + + { + let mut insert_op_dir = |fix| { + if let Some(op_data) = submodule.op_dir.get(&(name.clone(), fix)) { + self.op_dir().insert((name.clone(), fix), op_data.clone()); + found_op = true; + } + }; + + if arity == 1 { + insert_op_dir(Fixity::Pre); + insert_op_dir(Fixity::Post); + } else if arity == 2 { + insert_op_dir(Fixity::In); + } + } + + if let Some(code_data) = submodule.code_dir.get(&(name.clone(), arity)) { + self.insert_dir_entry(name, arity, code_data.clone()); + true + } else { + found_op + } + } + + fn use_qualified_module(&mut self, submodule: &Module, exports: &Vec) -> EvalSession + { + for (name, arity) in exports.iter().cloned() { + if !submodule.module_decl.exports.contains(&(name.clone(), arity)) { + continue; + } + + if !self.import_decl(name, arity, submodule) { + return EvalSession::from(SessionError::ModuleDoesNotContainExport); + } + } + + EvalSession::EntrySuccess + } -impl PartialOrd for LocalCodePtr { - fn partial_cmp(&self, other: &LocalCodePtr) -> Option { - match (self, other) { - (&LocalCodePtr::DirEntry(p1, _), &LocalCodePtr::DirEntry(p2, _)) => - p1.partial_cmp(&p2), - (&LocalCodePtr::DirEntry(..), &LocalCodePtr::TopLevel(_, _)) => - Some(Ordering::Less), - (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => - p1.partial_cmp(p2), - _ => Some(Ordering::Greater) + fn use_module(&mut self, submodule: &Module) -> EvalSession { + for (name, arity) in submodule.module_decl.exports.iter().cloned() { + if !self.import_decl(name, arity, submodule) { + return EvalSession::from(SessionError::ModuleDoesNotContainExport); + } } + + EvalSession::EntrySuccess } } -impl Default for CodePtr { - fn default() -> Self { - CodePtr::Local(LocalCodePtr::default()) - } +pub enum Declaration { + NonCountedBacktracking(ClauseName, usize), // name, arity + Module(ModuleDecl), + Op(OpDecl), + UseModule(ClauseName), + UseQualifiedModule(ClauseName, Vec) } -impl Default for LocalCodePtr { - fn default() -> Self { - LocalCodePtr::TopLevel(0, 0) - } +pub enum TopLevel { + Declaration(Declaration), + Fact(Term), + Predicate(Predicate), + Query(Vec), + Rule(Rule) } -impl Add for LocalCodePtr { - type Output = LocalCodePtr; +impl TopLevel { + pub fn name(&self) -> Option { + match self { + &TopLevel::Declaration(_) => None, + &TopLevel::Fact(ref term) => term.name(), + &TopLevel::Predicate(ref clauses) => + clauses.0.first().and_then(|ref term| term.name()), + &TopLevel::Query(_) => None, + &TopLevel::Rule(Rule { ref head, .. }) => + Some(head.0.clone()) + } + } - fn add(self, rhs: usize) -> Self::Output { + pub fn arity(&self) -> usize { match self { - LocalCodePtr::DirEntry(p, name) => LocalCodePtr::DirEntry(p + rhs, name), - LocalCodePtr::TopLevel(cn, p) => LocalCodePtr::TopLevel(cn, p + rhs) + &TopLevel::Declaration(_) => 0, + &TopLevel::Fact(ref term) => term.arity(), + &TopLevel::Predicate(ref clauses) => + clauses.0.first().map(|t| t.arity()).unwrap_or(0), + &TopLevel::Query(_) => 0, + &TopLevel::Rule(Rule { ref head, .. }) => head.1.len() } } -} -impl AddAssign for LocalCodePtr { - fn add_assign(&mut self, rhs: usize) { + pub fn as_predicate(self) -> Result { match self { - &mut LocalCodePtr::DirEntry(ref mut p, _) | - &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs + TopLevel::Fact(term) => Ok(Predicate(vec![PredicateClause::Fact(term)])), + TopLevel::Rule(rule) => Ok(Predicate(vec![PredicateClause::Rule(rule)])), + TopLevel::Predicate(pred) => Ok(pred), + _ => Err(self) } } } -impl Add for CodePtr { - type Output = CodePtr; +#[derive(Clone, Copy)] +pub enum Level { + Deep, Root, Shallow +} - fn add(self, rhs: usize) -> Self::Output { +impl Level { + pub fn child_level(self) -> Level { match self { - CodePtr::Local(local) => CodePtr::Local(local + rhs), - CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs), + Level::Root => Level::Shallow, + _ => Level::Deep } } } -impl AddAssign for CodePtr { - fn add_assign(&mut self, rhs: usize) { +// labeled with chunk numbers. +pub enum VarStatus { + Perm(usize), Temp(usize, TempVarData) // Perm(chunk_num) | Temp(chunk_num, _) +} + +pub type OccurrenceSet = BTreeSet<(GenContext, usize)>; + +// Perm: 0 initially, a stack register once processed. +// Temp: labeled with chunk_num and temp offset (unassigned if 0). +pub enum VarData { + Perm(usize), Temp(usize, usize, TempVarData) +} + +impl VarData { + pub fn as_reg_type(&self) -> RegType { match self { - &mut CodePtr::Local(ref mut local) => *local += rhs, - _ => *self = CodePtr::Local(self.local() + rhs) + &VarData::Temp(_, r, _) => RegType::Temp(r), + &VarData::Perm(r) => RegType::Perm(r) } } } -pub struct Heap { - heap: Vec, - pub h: usize +pub struct TempVarData { + pub last_term_arity: usize, + pub use_set: OccurrenceSet, + pub no_use_set: BTreeSet, + pub conflict_set: BTreeSet } -impl Heap { - pub fn with_capacity(cap: usize) -> Self { - Heap { heap: Vec::with_capacity(cap), h: 0 } +impl TempVarData { + pub fn new(last_term_arity: usize) -> Self { + TempVarData { + last_term_arity: last_term_arity, + use_set: BTreeSet::new(), + no_use_set: BTreeSet::new(), + conflict_set: BTreeSet::new() + } } - pub fn push(&mut self, val: HeapCellValue) { - self.heap.push(val); - self.h += 1; - } + pub fn uses_reg(&self, reg: usize) -> bool { + for &(_, nreg) in self.use_set.iter() { + if reg == nreg { + return true; + } + } - pub fn truncate(&mut self, h: usize) { - self.h = h; - self.heap.truncate(h); + return false; } - pub fn len(&self) -> usize { - self.heap.len() - } + pub fn populate_conflict_set(&mut self) { + if self.last_term_arity > 0 { + let arity = self.last_term_arity; + let mut conflict_set : BTreeSet = (1..arity).collect(); - pub fn append(&mut self, vals: Vec) { - let n = vals.len(); + for &(_, reg) in self.use_set.iter() { + conflict_set.remove(®); + } - self.heap.extend(vals.into_iter()); - self.h += n; + self.conflict_set = conflict_set; + } } +} - pub fn clear(&mut self) { - self.heap.clear(); - self.h = 0; - } +pub type HeapVarDict = HashMap, Addr>; +pub type AllocVarDict = HashMap, VarData>; + +pub enum SessionError { + ImpermissibleEntry(String), + ModuleDoesNotContainExport, + ModuleNotFound, + NamelessEntry, + OpIsInfixAndPostFix, + ParserError(ParserError), + QueryFailure, + QueryFailureWithException(String) } -impl Index for Heap { - type Output = HeapCellValue; +pub enum EvalSession { + EntrySuccess, + Error(SessionError), + InitialQuerySuccess(AllocVarDict, HeapVarDict), + SubsequentQuerySuccess, +} - fn index(&self, index: usize) -> &Self::Output { - &self.heap[index] +impl From for EvalSession { + fn from(err: SessionError) -> Self { + EvalSession::Error(err) } } -impl IndexMut for Heap { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.heap[index] +impl From for SessionError { + fn from(err: ParserError) -> Self { + SessionError::ParserError(err) } } -pub type Registers = Vec; - -impl Term { - pub fn to_constant(self) -> Option { - match self { - Term::Constant(_, c) => Some(c), - _ => None - } +impl From for EvalSession { + fn from(err: ParserError) -> Self { + EvalSession::from(SessionError::ParserError(err)) } +} - pub fn first_arg(&self) -> Option<&Term> { - match self { - &Term::Clause(_, _, ref terms, _) => - terms.first().map(|bt| bt.as_ref()), - _ => None - } - } +pub struct OpDecl(pub usize, pub Specifier, pub ClauseName); - pub fn name(&self) -> Option { - match self { - &Term::Constant(_, Constant::Atom(ref atom)) - | &Term::Clause(_, ref atom, ..) => Some(atom.clone()), - _ => None - } - } +impl OpDecl { + pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), SessionError> + { + let (prec, spec, name) = (self.0, self.1, self.2.clone()); - pub fn arity(&self) -> usize { - match self { - &Term::Clause(_, _, ref child_terms, ..) => child_terms.len(), - _ => 0 + if is_infix!(spec) { + match op_dir.get(&(name.clone(), Fixity::Post)) { + Some(_) => return Err(SessionError::OpIsInfixAndPostFix), + _ => {} + }; } - } -} -pub enum TermIterState<'a> { - AnonVar(Level), - Constant(Level, &'a Cell, &'a Constant), - Clause(Level, usize, &'a Cell, ClauseType, &'a Vec>), - InitialCons(Level, &'a Cell, &'a Term, &'a Term), - FinalCons(Level, &'a Cell, &'a Term, &'a Term), - Var(Level, &'a Cell, Rc) -} - -impl<'a> TermIterState<'a> { - pub fn subterm_to_state(lvl: Level, term: &'a Term) -> TermIterState<'a> { - match term { - &Term::AnonVar => - TermIterState::AnonVar(lvl), - &Term::Clause(ref cell, ref name, ref subterms, fixity) => { - let ct = if let Some(fixity) = fixity { - ClauseType::Op(name.clone(), fixity, CodeIndex::default()) - } else { - ClauseType::Named(name.clone(), CodeIndex::default()) - }; + if is_postfix!(spec) { + match op_dir.get(&(name.clone(), Fixity::In)) { + Some(_) => return Err(SessionError::OpIsInfixAndPostFix), + _ => {} + }; + } - TermIterState::Clause(lvl, 0, cell, ct, subterms) - }, - &Term::Cons(ref cell, ref head, ref tail) => - TermIterState::InitialCons(lvl, cell, head.as_ref(), tail.as_ref()), - &Term::Constant(ref cell, ref constant) => - TermIterState::Constant(lvl, cell, constant), - &Term::Var(ref cell, ref var) => - TermIterState::Var(lvl, cell, var.clone()) + if prec > 0 { + match spec { + XFY | XFX | YFX => op_dir.insert((name.clone(), Fixity::In), + (spec, prec, module.clone())), + XF | YF => op_dir.insert((name.clone(), Fixity::Post), (spec, prec, module.clone())), + FX | FY => op_dir.insert((name.clone(), Fixity::Pre), (spec, prec, module.clone())), + _ => None + }; + } else { + op_dir.remove(&(name.clone(), Fixity::Pre)); + op_dir.remove(&(name.clone(), Fixity::In)); + op_dir.remove(&(name.clone(), Fixity::Post)); } + + Ok(()) } } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 3c8d40a7..becf6e71 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -1,10 +1,11 @@ +use prolog_parser::ast::*; + +use prolog::ast::*; use prolog::allocator::*; use prolog::arithmetic::*; -use prolog::ast::*; use prolog::fixtures::*; use prolog::indexing::*; use prolog::iterators::*; -use prolog::machine::machine_state::MachineFlags; use prolog::targets::*; use std::cell::Cell; @@ -596,10 +597,10 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code { - self.update_var_count(term.post_order_iter()); + self.update_var_count(post_order_iter(term)); let mut vs = VariableFixtures::new(); - vs.mark_vars_in_chunk(term.post_order_iter(), term.arity(), GenContext::Head); + vs.mark_vars_in_chunk(post_order_iter(term), term.arity(), GenContext::Head); vs.populate_restricting_sets(); self.marker.drain_var_data(vs); @@ -628,7 +629,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { self.marker.reset_arg(term.arity()); - let iter = term.post_order_iter(); + let iter = query_term_post_order_iter(term); let query = self.compile_target(iter, term_loc, is_exposed); if !query.is_empty() { diff --git a/src/prolog/compile.rs b/src/prolog/compile.rs index f0bb2986..ca151441 100644 --- a/src/prolog/compile.rs +++ b/src/prolog/compile.rs @@ -1,8 +1,9 @@ +use prolog_parser::ast::*; + use prolog::ast::*; use prolog::debray_allocator::*; use prolog::codegen::*; use prolog::machine::*; -use prolog::machine::machine_state::MachineFlags; use prolog::toplevel::*; use std::collections::{HashMap, HashSet, VecDeque}; diff --git a/src/prolog/copier.rs b/src/prolog/copier.rs index 0595678d..6ac18b6a 100644 --- a/src/prolog/copier.rs +++ b/src/prolog/copier.rs @@ -1,5 +1,5 @@ -use prolog::and_stack::*; use prolog::ast::*; +use prolog::and_stack::*; use std::ops::IndexMut; diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index 2ded88f8..88a40a02 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -1,5 +1,7 @@ -use prolog::allocator::*; +use prolog_parser::ast::*; + use prolog::ast::*; +use prolog::allocator::*; use prolog::targets::*; use std::cell::Cell; diff --git a/src/prolog/fixtures.rs b/src/prolog/fixtures.rs index 00590e54..c2ee7e3f 100644 --- a/src/prolog/fixtures.rs +++ b/src/prolog/fixtures.rs @@ -1,56 +1,15 @@ -use prolog::ast::*; +use prolog_parser::ast::*; + use prolog::iterators::*; +use prolog::ast::*; use std::cell::Cell; -use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::collections::{BTreeMap, HashMap}; use std::collections::btree_map::{IntoIter, IterMut, Values}; use std::mem::swap; use std::rc::Rc; use std::vec::Vec; -impl VarData { - pub fn as_reg_type(&self) -> RegType { - match self { - &VarData::Temp(_, r, _) => RegType::Temp(r), - &VarData::Perm(r) => RegType::Perm(r) - } - } -} - -impl TempVarData { - fn new(last_term_arity: usize) -> Self { - TempVarData { - last_term_arity: last_term_arity, - use_set: BTreeSet::new(), - no_use_set: BTreeSet::new(), - conflict_set: BTreeSet::new() - } - } - - fn uses_reg(&self, reg: usize) -> bool { - for &(_, nreg) in self.use_set.iter() { - if reg == nreg { - return true; - } - } - - return false; - } - - fn populate_conflict_set(&mut self) { - if self.last_term_arity > 0 { - let arity = self.last_term_arity; - let mut conflict_set : BTreeSet = (1..arity).collect(); - - for &(_, reg) in self.use_set.iter() { - conflict_set.remove(®); - } - - self.conflict_set = conflict_set; - } - } -} - type VariableFixture<'a> = (VarStatus, Vec<&'a Cell>); pub struct VariableFixtures<'a>(BTreeMap, VariableFixture<'a>>); diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index 99206578..5ce1c543 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -1,5 +1,7 @@ +use prolog_parser::ast::*; + use prolog::ast::*; -use prolog::machine::machine_state::MachineState; +use prolog::machine::machine_state::*; use std::collections::HashSet; use std::vec::Vec; diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index 06e9acf8..4af86934 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -1,7 +1,9 @@ +use prolog_parser::ast::*; + use prolog::ast::*; +use prolog::machine::machine_state::*; use prolog::num::*; use prolog::heap_iter::*; -use prolog::machine::machine_state::MachineState; use prolog::ordered_float::OrderedFloat; use std::cell::Cell; diff --git a/src/prolog/indexing.rs b/src/prolog/indexing.rs index 84fbb8f3..2da72058 100644 --- a/src/prolog/indexing.rs +++ b/src/prolog/indexing.rs @@ -1,6 +1,6 @@ -use prolog::ast::*; -use prolog::machine::machine_state::MachineFlags; +use prolog_parser::ast::*; +use prolog::ast::*; use std::collections::{HashMap, VecDeque}; use std::hash::Hash; use std::rc::Rc; diff --git a/src/prolog/io.rs b/src/prolog/io.rs index ccd05857..f1ff550e 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -9,6 +9,10 @@ use termion::event::Key; use std::io::{Write, stdin, stdout}; use std::fmt; +fn error_string(e: &String) -> String { + format!("error: exception thrown: {}", e) +} + impl fmt::Display for IndexPtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -22,35 +26,6 @@ impl fmt::Display for IndexPtr { } } -impl fmt::Display for ClauseName { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.as_str()) - } -} - -impl fmt::Display for Constant { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &Constant::Atom(ref atom) => - if atom.as_str().chars().any(|c| "`.$'\" ".contains(c)) { - write!(f, "'{}'", atom.as_str()) - } else { - write!(f, "{}", atom.as_str()) - }, - &Constant::Char(c) => - write!(f, "'{}'", c as u8), - &Constant::EmptyList => - write!(f, "[]"), - &Constant::Number(ref n) => - write!(f, "{}", n), - &Constant::String(ref s) => - write!(f, "\"{}\"", s.borrow()), - &Constant::Usize(integer) => - write!(f, "u{}", integer) - } - } -} - impl fmt::Display for FactInstruction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -306,28 +281,6 @@ impl fmt::Display for Level { } } -impl fmt::Display for VarReg { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg), - &VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg), - &VarReg::ArgAndNorm(RegType::Perm(reg), arg) => - write!(f, "Y{} A{}", reg, arg), - &VarReg::ArgAndNorm(RegType::Temp(reg), arg) => - write!(f, "X{} A{}", reg, arg) - } - } -} - -impl fmt::Display for RegType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &RegType::Perm(val) => write!(f, "Y{}", val), - &RegType::Temp(val) => write!(f, "X{}", val) - } - } -} - pub enum Input { Quit, Clear, @@ -367,10 +320,6 @@ pub fn read() -> Input { } } -fn error_string(e: &String) -> String { - format!("error: exception thrown: {}", e) -} - pub fn print(wam: &mut Machine, result: EvalSession) { match result { EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => { diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index feb86038..1eff90f9 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -1,10 +1,33 @@ -use prolog::ast::*; +use prolog_parser::ast::*; +use prolog::ast::*; +use std::cell::Cell; use std::collections::VecDeque; use std::iter::*; use std::rc::Rc; use std::vec::Vec; +#[derive(Clone)] +pub enum TermRef<'a> { + AnonVar(Level), + Cons(Level, &'a Cell, &'a Term, &'a Term), + Constant(Level, &'a Cell, &'a Constant), + Clause(Level, &'a Cell, ClauseType, &'a Vec>), + Var(Level, &'a Cell, Rc) +} + +impl<'a> TermRef<'a> { + pub fn level(self) -> Level { + match self { + TermRef::AnonVar(lvl) + | TermRef::Cons(lvl, ..) + | TermRef::Constant(lvl, ..) + | TermRef::Var(lvl, ..) + | TermRef::Clause(lvl, ..) => lvl + } + } +} + pub struct QueryIterator<'a> { state_stack: Vec>, } @@ -192,14 +215,12 @@ impl<'a> Iterator for FactIterator<'a> { } } -impl Term { - pub fn post_order_iter(&self) -> QueryIterator { - QueryIterator::from_term(self) - } +pub fn post_order_iter(term: &Term) -> QueryIterator { + QueryIterator::from_term(term) +} - pub fn breadth_first_iter(&self, iterable_root: bool) -> FactIterator { - FactIterator::new(self, iterable_root) - } +pub fn breadth_first_iter(term: &Term, iterable_root: bool) -> FactIterator { + FactIterator::new(term, iterable_root) } pub enum ChunkedTerm<'a> { @@ -207,10 +228,8 @@ pub enum ChunkedTerm<'a> { BodyTerm(&'a QueryTerm) } -impl QueryTerm { - pub fn post_order_iter<'a>(&'a self) -> QueryIterator<'a> { - QueryIterator::new(self) - } +pub fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterator<'a> { + QueryIterator::new(query_term) } impl<'a> ChunkedTerm<'a> { diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 797dd220..d5907b7f 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -1,3 +1,5 @@ +use prolog_parser::ast::*; + use prolog::ast::*; use prolog::machine::machine_state::*; use prolog::num::bigint::BigInt; diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index f7c4c1cd..7432e599 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -1,12 +1,14 @@ -use prolog::and_stack::*; +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; + use prolog::ast::*; +use prolog::and_stack::*; use prolog::copier::*; use prolog::heap_print::*; use prolog::machine::machine_errors::*; use prolog::num::{BigInt, BigUint, Zero, One}; use prolog::or_stack::*; use prolog::read::*; -use prolog::tabled_rc::*; use downcast::Any; @@ -264,38 +266,6 @@ pub(super) enum MachineMode { Write } -#[derive(Clone, Copy)] -pub enum DoubleQuotes { - Atom, Chars, // Codes -} - -impl DoubleQuotes { - pub fn is_chars(self) -> bool { - if let DoubleQuotes::Chars = self { - true - } else { - false - } - } -} - -impl Default for DoubleQuotes { - fn default() -> Self { - DoubleQuotes::Chars - } -} - -#[derive(Clone, Copy)] -pub struct MachineFlags { - pub 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, diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index b0f8a579..942b491c 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -1,5 +1,8 @@ -use prolog::and_stack::*; +use prolog_parser::ast::*; +use prolog_parser::string_list::StringList; + use prolog::ast::*; +use prolog::and_stack::*; use prolog::copier::*; use prolog::heap_iter::*; use prolog::heap_print::*; @@ -9,7 +12,6 @@ use prolog::num::{Integer, Signed, ToPrimitive, Zero}; use prolog::num::bigint::{BigInt, BigUint}; use prolog::num::rational::Ratio; use prolog::or_stack::*; -use prolog::string_list::StringList; use std::cell::RefCell; use std::cmp::{max, Ordering}; diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 508eb904..7cf011fe 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -1,12 +1,14 @@ +use prolog_parser::ast::*; +use prolog_parser::tabled_rc::*; + use prolog::ast::*; use prolog::compile::*; use prolog::heap_print::*; -use prolog::tabled_rc::*; mod machine_errors; pub(super) mod machine_state; -#[macro_use] -mod machine_state_impl; + +#[macro_use] mod machine_state_impl; mod system_calls; use prolog::machine::machine_state::*; @@ -16,6 +18,8 @@ use std::mem::swap; use std::ops::Index; use std::rc::Rc; +static BUILTINS: &str = include_str!("../lib/builtins.pl"); + pub struct MachineCodeIndices<'a> { pub(super) code_dir: &'a mut CodeDir, pub(super) op_dir: &'a mut OpDir, diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index e99d7001..451c99e6 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -1,3 +1,5 @@ +use prolog_parser::ast::*; + use prolog::ast::*; use prolog::machine::machine_errors::*; use prolog::machine::machine_state::*; diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index da53a665..f348ed0d 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -1,27 +1,3 @@ -macro_rules! clause_name { - ($name: expr, $tbl: expr) => ( - ClauseName::User(TabledRc::new($name, $tbl.clone())) - ) ; - ($name: expr) => ( - ClauseName::BuiltIn($name) - ) -} - -macro_rules! tabled_rc { - ($e:expr, $tbl:expr) => ( - TabledRc::new(String::from($e), $tbl.clone()) - ) -} - -macro_rules! atom { - ($e:expr, $tbl:expr) => ( - Constant::Atom(ClauseName::User(tabled_rc!($e, $tbl))) - ); - ($e:expr) => ( - Constant::Atom(clause_name!($e)) - ) -} - macro_rules! interm { ($n: expr) => ( ArithmeticTerm::Interm($n) @@ -76,18 +52,6 @@ macro_rules! functor { ); } -macro_rules! temp_v { - ($x:expr) => ( - RegType::Temp($x) - ) -} - -macro_rules! perm_v { - ($x:expr) => ( - RegType::Perm($x) - ) -} - macro_rules! is_atom { ($r:expr) => ( call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtom($r)), 1, 0) @@ -191,18 +155,6 @@ macro_rules! set_cp { ) } -macro_rules! integer { - ($i:expr) => ( - Constant::Number(Number::Integer(Rc::new(BigInt::from($i)))) - ) -} - -macro_rules! rc_atom { - ($e:expr) => ( - Rc::new(String::from($e)) - ) -} - macro_rules! succeed { () => ( call_clause!(ClauseType::System(SystemClauseType::Succeed), 0, 0) diff --git a/src/prolog/mod.rs b/src/prolog/mod.rs index eb4e57f4..ffc4de43 100644 --- a/src/prolog/mod.rs +++ b/src/prolog/mod.rs @@ -1,13 +1,11 @@ extern crate num; extern crate ordered_float; +extern crate prolog_parser; +#[macro_use] pub mod ast; pub mod and_stack; -#[macro_use] -pub mod macros; -#[macro_use] -pub mod ast; -#[macro_use] -pub mod allocator; +#[macro_use] pub mod macros; +#[macro_use] pub mod allocator; pub mod toplevel; pub mod machine; pub mod compile; @@ -21,10 +19,6 @@ pub mod indexing; pub mod io; pub mod iterators; pub mod or_stack; -#[macro_use] -pub mod parser; pub mod heap_print; pub mod targets; -pub mod tabled_rc; pub mod read; -pub mod string_list; diff --git a/src/prolog/parser b/src/prolog/parser deleted file mode 160000 index 48814651..00000000 --- a/src/prolog/parser +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 48814651b857b2fd55149320f1ea71d0571b442e diff --git a/src/prolog/read.rs b/src/prolog/read.rs index b6e942a4..1f4bd4eb 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -1,6 +1,9 @@ +use prolog_parser::ast::*; +use prolog_parser::parser::*; + use prolog::ast::*; +use prolog::iterators::*; use prolog::machine::machine_state::*; -use prolog::parser::parser::*; use std::collections::VecDeque; use std::io::stdin; @@ -70,7 +73,7 @@ impl<'a> Reader<'a> { let mut queue = SubtermDeque::new(); let mut var_dict = HeapVarDict::new(); - for term in term.breadth_first_iter(true) { + for term in breadth_first_iter(&term, true) { let h = self.machine_st.heap.h; match &term { diff --git a/src/prolog/targets.rs b/src/prolog/targets.rs index f6d1fb36..9eaa2a34 100644 --- a/src/prolog/targets.rs +++ b/src/prolog/targets.rs @@ -1,3 +1,5 @@ +use prolog_parser::ast::*; + use prolog::ast::*; use prolog::iterators::*; @@ -32,7 +34,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction { type Iterator = FactIterator<'a>; fn iter(term: &'a Term) -> Self::Iterator { - term.breadth_first_iter(false) // do not iterate over the root clause if one exists. + breadth_first_iter(term, false) // do not iterate over the root clause if one exists. } fn to_constant(lvl: Level, constant: Constant, reg: RegType) -> Self { @@ -99,7 +101,7 @@ impl<'a> CompilationTarget<'a> for QueryInstruction { type Iterator = QueryIterator<'a>; fn iter(term: &'a Term) -> Self::Iterator { - term.post_order_iter() + post_order_iter(term) } fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self diff --git a/src/prolog/toplevel.rs b/src/prolog/toplevel.rs index 1f3919c4..266b153f 100644 --- a/src/prolog/toplevel.rs +++ b/src/prolog/toplevel.rs @@ -1,9 +1,11 @@ +use prolog_parser::ast::*; +use prolog_parser::parser::*; +use prolog_parser::tabled_rc::*; + use prolog::ast::*; +use prolog::iterators::*; use prolog::machine::*; -use prolog::machine::machine_state::MachineFlags; use prolog::num::*; -use prolog::parser::parser::*; -use prolog::tabled_rc::*; use std::collections::{HashSet, VecDeque}; use std::cell::{Cell, RefCell}; @@ -322,7 +324,7 @@ impl RelationWorker { { let mut vars = HashSet::new(); - for term in term.post_order_iter() { + for term in post_order_iter(term) { if let TermRef::Var(_, _, v) = term { vars.insert(v.clone()); } diff --git a/src/tests.rs b/src/tests.rs index b59abfa7..aef15b7e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,3 +1,5 @@ +use prolog_parser::ast::*; + use prolog::ast::*; use prolog::heap_print::*; use prolog::compile::*;