From 848068c734b67e4e26b45c9d4fc4cf7b071e42cd Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Tue, 9 Jan 2018 22:38:17 -0700 Subject: [PATCH] transition to reference counted constants --- src/prolog/arithmetic.rs | 11 ++-- src/prolog/ast.rs | 129 +++++++++++++++++++------------------- src/prolog/builtins.rs | 99 ++++++++++++++--------------- src/prolog/codegen.rs | 21 ++----- src/prolog/indexing.rs | 6 +- src/prolog/io.rs | 3 +- src/prolog/machine.rs | 132 ++++++++++++++++++--------------------- src/prolog/macros.rs | 22 +++++-- src/prolog/parser | 2 +- src/prolog/targets.rs | 8 ++- 10 files changed, 214 insertions(+), 219 deletions(-) diff --git a/src/prolog/arithmetic.rs b/src/prolog/arithmetic.rs index b80ccedc..cba7415f 100644 --- a/src/prolog/arithmetic.rs +++ b/src/prolog/arithmetic.rs @@ -2,6 +2,7 @@ use prolog::ast::*; use prolog::fixtures::*; use std::cmp::{min, max}; +use std::rc::Rc; use std::vec::Vec; pub struct ArithExprIterator<'a> { @@ -170,10 +171,8 @@ impl<'a> ArithmeticEvaluator<'a> { fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> { match c { - &Constant::Float(fl) => - self.interm.push(ArithmeticTerm::Float(fl)), - &Constant::Integer(ref bi) => - self.interm.push(ArithmeticTerm::Integer(bi.clone())), + &Constant::Number(ref n) => + self.interm.push(ArithmeticTerm::Number(n.clone())), _ => return Err(ArithmeticError::InvalidAtom), } @@ -202,11 +201,11 @@ impl<'a> ArithmeticEvaluator<'a> { self.interm.push(ArithmeticTerm::Reg(r)); }, TermRef::Clause(ClauseType::Deep(_, _, name), terms) => { - code.push(Line::Arithmetic(self.instr_from_clause(name, terms)?)); + code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?)); }, TermRef::Clause(ClauseType::Root, terms) => { let name = term.name().unwrap(); - code.push(Line::Arithmetic(self.instr_from_clause(name, terms)?)); + code.push(Line::Arithmetic(self.instr_from_clause(&*name, terms)?)); }, _ => return Err(ArithmeticError::InvalidTerm) diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index 2a570a1d..7cc9ed0e 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -11,6 +11,7 @@ use std::fmt; use std::io::Error as IOError; use std::num::{ParseFloatError}; use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, Neg}; +use std::rc::Rc; use std::str::Utf8Error; use std::vec::Vec; @@ -59,7 +60,7 @@ impl PredicateClause { } } - pub fn name(&self) -> Option<&Atom> { + pub fn name(&self) -> Option> { match self { &PredicateClause::Fact(ref term) => term.name(), &PredicateClause::Rule(ref rule) => @@ -73,7 +74,7 @@ impl PredicateClause { } pub enum Declaration { - Op(usize, Specifier, Atom) + Op(usize, Specifier, Rc) } pub enum TopLevel { @@ -266,18 +267,16 @@ pub enum Fixity { #[derive(Clone, Eq, Hash, PartialEq)] pub enum Constant { - Atom(Atom), - Float(OrderedFloat), - Integer(BigInt), - Rational(Ratio), - String(String), + Atom(Rc), + Number(Number), + String(Rc), Usize(usize), EmptyList } impl<'a> From<&'a str> for Constant { fn from(input: &str) -> Constant { - Constant::Atom(String::from(input)) + Constant::Atom(Rc::new(String::from(input))) } } @@ -288,12 +287,8 @@ impl fmt::Display for Constant { write!(f, "{}", atom), &Constant::EmptyList => write!(f, "[]"), - &Constant::Float(fl) => - write!(f, "{}", fl), - &Constant::Integer(ref i) => - write!(f, "{}", i), - &Constant::Rational(ref r) => - write!(f, "{}", r), + &Constant::Number(ref n) => + write!(f, "{}", n), &Constant::String(ref s) => write!(f, "{}", s), &Constant::Usize(integer) => @@ -302,22 +297,12 @@ impl fmt::Display for Constant { } } -impl From for Constant { - fn from(n: Number) -> Self { - match n { - Number::Rational(r) => Constant::Rational(r), - Number::Integer(n) => Constant::Integer(n), - Number::Float(f) => Constant::Float(f) - } - } -} - pub enum Term { AnonVar, - Clause(Cell, Atom, Vec>), + Clause(Cell, Rc, Vec>), Cons(Cell, Box, Box), Constant(Cell, Constant), - Var(Cell, Var) + Var(Cell, Rc) } pub enum InlinedQueryTerm { @@ -385,7 +370,7 @@ pub struct Rule { pub enum ClauseType<'a> { CallN, Catch, - Deep(Level, &'a Cell, &'a Atom), + Deep(Level, &'a Cell, &'a Rc), Is, Root, Throw, @@ -456,11 +441,27 @@ impl IndexedChoiceInstruction { } } -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq, Hash)] pub enum Number { Float(OrderedFloat), - Integer(BigInt), - Rational(Ratio) + Integer(Rc), + Rational(Rc>) +} + +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)) + } } impl Number { @@ -523,8 +524,8 @@ impl Number { enum NumberPair { Float(OrderedFloat, OrderedFloat), - Integer(BigInt, BigInt), - Rational(Ratio, Ratio) + Integer(Rc, Rc), + Rational(Rc>, Rc>) } impl NumberPair { @@ -536,11 +537,12 @@ impl NumberPair { } } - fn integer_float_pair(n1: BigInt, n2: OrderedFloat) -> NumberPair { + 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(Ratio::from_integer(n1), r) + 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())) @@ -551,12 +553,12 @@ impl NumberPair { } } - fn float_rational_pair(n1: OrderedFloat, n2: Ratio) -> NumberPair { + 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(r, n2) + NumberPair::Rational(Rc::new(r), n2) } else if n1.into_inner().is_sign_positive() { NumberPair::Float(OrderedFloat(f64::infinity()), OrderedFloat(f64::infinity())) @@ -585,9 +587,9 @@ impl NumberPair { (Number::Rational(n1), Number::Float(n2)) => Self::float_rational_pair(n2, n1).flip(), (Number::Rational(n1), Number::Integer(n2)) => - NumberPair::Rational(n1, Ratio::from_integer(n2)), + NumberPair::Rational(n1, Rc::new(Ratio::from_integer((*n2).clone()))), (Number::Integer(n1), Number::Rational(n2)) => - NumberPair::Rational(Ratio::from_integer(n1), n2) + NumberPair::Rational(Rc::new(Ratio::from_integer((*n1).clone())), n2) } } } @@ -600,9 +602,9 @@ impl Add for Number { NumberPair::Float(f1, f2) => Number::Float(OrderedFloat(f1.into_inner() + f2.into_inner())), NumberPair::Integer(n1, n2) => - Number::Integer(n1 + n2), + Number::Integer(Rc::new(&*n1 + &*n2)), NumberPair::Rational(r1, r2) => - Number::Rational(r1 + r2) + Number::Rational(Rc::new(&*r1 + &*r2)) } } } @@ -615,9 +617,9 @@ impl Sub for Number { NumberPair::Float(f1, f2) => Number::Float(OrderedFloat(f1.into_inner() - f2.into_inner())), NumberPair::Integer(n1, n2) => - Number::Integer(n1 - n2), + Number::Integer(Rc::new(&*n1 - &*n2)), NumberPair::Rational(r1, r2) => - Number::Rational(r1 - r2) + Number::Rational(Rc::new(&*r1 - &*r2)) } } } @@ -630,9 +632,9 @@ impl Mul for Number { NumberPair::Float(f1, f2) => Number::Float(OrderedFloat(f1.into_inner() * f2.into_inner())), NumberPair::Integer(n1, n2) => - Number::Integer(n1 * n2), + Number::Integer(Rc::new(&*n1 * &*n2)), NumberPair::Rational(r1, r2) => - Number::Rational(r1 * r2) + Number::Rational(Rc::new(&*r1 * &*r2)) } } } @@ -649,20 +651,20 @@ impl Div for Number { Some(f1) => if let Some(f2) = n2.to_f64() { Number::Float(OrderedFloat(f1 / f2)) } else { - let r1 = Ratio::from_integer(n1); - let r2 = Ratio::from_integer(n2); + let r1 = Ratio::from_integer((*n1).clone()); + let r2 = Ratio::from_integer((*n2).clone()); - Number::Rational(r1 / r2) + Number::Rational(Rc::new(r1 / r2)) }, None => { - let r1 = Ratio::from_integer(n1); - let r2 = Ratio::from_integer(n2); + let r1 = Ratio::from_integer((*n1).clone()); + let r2 = Ratio::from_integer((*n2).clone()); - Number::Rational(r1 / r2) + Number::Rational(Rc::new(r1 / r2)) }, }, NumberPair::Rational(r1, r2) => - Number::Rational(r1 / r2) + Number::Rational(Rc::new(&*r1 / &*r2)) } } } @@ -672,9 +674,9 @@ impl Neg for Number { fn neg(self) -> Self::Output { match self { - Number::Integer(n) => Number::Integer(-n), + Number::Integer(n) => Number::Integer(Rc::new(-&*n)), Number::Float(f) => Number::Float(OrderedFloat(-1.0 * f.into_inner())), - Number::Rational(r) => Number::Rational(- r) + Number::Rational(r) => Number::Rational(Rc::new(- &*r)) } } } @@ -683,8 +685,7 @@ impl Neg for Number { pub enum ArithmeticTerm { Reg(RegType), Interm(usize), - Float(OrderedFloat), - Integer(BigInt) + Number(Number) } impl ArithmeticTerm { @@ -742,12 +743,12 @@ pub enum ControlInstruction { Allocate(usize), // num_frames. ArgCall, ArgExecute, - Call(Atom, usize, usize), // name, arity, perm_vars after threshold. + Call(Rc, usize, usize), // name, arity, perm_vars after threshold. CallN(usize), // arity. CatchCall, CatchExecute, Deallocate, - Execute(Atom, usize), + Execute(Rc, usize), ExecuteN(usize), FunctorCall, FunctorExecute, @@ -786,7 +787,7 @@ impl ControlInstruction { pub enum IndexingInstruction { SwitchOnTerm(usize, usize, usize, usize), SwitchOnConstant(usize, HashMap), - SwitchOnStructure(usize, HashMap<(Atom, usize), usize>) + SwitchOnStructure(usize, HashMap<(Rc, usize), usize>) } impl From for Line { @@ -798,7 +799,7 @@ impl From for Line { pub enum FactInstruction { GetConstant(Level, Constant, RegType), GetList(Level, RegType), - GetStructure(Level, Atom, usize, RegType), + GetStructure(Level, Rc, usize, RegType), GetValue(RegType, usize), GetVariable(RegType, usize), UnifyConstant(Constant), @@ -812,7 +813,7 @@ pub enum QueryInstruction { GetVariable(RegType, usize), PutConstant(Level, Constant, RegType), PutList(Level, RegType), - PutStructure(Level, Atom, usize, RegType), + PutStructure(Level, Rc, usize, RegType), PutUnsafeValue(usize, usize), PutValue(RegType, usize), PutVariable(RegType, usize), @@ -861,7 +862,7 @@ impl Addr { _ => false } } - + pub fn as_ref(&self) -> Option { match self { &Addr::HeapCell(hc) => Some(Ref::HeapCell(hc)), @@ -897,7 +898,7 @@ pub enum Ref { pub enum HeapCellValue { Con(Constant), Lis(usize), - NamedStr(usize, Atom), + NamedStr(usize, Rc), Ref(Ref), Str(usize) } @@ -1047,10 +1048,10 @@ impl Term { } } - pub fn name(&self) -> Option<&Atom> { + pub fn name(&self) -> Option> { match self { &Term::Constant(_, Constant::Atom(ref atom)) - | &Term::Clause(_, ref atom, _) => Some(atom), + | &Term::Clause(_, ref atom, _) => Some(atom.clone()), _ => None } } diff --git a/src/prolog/builtins.rs b/src/prolog/builtins.rs index 34fa430e..73cac026 100644 --- a/src/prolog/builtins.rs +++ b/src/prolog/builtins.rs @@ -2,8 +2,9 @@ use prolog::ast::*; use prolog::num::bigint::{BigInt}; use std::collections::HashMap; +use std::rc::Rc; -pub type PredicateKey = (Atom, usize); // name, arity, type. +pub type PredicateKey = (Rc, usize); // name, arity, type. #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum PredicateKeyType { @@ -11,7 +12,7 @@ pub enum PredicateKeyType { User } -pub type OpDirKey = (Atom, Fixity); +pub type OpDirKey = (Rc, Fixity); // name and fixity -> operator type and precedence. pub type OpDir = HashMap; @@ -234,7 +235,7 @@ fn get_builtins() -> Code { String::from("type_error"), 1, temp_v!(1)), - set_constant!(Constant::Atom(String::from("integer_expected")))], + set_constant!(Constant::Atom(rc_atom!("integer_expected")))], goto!(59, 1), // goto throw/1. try_me_else!(5), // arg_/3, 173. fact![get_value!(temp_v!(1), 2), @@ -259,7 +260,7 @@ fn get_builtins() -> Code { ArithmeticTerm::Reg(temp_v!(2)), ArithmeticTerm::Reg(perm_v!(4))), add!(ArithmeticTerm::Reg(temp_v!(2)), - ArithmeticTerm::Integer(BigInt::from(1)), + ArithmeticTerm::Number(rc_integer!(1)), 1), query![put_var!(perm_v!(1), 1)], is_call!(perm_v!(1), interm!(1)), @@ -280,67 +281,67 @@ pub fn build_code_dir() -> (Code, CodeDir, OpDir) let builtin_code = get_builtins(); - op_dir.insert((String::from(":-"), Fixity::In), (XFX, 1200)); - op_dir.insert((String::from(":-"), Fixity::Pre), (FX, 1200)); - op_dir.insert((String::from("?-"), Fixity::Pre), (FX, 1200)); + op_dir.insert((rc_atom!(":-"), Fixity::In), (XFX, 1200)); + op_dir.insert((rc_atom!(":-"), Fixity::Pre), (FX, 1200)); + op_dir.insert((rc_atom!("?-"), Fixity::Pre), (FX, 1200)); // control operators. - op_dir.insert((String::from("\\+"), Fixity::Pre), (FY, 900)); - op_dir.insert((String::from("="), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!("\\+"), Fixity::Pre), (FY, 900)); + op_dir.insert((rc_atom!("="), Fixity::In), (XFX, 700)); // arithmetic operators. - op_dir.insert((String::from("is"), Fixity::In), (XFX, 700)); - op_dir.insert((String::from("+"), Fixity::In), (YFX, 500)); - op_dir.insert((String::from("-"), Fixity::In), (YFX, 500)); - op_dir.insert((String::from("/\\"), Fixity::In), (YFX, 500)); - op_dir.insert((String::from("\\/"), Fixity::In), (YFX, 500)); - op_dir.insert((String::from("xor"), Fixity::In), (YFX, 500)); - op_dir.insert((String::from("//"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from("/"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from("div"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from("*"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from("-"), Fixity::Pre), (FY, 200)); - op_dir.insert((String::from("rdiv"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from("<<"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from(">>"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from("mod"), Fixity::In), (YFX, 400)); - op_dir.insert((String::from("rem"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("is"), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!("+"), Fixity::In), (YFX, 500)); + op_dir.insert((rc_atom!("-"), Fixity::In), (YFX, 500)); + op_dir.insert((rc_atom!("/\\"), Fixity::In), (YFX, 500)); + op_dir.insert((rc_atom!("\\/"), Fixity::In), (YFX, 500)); + op_dir.insert((rc_atom!("xor"), Fixity::In), (YFX, 500)); + op_dir.insert((rc_atom!("//"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("/"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("div"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("*"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("-"), Fixity::Pre), (FY, 200)); + op_dir.insert((rc_atom!("rdiv"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("<<"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!(">>"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("mod"), Fixity::In), (YFX, 400)); + op_dir.insert((rc_atom!("rem"), Fixity::In), (YFX, 400)); // arithmetic comparison operators. - op_dir.insert((String::from(">"), Fixity::In), (XFX, 700)); - op_dir.insert((String::from("<"), Fixity::In), (XFX, 700)); - op_dir.insert((String::from("=\\="), Fixity::In), (XFX, 700)); - op_dir.insert((String::from("=:="), Fixity::In), (XFX, 700)); - op_dir.insert((String::from(">="), Fixity::In), (XFX, 700)); - op_dir.insert((String::from("=<"), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!(">"), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!("<"), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!("=\\="), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!("=:="), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!(">="), Fixity::In), (XFX, 700)); + op_dir.insert((rc_atom!("=<"), Fixity::In), (XFX, 700)); // control operators. - op_dir.insert((String::from(";"), Fixity::In), (XFY, 1100)); - op_dir.insert((String::from("->"), Fixity::In), (XFY, 1050)); + op_dir.insert((rc_atom!(";"), Fixity::In), (XFY, 1100)); + op_dir.insert((rc_atom!("->"), Fixity::In), (XFY, 1050)); // there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62 // (an extra register is needed for the predicate name) for arity in 0 .. 63 { - code_dir.insert((String::from("call"), arity), (PredicateKeyType::BuiltIn, 0)); + code_dir.insert((rc_atom!("call"), arity), (PredicateKeyType::BuiltIn, 0)); } - code_dir.insert((String::from("atomic"), 1), (PredicateKeyType::BuiltIn, 1)); - code_dir.insert((String::from("var"), 1), (PredicateKeyType::BuiltIn, 3)); - code_dir.insert((String::from("false"), 0), (PredicateKeyType::BuiltIn, 61)); - code_dir.insert((String::from("\\+"), 1), (PredicateKeyType::BuiltIn, 62)); - code_dir.insert((String::from("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71)); - code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5)); - code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 59)); - code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73)); - code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75)); + code_dir.insert((rc_atom!("atomic"), 1), (PredicateKeyType::BuiltIn, 1)); + code_dir.insert((rc_atom!("var"), 1), (PredicateKeyType::BuiltIn, 3)); + code_dir.insert((rc_atom!("false"), 0), (PredicateKeyType::BuiltIn, 61)); + code_dir.insert((rc_atom!("\\+"), 1), (PredicateKeyType::BuiltIn, 62)); + code_dir.insert((rc_atom!("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71)); + code_dir.insert((rc_atom!("catch"), 3), (PredicateKeyType::BuiltIn, 5)); + code_dir.insert((rc_atom!("throw"), 1), (PredicateKeyType::BuiltIn, 59)); + code_dir.insert((rc_atom!("="), 2), (PredicateKeyType::BuiltIn, 73)); + code_dir.insert((rc_atom!("true"), 0), (PredicateKeyType::BuiltIn, 75)); - code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 76)); - code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 120)); - code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 138)); + code_dir.insert((rc_atom!(","), 2), (PredicateKeyType::BuiltIn, 76)); + code_dir.insert((rc_atom!(";"), 2), (PredicateKeyType::BuiltIn, 120)); + code_dir.insert((rc_atom!("->"), 2), (PredicateKeyType::BuiltIn, 138)); - code_dir.insert((String::from("functor"), 3), (PredicateKeyType::BuiltIn, 146)); - code_dir.insert((String::from("arg"), 3), (PredicateKeyType::BuiltIn, 150)); - code_dir.insert((String::from("integer"), 1), (PredicateKeyType::BuiltIn, 147)); + code_dir.insert((rc_atom!("functor"), 3), (PredicateKeyType::BuiltIn, 146)); + code_dir.insert((rc_atom!("arg"), 3), (PredicateKeyType::BuiltIn, 150)); + code_dir.insert((rc_atom!("integer"), 1), (PredicateKeyType::BuiltIn, 147)); (builtin_code, code_dir, op_dir) } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index d3eeab24..d2d26fcd 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -9,6 +9,7 @@ use prolog::targets::*; use std::cell::Cell; use std::collections::HashMap; use std::mem::swap; +use std::rc::Rc; use std::vec::Vec; pub struct CodeGenerator<'a, TermMarker> { @@ -330,7 +331,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> }, &InlinedQueryTerm::IsInteger(ref inner_term) => match inner_term[0].as_ref() { - &Term::Constant(_, Constant::Integer(_)) => { + &Term::Constant(_, Constant::Number(Number::Integer(_))) => { code.push(succeed!()); }, &Term::Var(ref vr, ref name) => { @@ -404,23 +405,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker> code.push(is_call!(r, at.unwrap_or(interm!(1)))); }, - &Term::Constant(_, Constant::Float(fl)) => { + &Term::Constant(_, ref c @ Constant::Number(_)) => { code.push(query![put_constant!(Level::Shallow, - Constant::Float(fl), - temp_v!(1))]); - code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))); - }, - &Term::Constant(_, Constant::Integer(ref bi)) => { - let bi = bi.clone(); - code.push(query![put_constant!(Level::Shallow, - Constant::Integer(bi), - temp_v!(1))]); - code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))); - }, - &Term::Constant(_, Constant::Rational(ref r)) => { - let r = r.clone(); - code.push(query![put_constant!(Level::Shallow, - Constant::Rational(r), + c.clone(), temp_v!(1))]); code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))); }, diff --git a/src/prolog/indexing.rs b/src/prolog/indexing.rs index 3d94ec02..35b10011 100644 --- a/src/prolog/indexing.rs +++ b/src/prolog/indexing.rs @@ -2,6 +2,7 @@ use prolog::ast::*; use std::collections::{HashMap, VecDeque}; use std::hash::Hash; +use std::rc::Rc; #[derive(Clone, Copy)] enum IntIndex { @@ -11,7 +12,7 @@ enum IntIndex { pub struct CodeOffsets { pub constants: HashMap, pub lists: ThirdLevelIndex, - pub structures: HashMap<(Atom, usize), ThirdLevelIndex> + pub structures: HashMap<(Rc, usize), ThirdLevelIndex> } impl CodeOffsets { @@ -144,7 +145,8 @@ impl CodeOffsets { } } - fn switch_on_structure(str_ind: HashMap<(Atom, usize), ThirdLevelIndex>, prelude: &mut CodeDeque) + fn switch_on_structure(str_ind: HashMap<(Rc, usize), ThirdLevelIndex>, + prelude: &mut CodeDeque) -> IntIndex { let str_ind = Self::second_level_index(str_ind, prelude); diff --git a/src/prolog/io.rs b/src/prolog/io.rs index e1a6915c..2175959f 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -227,8 +227,7 @@ impl fmt::Display for ArithmeticTerm { match self { &ArithmeticTerm::Reg(r) => write!(f, "{}", r), &ArithmeticTerm::Interm(i) => write!(f, "@{}", i), - &ArithmeticTerm::Float(fl) => write!(f, "{}", fl), - &ArithmeticTerm::Integer(ref bi) => write!(f, "{}", bi) + &ArithmeticTerm::Number(ref n) => write!(f, "{}", n), } } } diff --git a/src/prolog/machine.rs b/src/prolog/machine.rs index 35a36276..314bc710 100644 --- a/src/prolog/machine.rs +++ b/src/prolog/machine.rs @@ -8,12 +8,12 @@ use prolog::num::{Integer, ToPrimitive, Zero}; use prolog::num::bigint::{BigInt, BigUint}; use prolog::num::rational::Ratio; use prolog::or_stack::*; -use prolog::ordered_float::OrderedFloat; use prolog::fixtures::*; use std::cmp::max; use std::collections::HashMap; use std::ops::{Index, IndexMut}; +use std::rc::Rc; use std::vec::Vec; #[derive(Clone, Copy)] @@ -226,7 +226,7 @@ impl Machine { self.ms.fail } - fn add_user_code<'a>(&mut self, name: Atom, arity: usize, offset: usize) -> EvalSession<'a> + fn add_user_code<'a>(&mut self, name: Rc, arity: usize, offset: usize) -> EvalSession<'a> { match self.code_dir.get(&(name.clone(), arity)) { Some(&(PredicateKeyType::BuiltIn, _)) => @@ -257,13 +257,11 @@ impl Machine { match &rule.head.0 { &QueryTerm::Term(Term::Clause(_, ref name, _)) | &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => { - let p = self.code.len(); - - let name = name.clone(); + let p = self.code.len(); let arity = rule.head.0.arity(); self.code.append(&mut code); - self.add_user_code(name, arity, p) + self.add_user_code(name.clone(), arity, p) }, _ => EvalSession::NamelessEntry } @@ -446,7 +444,8 @@ impl Machine { } } - pub fn submit_decl<'a>(&mut self, decl: &Declaration) -> EvalSession<'a> { + pub fn submit_decl<'a>(&mut self, decl: &Declaration) -> EvalSession<'a> + { match decl { &Declaration::Op(prec, spec, ref name) => { if is_infix!(spec) { @@ -631,7 +630,7 @@ impl MachineState { hb: 0, block: 0, ball: (0, Vec::new()), - interms: vec![Number::Float(OrderedFloat(0f64)); 256], + interms: vec![Number::default(); 256], } } @@ -814,7 +813,7 @@ impl MachineState { } } - fn write_constant_to_var(&mut self, addr: Addr, c: &Constant) { + fn write_constant_to_var(&mut self, addr: Addr, c: Constant) { let addr = self.deref(addr); match self.store(addr) { @@ -827,7 +826,7 @@ impl MachineState { self.trail(Ref::StackCell(fr, sc)); }, Addr::Con(c1) => { - if c1 != *c { + if c1 != c { self.fail = true; } }, @@ -835,47 +834,40 @@ impl MachineState { }; } - fn get_rational(&self, at: &ArithmeticTerm) -> Result, Vec> { + fn get_number(&self, at: &ArithmeticTerm) -> Result> { + match at { + &ArithmeticTerm::Reg(r) => { + let addr = self[r].clone(); + let item = self.store(self.deref(addr)); + + match item { + Addr::Con(Constant::Number(n)) => Ok(n), + _ => Err(functor!("instantiation_error", 1, [atom!("(is)/2")])) + } + }, + &ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()), + &ArithmeticTerm::Number(ref n) => Ok(n.clone()), + } + } + + fn get_rational(&self, at: &ArithmeticTerm) -> Result>, Vec> { let n = self.get_number(at)?; match n { Number::Rational(r) => Ok(r), Number::Float(fl) => if let Some(r) = Ratio::from_float(fl.into_inner()) { - Ok(r) + Ok(Rc::new(r)) } else { Err(functor!("instantiation_error", 1, [atom!("(is)/2")])) }, Number::Integer(bi) => - Ok(Ratio::from_integer(bi)) + Ok(Rc::new(Ratio::from_integer((*bi).clone()))) } } - fn get_number(&self, at: &ArithmeticTerm) -> Result> { - match at { - &ArithmeticTerm::Reg(r) => { - let addr = self[r].clone(); - let item = self.store(self.deref(addr)); - - match item { - Addr::Con(Constant::Integer(bi)) => - Ok(Number::Integer(bi)), - Addr::Con(Constant::Float(fl)) => - Ok(Number::Float(fl)), - Addr::Con(Constant::Rational(r)) => - Ok(Number::Rational(r)), - _ => - Err(functor!("instantiation_error", 1, [atom!("(is)/2")])) - } - }, - &ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()), - &ArithmeticTerm::Float(fl) => Ok(Number::Float(fl)), - &ArithmeticTerm::Integer(ref bi) => Ok(Number::Integer(bi.clone())) - } - } - - fn signed_bitwise_op(&mut self, n1: BigInt, n2: BigInt, t: usize, f: Op) - where Op: FnOnce(BigUint, BigUint) -> BigUint + fn signed_bitwise_op(&mut self, n1: &BigInt, n2: &BigInt, t: usize, f: Op) + where Op: FnOnce(&BigUint, &BigUint) -> BigUint { let n1_b = n1.to_signed_bytes_le(); let n2_b = n2.to_signed_bytes_le(); @@ -883,9 +875,9 @@ impl MachineState { let u_n1 = BigUint::from_bytes_le(&n1_b); let u_n2 = BigUint::from_bytes_le(&n2_b); - let result = BigInt::from_signed_bytes_le(&f(u_n1, u_n2).to_bytes_le()); + let result = BigInt::from_signed_bytes_le(&f(&u_n1, &u_n2).to_bytes_le()); - self.interms[t - 1] = Number::Integer(result); + self.interms[t - 1] = Number::Integer(Rc::new(result)); } fn execute_arith_instr(&mut self, instr: &ArithmeticInstruction) { @@ -915,14 +907,14 @@ impl MachineState { let r1 = try_or_fail!(self, self.get_rational(a1)); let r2 = try_or_fail!(self, self.get_rational(a2)); - if r2 == Ratio::zero() { + if *r2 == Ratio::zero() { self.throw_exception(functor!("evaluation_error", 1, [atom!("zero_divisor")])); return; } - self.interms[t - 1] = Number::Rational(r1 / r2); + self.interms[t - 1] = Number::Rational(Rc::new(&*r1 / &*r2)); self.p += 1; }, &ArithmeticInstruction::FIDiv(ref a1, ref a2, t) => { @@ -931,14 +923,14 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => { - if n2 == BigInt::zero() { + if *n2 == BigInt::zero() { self.throw_exception(functor!("evaluation_error", 1, [atom!("zero_divisor")])); return; } - self.interms[t - 1] = Number::Integer(n1.div_floor(&n2)); + self.interms[t - 1] = Number::Integer(Rc::new(n1.div_floor(&n2))); self.p += 1; }, _ => { @@ -955,14 +947,14 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => { - if n2 == BigInt::zero() { + if *n2 == BigInt::zero() { self.throw_exception(functor!("evaluation_error", 1, [atom!("zero_divisor")])); return; } - self.interms[t - 1] = Number::Integer(n1 / n2); + self.interms[t - 1] = Number::Integer(Rc::new(&*n1 / &*n2)); self.p += 1; }, _ => { @@ -1000,8 +992,8 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => match n2.to_usize() { - Some(n2) => self.interms[t - 1] = Number::Integer(n1 >> n2), - _ => self.interms[t - 1] = Number::Integer(n1 >> usize::max_value()) + Some(n2) => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 >> n2)), + _ => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 >> usize::max_value())) }, _ => { self.throw_exception(functor!("evaluation_error", @@ -1020,8 +1012,8 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => match n2.to_usize() { - Some(n2) => self.interms[t - 1] = Number::Integer(n1 << n2), - _ => self.interms[t - 1] = Number::Integer(n1 << usize::max_value()) + Some(n2) => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 << n2)), + _ => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 << usize::max_value())) }, _ => { self.throw_exception(functor!("evaluation_error", @@ -1039,7 +1031,7 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => - self.signed_bitwise_op(n1, n2, t, |u_n1, u_n2| u_n1 ^ u_n2), + self.signed_bitwise_op(&*n1, &*n2, t, |u_n1, u_n2| u_n1 ^ u_n2), _ => { self.throw_exception(functor!("evaluation_error", 1, @@ -1056,7 +1048,7 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => - self.signed_bitwise_op(n1, n2, t, |u_n1, u_n2| u_n1 & u_n2), + self.signed_bitwise_op(&*n1, &*n2, t, |u_n1, u_n2| u_n1 & u_n2), _ => { self.throw_exception(functor!("evaluation_error", 1, @@ -1073,7 +1065,7 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => - self.signed_bitwise_op(n1, n2, t, |u_n1, u_n2| u_n1 | u_n2), + self.signed_bitwise_op(&*n1, &*n2, t, |u_n1, u_n2| u_n1 | u_n2), _ => { self.throw_exception(functor!("evaluation_error", 1, @@ -1090,14 +1082,14 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => { - if n2 == BigInt::zero() { + if *n2 == BigInt::zero() { self.throw_exception(functor!("evaluation_error", 1, [atom!("zero_divisor")])); return; } - self.interms[t - 1] = Number::Integer(n1.mod_floor(&n2)); + self.interms[t - 1] = Number::Integer(Rc::new(n1.mod_floor(&n2))); }, _ => { self.throw_exception(functor!("evaluation_error", @@ -1115,14 +1107,14 @@ impl MachineState { match (n1, n2) { (Number::Integer(n1), Number::Integer(n2)) => { - if n2 == BigInt::zero() { + if *n2 == BigInt::zero() { self.throw_exception(functor!("evaluation_error", 1, [atom!("zero_divisor")])); return; } - self.interms[t - 1] = Number::Integer(n1 % n2); + self.interms[t - 1] = Number::Integer(Rc::new(&*n1 % &*n2)); }, _ => { self.throw_exception(functor!("evaluation_error", @@ -1141,7 +1133,7 @@ impl MachineState { match instr { &FactInstruction::GetConstant(_, ref c, reg) => { let addr = self[reg].clone(); - self.write_constant_to_var(addr, c); + self.write_constant_to_var(addr, c.clone()); }, &FactInstruction::GetList(_, reg) => { let addr = self.deref(self[reg].clone()); @@ -1211,7 +1203,7 @@ impl MachineState { match self.mode { MachineMode::Read => { let addr = Addr::HeapCell(self.s); - self.write_constant_to_var(addr, c); + self.write_constant_to_var(addr, c.clone()); }, MachineMode::Write => { self.heap.push(HeapCellValue::Con(c.clone())); @@ -1443,7 +1435,7 @@ impl MachineState { } } - fn try_call_predicate(&mut self, code_dir: &CodeDir, name: Atom, arity: usize) + fn try_call_predicate(&mut self, code_dir: &CodeDir, name: Rc, arity: usize) { let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1); @@ -1458,7 +1450,7 @@ impl MachineState { }; } - fn try_execute_predicate(&mut self, code_dir: &CodeDir, name: Atom, arity: usize) + fn try_execute_predicate(&mut self, code_dir: &CodeDir, name: Rc, arity: usize) { let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1); @@ -1574,7 +1566,7 @@ impl MachineState { { let a1 = self.store(self.deref(self[temp_v!(1)].clone())); - if let Addr::Con(Constant::Integer(i)) = a1 { + if let Addr::Con(Constant::Number(Number::Integer(i))) = a1 { let a2 = self.store(self.deref(self[temp_v!(2)].clone())); if let Addr::Str(o) = a2 { @@ -1645,7 +1637,7 @@ impl MachineState { let c = Constant::Usize(self.block); let addr = self[temp_v!(1)].clone(); - self.write_constant_to_var(addr, &c); + self.write_constant_to_var(addr, c); self.p += 1; }, &BuiltInInstruction::EraseBall => { @@ -1728,7 +1720,7 @@ impl MachineState { let c = Constant::Usize(self.block); let addr = self[temp_v!(1)].clone(); - self.write_constant_to_var(addr, &c); + self.write_constant_to_var(addr, c); self.p += 1; }, &BuiltInInstruction::ResetBlock => { @@ -1760,7 +1752,7 @@ impl MachineState { let d = self.store(self.deref(self[r].clone())); match d { - Addr::Con(Constant::Integer(_)) => self.p += 1, + Addr::Con(Constant::Number(Number::Integer(_))) => self.p += 1, _ => self.fail = true }; }, @@ -1799,7 +1791,7 @@ impl MachineState { match self.heap[o].clone() { HeapCellValue::NamedStr(arity, name) => { let name = Addr::Con(Constant::Atom(name)); // A2 - let arity = Addr::Con(Constant::Integer(BigInt::from(arity))); // A3 + let arity = Addr::Con(Constant::Number(rc_integer!(arity))); let a2 = self[temp_v!(2)].clone(); self.unify(a2, name); @@ -1816,7 +1808,7 @@ impl MachineState { let arity = self.store(self.deref(self[temp_v!(3)].clone())); if let Addr::Con(Constant::Atom(name)) = name { - if let Addr::Con(Constant::Integer(arity)) = arity { + if let Addr::Con(Constant::Number(Number::Integer(arity))) = arity { let f_a = Addr::Str(self.heap.h); let arity = match arity.to_usize() { Some(arity) => arity, @@ -1847,7 +1839,7 @@ impl MachineState { if !self.fail { let a3 = self[temp_v!(3)].clone(); - self.unify(a3, Addr::Con(Constant::Integer(BigInt::from(0)))); + self.unify(a3, Addr::Con(Constant::Number(rc_integer!(0)))); } } }; @@ -1950,14 +1942,14 @@ impl MachineState { let a1 = self[r].clone(); let a2 = try_or_fail!(self, self.get_number(at)); - self.unify(a1, Addr::Con(Constant::from(a2))); + self.unify(a1, Addr::Con(Constant::Number(a2))); self.p += 1; }, &ControlInstruction::IsExecute(r, ref at) => { let a1 = self[r].clone(); let a2 = try_or_fail!(self, self.get_number(at)); - self.unify(a1, Addr::Con(Constant::from(a2))); + self.unify(a1, Addr::Con(Constant::Number(a2))); self.p = self.cp; }, &ControlInstruction::Proceed => diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 0cad85cc..3ac2f46a 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -44,7 +44,7 @@ macro_rules! query { macro_rules! functor { ($name:expr, $len:expr, [$($args:expr),*]) => {{ if $len > 0 { - vec![ HeapCellValue::NamedStr($len, String::from($name)), $($args),* ] + vec![ HeapCellValue::NamedStr($len, Rc::new(String::from($name))), $($args),* ] } else { vec![ atom!($name) ] } @@ -53,7 +53,7 @@ macro_rules! functor { macro_rules! atom { ($name:expr) => ( - HeapCellValue::Con(Constant::Atom(String::from($name))) + HeapCellValue::Con(Constant::Atom(Rc::new(String::from($name)))) ) } @@ -102,7 +102,7 @@ macro_rules! put_var { macro_rules! put_structure { ($lvl:expr, $name:expr, $arity:expr, $r:expr) => ( - QueryInstruction::PutStructure($lvl, $name, $arity, $r) + QueryInstruction::PutStructure($lvl, Rc::new($name), $arity, $r) ) } @@ -318,7 +318,7 @@ macro_rules! get_constant { macro_rules! get_structure { ($atom:expr, $arity:expr, $r:expr) => ( - FactInstruction::GetStructure(Level::Shallow, $atom, $arity, $r) + FactInstruction::GetStructure(Level::Shallow, Rc::new($atom), $arity, $r) ) } @@ -360,7 +360,7 @@ macro_rules! get_cp { macro_rules! integer { ($i:expr) => ( - Constant::Integer(BigInt::from($i)) + Constant::Number(Number::Integer(Rc::new(BigInt::from($i)))) ) } @@ -375,3 +375,15 @@ macro_rules! get_arg { Line::BuiltIn(BuiltInInstruction::GetArg) ) } + +macro_rules! rc_integer { + ($e:expr) => ( + Number::Integer(Rc::new(BigInt::from($e))) + ) +} + +macro_rules! rc_atom { + ($e:expr) => ( + Rc::new(String::from($e)) + ) +} diff --git a/src/prolog/parser b/src/prolog/parser index f51fc401..57001ad9 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit f51fc401fa86fa90136c05e83dee5a5b85e579be +Subproject commit 57001ad9911a4a973fae5cf16e4be1273e3ad55f diff --git a/src/prolog/targets.rs b/src/prolog/targets.rs index fe2974f9..e08d4717 100644 --- a/src/prolog/targets.rs +++ b/src/prolog/targets.rs @@ -1,6 +1,8 @@ use prolog::ast::*; use prolog::iterators::*; +use std::rc::Rc; + pub trait CompilationTarget<'a> { type Iterator : Iterator>; @@ -8,7 +10,7 @@ pub trait CompilationTarget<'a> { fn to_constant(Level, Constant, RegType) -> Self; fn to_list(Level, RegType) -> Self; - fn to_structure(Level, Atom, usize, RegType) -> Self; + fn to_structure(Level, Rc, usize, RegType) -> Self; fn to_void(usize) -> Self; fn is_void_instr(&self) -> bool; @@ -39,7 +41,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction { FactInstruction::GetConstant(lvl, constant, reg) } - fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self { + fn to_structure(lvl: Level, atom: Rc, arity: usize, reg: RegType) -> Self { FactInstruction::GetStructure(lvl, atom, arity, reg) } @@ -101,7 +103,7 @@ impl<'a> CompilationTarget<'a> for QueryInstruction { term.post_order_iter() } - fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self { + fn to_structure(lvl: Level, atom: Rc, arity: usize, reg: RegType) -> Self { QueryInstruction::PutStructure(lvl, atom, arity, reg) } -- 2.54.0