Implemented a different way to index clauses
This commit is contained in:
@@ -857,21 +857,28 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
Ok(code)
|
Ok(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_predicate(clauses: &Vec<PredicateClause>) -> Vec<(usize, usize)> {
|
fn split_predicate(clauses: &Vec<PredicateClause>, optimal_index: Option<usize>) -> Vec<(usize, usize)> {
|
||||||
let mut subseqs = Vec::new();
|
let mut subseqs = Vec::new();
|
||||||
let mut left_index = 0;
|
let mut left_index = 0;
|
||||||
|
|
||||||
for (right_index, clause) in clauses.iter().enumerate() {
|
if let Some(optimal_i) = optimal_index {
|
||||||
match clause.first_arg() {
|
for (right_index, clause) in clauses.iter().enumerate() {
|
||||||
Some(&Term::Var(_, _)) | Some(&Term::AnonVar) => {
|
if clause.args().is_none() {
|
||||||
if left_index < right_index {
|
continue;
|
||||||
subseqs.push((left_index, right_index));
|
}
|
||||||
}
|
if let Some(arg) = clause.args().unwrap().iter().nth(optimal_i) {
|
||||||
|
match **arg {
|
||||||
subseqs.push((right_index, right_index + 1));
|
Term::Var(..) | Term::AnonVar => {
|
||||||
left_index = right_index + 1;
|
if left_index < right_index {
|
||||||
|
subseqs.push((left_index, right_index));
|
||||||
|
}
|
||||||
|
|
||||||
|
subseqs.push((right_index, right_index + 1));
|
||||||
|
left_index = right_index + 1;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,6 +908,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
fn compile_pred_subseq<'b: 'a>(
|
fn compile_pred_subseq<'b: 'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
clauses: &'b [PredicateClause],
|
clauses: &'b [PredicateClause],
|
||||||
|
optimal_index: Option<usize>,
|
||||||
) -> Result<Code, ParserError> {
|
) -> Result<Code, ParserError> {
|
||||||
let mut code_body = Vec::new();
|
let mut code_body = Vec::new();
|
||||||
let mut code_offsets = CodeOffsets::new();
|
let mut code_offsets = CodeOffsets::new();
|
||||||
@@ -910,9 +918,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
for (i, clause) in clauses.iter().enumerate() {
|
for (i, clause) in clauses.iter().enumerate() {
|
||||||
self.marker.reset();
|
self.marker.reset();
|
||||||
|
|
||||||
let mut clause_code = match clause {
|
let mut clause_code = match *clause {
|
||||||
&PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
|
PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
|
||||||
&PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
|
PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
if num_clauses > 1 {
|
if num_clauses > 1 {
|
||||||
@@ -925,17 +933,28 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
code_body.push(Line::Choice(choice));
|
code_body.push(Line::Choice(choice));
|
||||||
}
|
}
|
||||||
|
|
||||||
clause.first_arg().map(|arg| {
|
if let Some(optimal_i) = optimal_index {
|
||||||
let index = code_body.len();
|
let arg = match clause.args() {
|
||||||
code_offsets.index_term(arg, index);
|
Some(args) => match args.iter().nth(optimal_i) {
|
||||||
});
|
Some(term) => Some(term),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
if let Some(arg) = arg {
|
||||||
|
let index = code_body.len();
|
||||||
|
code_offsets.index_term(arg, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
code_body.append(&mut clause_code);
|
code_body.append(&mut clause_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
|
|
||||||
code_offsets.add_indices(&mut code, code_body);
|
if let Some(optimal_i) = optimal_index {
|
||||||
|
code_offsets.add_indices(&mut code, code_body, optimal_i + 1);
|
||||||
|
}
|
||||||
Ok(code)
|
Ok(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -944,11 +963,48 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
|
|||||||
clauses: &'b Vec<PredicateClause>,
|
clauses: &'b Vec<PredicateClause>,
|
||||||
) -> Result<Code, ParserError> {
|
) -> Result<Code, ParserError> {
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
let split_pred = Self::split_predicate(&clauses);
|
let mut optimal_index = None;
|
||||||
|
let has_args = match clauses.first() {
|
||||||
|
Some(clause) => match clause.args() {
|
||||||
|
Some(args) => !args.is_empty(),
|
||||||
|
None => false,
|
||||||
|
},
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
|
if has_args {
|
||||||
|
for clause in clauses.iter() {
|
||||||
|
let args = clause.args().unwrap();
|
||||||
|
for (i, arg) in args.iter().enumerate() {
|
||||||
|
if let Some(optimal_index) = optimal_index {
|
||||||
|
if i >= optimal_index {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match **arg {
|
||||||
|
Term::AnonVar | Term::Var(..) => (),
|
||||||
|
_ => {
|
||||||
|
match optimal_index {
|
||||||
|
Some(ref mut optimal_i) => *optimal_i = i,
|
||||||
|
None => optimal_index = Some(i),
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match optimal_index {
|
||||||
|
// No good index or no argument, default to 0.
|
||||||
|
// TODO: Why?
|
||||||
|
None => optimal_index = Some(0),
|
||||||
|
Some(_) => (),
|
||||||
|
}
|
||||||
|
let split_pred = Self::split_predicate(&clauses, optimal_index);
|
||||||
let multi_seq = split_pred.len() > 1;
|
let multi_seq = split_pred.len() > 1;
|
||||||
|
|
||||||
for (l, r) in split_pred {
|
for (l, r) in split_pred {
|
||||||
let mut code_segment = self.compile_pred_subseq(&clauses[l..r])?;
|
let mut code_segment =
|
||||||
|
self.compile_pred_subseq(&clauses[l..r], optimal_index)?;
|
||||||
|
|
||||||
if multi_seq {
|
if multi_seq {
|
||||||
let choice = match l {
|
let choice = match l {
|
||||||
|
|||||||
13
src/forms.rs
13
src/forms.rs
@@ -339,6 +339,19 @@ impl PredicateClause {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add this to `Term` in `prolog_parser` like `first_arg`.
|
||||||
|
pub fn args(&self) -> Option<&[Box<Term>]> {
|
||||||
|
match *self {
|
||||||
|
PredicateClause::Fact(ref term, ..) => {
|
||||||
|
match term {
|
||||||
|
Term::Clause(_, _, args, _) => Some(&args),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PredicateClause::Rule(ref rule, ..) => Some(&rule.head.1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn arity(&self) -> usize {
|
pub fn arity(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
&PredicateClause::Fact(ref term, ..) => {
|
&PredicateClause::Fact(ref term, ..) => {
|
||||||
|
|||||||
@@ -237,12 +237,17 @@ impl CodeOffsets {
|
|||||||
fn switch_on_constant(
|
fn switch_on_constant(
|
||||||
con_ind: IndexMap<Constant, ThirdLevelIndex>,
|
con_ind: IndexMap<Constant, ThirdLevelIndex>,
|
||||||
prelude: &mut CodeDeque,
|
prelude: &mut CodeDeque,
|
||||||
|
optimal_index: usize,
|
||||||
) -> IntIndex {
|
) -> IntIndex {
|
||||||
let con_ind = Self::second_level_index(con_ind, prelude);
|
let con_ind = Self::second_level_index(con_ind, prelude);
|
||||||
|
|
||||||
if con_ind.len() > 1 {
|
if con_ind.len() > 1 {
|
||||||
let index = Self::flatten_index(con_ind, prelude.len());
|
let index = Self::flatten_index(con_ind, prelude.len());
|
||||||
let instr = IndexingInstruction::SwitchOnConstant(index.len(), index);
|
let instr = IndexingInstruction::SwitchOnConstant(
|
||||||
|
optimal_index,
|
||||||
|
index.len(),
|
||||||
|
index
|
||||||
|
);
|
||||||
|
|
||||||
prelude.push_front(Line::from(instr));
|
prelude.push_front(Line::from(instr));
|
||||||
|
|
||||||
@@ -259,12 +264,17 @@ impl CodeOffsets {
|
|||||||
fn switch_on_structure(
|
fn switch_on_structure(
|
||||||
str_ind: IndexMap<(ClauseName, usize), ThirdLevelIndex>,
|
str_ind: IndexMap<(ClauseName, usize), ThirdLevelIndex>,
|
||||||
prelude: &mut CodeDeque,
|
prelude: &mut CodeDeque,
|
||||||
|
optimal_index: usize,
|
||||||
) -> IntIndex {
|
) -> IntIndex {
|
||||||
let str_ind = Self::second_level_index(str_ind, prelude);
|
let str_ind = Self::second_level_index(str_ind, prelude);
|
||||||
|
|
||||||
if str_ind.len() > 1 {
|
if str_ind.len() > 1 {
|
||||||
let index = Self::flatten_index(str_ind, prelude.len());
|
let index = Self::flatten_index(str_ind, prelude.len());
|
||||||
let instr = IndexingInstruction::SwitchOnStructure(index.len(), index);
|
let instr = IndexingInstruction::SwitchOnStructure(
|
||||||
|
optimal_index,
|
||||||
|
index.len(),
|
||||||
|
index
|
||||||
|
);
|
||||||
|
|
||||||
prelude.push_front(Line::from(instr));
|
prelude.push_front(Line::from(instr));
|
||||||
|
|
||||||
@@ -325,7 +335,7 @@ impl CodeOffsets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_indices(self, code: &mut Code, mut code_body: Code) {
|
pub fn add_indices(self, code: &mut Code, mut code_body: Code, optimal_index: usize) {
|
||||||
if self.no_indices() {
|
if self.no_indices() {
|
||||||
*code = code_body;
|
*code = code_body;
|
||||||
return;
|
return;
|
||||||
@@ -334,8 +344,10 @@ impl CodeOffsets {
|
|||||||
let mut prelude = VecDeque::new();
|
let mut prelude = VecDeque::new();
|
||||||
|
|
||||||
let lst_loc = Self::switch_on_list(self.lists, &mut prelude);
|
let lst_loc = Self::switch_on_list(self.lists, &mut prelude);
|
||||||
let str_loc = Self::switch_on_structure(self.structures, &mut prelude);
|
let str_loc =
|
||||||
let con_loc = Self::switch_on_constant(self.constants, &mut prelude);
|
Self::switch_on_structure(self.structures, &mut prelude, optimal_index);
|
||||||
|
let con_loc =
|
||||||
|
Self::switch_on_constant(self.constants, &mut prelude, optimal_index);
|
||||||
|
|
||||||
let prelude_length = prelude.len();
|
let prelude_length = prelude.len();
|
||||||
|
|
||||||
@@ -355,8 +367,13 @@ impl CodeOffsets {
|
|||||||
let con_loc = Self::switch_on_con_offset_from(con_loc, prelude.len());
|
let con_loc = Self::switch_on_con_offset_from(con_loc, prelude.len());
|
||||||
let lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len());
|
let lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len());
|
||||||
|
|
||||||
let switch_instr =
|
let switch_instr = IndexingInstruction::SwitchOnTerm(
|
||||||
IndexingInstruction::SwitchOnTerm(prelude.len() + 1, con_loc, lst_loc, str_loc);
|
optimal_index,
|
||||||
|
prelude.len() + 1,
|
||||||
|
con_loc,
|
||||||
|
lst_loc,
|
||||||
|
str_loc
|
||||||
|
);
|
||||||
|
|
||||||
prelude.push_front(Line::from(switch_instr));
|
prelude.push_front(Line::from(switch_instr));
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ impl IndexedChoiceInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A `Line` is an instruction (cf. page 98 of wambook).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Line {
|
pub enum Line {
|
||||||
Arithmetic(ArithmeticInstruction),
|
Arithmetic(ArithmeticInstruction),
|
||||||
@@ -424,11 +425,13 @@ impl ControlInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `IndexingInstruction` cf. page 110 of wambook.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum IndexingInstruction {
|
pub enum IndexingInstruction {
|
||||||
SwitchOnTerm(usize, usize, usize, usize),
|
// The first index is the optimal argument being indexed.
|
||||||
SwitchOnConstant(usize, IndexMap<Constant, usize>),
|
SwitchOnTerm(usize, usize, usize, usize, usize),
|
||||||
SwitchOnStructure(usize, IndexMap<(ClauseName, usize), usize>),
|
SwitchOnConstant(usize, usize, IndexMap<Constant, usize>),
|
||||||
|
SwitchOnStructure(usize, usize, IndexMap<(ClauseName, usize), usize>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IndexingInstruction> for Line {
|
impl From<IndexingInstruction> for Line {
|
||||||
@@ -440,25 +443,26 @@ impl From<IndexingInstruction> for Line {
|
|||||||
impl IndexingInstruction {
|
impl IndexingInstruction {
|
||||||
pub fn to_functor(&self) -> MachineStub {
|
pub fn to_functor(&self) -> MachineStub {
|
||||||
match self {
|
match self {
|
||||||
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => {
|
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
|
||||||
functor!(
|
functor!(
|
||||||
"switch_on_term",
|
"switch_on_term",
|
||||||
[integer(vars),
|
[integer(arg),
|
||||||
|
integer(vars),
|
||||||
integer(constants),
|
integer(constants),
|
||||||
integer(lists),
|
integer(lists),
|
||||||
integer(structures)]
|
integer(structures)]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnConstant(constants, _) => {
|
&IndexingInstruction::SwitchOnConstant(arg, constants, _) => {
|
||||||
functor!(
|
functor!(
|
||||||
"switch_on_constant",
|
"switch_on_constant",
|
||||||
[integer(constants)]
|
[integer(arg), integer(constants)]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(structures, _) => {
|
&IndexingInstruction::SwitchOnStructure(arg, structures, _) => {
|
||||||
functor!(
|
functor!(
|
||||||
"switch_on_structure",
|
"switch_on_structure",
|
||||||
[integer(structures)]
|
[integer(arg), integer(structures)]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1392,8 +1392,8 @@ impl MachineState {
|
|||||||
pub(super)
|
pub(super)
|
||||||
fn execute_indexing_instr(&mut self, instr: &IndexingInstruction) {
|
fn execute_indexing_instr(&mut self, instr: &IndexingInstruction) {
|
||||||
match instr {
|
match instr {
|
||||||
&IndexingInstruction::SwitchOnTerm(v, c, l, s) => {
|
&IndexingInstruction::SwitchOnTerm(arg, v, c, l, s) => {
|
||||||
let addr = self[temp_v!(1)];
|
let addr = self[temp_v!(arg)];
|
||||||
let addr = self.store(self.deref(addr));
|
let addr = self.store(self.deref(addr));
|
||||||
|
|
||||||
let offset = match addr {
|
let offset = match addr {
|
||||||
@@ -1423,8 +1423,8 @@ impl MachineState {
|
|||||||
o => self.p += o,
|
o => self.p += o,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnConstant(_, ref hm) => {
|
&IndexingInstruction::SwitchOnConstant(arg, _, ref hm) => {
|
||||||
let addr = self[temp_v!(1)];
|
let addr = self[temp_v!(arg)];
|
||||||
let addr = self.store(self.deref(addr));
|
let addr = self.store(self.deref(addr));
|
||||||
|
|
||||||
let offset =
|
let offset =
|
||||||
@@ -1445,8 +1445,8 @@ impl MachineState {
|
|||||||
o => self.p += o,
|
o => self.p += o,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(_, ref hm) => {
|
&IndexingInstruction::SwitchOnStructure(arg, _, ref hm) => {
|
||||||
let a1 = self.registers[1];
|
let a1 = self.registers[arg];
|
||||||
let addr = self.store(self.deref(a1));
|
let addr = self.store(self.deref(a1));
|
||||||
|
|
||||||
let offset = match addr {
|
let offset = match addr {
|
||||||
|
|||||||
@@ -276,13 +276,13 @@ impl fmt::Display for ChoiceInstruction {
|
|||||||
impl fmt::Display for IndexingInstruction {
|
impl fmt::Display for IndexingInstruction {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&IndexingInstruction::SwitchOnTerm(v, c, l, s) => {
|
&IndexingInstruction::SwitchOnTerm(a, v, c, l, s) => {
|
||||||
write!(f, "switch_on_term {}, {}, {}, {}", v, c, l, s)
|
write!(f, "switch_on_term {}, {}, {}, {}, {}", a, v, c, l, s)
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnConstant(num_cs, _) => {
|
&IndexingInstruction::SwitchOnConstant(_, num_cs, _) => {
|
||||||
write!(f, "switch_on_constant {}", num_cs)
|
write!(f, "switch_on_constant {}", num_cs)
|
||||||
}
|
}
|
||||||
&IndexingInstruction::SwitchOnStructure(num_ss, _) => {
|
&IndexingInstruction::SwitchOnStructure(_, num_ss, _) => {
|
||||||
write!(f, "switch_on_structure {}", num_ss)
|
write!(f, "switch_on_structure {}", num_ss)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user