transition to reference counted constants

This commit is contained in:
Mark Thom
2018-01-09 22:38:17 -07:00
parent 9b225a0a56
commit 848068c734
10 changed files with 215 additions and 220 deletions

View File

@@ -2,6 +2,7 @@ use prolog::ast::*;
use prolog::fixtures::*; use prolog::fixtures::*;
use std::cmp::{min, max}; use std::cmp::{min, max};
use std::rc::Rc;
use std::vec::Vec; use std::vec::Vec;
pub struct ArithExprIterator<'a> { pub struct ArithExprIterator<'a> {
@@ -170,10 +171,8 @@ impl<'a> ArithmeticEvaluator<'a> {
fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> { fn push_constant(&mut self, c: &Constant) -> Result<(), ArithmeticError> {
match c { match c {
&Constant::Float(fl) => &Constant::Number(ref n) =>
self.interm.push(ArithmeticTerm::Float(fl)), self.interm.push(ArithmeticTerm::Number(n.clone())),
&Constant::Integer(ref bi) =>
self.interm.push(ArithmeticTerm::Integer(bi.clone())),
_ => _ =>
return Err(ArithmeticError::InvalidAtom), return Err(ArithmeticError::InvalidAtom),
} }
@@ -202,11 +201,11 @@ impl<'a> ArithmeticEvaluator<'a> {
self.interm.push(ArithmeticTerm::Reg(r)); self.interm.push(ArithmeticTerm::Reg(r));
}, },
TermRef::Clause(ClauseType::Deep(_, _, name), terms) => { 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) => { TermRef::Clause(ClauseType::Root, terms) => {
let name = term.name().unwrap(); 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) return Err(ArithmeticError::InvalidTerm)

View File

@@ -11,6 +11,7 @@ use std::fmt;
use std::io::Error as IOError; use std::io::Error as IOError;
use std::num::{ParseFloatError}; use std::num::{ParseFloatError};
use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, Neg}; use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, Mul, Neg};
use std::rc::Rc;
use std::str::Utf8Error; use std::str::Utf8Error;
use std::vec::Vec; use std::vec::Vec;
@@ -59,7 +60,7 @@ impl PredicateClause {
} }
} }
pub fn name(&self) -> Option<&Atom> { pub fn name(&self) -> Option<Rc<Atom>> {
match self { match self {
&PredicateClause::Fact(ref term) => term.name(), &PredicateClause::Fact(ref term) => term.name(),
&PredicateClause::Rule(ref rule) => &PredicateClause::Rule(ref rule) =>
@@ -73,7 +74,7 @@ impl PredicateClause {
} }
pub enum Declaration { pub enum Declaration {
Op(usize, Specifier, Atom) Op(usize, Specifier, Rc<Atom>)
} }
pub enum TopLevel { pub enum TopLevel {
@@ -266,18 +267,16 @@ pub enum Fixity {
#[derive(Clone, Eq, Hash, PartialEq)] #[derive(Clone, Eq, Hash, PartialEq)]
pub enum Constant { pub enum Constant {
Atom(Atom), Atom(Rc<Atom>),
Float(OrderedFloat<f64>), Number(Number),
Integer(BigInt), String(Rc<String>),
Rational(Ratio<BigInt>),
String(String),
Usize(usize), Usize(usize),
EmptyList EmptyList
} }
impl<'a> From<&'a str> for Constant { impl<'a> From<&'a str> for Constant {
fn from(input: &str) -> 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), write!(f, "{}", atom),
&Constant::EmptyList => &Constant::EmptyList =>
write!(f, "[]"), write!(f, "[]"),
&Constant::Float(fl) => &Constant::Number(ref n) =>
write!(f, "{}", fl), write!(f, "{}", n),
&Constant::Integer(ref i) =>
write!(f, "{}", i),
&Constant::Rational(ref r) =>
write!(f, "{}", r),
&Constant::String(ref s) => &Constant::String(ref s) =>
write!(f, "{}", s), write!(f, "{}", s),
&Constant::Usize(integer) => &Constant::Usize(integer) =>
@@ -302,22 +297,12 @@ impl fmt::Display for Constant {
} }
} }
impl From<Number> 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 { pub enum Term {
AnonVar, AnonVar,
Clause(Cell<RegType>, Atom, Vec<Box<Term>>), Clause(Cell<RegType>, Rc<Atom>, Vec<Box<Term>>),
Cons(Cell<RegType>, Box<Term>, Box<Term>), Cons(Cell<RegType>, Box<Term>, Box<Term>),
Constant(Cell<RegType>, Constant), Constant(Cell<RegType>, Constant),
Var(Cell<VarReg>, Var) Var(Cell<VarReg>, Rc<Var>)
} }
pub enum InlinedQueryTerm { pub enum InlinedQueryTerm {
@@ -385,7 +370,7 @@ pub struct Rule {
pub enum ClauseType<'a> { pub enum ClauseType<'a> {
CallN, CallN,
Catch, Catch,
Deep(Level, &'a Cell<RegType>, &'a Atom), Deep(Level, &'a Cell<RegType>, &'a Rc<Atom>),
Is, Is,
Root, Root,
Throw, Throw,
@@ -456,11 +441,27 @@ impl IndexedChoiceInstruction {
} }
} }
#[derive(Clone)] #[derive(Clone, PartialEq, Eq, Hash)]
pub enum Number { pub enum Number {
Float(OrderedFloat<f64>), Float(OrderedFloat<f64>),
Integer(BigInt), Integer(Rc<BigInt>),
Rational(Ratio<BigInt>) Rational(Rc<Ratio<BigInt>>)
}
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 { impl Number {
@@ -523,8 +524,8 @@ impl Number {
enum NumberPair { enum NumberPair {
Float(OrderedFloat<f64>, OrderedFloat<f64>), Float(OrderedFloat<f64>, OrderedFloat<f64>),
Integer(BigInt, BigInt), Integer(Rc<BigInt>, Rc<BigInt>),
Rational(Ratio<BigInt>, Ratio<BigInt>) Rational(Rc<Ratio<BigInt>>, Rc<Ratio<BigInt>>)
} }
impl NumberPair { impl NumberPair {
@@ -536,11 +537,12 @@ impl NumberPair {
} }
} }
fn integer_float_pair(n1: BigInt, n2: OrderedFloat<f64>) -> NumberPair { fn integer_float_pair(n1: Rc<BigInt>, n2: OrderedFloat<f64>) -> NumberPair {
match n1.to_f64() { match n1.to_f64() {
Some(f1) => NumberPair::Float(OrderedFloat(f1), n2), Some(f1) => NumberPair::Float(OrderedFloat(f1), n2),
None => if let Some(r) = Ratio::from_float(n2.into_inner()) { 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() { } else if n2.into_inner().is_sign_positive() {
NumberPair::Float(OrderedFloat(f64::infinity()), NumberPair::Float(OrderedFloat(f64::infinity()),
OrderedFloat(f64::infinity())) OrderedFloat(f64::infinity()))
@@ -551,12 +553,12 @@ impl NumberPair {
} }
} }
fn float_rational_pair(n1: OrderedFloat<f64>, n2: Ratio<BigInt>) -> NumberPair { fn float_rational_pair(n1: OrderedFloat<f64>, n2: Rc<Ratio<BigInt>>) -> NumberPair {
match (n2.numer().to_f64(), n2.denom().to_f64()) { match (n2.numer().to_f64(), n2.denom().to_f64()) {
(Some(num), Some(denom)) => (Some(num), Some(denom)) =>
NumberPair::Float(n1, OrderedFloat(num / denom)), NumberPair::Float(n1, OrderedFloat(num / denom)),
_ => if let Some(r) = Ratio::from_float(n1.into_inner()) { _ => 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() { } else if n1.into_inner().is_sign_positive() {
NumberPair::Float(OrderedFloat(f64::infinity()), NumberPair::Float(OrderedFloat(f64::infinity()),
OrderedFloat(f64::infinity())) OrderedFloat(f64::infinity()))
@@ -585,9 +587,9 @@ impl NumberPair {
(Number::Rational(n1), Number::Float(n2)) => (Number::Rational(n1), Number::Float(n2)) =>
Self::float_rational_pair(n2, n1).flip(), Self::float_rational_pair(n2, n1).flip(),
(Number::Rational(n1), Number::Integer(n2)) => (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)) => (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<Number> for Number {
NumberPair::Float(f1, f2) => NumberPair::Float(f1, f2) =>
Number::Float(OrderedFloat(f1.into_inner() + f2.into_inner())), Number::Float(OrderedFloat(f1.into_inner() + f2.into_inner())),
NumberPair::Integer(n1, n2) => NumberPair::Integer(n1, n2) =>
Number::Integer(n1 + n2), Number::Integer(Rc::new(&*n1 + &*n2)),
NumberPair::Rational(r1, r2) => NumberPair::Rational(r1, r2) =>
Number::Rational(r1 + r2) Number::Rational(Rc::new(&*r1 + &*r2))
} }
} }
} }
@@ -615,9 +617,9 @@ impl Sub<Number> for Number {
NumberPair::Float(f1, f2) => NumberPair::Float(f1, f2) =>
Number::Float(OrderedFloat(f1.into_inner() - f2.into_inner())), Number::Float(OrderedFloat(f1.into_inner() - f2.into_inner())),
NumberPair::Integer(n1, n2) => NumberPair::Integer(n1, n2) =>
Number::Integer(n1 - n2), Number::Integer(Rc::new(&*n1 - &*n2)),
NumberPair::Rational(r1, r2) => NumberPair::Rational(r1, r2) =>
Number::Rational(r1 - r2) Number::Rational(Rc::new(&*r1 - &*r2))
} }
} }
} }
@@ -630,9 +632,9 @@ impl Mul<Number> for Number {
NumberPair::Float(f1, f2) => NumberPair::Float(f1, f2) =>
Number::Float(OrderedFloat(f1.into_inner() * f2.into_inner())), Number::Float(OrderedFloat(f1.into_inner() * f2.into_inner())),
NumberPair::Integer(n1, n2) => NumberPair::Integer(n1, n2) =>
Number::Integer(n1 * n2), Number::Integer(Rc::new(&*n1 * &*n2)),
NumberPair::Rational(r1, r2) => NumberPair::Rational(r1, r2) =>
Number::Rational(r1 * r2) Number::Rational(Rc::new(&*r1 * &*r2))
} }
} }
} }
@@ -649,20 +651,20 @@ impl Div<Number> for Number {
Some(f1) => if let Some(f2) = n2.to_f64() { Some(f1) => if let Some(f2) = n2.to_f64() {
Number::Float(OrderedFloat(f1 / f2)) Number::Float(OrderedFloat(f1 / f2))
} else { } else {
let r1 = Ratio::from_integer(n1); let r1 = Ratio::from_integer((*n1).clone());
let r2 = Ratio::from_integer(n2); let r2 = Ratio::from_integer((*n2).clone());
Number::Rational(r1 / r2) Number::Rational(Rc::new(r1 / r2))
}, },
None => { None => {
let r1 = Ratio::from_integer(n1); let r1 = Ratio::from_integer((*n1).clone());
let r2 = Ratio::from_integer(n2); let r2 = Ratio::from_integer((*n2).clone());
Number::Rational(r1 / r2) Number::Rational(Rc::new(r1 / r2))
}, },
}, },
NumberPair::Rational(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 { fn neg(self) -> Self::Output {
match self { 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::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 { pub enum ArithmeticTerm {
Reg(RegType), Reg(RegType),
Interm(usize), Interm(usize),
Float(OrderedFloat<f64>), Number(Number)
Integer(BigInt)
} }
impl ArithmeticTerm { impl ArithmeticTerm {
@@ -742,12 +743,12 @@ pub enum ControlInstruction {
Allocate(usize), // num_frames. Allocate(usize), // num_frames.
ArgCall, ArgCall,
ArgExecute, ArgExecute,
Call(Atom, usize, usize), // name, arity, perm_vars after threshold. Call(Rc<Atom>, usize, usize), // name, arity, perm_vars after threshold.
CallN(usize), // arity. CallN(usize), // arity.
CatchCall, CatchCall,
CatchExecute, CatchExecute,
Deallocate, Deallocate,
Execute(Atom, usize), Execute(Rc<Atom>, usize),
ExecuteN(usize), ExecuteN(usize),
FunctorCall, FunctorCall,
FunctorExecute, FunctorExecute,
@@ -786,7 +787,7 @@ impl ControlInstruction {
pub enum IndexingInstruction { pub enum IndexingInstruction {
SwitchOnTerm(usize, usize, usize, usize), SwitchOnTerm(usize, usize, usize, usize),
SwitchOnConstant(usize, HashMap<Constant, usize>), SwitchOnConstant(usize, HashMap<Constant, usize>),
SwitchOnStructure(usize, HashMap<(Atom, usize), usize>) SwitchOnStructure(usize, HashMap<(Rc<Atom>, usize), usize>)
} }
impl From<IndexingInstruction> for Line { impl From<IndexingInstruction> for Line {
@@ -798,7 +799,7 @@ impl From<IndexingInstruction> for Line {
pub enum FactInstruction { pub enum FactInstruction {
GetConstant(Level, Constant, RegType), GetConstant(Level, Constant, RegType),
GetList(Level, RegType), GetList(Level, RegType),
GetStructure(Level, Atom, usize, RegType), GetStructure(Level, Rc<Atom>, usize, RegType),
GetValue(RegType, usize), GetValue(RegType, usize),
GetVariable(RegType, usize), GetVariable(RegType, usize),
UnifyConstant(Constant), UnifyConstant(Constant),
@@ -812,7 +813,7 @@ pub enum QueryInstruction {
GetVariable(RegType, usize), GetVariable(RegType, usize),
PutConstant(Level, Constant, RegType), PutConstant(Level, Constant, RegType),
PutList(Level, RegType), PutList(Level, RegType),
PutStructure(Level, Atom, usize, RegType), PutStructure(Level, Rc<Atom>, usize, RegType),
PutUnsafeValue(usize, usize), PutUnsafeValue(usize, usize),
PutValue(RegType, usize), PutValue(RegType, usize),
PutVariable(RegType, usize), PutVariable(RegType, usize),
@@ -861,7 +862,7 @@ impl Addr {
_ => false _ => false
} }
} }
pub fn as_ref(&self) -> Option<Ref> { pub fn as_ref(&self) -> Option<Ref> {
match self { match self {
&Addr::HeapCell(hc) => Some(Ref::HeapCell(hc)), &Addr::HeapCell(hc) => Some(Ref::HeapCell(hc)),
@@ -897,7 +898,7 @@ pub enum Ref {
pub enum HeapCellValue { pub enum HeapCellValue {
Con(Constant), Con(Constant),
Lis(usize), Lis(usize),
NamedStr(usize, Atom), NamedStr(usize, Rc<Atom>),
Ref(Ref), Ref(Ref),
Str(usize) Str(usize)
} }
@@ -1047,10 +1048,10 @@ impl Term {
} }
} }
pub fn name(&self) -> Option<&Atom> { pub fn name(&self) -> Option<Rc<Atom>> {
match self { match self {
&Term::Constant(_, Constant::Atom(ref atom)) &Term::Constant(_, Constant::Atom(ref atom))
| &Term::Clause(_, ref atom, _) => Some(atom), | &Term::Clause(_, ref atom, _) => Some(atom.clone()),
_ => None _ => None
} }
} }

View File

@@ -2,8 +2,9 @@ use prolog::ast::*;
use prolog::num::bigint::{BigInt}; use prolog::num::bigint::{BigInt};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc;
pub type PredicateKey = (Atom, usize); // name, arity, type. pub type PredicateKey = (Rc<Atom>, usize); // name, arity, type.
#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum PredicateKeyType { pub enum PredicateKeyType {
@@ -11,7 +12,7 @@ pub enum PredicateKeyType {
User User
} }
pub type OpDirKey = (Atom, Fixity); pub type OpDirKey = (Rc<Atom>, Fixity);
// name and fixity -> operator type and precedence. // name and fixity -> operator type and precedence.
pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>; pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
@@ -234,7 +235,7 @@ fn get_builtins() -> Code {
String::from("type_error"), String::from("type_error"),
1, 1,
temp_v!(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. goto!(59, 1), // goto throw/1.
try_me_else!(5), // arg_/3, 173. try_me_else!(5), // arg_/3, 173.
fact![get_value!(temp_v!(1), 2), fact![get_value!(temp_v!(1), 2),
@@ -259,7 +260,7 @@ fn get_builtins() -> Code {
ArithmeticTerm::Reg(temp_v!(2)), ArithmeticTerm::Reg(temp_v!(2)),
ArithmeticTerm::Reg(perm_v!(4))), ArithmeticTerm::Reg(perm_v!(4))),
add!(ArithmeticTerm::Reg(temp_v!(2)), add!(ArithmeticTerm::Reg(temp_v!(2)),
ArithmeticTerm::Integer(BigInt::from(1)), ArithmeticTerm::Number(rc_integer!(1)),
1), 1),
query![put_var!(perm_v!(1), 1)], query![put_var!(perm_v!(1), 1)],
is_call!(perm_v!(1), interm!(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(); let builtin_code = get_builtins();
op_dir.insert((String::from(":-"), Fixity::In), (XFX, 1200)); op_dir.insert((rc_atom!(":-"), Fixity::In), (XFX, 1200));
op_dir.insert((String::from(":-"), Fixity::Pre), (FX, 1200)); op_dir.insert((rc_atom!(":-"), Fixity::Pre), (FX, 1200));
op_dir.insert((String::from("?-"), Fixity::Pre), (FX, 1200)); op_dir.insert((rc_atom!("?-"), Fixity::Pre), (FX, 1200));
// control operators. // control operators.
op_dir.insert((String::from("\\+"), Fixity::Pre), (FY, 900)); op_dir.insert((rc_atom!("\\+"), Fixity::Pre), (FY, 900));
op_dir.insert((String::from("="), Fixity::In), (XFX, 700)); op_dir.insert((rc_atom!("="), Fixity::In), (XFX, 700));
// arithmetic operators. // arithmetic operators.
op_dir.insert((String::from("is"), Fixity::In), (XFX, 700)); op_dir.insert((rc_atom!("is"), Fixity::In), (XFX, 700));
op_dir.insert((String::from("+"), Fixity::In), (YFX, 500)); op_dir.insert((rc_atom!("+"), Fixity::In), (YFX, 500));
op_dir.insert((String::from("-"), Fixity::In), (YFX, 500)); op_dir.insert((rc_atom!("-"), Fixity::In), (YFX, 500));
op_dir.insert((String::from("/\\"), Fixity::In), (YFX, 500)); op_dir.insert((rc_atom!("/\\"), Fixity::In), (YFX, 500));
op_dir.insert((String::from("\\/"), Fixity::In), (YFX, 500)); op_dir.insert((rc_atom!("\\/"), Fixity::In), (YFX, 500));
op_dir.insert((String::from("xor"), Fixity::In), (YFX, 500)); op_dir.insert((rc_atom!("xor"), Fixity::In), (YFX, 500));
op_dir.insert((String::from("//"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("//"), Fixity::In), (YFX, 400));
op_dir.insert((String::from("/"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("/"), Fixity::In), (YFX, 400));
op_dir.insert((String::from("div"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("div"), Fixity::In), (YFX, 400));
op_dir.insert((String::from("*"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("*"), Fixity::In), (YFX, 400));
op_dir.insert((String::from("-"), Fixity::Pre), (FY, 200)); op_dir.insert((rc_atom!("-"), Fixity::Pre), (FY, 200));
op_dir.insert((String::from("rdiv"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("rdiv"), Fixity::In), (YFX, 400));
op_dir.insert((String::from("<<"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("<<"), Fixity::In), (YFX, 400));
op_dir.insert((String::from(">>"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!(">>"), Fixity::In), (YFX, 400));
op_dir.insert((String::from("mod"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("mod"), Fixity::In), (YFX, 400));
op_dir.insert((String::from("rem"), Fixity::In), (YFX, 400)); op_dir.insert((rc_atom!("rem"), Fixity::In), (YFX, 400));
// arithmetic comparison operators. // arithmetic comparison operators.
op_dir.insert((String::from(">"), Fixity::In), (XFX, 700)); op_dir.insert((rc_atom!(">"), 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((String::from("=\\="), Fixity::In), (XFX, 700)); op_dir.insert((rc_atom!("=\\="), 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((String::from(">="), Fixity::In), (XFX, 700)); op_dir.insert((rc_atom!(">="), Fixity::In), (XFX, 700));
op_dir.insert((String::from("=<"), Fixity::In), (XFX, 700)); op_dir.insert((rc_atom!("=<"), Fixity::In), (XFX, 700));
// control operators. // control operators.
op_dir.insert((String::from(";"), Fixity::In), (XFY, 1100)); op_dir.insert((rc_atom!(";"), Fixity::In), (XFY, 1100));
op_dir.insert((String::from("->"), Fixity::In), (XFY, 1050)); 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 // 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) // (an extra register is needed for the predicate name)
for arity in 0 .. 63 { 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((rc_atom!("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
code_dir.insert((String::from("var"), 1), (PredicateKeyType::BuiltIn, 3)); code_dir.insert((rc_atom!("var"), 1), (PredicateKeyType::BuiltIn, 3));
code_dir.insert((String::from("false"), 0), (PredicateKeyType::BuiltIn, 61)); code_dir.insert((rc_atom!("false"), 0), (PredicateKeyType::BuiltIn, 61));
code_dir.insert((String::from("\\+"), 1), (PredicateKeyType::BuiltIn, 62)); code_dir.insert((rc_atom!("\\+"), 1), (PredicateKeyType::BuiltIn, 62));
code_dir.insert((String::from("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71)); code_dir.insert((rc_atom!("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5)); code_dir.insert((rc_atom!("catch"), 3), (PredicateKeyType::BuiltIn, 5));
code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 59)); code_dir.insert((rc_atom!("throw"), 1), (PredicateKeyType::BuiltIn, 59));
code_dir.insert((String::from("="), 2), (PredicateKeyType::BuiltIn, 73)); code_dir.insert((rc_atom!("="), 2), (PredicateKeyType::BuiltIn, 73));
code_dir.insert((String::from("true"), 0), (PredicateKeyType::BuiltIn, 75)); code_dir.insert((rc_atom!("true"), 0), (PredicateKeyType::BuiltIn, 75));
code_dir.insert((String::from(","), 2), (PredicateKeyType::BuiltIn, 76)); code_dir.insert((rc_atom!(","), 2), (PredicateKeyType::BuiltIn, 76));
code_dir.insert((String::from(";"), 2), (PredicateKeyType::BuiltIn, 120)); code_dir.insert((rc_atom!(";"), 2), (PredicateKeyType::BuiltIn, 120));
code_dir.insert((String::from("->"), 2), (PredicateKeyType::BuiltIn, 138)); code_dir.insert((rc_atom!("->"), 2), (PredicateKeyType::BuiltIn, 138));
code_dir.insert((String::from("functor"), 3), (PredicateKeyType::BuiltIn, 146)); code_dir.insert((rc_atom!("functor"), 3), (PredicateKeyType::BuiltIn, 146));
code_dir.insert((String::from("arg"), 3), (PredicateKeyType::BuiltIn, 150)); code_dir.insert((rc_atom!("arg"), 3), (PredicateKeyType::BuiltIn, 150));
code_dir.insert((String::from("integer"), 1), (PredicateKeyType::BuiltIn, 147)); code_dir.insert((rc_atom!("integer"), 1), (PredicateKeyType::BuiltIn, 147));
(builtin_code, code_dir, op_dir) (builtin_code, code_dir, op_dir)
} }

View File

@@ -9,6 +9,7 @@ use prolog::targets::*;
use std::cell::Cell; use std::cell::Cell;
use std::collections::HashMap; use std::collections::HashMap;
use std::mem::swap; use std::mem::swap;
use std::rc::Rc;
use std::vec::Vec; use std::vec::Vec;
pub struct CodeGenerator<'a, TermMarker> { pub struct CodeGenerator<'a, TermMarker> {
@@ -330,7 +331,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
}, },
&InlinedQueryTerm::IsInteger(ref inner_term) => &InlinedQueryTerm::IsInteger(ref inner_term) =>
match inner_term[0].as_ref() { match inner_term[0].as_ref() {
&Term::Constant(_, Constant::Integer(_)) => { &Term::Constant(_, Constant::Number(Number::Integer(_))) => {
code.push(succeed!()); code.push(succeed!());
}, },
&Term::Var(ref vr, ref name) => { &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)))); 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, code.push(query![put_constant!(Level::Shallow,
Constant::Float(fl), c.clone(),
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),
temp_v!(1))]); temp_v!(1))]);
code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1)))); code.push(is_call!(temp_v!(1), at.unwrap_or(interm!(1))));
}, },

View File

@@ -2,6 +2,7 @@ use prolog::ast::*;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::hash::Hash; use std::hash::Hash;
use std::rc::Rc;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum IntIndex { enum IntIndex {
@@ -11,7 +12,7 @@ enum IntIndex {
pub struct CodeOffsets { pub struct CodeOffsets {
pub constants: HashMap<Constant, ThirdLevelIndex>, pub constants: HashMap<Constant, ThirdLevelIndex>,
pub lists: ThirdLevelIndex, pub lists: ThirdLevelIndex,
pub structures: HashMap<(Atom, usize), ThirdLevelIndex> pub structures: HashMap<(Rc<Atom>, usize), ThirdLevelIndex>
} }
impl CodeOffsets { 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<Atom>, usize), ThirdLevelIndex>,
prelude: &mut CodeDeque)
-> IntIndex -> IntIndex
{ {
let str_ind = Self::second_level_index(str_ind, prelude); let str_ind = Self::second_level_index(str_ind, prelude);

View File

@@ -227,8 +227,7 @@ impl fmt::Display for ArithmeticTerm {
match self { match self {
&ArithmeticTerm::Reg(r) => write!(f, "{}", r), &ArithmeticTerm::Reg(r) => write!(f, "{}", r),
&ArithmeticTerm::Interm(i) => write!(f, "@{}", i), &ArithmeticTerm::Interm(i) => write!(f, "@{}", i),
&ArithmeticTerm::Float(fl) => write!(f, "{}", fl), &ArithmeticTerm::Number(ref n) => write!(f, "{}", n),
&ArithmeticTerm::Integer(ref bi) => write!(f, "{}", bi)
} }
} }
} }

View File

@@ -8,12 +8,12 @@ use prolog::num::{Integer, ToPrimitive, Zero};
use prolog::num::bigint::{BigInt, BigUint}; use prolog::num::bigint::{BigInt, BigUint};
use prolog::num::rational::Ratio; use prolog::num::rational::Ratio;
use prolog::or_stack::*; use prolog::or_stack::*;
use prolog::ordered_float::OrderedFloat;
use prolog::fixtures::*; use prolog::fixtures::*;
use std::cmp::max; use std::cmp::max;
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use std::rc::Rc;
use std::vec::Vec; use std::vec::Vec;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@@ -226,7 +226,7 @@ impl Machine {
self.ms.fail 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<Atom>, arity: usize, offset: usize) -> EvalSession<'a>
{ {
match self.code_dir.get(&(name.clone(), arity)) { match self.code_dir.get(&(name.clone(), arity)) {
Some(&(PredicateKeyType::BuiltIn, _)) => Some(&(PredicateKeyType::BuiltIn, _)) =>
@@ -257,13 +257,11 @@ impl Machine {
match &rule.head.0 { match &rule.head.0 {
&QueryTerm::Term(Term::Clause(_, ref name, _)) &QueryTerm::Term(Term::Clause(_, ref name, _))
| &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => { | &QueryTerm::Term(Term::Constant(_, Constant::Atom(ref name))) => {
let p = self.code.len(); let p = self.code.len();
let name = name.clone();
let arity = rule.head.0.arity(); let arity = rule.head.0.arity();
self.code.append(&mut code); self.code.append(&mut code);
self.add_user_code(name, arity, p) self.add_user_code(name.clone(), arity, p)
}, },
_ => EvalSession::NamelessEntry _ => 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 { match decl {
&Declaration::Op(prec, spec, ref name) => { &Declaration::Op(prec, spec, ref name) => {
if is_infix!(spec) { if is_infix!(spec) {
@@ -631,7 +630,7 @@ impl MachineState {
hb: 0, hb: 0,
block: 0, block: 0,
ball: (0, Vec::new()), 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); let addr = self.deref(addr);
match self.store(addr) { match self.store(addr) {
@@ -827,7 +826,7 @@ impl MachineState {
self.trail(Ref::StackCell(fr, sc)); self.trail(Ref::StackCell(fr, sc));
}, },
Addr::Con(c1) => { Addr::Con(c1) => {
if c1 != *c { if c1 != c {
self.fail = true; self.fail = true;
} }
}, },
@@ -835,22 +834,6 @@ impl MachineState {
}; };
} }
fn get_rational(&self, at: &ArithmeticTerm) -> Result<Ratio<BigInt>, Vec<HeapCellValue>> {
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)
} else {
Err(functor!("instantiation_error", 1, [atom!("(is)/2")]))
},
Number::Integer(bi) =>
Ok(Ratio::from_integer(bi))
}
}
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, Vec<HeapCellValue>> { fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, Vec<HeapCellValue>> {
match at { match at {
&ArithmeticTerm::Reg(r) => { &ArithmeticTerm::Reg(r) => {
@@ -858,24 +841,33 @@ impl MachineState {
let item = self.store(self.deref(addr)); let item = self.store(self.deref(addr));
match item { match item {
Addr::Con(Constant::Integer(bi)) => Addr::Con(Constant::Number(n)) => Ok(n),
Ok(Number::Integer(bi)), _ => Err(functor!("instantiation_error", 1, [atom!("(is)/2")]))
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::Interm(i) => Ok(self.interms[i-1].clone()),
&ArithmeticTerm::Float(fl) => Ok(Number::Float(fl)), &ArithmeticTerm::Number(ref n) => Ok(n.clone()),
&ArithmeticTerm::Integer(ref bi) => Ok(Number::Integer(bi.clone()))
} }
} }
fn signed_bitwise_op<Op>(&mut self, n1: BigInt, n2: BigInt, t: usize, f: Op) fn get_rational(&self, at: &ArithmeticTerm) -> Result<Rc<Ratio<BigInt>>, Vec<HeapCellValue>> {
where Op: FnOnce(BigUint, BigUint) -> BigUint 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(Rc::new(r))
} else {
Err(functor!("instantiation_error", 1, [atom!("(is)/2")]))
},
Number::Integer(bi) =>
Ok(Rc::new(Ratio::from_integer((*bi).clone())))
}
}
fn signed_bitwise_op<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 n1_b = n1.to_signed_bytes_le();
let n2_b = n2.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_n1 = BigUint::from_bytes_le(&n1_b);
let u_n2 = BigUint::from_bytes_le(&n2_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) { 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 r1 = try_or_fail!(self, self.get_rational(a1));
let r2 = try_or_fail!(self, self.get_rational(a2)); let r2 = try_or_fail!(self, self.get_rational(a2));
if r2 == Ratio::zero() { if *r2 == Ratio::zero() {
self.throw_exception(functor!("evaluation_error", self.throw_exception(functor!("evaluation_error",
1, 1,
[atom!("zero_divisor")])); [atom!("zero_divisor")]));
return; return;
} }
self.interms[t - 1] = Number::Rational(r1 / r2); self.interms[t - 1] = Number::Rational(Rc::new(&*r1 / &*r2));
self.p += 1; self.p += 1;
}, },
&ArithmeticInstruction::FIDiv(ref a1, ref a2, t) => { &ArithmeticInstruction::FIDiv(ref a1, ref a2, t) => {
@@ -931,14 +923,14 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
if n2 == BigInt::zero() { if *n2 == BigInt::zero() {
self.throw_exception(functor!("evaluation_error", self.throw_exception(functor!("evaluation_error",
1, 1,
[atom!("zero_divisor")])); [atom!("zero_divisor")]));
return; 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; self.p += 1;
}, },
_ => { _ => {
@@ -955,14 +947,14 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
if n2 == BigInt::zero() { if *n2 == BigInt::zero() {
self.throw_exception(functor!("evaluation_error", self.throw_exception(functor!("evaluation_error",
1, 1,
[atom!("zero_divisor")])); [atom!("zero_divisor")]));
return; return;
} }
self.interms[t - 1] = Number::Integer(n1 / n2); self.interms[t - 1] = Number::Integer(Rc::new(&*n1 / &*n2));
self.p += 1; self.p += 1;
}, },
_ => { _ => {
@@ -1000,8 +992,8 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
match n2.to_usize() { match n2.to_usize() {
Some(n2) => self.interms[t - 1] = Number::Integer(n1 >> n2), Some(n2) => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 >> n2)),
_ => self.interms[t - 1] = Number::Integer(n1 >> usize::max_value()) _ => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 >> usize::max_value()))
}, },
_ => { _ => {
self.throw_exception(functor!("evaluation_error", self.throw_exception(functor!("evaluation_error",
@@ -1020,8 +1012,8 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => (Number::Integer(n1), Number::Integer(n2)) =>
match n2.to_usize() { match n2.to_usize() {
Some(n2) => self.interms[t - 1] = Number::Integer(n1 << n2), Some(n2) => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 << n2)),
_ => self.interms[t - 1] = Number::Integer(n1 << usize::max_value()) _ => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 << usize::max_value()))
}, },
_ => { _ => {
self.throw_exception(functor!("evaluation_error", self.throw_exception(functor!("evaluation_error",
@@ -1039,7 +1031,7 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(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", self.throw_exception(functor!("evaluation_error",
1, 1,
@@ -1056,7 +1048,7 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(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", self.throw_exception(functor!("evaluation_error",
1, 1,
@@ -1073,7 +1065,7 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(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", self.throw_exception(functor!("evaluation_error",
1, 1,
@@ -1090,14 +1082,14 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
if n2 == BigInt::zero() { if *n2 == BigInt::zero() {
self.throw_exception(functor!("evaluation_error", self.throw_exception(functor!("evaluation_error",
1, 1,
[atom!("zero_divisor")])); [atom!("zero_divisor")]));
return; 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", self.throw_exception(functor!("evaluation_error",
@@ -1115,14 +1107,14 @@ impl MachineState {
match (n1, n2) { match (n1, n2) {
(Number::Integer(n1), Number::Integer(n2)) => { (Number::Integer(n1), Number::Integer(n2)) => {
if n2 == BigInt::zero() { if *n2 == BigInt::zero() {
self.throw_exception(functor!("evaluation_error", self.throw_exception(functor!("evaluation_error",
1, 1,
[atom!("zero_divisor")])); [atom!("zero_divisor")]));
return; 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", self.throw_exception(functor!("evaluation_error",
@@ -1141,7 +1133,7 @@ impl MachineState {
match instr { match instr {
&FactInstruction::GetConstant(_, ref c, reg) => { &FactInstruction::GetConstant(_, ref c, reg) => {
let addr = self[reg].clone(); let addr = self[reg].clone();
self.write_constant_to_var(addr, c); self.write_constant_to_var(addr, c.clone());
}, },
&FactInstruction::GetList(_, reg) => { &FactInstruction::GetList(_, reg) => {
let addr = self.deref(self[reg].clone()); let addr = self.deref(self[reg].clone());
@@ -1211,7 +1203,7 @@ impl MachineState {
match self.mode { match self.mode {
MachineMode::Read => { MachineMode::Read => {
let addr = Addr::HeapCell(self.s); let addr = Addr::HeapCell(self.s);
self.write_constant_to_var(addr, c); self.write_constant_to_var(addr, c.clone());
}, },
MachineMode::Write => { MachineMode::Write => {
self.heap.push(HeapCellValue::Con(c.clone())); 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<Atom>, arity: usize)
{ {
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1); 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<Atom>, arity: usize)
{ {
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1); 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())); 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())); let a2 = self.store(self.deref(self[temp_v!(2)].clone()));
if let Addr::Str(o) = a2 { if let Addr::Str(o) = a2 {
@@ -1645,7 +1637,7 @@ impl MachineState {
let c = Constant::Usize(self.block); let c = Constant::Usize(self.block);
let addr = self[temp_v!(1)].clone(); let addr = self[temp_v!(1)].clone();
self.write_constant_to_var(addr, &c); self.write_constant_to_var(addr, c);
self.p += 1; self.p += 1;
}, },
&BuiltInInstruction::EraseBall => { &BuiltInInstruction::EraseBall => {
@@ -1728,7 +1720,7 @@ impl MachineState {
let c = Constant::Usize(self.block); let c = Constant::Usize(self.block);
let addr = self[temp_v!(1)].clone(); let addr = self[temp_v!(1)].clone();
self.write_constant_to_var(addr, &c); self.write_constant_to_var(addr, c);
self.p += 1; self.p += 1;
}, },
&BuiltInInstruction::ResetBlock => { &BuiltInInstruction::ResetBlock => {
@@ -1760,7 +1752,7 @@ impl MachineState {
let d = self.store(self.deref(self[r].clone())); let d = self.store(self.deref(self[r].clone()));
match d { match d {
Addr::Con(Constant::Integer(_)) => self.p += 1, Addr::Con(Constant::Number(Number::Integer(_))) => self.p += 1,
_ => self.fail = true _ => self.fail = true
}; };
}, },
@@ -1799,7 +1791,7 @@ impl MachineState {
match self.heap[o].clone() { match self.heap[o].clone() {
HeapCellValue::NamedStr(arity, name) => { HeapCellValue::NamedStr(arity, name) => {
let name = Addr::Con(Constant::Atom(name)); // A2 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(); let a2 = self[temp_v!(2)].clone();
self.unify(a2, name); self.unify(a2, name);
@@ -1816,7 +1808,7 @@ impl MachineState {
let arity = self.store(self.deref(self[temp_v!(3)].clone())); let arity = self.store(self.deref(self[temp_v!(3)].clone()));
if let Addr::Con(Constant::Atom(name)) = name { 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 f_a = Addr::Str(self.heap.h);
let arity = match arity.to_usize() { let arity = match arity.to_usize() {
Some(arity) => arity, Some(arity) => arity,
@@ -1847,7 +1839,7 @@ impl MachineState {
if !self.fail { if !self.fail {
let a3 = self[temp_v!(3)].clone(); 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 a1 = self[r].clone();
let a2 = try_or_fail!(self, self.get_number(at)); 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; self.p += 1;
}, },
&ControlInstruction::IsExecute(r, ref at) => { &ControlInstruction::IsExecute(r, ref at) => {
let a1 = self[r].clone(); let a1 = self[r].clone();
let a2 = try_or_fail!(self, self.get_number(at)); 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; self.p = self.cp;
}, },
&ControlInstruction::Proceed => &ControlInstruction::Proceed =>

View File

@@ -44,7 +44,7 @@ macro_rules! query {
macro_rules! functor { macro_rules! functor {
($name:expr, $len:expr, [$($args:expr),*]) => {{ ($name:expr, $len:expr, [$($args:expr),*]) => {{
if $len > 0 { if $len > 0 {
vec![ HeapCellValue::NamedStr($len, String::from($name)), $($args),* ] vec![ HeapCellValue::NamedStr($len, Rc::new(String::from($name))), $($args),* ]
} else { } else {
vec![ atom!($name) ] vec![ atom!($name) ]
} }
@@ -53,7 +53,7 @@ macro_rules! functor {
macro_rules! atom { macro_rules! atom {
($name:expr) => ( ($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 { macro_rules! put_structure {
($lvl:expr, $name:expr, $arity:expr, $r:expr) => ( ($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 { macro_rules! get_structure {
($atom:expr, $arity:expr, $r:expr) => ( ($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 { macro_rules! integer {
($i:expr) => ( ($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) 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))
)
}

View File

@@ -1,6 +1,8 @@
use prolog::ast::*; use prolog::ast::*;
use prolog::iterators::*; use prolog::iterators::*;
use std::rc::Rc;
pub trait CompilationTarget<'a> { pub trait CompilationTarget<'a> {
type Iterator : Iterator<Item=TermRef<'a>>; type Iterator : Iterator<Item=TermRef<'a>>;
@@ -8,7 +10,7 @@ pub trait CompilationTarget<'a> {
fn to_constant(Level, Constant, RegType) -> Self; fn to_constant(Level, Constant, RegType) -> Self;
fn to_list(Level, RegType) -> Self; fn to_list(Level, RegType) -> Self;
fn to_structure(Level, Atom, usize, RegType) -> Self; fn to_structure(Level, Rc<Atom>, usize, RegType) -> Self;
fn to_void(usize) -> Self; fn to_void(usize) -> Self;
fn is_void_instr(&self) -> bool; fn is_void_instr(&self) -> bool;
@@ -39,7 +41,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
FactInstruction::GetConstant(lvl, constant, reg) FactInstruction::GetConstant(lvl, constant, reg)
} }
fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self { fn to_structure(lvl: Level, atom: Rc<Atom>, arity: usize, reg: RegType) -> Self {
FactInstruction::GetStructure(lvl, atom, arity, reg) FactInstruction::GetStructure(lvl, atom, arity, reg)
} }
@@ -101,7 +103,7 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
term.post_order_iter() term.post_order_iter()
} }
fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self { fn to_structure(lvl: Level, atom: Rc<Atom>, arity: usize, reg: RegType) -> Self {
QueryInstruction::PutStructure(lvl, atom, arity, reg) QueryInstruction::PutStructure(lvl, atom, arity, reg)
} }