introduce bespoke Heap type for in-heap partial strings

This commit is contained in:
Mark Thom
2024-05-13 18:00:56 -06:00
committed by Mark Thom
parent f7bbdfe73a
commit c0f72704ec
54 changed files with 7836 additions and 7167 deletions

View File

@@ -48,7 +48,6 @@ jobs:
# Cargo.toml rust-version # Cargo.toml rust-version
- { os: ubuntu-22.04, rust-version: "1.85", target: 'x86_64-unknown-linux-gnu'} - { os: ubuntu-22.04, rust-version: "1.85", target: 'x86_64-unknown-linux-gnu'}
# rust versions # rust versions
- { os: ubuntu-22.04, rust-version: "1.77", target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-22.04, rust-version: beta, target: 'x86_64-unknown-linux-gnu'} - { os: ubuntu-22.04, rust-version: beta, target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-22.04, rust-version: nightly, target: 'x86_64-unknown-linux-gnu', miri: true, components: "miri"} - { os: ubuntu-22.04, rust-version: nightly, target: 'x86_64-unknown-linux-gnu', miri: true, components: "miri"}
defaults: defaults:

View File

@@ -19,6 +19,7 @@ use to_syn_value_derive::ToDeriveInput;
*/ */
use std::any::*; use std::any::*;
use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
struct ArithmeticTerm; struct ArithmeticTerm;
@@ -28,6 +29,7 @@ struct Death;
struct HeapCellValue; struct HeapCellValue;
struct IndexingLine; struct IndexingLine;
struct Level; struct Level;
// struct Literal;
struct NextOrFail; struct NextOrFail;
struct RegType; struct RegType;
@@ -622,7 +624,7 @@ enum InstructionTemplate {
#[strum_discriminants(strum(props(Arity = "2", Name = "get_list")))] #[strum_discriminants(strum(props(Arity = "2", Name = "get_list")))]
GetList(Level, RegType), GetList(Level, RegType),
#[strum_discriminants(strum(props(Arity = "4", Name = "get_partial_string")))] #[strum_discriminants(strum(props(Arity = "4", Name = "get_partial_string")))]
GetPartialString(Level, Atom, RegType, bool), GetPartialString(Level, Rc<String>, RegType),
#[strum_discriminants(strum(props(Arity = "3", Name = "get_structure")))] #[strum_discriminants(strum(props(Arity = "3", Name = "get_structure")))]
GetStructure(Level, Atom, usize, RegType), GetStructure(Level, Atom, usize, RegType),
#[strum_discriminants(strum(props(Arity = "2", Name = "get_variable")))] #[strum_discriminants(strum(props(Arity = "2", Name = "get_variable")))]
@@ -645,7 +647,7 @@ enum InstructionTemplate {
#[strum_discriminants(strum(props(Arity = "2", Name = "put_list")))] #[strum_discriminants(strum(props(Arity = "2", Name = "put_list")))]
PutList(Level, RegType), PutList(Level, RegType),
#[strum_discriminants(strum(props(Arity = "4", Name = "put_partial_string")))] #[strum_discriminants(strum(props(Arity = "4", Name = "put_partial_string")))]
PutPartialString(Level, Atom, RegType, bool), PutPartialString(Level, Rc<String>, RegType),
#[strum_discriminants(strum(props(Arity = "3", Name = "put_structure")))] #[strum_discriminants(strum(props(Arity = "3", Name = "put_structure")))]
PutStructure(Atom, usize, RegType), PutStructure(Atom, usize, RegType),
#[strum_discriminants(strum(props(Arity = "2", Name = "put_unsafe_value")))] #[strum_discriminants(strum(props(Arity = "2", Name = "put_unsafe_value")))]
@@ -875,6 +877,7 @@ fn generate_instruction_preface() -> TokenStream {
use crate::arithmetic::*; use crate::arithmetic::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::forms::*; use crate::forms::*;
use crate::functor_macro::*;
use crate::machine::heap::*; use crate::machine::heap::*;
use crate::machine::machine_errors::MachineStub; use crate::machine::machine_errors::MachineStub;
use crate::machine::machine_indices::CodeIndex; use crate::machine::machine_indices::CodeIndex;
@@ -885,6 +888,7 @@ fn generate_instruction_preface() -> TokenStream {
use indexmap::IndexMap; use indexmap::IndexMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::rc::Rc;
fn reg_type_into_functor(r: RegType) -> MachineStub { fn reg_type_into_functor(r: RegType) -> MachineStub {
match r { match r {
@@ -896,9 +900,9 @@ fn generate_instruction_preface() -> TokenStream {
impl Level { impl Level {
fn into_functor(self) -> MachineStub { fn into_functor(self) -> MachineStub {
match self { match self {
Level::Root => functor!(atom!("level"), [atom(atom!("root"))]), Level::Root => functor!(atom!("level"), [atom_as_cell((atom!("root")))]),
Level::Shallow => functor!(atom!("level"), [atom(atom!("shallow"))]), Level::Shallow => functor!(atom!("level"), [atom_as_cell((atom!("shallow")))]),
Level::Deep => functor!(atom!("level"), [atom(atom!("deep"))]), Level::Deep => functor!(atom!("level"), [atom_as_cell((atom!("deep")))]),
} }
} }
} }
@@ -911,7 +915,7 @@ fn generate_instruction_preface() -> TokenStream {
functor!(atom!("intermediate"), [fixnum(i)]) functor!(atom!("intermediate"), [fixnum(i)])
} }
ArithmeticTerm::Number(n) => { ArithmeticTerm::Number(n) => {
functor!(atom!("number"), [cell(HeapCellValue::from((n, arena)))]) functor!(atom!("number"), [number(n, arena)])
} }
} }
} }
@@ -996,7 +1000,7 @@ fn generate_instruction_preface() -> TokenStream {
IndexingCodePtr, IndexingCodePtr,
IndexingCodePtr, IndexingCodePtr,
), ),
SwitchOnConstant(IndexMap<Literal, IndexingCodePtr, FxBuildHasher>), SwitchOnConstant(IndexMap<HeapCellValue, IndexingCodePtr, FxBuildHasher>),
SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr, FxBuildHasher>), SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr, FxBuildHasher>),
} }
@@ -1016,7 +1020,7 @@ fn generate_instruction_preface() -> TokenStream {
IndexingCodePtr::External(o) => functor!(atom!("external"), [fixnum(o)]), IndexingCodePtr::External(o) => functor!(atom!("external"), [fixnum(o)]),
IndexingCodePtr::Internal(o) => functor!(atom!("internal"), [fixnum(o)]), IndexingCodePtr::Internal(o) => functor!(atom!("internal"), [fixnum(o)]),
IndexingCodePtr::Fail => { IndexingCodePtr::Fail => {
vec![atom_as_cell!(atom!("fail"))] functor!(atom!("fail"))
}, },
} }
} }
@@ -1030,80 +1034,43 @@ fn generate_instruction_preface() -> TokenStream {
} }
impl IndexingInstruction { impl IndexingInstruction {
pub fn to_functor(&self, mut h: usize) -> MachineStub { pub fn to_functor(&self) -> MachineStub {
match self { match self {
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => { &IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
functor!( functor!(
atom!("switch_on_term"), atom!("switch_on_term"),
[ [
fixnum(arg), fixnum(arg),
indexing_code_ptr(h, vars), indexing_code_ptr(vars),
indexing_code_ptr(h, constants), indexing_code_ptr(constants),
indexing_code_ptr(h, lists), indexing_code_ptr(lists),
indexing_code_ptr(h, structures) indexing_code_ptr(structures)
] ]
) )
} }
IndexingInstruction::SwitchOnConstant(constants) => { IndexingInstruction::SwitchOnConstant(constants) => {
let mut key_value_list_stub = vec![]; variadic_functor(
let orig_h = h; atom!("switch_on_constants"),
1,
h += 2; // skip the 2-cell "switch_on_constant" functor. constants.iter().map(|(c, ptr)| {
functor!(
for (c, ptr) in constants.iter() { atom!(":"),
let key_value_pair = functor!( [cell((c.clone())), indexing_code_ptr((*ptr))]
atom!(":"), )
[literal(*c), indexing_code_ptr(h + 3, *ptr)] }),
);
key_value_list_stub.push(list_loc_as_cell!(h + 1));
key_value_list_stub.push(str_loc_as_cell!(h + 3));
key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
h += key_value_pair.len() + 3;
key_value_list_stub.extend(key_value_pair.into_iter());
}
key_value_list_stub.push(empty_list_as_cell!());
functor!(
atom!("switch_on_constant"),
[str(orig_h, 0)],
[key_value_list_stub]
) )
} }
IndexingInstruction::SwitchOnStructure(structures) => { IndexingInstruction::SwitchOnStructure(structures) => {
let mut key_value_list_stub = vec![]; variadic_functor(
let orig_h = h;
h += 2; // skip the 2-cell "switch_on_constant" functor.
for ((name, arity), ptr) in structures.iter() {
let predicate_indicator_stub = functor!(
atom!("/"),
[atom(name), fixnum(*arity)]
);
let key_value_pair = functor!(
atom!(":"),
[str(h + 3, 0), indexing_code_ptr(h + 3, *ptr)],
[predicate_indicator_stub]
);
key_value_list_stub.push(list_loc_as_cell!(h + 1));
key_value_list_stub.push(str_loc_as_cell!(h + 3));
key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
h += key_value_pair.len() + 3;
key_value_list_stub.extend(key_value_pair.into_iter());
}
key_value_list_stub.push(empty_list_as_cell!());
functor!(
atom!("switch_on_structure"), atom!("switch_on_structure"),
[str(orig_h, 0)], 1,
[key_value_list_stub] structures.iter().map(|((name, arity), ptr)| {
functor!(
atom!(":"),
[functor((atom!("/")), [atom_as_cell(name), fixnum((*arity))]),
indexing_code_ptr((*ptr))]
)
}),
) )
} }
} }
@@ -1133,18 +1100,16 @@ fn generate_instruction_preface() -> TokenStream {
} }
fn arith_instr_unary_functor( fn arith_instr_unary_functor(
h: usize,
name: Atom, name: Atom,
arena: &mut Arena, arena: &mut Arena,
at: &ArithmeticTerm, at: &ArithmeticTerm,
t: usize, t: usize,
) -> MachineStub { ) -> MachineStub {
let at_stub = at.into_functor(arena); let at_stub = at.into_functor(arena);
functor!(name, [str(h, 0), fixnum(t)], [at_stub]) functor!(name, [functor(at_stub), fixnum(t)])
} }
fn arith_instr_bin_functor( fn arith_instr_bin_functor(
h: usize,
name: Atom, name: Atom,
arena: &mut Arena, arena: &mut Arena,
at_1: &ArithmeticTerm, at_1: &ArithmeticTerm,
@@ -1154,11 +1119,9 @@ fn generate_instruction_preface() -> TokenStream {
let at_1_stub = at_1.into_functor(arena); let at_1_stub = at_1.into_functor(arena);
let at_2_stub = at_2.into_functor(arena); let at_2_stub = at_2.into_functor(arena);
functor!( functor!(name, [functor(at_1_stub),
name, functor(at_2_stub),
[str(h, 0), str(h, 1), fixnum(t)], fixnum(t)])
[at_1_stub, at_2_stub]
)
} }
pub type Code = Vec<Instruction>; pub type Code = Vec<Instruction>;
@@ -1170,7 +1133,7 @@ fn generate_instruction_preface() -> TokenStream {
match *self { match *self {
Instruction::GetConstant(_, _, r) => vec![r], Instruction::GetConstant(_, _, r) => vec![r],
Instruction::GetList(_, r) => vec![r], Instruction::GetList(_, r) => vec![r],
Instruction::GetPartialString(_, _, r, _) => vec![r], Instruction::GetPartialString(_, _, r) => vec![r],
Instruction::GetStructure(_, _, _, r) => vec![r], Instruction::GetStructure(_, _, _, r) => vec![r],
Instruction::GetVariable(r, t) => vec![r, temp_v!(t)], Instruction::GetVariable(r, t) => vec![r, temp_v!(t)],
Instruction::GetValue(r, t) => vec![r, temp_v!(t)], Instruction::GetValue(r, t) => vec![r, temp_v!(t)],
@@ -1178,7 +1141,7 @@ fn generate_instruction_preface() -> TokenStream {
Instruction::UnifyVariable(r) => vec![r], Instruction::UnifyVariable(r) => vec![r],
Instruction::PutConstant(_, _, r) => vec![r], Instruction::PutConstant(_, _, r) => vec![r],
Instruction::PutList(_, r) => vec![r], Instruction::PutList(_, r) => vec![r],
Instruction::PutPartialString(_, _, r, _) => vec![r], Instruction::PutPartialString(_, _, r) => vec![r],
Instruction::PutStructure(_, _, r) => vec![r], Instruction::PutStructure(_, _, r) => vec![r],
Instruction::PutValue(r, t) => vec![r, temp_v!(t)], Instruction::PutValue(r, t) => vec![r, temp_v!(t)],
Instruction::PutVariable(r, t) => vec![r, temp_v!(t)], Instruction::PutVariable(r, t) => vec![r, temp_v!(t)],
@@ -1242,7 +1205,6 @@ fn generate_instruction_preface() -> TokenStream {
pub fn enqueue_functors( pub fn enqueue_functors(
&self, &self,
mut h: usize,
arena: &mut Arena, arena: &mut Arena,
functors: &mut Vec<MachineStub>, functors: &mut Vec<MachineStub>,
) { ) {
@@ -1251,33 +1213,30 @@ fn generate_instruction_preface() -> TokenStream {
for indexing_instr in indexing_instrs { for indexing_instr in indexing_instrs {
match indexing_instr { match indexing_instr {
IndexingLine::Indexing(indexing_instr) => { IndexingLine::Indexing(indexing_instr) => {
let section = indexing_instr.to_functor(h); let section = indexing_instr.to_functor();
h += section.len();
functors.push(section); functors.push(section);
} }
IndexingLine::IndexedChoice(indexed_choice_instrs) => { IndexingLine::IndexedChoice(indexed_choice_instrs) => {
for indexed_choice_instr in indexed_choice_instrs { for indexed_choice_instr in indexed_choice_instrs {
let section = indexed_choice_instr.to_functor(); let section = indexed_choice_instr.to_functor();
h += section.len();
functors.push(section); functors.push(section);
} }
} }
IndexingLine::DynamicIndexedChoice(indexed_choice_instrs) => { IndexingLine::DynamicIndexedChoice(indexed_choice_instrs) => {
for indexed_choice_instr in indexed_choice_instrs { for indexed_choice_instr in indexed_choice_instrs {
let section = functor!(atom!("dynamic"), [fixnum(*indexed_choice_instr)]); let section = functor!(atom!("dynamic"),
[fixnum((*indexed_choice_instr))]);
h += section.len();
functors.push(section); functors.push(section);
} }
} }
} }
} }
} }
instr => functors.push(instr.to_functor(h, arena)), instr => functors.push(instr.to_functor(arena)),
} }
} }
fn to_functor(&self, h: usize, arena: &mut Arena) -> MachineStub { fn to_functor(&self, arena: &mut Arena) -> MachineStub {
match self { match self {
&Instruction::InstallVerifyAttr => { &Instruction::InstallVerifyAttr => {
functor!(atom!("install_verify_attr")) functor!(atom!("install_verify_attr"))
@@ -1290,25 +1249,23 @@ fn generate_instruction_preface() -> TokenStream {
(Death::Infinity, NextOrFail::Next(i)) => { (Death::Infinity, NextOrFail::Next(i)) => {
functor!( functor!(
atom!("dynamic_else"), atom!("dynamic_else"),
[fixnum(birth), atom(atom!("inf")), fixnum(i)] [fixnum(birth), atom_as_cell((atom!("inf"))), fixnum(i)]
) )
} }
(Death::Infinity, NextOrFail::Fail(i)) => { (Death::Infinity, NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!( functor!(
atom!("dynamic_else"), atom!("dynamic_else"),
[fixnum(birth), atom(atom!("inf")), str(h, 0)], [fixnum(birth),
[next_functor] atom_as_cell((atom!("inf"))),
functor((atom!("fail")), [fixnum(i)])]
) )
} }
(Death::Finite(d), NextOrFail::Fail(i)) => { (Death::Finite(d), NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!( functor!(
atom!("dynamic_else"), atom!("dynamic_else"),
[fixnum(birth), fixnum(d), str(h, 0)], [fixnum(birth),
[next_functor] fixnum(d),
functor((atom!("fail")), [fixnum(i)])]
) )
} }
(Death::Finite(d), NextOrFail::Next(i)) => { (Death::Finite(d), NextOrFail::Next(i)) => {
@@ -1321,25 +1278,23 @@ fn generate_instruction_preface() -> TokenStream {
(Death::Infinity, NextOrFail::Next(i)) => { (Death::Infinity, NextOrFail::Next(i)) => {
functor!( functor!(
atom!("dynamic_internal_else"), atom!("dynamic_internal_else"),
[fixnum(birth), atom(atom!("inf")), fixnum(i)] [fixnum(birth), atom_as_cell((atom!("inf"))), fixnum(i)]
) )
} }
(Death::Infinity, NextOrFail::Fail(i)) => { (Death::Infinity, NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!( functor!(
atom!("dynamic_internal_else"), atom!("dynamic_internal_else"),
[fixnum(birth), atom(atom!("inf")), str(h, 0)], [fixnum(birth),
[next_functor] atom_as_cell((atom!("inf"))),
functor((atom!("fail")), [fixnum(i)])]
) )
} }
(Death::Finite(d), NextOrFail::Fail(i)) => { (Death::Finite(d), NextOrFail::Fail(i)) => {
let next_functor = functor!(atom!("fail"), [fixnum(i)]);
functor!( functor!(
atom!("dynamic_internal_else"), atom!("dynamic_internal_else"),
[fixnum(birth), fixnum(d), str(h, 0)], [fixnum(birth),
[next_functor] fixnum(d),
functor((atom!("fail")), [fixnum(i)])]
) )
} }
(Death::Finite(d), NextOrFail::Next(i)) => { (Death::Finite(d), NextOrFail::Next(i)) => {
@@ -1367,157 +1322,154 @@ fn generate_instruction_preface() -> TokenStream {
} }
&Instruction::Cut(r) => { &Instruction::Cut(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("cut"), [str(h, 0)], [rt_stub]) functor!(atom!("cut"), [functor(rt_stub)])
} }
&Instruction::CutPrev(r) => { &Instruction::CutPrev(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("cut_prev"), [str(h, 0)], [rt_stub]) functor!(atom!("cut_prev"), [functor(rt_stub)])
} }
&Instruction::GetLevel(r) => { &Instruction::GetLevel(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_level"), [str(h, 0)], [rt_stub]) functor!(atom!("get_level"), [functor(rt_stub)])
} }
&Instruction::GetPrevLevel(r) => { &Instruction::GetPrevLevel(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_prev_level"), [str(h, 0)], [rt_stub]) functor!(atom!("get_prev_level"), [functor(rt_stub)])
} }
&Instruction::GetCutPoint(r) => { &Instruction::GetCutPoint(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_cut_point"), [str(h, 0)], [rt_stub]) functor!(atom!("get_cut_point"), [functor(rt_stub)])
} }
&Instruction::NeckCut => { &Instruction::NeckCut => {
functor!(atom!("neck_cut")) functor!(atom!("neck_cut"))
} }
&Instruction::Add(ref at_1, ref at_2, t) => { &Instruction::Add(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("add"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("add"), arena, at_1, at_2, t)
} }
&Instruction::Sub(ref at_1, ref at_2, t) => { &Instruction::Sub(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("sub"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("sub"), arena, at_1, at_2, t)
} }
&Instruction::Mul(ref at_1, ref at_2, t) => { &Instruction::Mul(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("mul"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("mul"), arena, at_1, at_2, t)
} }
&Instruction::IntPow(ref at_1, ref at_2, t) => { &Instruction::IntPow(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("int_pow"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("int_pow"), arena, at_1, at_2, t)
} }
&Instruction::Pow(ref at_1, ref at_2, t) => { &Instruction::Pow(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("pow"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("pow"), arena, at_1, at_2, t)
} }
&Instruction::IDiv(ref at_1, ref at_2, t) => { &Instruction::IDiv(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("idiv"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("idiv"), arena, at_1, at_2, t)
} }
&Instruction::Max(ref at_1, ref at_2, t) => { &Instruction::Max(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("max"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("max"), arena, at_1, at_2, t)
} }
&Instruction::Min(ref at_1, ref at_2, t) => { &Instruction::Min(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("min"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("min"), arena, at_1, at_2, t)
} }
&Instruction::IntFloorDiv(ref at_1, ref at_2, t) => { &Instruction::IntFloorDiv(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("int_floor_div"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("int_floor_div"), arena, at_1, at_2, t)
} }
&Instruction::RDiv(ref at_1, ref at_2, t) => { &Instruction::RDiv(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("rdiv"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("rdiv"), arena, at_1, at_2, t)
} }
&Instruction::Div(ref at_1, ref at_2, t) => { &Instruction::Div(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("div"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("div"), arena, at_1, at_2, t)
} }
&Instruction::Shl(ref at_1, ref at_2, t) => { &Instruction::Shl(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("shl"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("shl"), arena, at_1, at_2, t)
} }
&Instruction::Shr(ref at_1, ref at_2, t) => { &Instruction::Shr(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("shr"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("shr"), arena, at_1, at_2, t)
} }
&Instruction::Xor(ref at_1, ref at_2, t) => { &Instruction::Xor(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("xor"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("xor"), arena, at_1, at_2, t)
} }
&Instruction::And(ref at_1, ref at_2, t) => { &Instruction::And(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("and"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("and"), arena, at_1, at_2, t)
} }
&Instruction::Or(ref at_1, ref at_2, t) => { &Instruction::Or(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("or"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("or"), arena, at_1, at_2, t)
} }
&Instruction::Mod(ref at_1, ref at_2, t) => { &Instruction::Mod(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("mod"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("mod"), arena, at_1, at_2, t)
} }
&Instruction::Rem(ref at_1, ref at_2, t) => { &Instruction::Rem(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("rem"), arena, at_1, at_2, t)
} }
&Instruction::ATan2(ref at_1, ref at_2, t) => { &Instruction::ATan2(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("rem"), arena, at_1, at_2, t)
} }
&Instruction::Gcd(ref at_1, ref at_2, t) => { &Instruction::Gcd(ref at_1, ref at_2, t) => {
arith_instr_bin_functor(h, atom!("gcd"), arena, at_1, at_2, t) arith_instr_bin_functor(atom!("gcd"), arena, at_1, at_2, t)
} }
&Instruction::Sign(ref at, t) => { &Instruction::Sign(ref at, t) => {
arith_instr_unary_functor(h, atom!("sign"), arena, at, t) arith_instr_unary_functor(atom!("sign"), arena, at, t)
} }
&Instruction::Cos(ref at, t) => { &Instruction::Cos(ref at, t) => {
arith_instr_unary_functor(h, atom!("cos"), arena, at, t) arith_instr_unary_functor(atom!("cos"), arena, at, t)
} }
&Instruction::Sin(ref at, t) => { &Instruction::Sin(ref at, t) => {
arith_instr_unary_functor(h, atom!("sin"), arena, at, t) arith_instr_unary_functor(atom!("sin"), arena, at, t)
} }
&Instruction::Tan(ref at, t) => { &Instruction::Tan(ref at, t) => {
arith_instr_unary_functor(h, atom!("tan"), arena, at, t) arith_instr_unary_functor(atom!("tan"), arena, at, t)
} }
&Instruction::Log(ref at, t) => { &Instruction::Log(ref at, t) => {
arith_instr_unary_functor(h, atom!("log"), arena, at, t) arith_instr_unary_functor(atom!("log"), arena, at, t)
} }
&Instruction::Exp(ref at, t) => { &Instruction::Exp(ref at, t) => {
arith_instr_unary_functor(h, atom!("exp"), arena, at, t) arith_instr_unary_functor(atom!("exp"), arena, at, t)
} }
&Instruction::ACos(ref at, t) => { &Instruction::ACos(ref at, t) => {
arith_instr_unary_functor(h, atom!("acos"), arena, at, t) arith_instr_unary_functor(atom!("acos"), arena, at, t)
} }
&Instruction::ASin(ref at, t) => { &Instruction::ASin(ref at, t) => {
arith_instr_unary_functor(h, atom!("asin"), arena, at, t) arith_instr_unary_functor(atom!("asin"), arena, at, t)
} }
&Instruction::ATan(ref at, t) => { &Instruction::ATan(ref at, t) => {
arith_instr_unary_functor(h, atom!("atan"), arena, at, t) arith_instr_unary_functor(atom!("atan"), arena, at, t)
} }
&Instruction::Sqrt(ref at, t) => { &Instruction::Sqrt(ref at, t) => {
arith_instr_unary_functor(h, atom!("sqrt"), arena, at, t) arith_instr_unary_functor(atom!("sqrt"), arena, at, t)
} }
&Instruction::Abs(ref at, t) => { &Instruction::Abs(ref at, t) => {
arith_instr_unary_functor(h, atom!("abs"), arena, at, t) arith_instr_unary_functor(atom!("abs"), arena, at, t)
} }
&Instruction::Float(ref at, t) => { &Instruction::Float(ref at, t) => {
arith_instr_unary_functor(h, atom!("float"), arena, at, t) arith_instr_unary_functor(atom!("float"), arena, at, t)
} }
&Instruction::Truncate(ref at, t) => { &Instruction::Truncate(ref at, t) => {
arith_instr_unary_functor(h, atom!("truncate"), arena, at, t) arith_instr_unary_functor(atom!("truncate"), arena, at, t)
} }
&Instruction::Round(ref at, t) => { &Instruction::Round(ref at, t) => {
arith_instr_unary_functor(h, atom!("round"), arena, at, t) arith_instr_unary_functor(atom!("round"), arena, at, t)
} }
&Instruction::Ceiling(ref at, t) => { &Instruction::Ceiling(ref at, t) => {
arith_instr_unary_functor(h, atom!("ceiling"), arena, at, t) arith_instr_unary_functor(atom!("ceiling"), arena, at, t)
} }
&Instruction::Floor(ref at, t) => { &Instruction::Floor(ref at, t) => {
arith_instr_unary_functor(h, atom!("floor"), arena, at, t) arith_instr_unary_functor(atom!("floor"), arena, at, t)
} }
&Instruction::FloatFractionalPart(ref at, t) => { &Instruction::FloatFractionalPart(ref at, t) => {
arith_instr_unary_functor(h, atom!("float_fractional_part"), arena, at, t) arith_instr_unary_functor(atom!("float_fractional_part"), arena, at, t)
} }
&Instruction::FloatIntegerPart(ref at, t) => { &Instruction::FloatIntegerPart(ref at, t) => {
arith_instr_unary_functor(h, atom!("float_integer_part"), arena, at, t) arith_instr_unary_functor(atom!("float_integer_part"), arena, at, t)
} }
&Instruction::Neg(ref at, t) => arith_instr_unary_functor( &Instruction::Neg(ref at, t) => arith_instr_unary_functor(
h,
atom!("-"), atom!("-"),
arena, arena,
at, at,
t, t,
), ),
&Instruction::Plus(ref at, t) => arith_instr_unary_functor( &Instruction::Plus(ref at, t) => arith_instr_unary_functor(
h,
atom!("+"), atom!("+"),
arena, arena,
at, at,
t, t,
), ),
&Instruction::BitwiseComplement(ref at, t) => arith_instr_unary_functor( &Instruction::BitwiseComplement(ref at, t) => arith_instr_unary_functor(
h,
atom!("\\"), atom!("\\"),
arena, arena,
at, at,
@@ -1533,16 +1485,16 @@ fn generate_instruction_preface() -> TokenStream {
functor!(atom!("allocate"), [fixnum(num_frames)]) functor!(atom!("allocate"), [fixnum(num_frames)])
} }
&Instruction::CallNamed(arity, name, ..) => { &Instruction::CallNamed(arity, name, ..) => {
functor!(atom!("call"), [atom(name), fixnum(arity)]) functor!(atom!("call"), [atom_as_cell(name), fixnum(arity)])
} }
&Instruction::ExecuteNamed(arity, name, ..) => { &Instruction::ExecuteNamed(arity, name, ..) => {
functor!(atom!("execute"), [atom(name), fixnum(arity)]) functor!(atom!("execute"), [atom_as_cell(name), fixnum(arity)])
} }
&Instruction::DefaultCallNamed(arity, name, ..) => { &Instruction::DefaultCallNamed(arity, name, ..) => {
functor!(atom!("call_default"), [atom(name), fixnum(arity)]) functor!(atom!("call_default"), [atom_as_cell(name), fixnum(arity)])
} }
&Instruction::DefaultExecuteNamed(arity, name, ..) => { &Instruction::DefaultExecuteNamed(arity, name, ..) => {
functor!(atom!("execute_default"), [atom(name), fixnum(arity)]) functor!(atom!("execute_default"), [atom_as_cell(name), fixnum(arity)])
} }
&Instruction::CallN(arity) => { &Instruction::CallN(arity) => {
functor!(atom!("call_n"), [fixnum(arity)]) functor!(atom!("call_n"), [fixnum(arity)])
@@ -1585,7 +1537,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallSort | &Instruction::CallSort |
&Instruction::CallGetNumber(_) => { &Instruction::CallGetNumber(_) => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("call"), [atom(name), fixnum(arity)]) functor!(atom!("call"), [atom_as_cell(name), fixnum(arity)])
} }
// //
&Instruction::ExecuteTermGreaterThan | &Instruction::ExecuteTermGreaterThan |
@@ -1611,7 +1563,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteSort | &Instruction::ExecuteSort |
&Instruction::ExecuteGetNumber(_) => { &Instruction::ExecuteGetNumber(_) => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("execute"), [atom(name), fixnum(arity)]) functor!(atom!("execute"), [atom_as_cell(name), fixnum(arity)])
} }
// //
&Instruction::DefaultCallTermGreaterThan | &Instruction::DefaultCallTermGreaterThan |
@@ -1637,7 +1589,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::DefaultCallSort | &Instruction::DefaultCallSort |
&Instruction::DefaultCallGetNumber(_) => { &Instruction::DefaultCallGetNumber(_) => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("call_default"), [atom(name), fixnum(arity)]) functor!(atom!("call_default"), [atom_as_cell(name), fixnum(arity)])
} }
// //
&Instruction::DefaultExecuteTermGreaterThan | &Instruction::DefaultExecuteTermGreaterThan |
@@ -1663,7 +1615,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::DefaultExecuteSort | &Instruction::DefaultExecuteSort |
&Instruction::DefaultExecuteGetNumber(_) => { &Instruction::DefaultExecuteGetNumber(_) => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("execute_default"), [atom(name), fixnum(arity)]) functor!(atom!("execute_default"), [atom_as_cell(name), fixnum(arity)])
} }
&Instruction::CallIsAtom(r) | &Instruction::CallIsAtom(r) |
&Instruction::CallIsAtomic(r) | &Instruction::CallIsAtomic(r) |
@@ -1676,7 +1628,8 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallIsVar(r) => { &Instruction::CallIsVar(r) => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("call"), [atom(name), fixnum(arity), str(h, 0)], [rt_stub])
functor!(atom!("call"), [atom_as_cell(name), fixnum(arity), functor(rt_stub)])
} }
&Instruction::ExecuteIsAtom(r) | &Instruction::ExecuteIsAtom(r) |
&Instruction::ExecuteIsAtomic(r) | &Instruction::ExecuteIsAtomic(r) |
@@ -1689,7 +1642,8 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteIsVar(r) => { &Instruction::ExecuteIsVar(r) => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("execute"), [atom(name), fixnum(arity), str(h, 0)], [rt_stub])
functor!(atom!("execute"), [atom_as_cell(name), fixnum(arity), functor(rt_stub)])
} }
// //
&Instruction::CallAtomChars | &Instruction::CallAtomChars |
@@ -1920,14 +1874,14 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallEd25519VerifyRaw | &Instruction::CallEd25519VerifyRaw |
&Instruction::CallEd25519SeedToPublicKey => { &Instruction::CallEd25519SeedToPublicKey => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("call"), [atom(name), fixnum(arity)]) functor!(atom!("call"), [atom_as_cell(name), fixnum(arity)])
} }
// //
#[cfg(feature = "crypto-full")] #[cfg(feature = "crypto-full")]
&Instruction::CallCryptoDataEncrypt | &Instruction::CallCryptoDataEncrypt |
&Instruction::CallCryptoDataDecrypt => { &Instruction::CallCryptoDataDecrypt => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("call"), [atom(name), fixnum(arity)]) functor!(atom!("call"), [atom_as_cell(name), fixnum(arity)])
} }
// //
&Instruction::ExecuteAtomChars | &Instruction::ExecuteAtomChars |
@@ -2158,14 +2112,14 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteEd25519VerifyRaw | &Instruction::ExecuteEd25519VerifyRaw |
&Instruction::ExecuteEd25519SeedToPublicKey => { &Instruction::ExecuteEd25519SeedToPublicKey => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("execute"), [atom(name), fixnum(arity)]) functor!(atom!("execute"), [atom_as_cell(name), fixnum(arity)])
} }
// //
#[cfg(feature = "crypto-full")] #[cfg(feature = "crypto-full")]
&Instruction::ExecuteCryptoDataEncrypt | &Instruction::ExecuteCryptoDataEncrypt |
&Instruction::ExecuteCryptoDataDecrypt => { &Instruction::ExecuteCryptoDataDecrypt => {
let (name, arity) = self.to_name_and_arity(); let (name, arity) = self.to_name_and_arity();
functor!(atom!("execute"), [atom(name), fixnum(arity)]) functor!(atom!("execute"), [atom_as_cell(name), fixnum(arity)])
} }
// //
&Instruction::Deallocate => { &Instruction::Deallocate => {
@@ -2180,73 +2134,60 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::Proceed => { &Instruction::Proceed => {
functor!(atom!("proceed")) functor!(atom!("proceed"))
} }
&Instruction::GetConstant(lvl, c, r) => { &Instruction::GetConstant(lvl, lit, r) => {
let lvl_stub = lvl.into_functor(); let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("get_constant"), [functor(lvl_stub),
atom!("get_constant"), cell(lit),
[str(h, 0), cell(c), str(h, 1)], functor(rt_stub)])
[lvl_stub, rt_stub]
)
} }
&Instruction::GetList(lvl, r) => { &Instruction::GetList(lvl, r) => {
let lvl_stub = lvl.into_functor(); let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("get_list"), [functor(lvl_stub), functor(rt_stub)])
atom!("get_list"),
[str(h, 0), str(h, 1)],
[lvl_stub, rt_stub]
)
} }
&Instruction::GetPartialString(lvl, s, r, has_tail) => { &Instruction::GetPartialString(lvl, ref s, r) => {
let lvl_stub = lvl.into_functor(); let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("get_partial_string"), [functor(lvl_stub),
atom!("get_partial_string"), string((s.to_string())),
[ functor(rt_stub)])
str(h, 0),
string(h, s),
str(h, 1),
boolean(has_tail)
],
[lvl_stub, rt_stub]
)
} }
&Instruction::GetStructure(lvl, name, arity, r) => { &Instruction::GetStructure(lvl, name, arity, r) => {
let lvl_stub = lvl.into_functor(); let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("get_structure"), [functor(lvl_stub),
atom!("get_structure"), atom_as_cell(name),
[str(h, 0), atom(name), fixnum(arity), str(h, 1)], fixnum(arity),
[lvl_stub, rt_stub] functor(rt_stub)])
)
} }
&Instruction::GetValue(r, arg) => { &Instruction::GetValue(r, arg) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_value"), [str(h, 0), fixnum(arg)], [rt_stub]) functor!(atom!("get_value"), [functor(rt_stub),
fixnum(arg)])
} }
&Instruction::GetVariable(r, arg) => { &Instruction::GetVariable(r, arg) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("get_variable"), [str(h, 0), fixnum(arg)], [rt_stub]) functor!(atom!("get_variable"), [functor(rt_stub), fixnum(arg)])
} }
&Instruction::UnifyConstant(c) => { &Instruction::UnifyConstant(c) => {
functor!(atom!("unify_constant"), [cell(c)]) functor!(atom!("unify_constant"), [cell(c)])
} }
&Instruction::UnifyLocalValue(r) => { &Instruction::UnifyLocalValue(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("unify_local_value"), [str(h, 0)], [rt_stub]) functor!(atom!("unify_local_value"), [functor(rt_stub)])
} }
&Instruction::UnifyVariable(r) => { &Instruction::UnifyVariable(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("unify_variable"), [str(h, 0)], [rt_stub]) functor!(atom!("unify_variable"), [functor(rt_stub)])
} }
&Instruction::UnifyValue(r) => { &Instruction::UnifyValue(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("unify_value"), [str(h, 0)], [rt_stub]) functor!(atom!("unify_value"), [functor(rt_stub)])
} }
&Instruction::UnifyVoid(vars) => { &Instruction::UnifyVoid(vars) => {
functor!(atom!("unify_void"), [fixnum(vars)]) functor!(atom!("unify_void"), [fixnum(vars)])
@@ -2258,68 +2199,55 @@ fn generate_instruction_preface() -> TokenStream {
let lvl_stub = lvl.into_functor(); let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("put_constant"), [functor(rt_stub), cell(c), functor(lvl_stub)])
atom!("put_constant"),
[str(h, 0), cell(c), str(h, 1)],
[lvl_stub, rt_stub]
)
} }
&Instruction::PutList(lvl, r) => { &Instruction::PutList(lvl, r) => {
let lvl_stub = lvl.into_functor(); let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("put_list"), [functor(lvl_stub), functor(rt_stub)])
atom!("put_list"),
[str(h, 0), str(h, 1)],
[lvl_stub, rt_stub]
)
} }
&Instruction::PutPartialString(lvl, s, r, has_tail) => { &Instruction::PutPartialString(lvl, ref s, r) => {
let lvl_stub = lvl.into_functor(); let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("put_partial_string"), [functor(lvl_stub),
atom!("put_partial_string"), string((s.to_string())),
[ functor(rt_stub)])
str(h, 0),
string(h, s),
str(h, 1),
boolean(has_tail)
],
[lvl_stub, rt_stub]
)
} }
&Instruction::PutStructure(name, arity, r) => { &Instruction::PutStructure(name, arity, r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!( functor!(atom!("put_structure"), [atom_as_cell(name),
atom!("put_structure"), fixnum(arity),
[atom(name), fixnum(arity), str(h, 0)], functor(rt_stub)])
[rt_stub]
)
} }
&Instruction::PutValue(r, arg) => { &Instruction::PutValue(r, arg) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("put_value"), [str(h, 0), fixnum(arg)], [rt_stub])
functor!(atom!("put_value"), [functor(rt_stub),
fixnum(arg)])
} }
&Instruction::PutVariable(r, arg) => { &Instruction::PutVariable(r, arg) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("put_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
functor!(atom!("put_variable"), [functor(rt_stub),
fixnum(arg)])
} }
&Instruction::SetConstant(c) => { &Instruction::SetConstant(c) => {
functor!(atom!("set_constant"), [cell(c)]) functor!(atom!("set_constant"), [cell(c)])
} }
&Instruction::SetLocalValue(r) => { &Instruction::SetLocalValue(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("set_local_value"), [str(h, 0)], [rt_stub]) functor!(atom!("set_local_value"), [functor(rt_stub)])
} }
&Instruction::SetVariable(r) => { &Instruction::SetVariable(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("set_variable"), [str(h, 0)], [rt_stub]) functor!(atom!("set_variable"), [functor(rt_stub)])
} }
&Instruction::SetValue(r) => { &Instruction::SetValue(r) => {
let rt_stub = reg_type_into_functor(r); let rt_stub = reg_type_into_functor(r);
functor!(atom!("set_value"), [str(h, 0)], [rt_stub]) functor!(atom!("set_value"), [functor(rt_stub)])
} }
&Instruction::SetVoid(vars) => { &Instruction::SetVoid(vars) => {
functor!(atom!("set_void"), [fixnum(vars)]) functor!(atom!("set_void"), [fixnum(vars)])
@@ -3204,14 +3132,6 @@ pub fn generate_instructions_rs() -> TokenStream {
) )
} }
pub fn name(&self) -> Atom {
match self {
#(
#clause_type_name_arms,
)*
}
}
pub fn is_inlined(name: Atom, arity: usize) -> bool { pub fn is_inlined(name: Atom, arity: usize) -> bool {
matches!((name, arity), matches!((name, arity),
#(#is_inlined_arms)|* #(#is_inlined_arms)|*

View File

@@ -84,6 +84,18 @@ impl<'ast> Visit<'ast> for StaticStrVisitor {
} }
} }
const INLINED_ATOM_MAX_LEN: usize = 6;
fn static_string_index(string: &str, index: usize) -> u64 {
if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN {
let mut string_buf: [u8; 8] = [0u8; 8];
string_buf[.. string.len()].copy_from_slice(string.as_bytes());
(u64::from_le_bytes(string_buf) << 1) | 1
} else {
(index << 1) as u64
}
}
pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStream { pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStream {
use quote::*; use quote::*;
@@ -149,11 +161,26 @@ pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStrea
visitor.visit_file(&syntax) visitor.visit_file(&syntax)
} }
let indices = (0..visitor.static_strs.len()).map(|i| (i << 3) as u64); let mut static_str_keys = vec![];
let indices_iter = indices.clone(); let mut static_strs = vec![];
let mut static_str_indices = vec![];
let static_strs_len = visitor.static_strs.len(); let indices: Vec<u64> = visitor.static_strs.iter().map(|string| {
let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect(); let index = static_string_index(string, static_strs.len());
static_str_keys.push(string);
if index & 1 == 1 {
index
} else {
static_str_indices.push(index);
static_strs.push(string);
index
}
}).collect();
let static_strs_len = static_strs.len(); // visitor.static_strs.len();
//let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
quote! { quote! {
static STRINGS: [&str; #static_strs_len] = [ static STRINGS: [&str; #static_strs_len] = [
@@ -163,11 +190,11 @@ pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStrea
]; ];
macro_rules! atom { macro_rules! atom {
#((#static_strs) => { Atom { index: #indices_iter } };)* #((#static_str_keys) => { Atom { index: #indices } };)*
} }
pub static STATIC_ATOMS_MAP: phf::Map<&'static str, Atom> = phf::phf_map! { pub static STATIC_ATOMS_MAP: phf::Map<&'static str, Atom> = phf::phf_map! {
#(#static_strs => { Atom { index: #indices } },)* #(#static_strs => { Atom { index: #static_str_indices } },)*
}; };
} }
} }

View File

@@ -2,6 +2,7 @@ use crate::parser::ast::*;
use crate::forms::*; use crate::forms::*;
use crate::instructions::*; use crate::instructions::*;
use crate::machine::heap::Heap;
use crate::targets::*; use crate::targets::*;
pub(crate) trait Allocator { pub(crate) trait Allocator {
@@ -45,7 +46,7 @@ pub(crate) trait Allocator {
fn reset(&mut self); fn reset(&mut self);
fn reset_arg(&mut self, arg_num: usize); fn reset_arg(&mut self, arg_num: usize);
fn reset_at_head(&mut self, term: &mut FocusedHeap, head_loc: usize); fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize);
fn reset_contents(&mut self); fn reset_contents(&mut self);
fn advance_arg(&mut self); fn advance_arg(&mut self);

View File

@@ -909,7 +909,7 @@ mod tests {
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::machine::mock_wam::*; use crate::machine::mock_wam::*;
use crate::machine::partial_string::*; use crate::types::*;
use crate::parser::dashu::{Integer, Rational}; use crate::parser::dashu::{Integer, Rational};
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
@@ -992,7 +992,7 @@ mod tests {
assert!(!big_int_ptr.as_ptr().is_null()); assert!(!big_int_ptr.as_ptr().is_null());
let cell = HeapCellValue::from(Literal::Integer(big_int_ptr)); let cell = HeapCellValue::from(big_int_ptr);
assert_eq!(cell.get_tag(), HeapCellValueTag::Cons); assert_eq!(cell.get_tag(), HeapCellValueTag::Cons);
let untyped_arena_ptr = match cell.to_untyped_arena_ptr() { let untyped_arena_ptr = match cell.to_untyped_arena_ptr() {
@@ -1098,31 +1098,6 @@ mod tests {
_ => { unreachable!() } _ => { unreachable!() }
); );
// complete string
let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "ronan", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
assert_eq!(pstr_cell.get_tag(), HeapCellValueTag::PStr);
match pstr_cell.to_pstr() {
Some(pstr) => {
assert_eq!(&*pstr.as_str_from(0), "ronan");
}
None => {
unreachable!();
}
}
read_heap_cell!(pstr_cell,
(HeapCellValueTag::PStr, pstr_atom) => {
let pstr = PartialString::from(pstr_atom);
assert_eq!(&*pstr.as_str_from(0), "ronan");
}
_ => { unreachable!() }
);
// fixnum // fixnum
let fixnum_cell = fixnum_as_cell!(Fixnum::build_with(3)); let fixnum_cell = fixnum_as_cell!(Fixnum::build_with(3));
@@ -1200,8 +1175,8 @@ mod tests {
let char_cell = char_as_cell!(c); let char_cell = char_as_cell!(c);
read_heap_cell!(char_cell, read_heap_cell!(char_cell,
(HeapCellValueTag::Char, c) => { (HeapCellValueTag::Atom, (c, _arity)) => {
assert_eq!(c, 'c'); assert_eq!(&*c.as_str(), "c");
} }
_ => { unreachable!() } _ => { unreachable!() }
); );
@@ -1210,8 +1185,8 @@ mod tests {
let cyrillic_char_cell = char_as_cell!(c); let cyrillic_char_cell = char_as_cell!(c);
read_heap_cell!(cyrillic_char_cell, read_heap_cell!(cyrillic_char_cell,
(HeapCellValueTag::Char, c) => { (HeapCellValueTag::Atom, (c, _arity)) => {
assert_eq!(c, 'Ћ'); assert_eq!(&*c.as_str(), "Ћ");
} }
_ => { unreachable!() } _ => { unreachable!() }
); );

View File

@@ -9,7 +9,6 @@ use crate::instructions::*;
use crate::iterators::*; use crate::iterators::*;
use crate::machine::disjuncts::*; use crate::machine::disjuncts::*;
use crate::machine::stack::Stack; use crate::machine::stack::Stack;
use crate::parser::ast::FocusedHeap;
use crate::targets::QueryInstruction; use crate::targets::QueryInstruction;
use crate::types::*; use crate::types::*;
@@ -55,103 +54,6 @@ impl Default for ArithmeticTerm {
pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>); pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>);
/*
#[derive(Debug)]
pub(crate) struct ArithInstructionIterator<'a> {
state_stack: Vec<TermIterState<'a>>,
}
impl<'a> ArithInstructionIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack
.push(TermIterState::subterm_to_state(lvl, term));
}
fn from(term: &'a Term) -> Result<Self, ArithmeticError> {
let state = match term {
Term::AnonVar => return Err(ArithmeticError::UninstantiatedVar),
Term::Clause(cell, name, terms) => {
TermIterState::Clause(Level::Shallow, 0, cell, *name, terms)
}
Term::Literal(cell, cons) => TermIterState::Literal(Level::Shallow, cell, cons),
Term::Cons(..) | Term::PartialString(..) | Term::CompleteString(..) => {
return Err(ArithmeticError::NonEvaluableFunctor(
Literal::Atom(atom!(".")),
2,
))
}
Term::Var(cell, var_ptr) => TermIterState::Var(Level::Shallow, cell, var_ptr.clone()),
};
Ok(ArithInstructionIterator {
state_stack: vec![state],
})
}
}
#[derive(Debug)]
pub(crate) enum ArithTermRef<'a> {
Literal(&'a Literal),
Op(Atom, usize), // name, arity.
Var(Level, &'a Cell<VarReg>, VarPtr),
}
impl<'a> Iterator for ArithInstructionIterator<'a> {
type Item = Result<ArithTermRef<'a>, ArithmeticError>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(iter_state) = self.state_stack.pop() {
match iter_state {
TermIterState::AnonVar(_) => return Some(Err(ArithmeticError::UninstantiatedVar)),
TermIterState::Clause(lvl, child_num, cell, name, subterms) => {
let arity = subterms.len();
if child_num == arity {
return Some(Ok(ArithTermRef::Op(name, arity)));
} else {
self.state_stack.push(TermIterState::Clause(
lvl,
child_num + 1,
cell,
name,
subterms,
));
self.push_subterm(lvl.child_level(), &subterms[child_num]);
}
}
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
TermIterState::Var(lvl, cell, var_ptr) => {
return Some(Ok(ArithTermRef::Var(lvl, cell, var_ptr)));
}
_ => {
return Some(Err(ArithmeticError::NonEvaluableFunctor(
Literal::Atom(atom!(".")),
2,
)));
}
};
}
None
}
}
pub(crate) trait ArithmeticTermIter<'a> {
type Iter: Iterator<Item = Result<ArithTermRef<'a>, ArithmeticError>>;
fn iter(self) -> Result<Self::Iter, ArithmeticError>;
}
impl<'a> ArithmeticTermIter<'a> for &'a Term {
type Iter = ArithInstructionIterator<'a>;
fn iter(self) -> Result<Self::Iter, ArithmeticError> {
ArithInstructionIterator::from(self)
}
}
*/
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct ArithmeticEvaluator<'a> { pub(crate) struct ArithmeticEvaluator<'a> {
marker: &'a mut DebrayAllocator, marker: &'a mut DebrayAllocator,
@@ -159,23 +61,45 @@ pub(crate) struct ArithmeticEvaluator<'a> {
interm_c: usize, interm_c: usize,
} }
fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: Literal) -> Result<(), ArithmeticError> { fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: HeapCellValue) -> Result<(), ArithmeticError> {
match c { read_heap_cell!(c,
Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(n))), (HeapCellValueTag::Fixnum, n) => {
Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(n))), interm.push(ArithmeticTerm::Number(Number::Fixnum(n)))
Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))), }
Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(n))), (HeapCellValueTag::Cons, cons_ptr) => {
Literal::Atom(name) if name == atom!("e") => interm.push(ArithmeticTerm::Number( match_untyped_arena_ptr!(cons_ptr,
Number::Float(OrderedFloat(std::f64::consts::E)), (ArenaHeaderTag::Integer, n) => {
)), interm.push(ArithmeticTerm::Number(Number::Integer(n)));
Literal::Atom(name) if name == atom!("pi") => interm.push(ArithmeticTerm::Number( }
Number::Float(OrderedFloat(std::f64::consts::PI)), (ArenaHeaderTag::Rational, n) => {
)), interm.push(ArithmeticTerm::Number(Number::Rational(n)));
Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number( }
Number::Float(OrderedFloat(f64::EPSILON)), _ => return Err(ArithmeticError::NonEvaluableFunctor(c, 0)),
)), );
_ => return Err(ArithmeticError::NonEvaluableFunctor(HeapCellValue::from(c), 0)), }
} (HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
match name {
atom!("pi") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::PI)),
)),
atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::EPSILON)),
)),
atom!("e") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::E)),
)),
_ => unreachable!(),
}
}
(HeapCellValueTag::F64, n) => {
interm.push(ArithmeticTerm::Number(Number::Float(*n)));
}
_ => {
return Err(ArithmeticError::NonEvaluableFunctor(c, 0));
}
);
Ok(()) Ok(())
} }
@@ -313,7 +237,7 @@ impl<'a> ArithmeticEvaluator<'a> {
pub(crate) fn compile_is( pub(crate) fn compile_is(
&mut self, &mut self,
src: &mut FocusedHeap, src: &mut FocusedHeapRefMut,
term_loc: usize, term_loc: usize,
context: GenContext, context: GenContext,
arg: usize, arg: usize,
@@ -360,16 +284,13 @@ impl<'a> ArithmeticEvaluator<'a> {
} }
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 { if arity == 0 {
push_literal(&mut self.interm, Literal::Atom(name))?; push_literal(&mut self.interm, atom_as_cell!(name))?;
} else { } else {
code.push_back(self.instr_from_clause(name, arity)?); code.push_back(self.instr_from_clause(name, arity)?);
} }
} }
_ => { _ => {
match Literal::try_from(term) { push_literal(&mut self.interm, term)?;
Ok(lit) => push_literal(&mut self.interm, lit)?,
_ => return Err(ArithmeticError::NonEvaluableFunctor(term, 0)),
}
} }
); );
} }

View File

@@ -23,15 +23,117 @@ use indexmap::IndexSet;
use scryer_modular_bitfield::prelude::*; use scryer_modular_bitfield::prelude::*;
#[bitfield]
#[repr(u64)]
#[derive(Copy, Clone, Debug)]
pub struct AtomCell {
name: B48,
arity: B8,
#[allow(unused)]
f: bool,
#[allow(unused)]
m: bool,
#[allow(unused)]
is_inlined: bool,
#[allow(unused)]
tag: B5,
}
const INLINED_ATOM_MAX_LEN: usize = 6;
const_assert!(INLINED_ATOM_MAX_LEN < mem::size_of::<AtomCell>());
const_assert!(mem::size_of::<AtomCell>() == 8);
const_assert!(INLINED_ATOM_MAX_LEN < mem::size_of::<Atom>());
const_assert!(mem::size_of::<Atom>() == 8);
impl AtomCell {
#[inline]
pub fn new_static(index: u64) -> Self {
// upper 23 bits of index must be 0
debug_assert!(index & !((1 << 49) - 1) == 0);
AtomCell::new()
.with_name(index)
.with_arity(0u8)
.with_m(false)
.with_f(false)
.with_is_inlined(false)
.with_tag(HeapCellValueTag::Atom as u8)
}
#[inline]
pub fn new_inlined(string: &str, arity: u8) -> Self {
debug_assert!(string.len() <= INLINED_ATOM_MAX_LEN);
let mut string_buf: [u8; 8] = [0u8; 8];
string_buf[.. string.len()].copy_from_slice(string.as_bytes());
let encoding = u64::from_le_bytes(string_buf);
AtomCell::new()
.with_name(encoding)
.with_arity(arity)
.with_m(false)
.with_f(false)
.with_is_inlined(true)
.with_tag(HeapCellValueTag::Atom as u8)
}
#[inline]
pub fn new_char_inlined(c: char) -> Self {
let mut char_buf = [0u8;8];
c.encode_utf8(&mut char_buf);
let encoding = u64::from_le_bytes(char_buf);
AtomCell::new()
.with_name(encoding)
.with_arity(0u8)
.with_m(false)
.with_f(false)
.with_is_inlined(true)
.with_tag(HeapCellValueTag::Atom as u8)
}
#[inline]
pub fn build_with(atom_index: u64, arity: u8) -> Self {
debug_assert!((arity as usize) <= MAX_ARITY);
AtomCell::new()
.with_name(atom_index >> 1)
.with_arity(arity)
.with_f(false)
.with_m(false)
.with_is_inlined(atom_index & 1 == 1)
.with_tag(HeapCellValueTag::Atom as u8)
}
#[inline]
pub fn get_name(self) -> Atom {
Atom { index: (self.name() << 1) | self.is_inlined() as u64 }
}
#[inline]
pub fn get_arity(self) -> usize {
self.arity() as usize
}
#[inline]
pub fn get_name_and_arity(self) -> (Atom, usize) {
(self.get_name(), self.get_arity())
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Atom { pub struct Atom {
pub index: u64, pub index: u64,
} }
const_assert!(mem::size_of::<Atom>() == 8);
include!(concat!(env!("OUT_DIR"), "/static_atoms.rs")); include!(concat!(env!("OUT_DIR"), "/static_atoms.rs"));
// populate these in STRINGS so they can be used from build_functor
const _: Atom = atom!(".");
const _: Atom = atom!("[]");
impl<'a> From<&'a Atom> for Atom { impl<'a> From<&'a Atom> for Atom {
#[inline] #[inline]
fn from(atom: &'a Atom) -> Self { fn from(atom: &'a Atom) -> Self {
@@ -39,17 +141,6 @@ impl<'a> From<&'a Atom> for Atom {
} }
} }
impl From<bool> for Atom {
#[inline]
fn from(value: bool) -> Self {
if value {
atom!("true")
} else {
atom!("false")
}
}
}
impl indexmap::Equivalent<Atom> for str { impl indexmap::Equivalent<Atom> for str {
fn equivalent(&self, key: &Atom) -> bool { fn equivalent(&self, key: &Atom) -> bool {
&*key.as_str() == self &*key.as_str() == self
@@ -120,24 +211,25 @@ impl Hash for Atom {
#[inline] #[inline]
fn hash<H: Hasher>(&self, hasher: &mut H) { fn hash<H: Hasher>(&self, hasher: &mut H) {
self.as_str().hash(hasher) self.as_str().hash(hasher)
// hasher.write_usize(self.index)
} }
} }
pub enum AtomString<'a> { pub enum AtomString<'a> {
Static(&'a str), Static(&'a str),
Inlined([u8;8]),
Dynamic(AtomTableRef<str>), Dynamic(AtomTableRef<str>),
} }
impl AtomString<'_> { fn inlined_to_str<'a>(bytes: &'a [u8;8]) -> &'a str {
pub fn map<F>(self, f: F) -> Self // allow the '\0\' atom to be represented as the 0-valued inlined atom
where let slice_len = if bytes[0] == 0 {
for<'a> F: FnOnce(&'a str) -> &'a str, 1
{ } else {
match self { bytes.iter().position(|&b| b == 0u8).unwrap_or(INLINED_ATOM_MAX_LEN)
Self::Static(reference) => Self::Static(f(reference)), };
Self::Dynamic(guard) => Self::Dynamic(AtomTableRef::map(guard, f)),
} unsafe {
str::from_utf8_unchecked(&bytes[..slice_len])
} }
} }
@@ -158,6 +250,7 @@ impl std::ops::Deref for AtomString<'_> {
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match self { match self {
Self::Static(reference) => reference, Self::Static(reference) => reference,
Self::Inlined(inlined) => inlined_to_str(&inlined),
Self::Dynamic(guard) => guard.deref(), Self::Dynamic(guard) => guard.deref(),
} }
} }
@@ -175,13 +268,32 @@ impl rustyline::completion::Candidate for AtomString<'_> {
} }
impl Atom { impl Atom {
#[inline(always)] #[inline]
pub fn is_static(self) -> bool { fn new_inlined(string: &str) -> Self {
(self.index as usize) < STRINGS.len() << 3 AtomCell::new_inlined(string, 0).get_name()
} }
#[inline(always)] #[inline(always)]
pub fn as_ptr(self) -> Option<AtomTableRef<AtomData>> { fn is_static(self) -> bool {
if self.is_inlined() {
true
} else {
(self.flat_index() as usize) < STRINGS.len()
}
}
#[inline]
pub(crate) fn flat_index(self) -> u64 {
self.index >> 1
}
#[inline(always)]
pub(crate) fn is_inlined(self) -> bool {
self.index & 1 == 1
}
#[inline(always)]
fn as_ptr(self) -> Option<AtomTableRef<AtomData>> {
if self.is_static() { if self.is_static() {
None None
} else { } else {
@@ -192,7 +304,7 @@ impl Atom {
let ptr = buf let ptr = buf
.block .block
.base .base
.add((self.index as usize) - (STRINGS.len() << 3)); .add(self.flat_index() as usize - STRINGS.len());
// TODO use std::ptr::from_raw_parts instead when feature ptr_metadata is stable rust-lang/rust#81513 // TODO use std::ptr::from_raw_parts instead when feature ptr_metadata is stable rust-lang/rust#81513
let atom_data = &*(std::ptr::slice_from_raw_parts(ptr, 0) as *const AtomData); let atom_data = &*(std::ptr::slice_from_raw_parts(ptr, 0) as *const AtomData);
let len = atom_data.header.len(); let len = atom_data.header.len();
@@ -208,8 +320,11 @@ impl Atom {
#[inline(always)] #[inline(always)]
pub fn len(self) -> usize { pub fn len(self) -> usize {
if self.is_static() { if let Some(s) = self.inlined_str() {
STRINGS[(self.index >> 3) as usize].len() s.len()
} else if self.is_static() {
let index = self.flat_index();
STRINGS[index as usize].len()
} else { } else {
let len: u64 = self.as_ptr().unwrap().header.len(); let len: u64 = self.as_ptr().unwrap().header.len();
len as usize len as usize
@@ -220,11 +335,6 @@ impl Atom {
self.len() == 0 self.len() == 0
} }
#[inline(always)]
pub fn flat_index(self) -> u64 {
self.index >> 3
}
pub fn as_char(self) -> Option<char> { pub fn as_char(self) -> Option<char> {
let s = self.as_str(); let s = self.as_str();
let mut it = s.chars(); let mut it = s.chars();
@@ -239,14 +349,26 @@ impl Atom {
} }
} }
#[inline]
fn inlined_str<'a>(&self) -> Option<AtomString<'a>> {
if self.is_inlined() {
Some(AtomString::Inlined(self.flat_index().to_le_bytes()))
} else {
None
}
}
#[inline] #[inline]
pub fn as_str(&self) -> AtomString<'static> { pub fn as_str(&self) -> AtomString<'static> {
if self.is_static() { if let Some(s) = self.inlined_str() {
AtomString::Static(STRINGS[(self.index >> 3) as usize]) s
} else if self.is_static() {
let index = self.flat_index() as usize;
AtomString::Static(STRINGS[index])
} else if let Some(ptr) = self.as_ptr() { } else if let Some(ptr) = self.as_ptr() {
AtomString::Dynamic(AtomTableRef::map(ptr, |ptr| &ptr.data)) AtomString::Dynamic(AtomTableRef::map(ptr, |ptr| &ptr.data))
} else { } else {
AtomString::Static(STRINGS[(self.index >> 3) as usize]) AtomString::Static(STRINGS[(self.index >> 1) as usize])
} }
} }
@@ -342,6 +464,10 @@ impl AtomTable {
} }
pub fn build_with(atom_table: &AtomTable, string: &str) -> Atom { pub fn build_with(atom_table: &AtomTable, string: &str) -> Atom {
if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN {
return Atom::new_inlined(string);
}
loop { loop {
let mut block_epoch = atom_table.inner.read(); let mut block_epoch = atom_table.inner.read();
let mut table_epoch = block_epoch.table.read(); let mut table_epoch = block_epoch.table.read();
@@ -390,9 +516,14 @@ impl AtomTable {
write_to_ptr(string, len_ptr); write_to_ptr(string, len_ptr);
let atom = Atom { let atom = AtomCell::new()
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64, .with_name((STRINGS.len() + len_ptr as usize - ptr_base) as u64)
}; .with_arity(0)
.with_f(false)
.with_m(false)
.with_is_inlined(false)
.with_tag(HeapCellValueTag::Atom as u8)
.get_name();
let mut table = table_epoch.clone(); let mut table = table_epoch.clone();
table.insert(atom); table.insert(atom);
@@ -410,18 +541,21 @@ impl AtomTable {
unsafe impl Send for AtomTable {} unsafe impl Send for AtomTable {}
unsafe impl Sync for AtomTable {} unsafe impl Sync for AtomTable {}
/*
#[bitfield] #[bitfield]
#[repr(u64)] #[repr(u64)]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct AtomCell { pub struct AtomCell {
name: B46, name: B48,
arity: B10, arity: B10,
#[allow(unused)] #[allow(unused)]
f: bool, f: bool,
#[allow(unused)] #[allow(unused)]
m: bool, m: bool,
#[allow(unused)] #[allow(unused)]
tag: B6, inlined: bool,
#[allow(unused)]
tag: B3,
} }
impl AtomCell { impl AtomCell {
@@ -463,3 +597,4 @@ impl AtomCell {
(Atom::from((self.get_index() as u64) << 3), self.get_arity()) (Atom::from((self.get_index() as u64) << 3), self.get_arity())
} }
} }
*/

View File

@@ -7,7 +7,7 @@ use crate::forms::*;
use crate::indexing::*; use crate::indexing::*;
use crate::instructions::*; use crate::instructions::*;
use crate::iterators::*; use crate::iterators::*;
use crate::machine::heap::{heap_bound_deref, heap_bound_store}; use crate::machine::heap::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::targets::*; use crate::targets::*;
use crate::types::*; use crate::types::*;
@@ -16,7 +16,6 @@ use crate::variable_records::*;
use crate::machine::disjuncts::*; use crate::machine::disjuncts::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::machine_indices::CodeIndex; use crate::machine::machine_indices::CodeIndex;
use crate::machine::machine_state::pstr_loc_and_offset;
use crate::machine::stack::Stack; use crate::machine::stack::Stack;
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
@@ -24,6 +23,7 @@ use indexmap::IndexMap;
use indexmap::IndexSet; use indexmap::IndexSet;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::rc::Rc;
#[derive(Debug)] #[derive(Debug)]
pub struct BranchCodeStack { pub struct BranchCodeStack {
@@ -274,33 +274,12 @@ impl CodeGenSettings {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct CodeGenerator<'a> { pub(crate) struct CodeGenerator {
pub(crate) atom_tbl: &'a AtomTable,
marker: DebrayAllocator, marker: DebrayAllocator,
settings: CodeGenSettings, settings: CodeGenSettings,
pub(crate) skeleton: PredicateSkeleton, pub(crate) skeleton: PredicateSkeleton,
} }
fn subterm_index(heap: &[HeapCellValue], subterm_loc: usize) -> (usize, HeapCellValue) {
let subterm = heap[subterm_loc];
if subterm.is_ref() {
let subterm = heap_bound_deref(heap, subterm);
let subterm_loc = subterm.get_value() as usize;
let subterm = heap_bound_store(heap, subterm);
let subterm_loc = if subterm.is_ref() {
subterm.get_value() as usize
} else {
subterm_loc
};
(subterm_loc, subterm)
} else {
(subterm_loc, subterm)
}
}
impl DebrayAllocator { impl DebrayAllocator {
pub(crate) fn mark_non_callable( pub(crate) fn mark_non_callable(
&mut self, &mut self,
@@ -337,7 +316,7 @@ trait AddToFreeList<'a, Target: CompilationTarget<'a>> {
fn add_subterm_to_free_list(&mut self, r: RegType); fn add_subterm_to_free_list(&mut self, r: RegType);
} }
impl<'a, 'b> AddToFreeList<'a, FactInstruction> for CodeGenerator<'b> { impl<'a> AddToFreeList<'a, FactInstruction> for CodeGenerator {
fn add_term_to_free_list(&mut self, r: RegType) { fn add_term_to_free_list(&mut self, r: RegType) {
self.marker.add_reg_to_free_list(r); self.marker.add_reg_to_free_list(r);
} }
@@ -345,7 +324,7 @@ impl<'a, 'b> AddToFreeList<'a, FactInstruction> for CodeGenerator<'b> {
fn add_subterm_to_free_list(&mut self, _r: RegType) {} fn add_subterm_to_free_list(&mut self, _r: RegType) {}
} }
impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> { impl<'a> AddToFreeList<'a, QueryInstruction> for CodeGenerator {
#[inline(always)] #[inline(always)]
fn add_term_to_free_list(&mut self, _r: RegType) {} fn add_term_to_free_list(&mut self, _r: RegType) {}
@@ -357,19 +336,19 @@ impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> {
fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>( fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>(
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>, index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
heap: &[HeapCellValue], heap: &Heap,
arity: usize, arity: usize,
heap_loc: usize, heap_loc: usize,
) -> Option<Instruction> { ) -> Option<Instruction> {
match fetch_index_ptr(heap, arity, heap_loc) { match fetch_index_ptr(heap, arity, heap_loc) {
Some(index_ptr) => { Some(index_ptr) => {
let subterm = Literal::CodeIndex(index_ptr); let subterm = HeapCellValue::from(index_ptr);
return Some(Target::constant_subterm(subterm)); return Some(Target::constant_subterm(subterm));
} }
None => { None => {
// if Level::Shallow == lvl { // if Level::Shallow == lvl {
if let Some(index_ptr) = index_ptrs.get(&heap_loc) { if let Some(index_ptr) = index_ptrs.get(&heap_loc) {
let subterm = Literal::CodeIndex(*index_ptr); let subterm = HeapCellValue::from(*index_ptr);
return Some(Target::constant_subterm(subterm)); return Some(Target::constant_subterm(subterm));
} }
// } // }
@@ -379,10 +358,9 @@ fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>(
None None
} }
impl<'b> CodeGenerator<'b> { impl CodeGenerator {
pub(crate) fn new(atom_tbl: &'b AtomTable, settings: CodeGenSettings) -> Self { pub(crate) fn new(settings: CodeGenSettings) -> Self {
CodeGenerator { CodeGenerator {
atom_tbl,
marker: DebrayAllocator::new(), marker: DebrayAllocator::new(),
settings, settings,
skeleton: PredicateSkeleton::new(), skeleton: PredicateSkeleton::new(),
@@ -445,33 +423,26 @@ impl<'b> CodeGenerator<'b> {
None None
} }
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(arity, 0);
if index_ptrs.contains_key(&heap_loc) { if index_ptrs.contains_key(&heap_loc) {
let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target); let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target);
target.push_back(Target::clause_arg_to_instr(r)); target.push_back(Target::clause_arg_to_instr(r));
return Some(r); return Some(r);
} else { } else {
target.push_back(Target::constant_subterm(Literal::Atom(name))); target.push_back(Target::constant_subterm(atom_as_cell!(name)));
} }
None None
} }
(HeapCellValueTag::Str (HeapCellValueTag::Str
| HeapCellValueTag::Lis | HeapCellValueTag::Lis
| HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrLoc) => {
| HeapCellValueTag::CStr) => {
let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target); let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target);
target.push_back(Target::clause_arg_to_instr(r)); target.push_back(Target::clause_arg_to_instr(r));
return Some(r); return Some(r);
} }
_ => { _ => {
match Literal::try_from(subterm) { target.push_back(Target::constant_subterm(subterm));
Ok(lit) => target.push_back(Target::constant_subterm(lit)),
Err(_) => unreachable!(),
}
None None
} }
) )
@@ -486,7 +457,7 @@ impl<'b> CodeGenerator<'b> {
where where
Target: crate::targets::CompilationTarget<'a>, Target: crate::targets::CompilationTarget<'a>,
Iter: TermIterator, Iter: TermIterator,
CodeGenerator<'b>: AddToFreeList<'a, Target>, CodeGenerator: AddToFreeList<'a, Target>,
{ {
let mut target = CodeDeque::new(); let mut target = CodeDeque::new();
let chunk_num = context.chunk_num(); let chunk_num = context.chunk_num();
@@ -530,13 +501,13 @@ impl<'b> CodeGenerator<'b> {
target.push_back(instr); target.push_back(instr);
} else if lvl == Level::Shallow { } else if lvl == Level::Shallow {
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target); let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
target.push_back(Target::to_constant(lvl, Literal::Atom(name), r)); target.push_back(Target::to_constant(lvl, atom_as_cell!(name), r));
} }
} else { } else {
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target); let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
target.push_back(Target::to_structure(lvl, name, arity, r)); target.push_back(Target::to_structure(lvl, name, arity, r));
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list( <CodeGenerator as AddToFreeList<'a, Target>>::add_term_to_free_list(
self, self,
r, r,
); );
@@ -557,7 +528,7 @@ impl<'b> CodeGenerator<'b> {
for r_opt in free_list_regs { for r_opt in free_list_regs {
if let Some(r) = r_opt { if let Some(r) = r_opt {
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list( <CodeGenerator as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, r, self, r,
); );
} }
@@ -572,7 +543,7 @@ impl<'b> CodeGenerator<'b> {
target.push_back(Target::to_list(lvl, r)); target.push_back(Target::to_list(lvl, r));
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list( <CodeGenerator as AddToFreeList<'a, Target>>::add_term_to_free_list(
self, self,
r, r,
); );
@@ -597,62 +568,36 @@ impl<'b> CodeGenerator<'b> {
); );
if let Some(r) = head_r_opt { if let Some(r) = head_r_opt {
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list( <CodeGenerator as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, r, self, r,
); );
} }
if let Some(r) = tail_r_opt { if let Some(r) = tail_r_opt {
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list( <CodeGenerator as AddToFreeList<'a, Target>>::add_subterm_to_free_list(
self, r, self, r,
); );
} }
} }
(HeapCellValueTag::CStr, cstr_atom) => { (HeapCellValueTag::PStrLoc, pstr_loc) => {
let heap_loc = iter.focus().value() as usize;
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
target.push_back(Target::to_pstr(lvl, cstr_atom, r, false));
}
(HeapCellValueTag::PStr, pstr_atom) => {
let heap_loc = iter.focus().value() as usize; let heap_loc = iter.focus().value() as usize;
let (heap_loc, _) = subterm_index(iter.deref(), heap_loc); let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target); let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
let (pstr_str, tail_loc) = iter.scan_slice_to_str(pstr_loc);
target.push_back(Target::to_pstr(lvl, pstr_atom, r, true)); target.push_back(Target::to_pstr(lvl, Rc::new(pstr_str.to_owned()), r));
let (tail_loc, tail) = subterm_index(iter.deref(), heap_loc + 1);
self.subterm_to_instr::<Target>(
tail, tail_loc, context, index_ptrs, &mut target,
);
}
(HeapCellValueTag::PStrOffset, l) => {
let heap_loc = iter.focus().value() as usize;
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
let (index, n) = pstr_loc_and_offset(&iter, l);
let n = n.get_num() as usize;
let pstr_atom = cell_as_atom!(iter[index]);
let pstr_offset_atom = if n == 0 {
pstr_atom
} else {
AtomTable::build_with(self.atom_tbl, &pstr_atom.as_str()[n ..])
};
let (tail_loc, tail) = subterm_index(iter.deref(), l+1);
target.push_back(Target::to_pstr(lvl, pstr_offset_atom, r, true));
let (tail_loc, tail) = subterm_index(iter.deref(), tail_loc);
self.subterm_to_instr::<Target>( self.subterm_to_instr::<Target>(
tail, tail_loc, context, index_ptrs, &mut target, tail, tail_loc, context, index_ptrs, &mut target,
); );
} }
_ if lvl == Level::Shallow => { _ if lvl == Level::Shallow => {
if let Ok(lit) = Literal::try_from(term) { if term.is_constant() {
let heap_loc = iter.focus().value() as usize; let heap_loc = iter.focus().value() as usize;
let (heap_loc, _) = subterm_index(iter.deref(), heap_loc); let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target); let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
target.push_back(Target::to_constant(lvl, lit, r)); target.push_back(Target::to_constant(lvl, term, r));
} }
} }
_ => {} _ => {}
@@ -688,7 +633,7 @@ impl<'b> CodeGenerator<'b> {
fn compile_inlined( fn compile_inlined(
&mut self, &mut self,
ct: &InlinedClauseType, ct: &InlinedClauseType,
terms: &mut FocusedHeap, terms: &mut FocusedHeapRefMut,
term_loc: usize, term_loc: usize,
context: GenContext, context: GenContext,
code: &mut CodeDeque, code: &mut CodeDeque,
@@ -763,9 +708,6 @@ impl<'b> CodeGenerator<'b> {
instr!("$fail") instr!("$fail")
} }
} }
(HeapCellValueTag::Char) => {
instr!("$succeed")
}
_ => { _ => {
instr!("$fail") instr!("$fail")
} }
@@ -780,7 +722,6 @@ impl<'b> CodeGenerator<'b> {
} else { } else {
read_heap_cell!(first_arg, read_heap_cell!(first_arg,
(HeapCellValueTag::Fixnum | (HeapCellValueTag::Fixnum |
HeapCellValueTag::Char |
HeapCellValueTag::F64) => { HeapCellValueTag::F64) => {
instr!("$succeed") instr!("$succeed")
} }
@@ -803,12 +744,11 @@ impl<'b> CodeGenerator<'b> {
} }
(HeapCellValueTag::Lis (HeapCellValueTag::Lis
| HeapCellValueTag::Str | HeapCellValueTag::Str
| HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrLoc) => {
| HeapCellValueTag::CStr) => {
instr!("$fail") instr!("$fail")
} }
_ => { _ => {
if Literal::try_from(first_arg).is_ok() { if first_arg.is_constant() {
instr!("$succeed") instr!("$succeed")
} else { } else {
instr!("$fail") instr!("$fail")
@@ -833,8 +773,7 @@ impl<'b> CodeGenerator<'b> {
} }
(HeapCellValueTag::Lis (HeapCellValueTag::Lis
| HeapCellValueTag::Str | HeapCellValueTag::Str
| HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrLoc) => {
| HeapCellValueTag::CStr) => {
instr!("$succeed") instr!("$succeed")
} }
_ => { _ => {
@@ -889,12 +828,10 @@ impl<'b> CodeGenerator<'b> {
self.marker.reset_arg(1); self.marker.reset_arg(1);
if let Some(r) = variable_marker(&mut self.marker) { if let Some(r) = variable_marker(&mut self.marker) {
instr!("number", r) instr!("number", r)
} else if Number::try_from(first_arg).is_ok() {
instr!("$succeed")
} else { } else {
if Number::try_from(first_arg).is_ok() { instr!("$fail")
instr!("$succeed")
} else {
instr!("$fail")
}
} }
} }
InlinedClauseType::IsNonVar(..) => { InlinedClauseType::IsNonVar(..) => {
@@ -902,12 +839,10 @@ impl<'b> CodeGenerator<'b> {
if let Some(r) = variable_marker(&mut self.marker) { if let Some(r) = variable_marker(&mut self.marker) {
instr!("nonvar", r) instr!("nonvar", r)
} else if first_arg.is_var() {
instr!("$fail")
} else { } else {
if first_arg.is_var() { instr!("$succeed")
instr!("$fail")
} else {
instr!("$succeed")
}
} }
} }
InlinedClauseType::IsInteger(..) => { InlinedClauseType::IsInteger(..) => {
@@ -931,12 +866,10 @@ impl<'b> CodeGenerator<'b> {
if let Some(r) = variable_marker(&mut self.marker) { if let Some(r) = variable_marker(&mut self.marker) {
instr!("var", r) instr!("var", r)
} else if first_arg.is_var() {
instr!("$succeed")
} else { } else {
if first_arg.is_var() { instr!("$fail")
instr!("$succeed")
} else {
instr!("$fail")
}
} }
}, },
}; };
@@ -948,7 +881,7 @@ impl<'b> CodeGenerator<'b> {
fn compile_arith_expr( fn compile_arith_expr(
&mut self, &mut self,
terms: &mut FocusedHeap, terms: &mut FocusedHeapRefMut,
term_loc: usize, term_loc: usize,
target_int: usize, target_int: usize,
context: GenContext, context: GenContext,
@@ -960,7 +893,7 @@ impl<'b> CodeGenerator<'b> {
fn compile_is_call( fn compile_is_call(
&mut self, &mut self,
terms: &mut FocusedHeap, terms: &mut FocusedHeapRefMut,
term_loc: usize, term_loc: usize,
code: &mut CodeDeque, code: &mut CodeDeque,
context: GenContext, context: GenContext,
@@ -977,12 +910,10 @@ impl<'b> CodeGenerator<'b> {
self.marker.reset_arg(2); self.marker.reset_arg(2);
let var = { let var = heap_bound_store(
let var_cell = terms.heap[term_loc + 1]; terms.heap,
let terms = FocusedHeapRefMut::from_cell(&mut terms.heap, var_cell); heap_bound_deref(terms.heap, heap_loc_as_cell!(term_loc + 1)),
);
terms.deref_loc(term_loc + 1)
};
let at = read_heap_cell!(var, let at = read_heap_cell!(var,
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
@@ -1029,7 +960,7 @@ impl<'b> CodeGenerator<'b> {
fn compile_seq( fn compile_seq(
&mut self, &mut self,
focused_heap: &mut FocusedHeap, mut focused_heap: FocusedHeapRefMut,
clauses: &ChunkedTermVec, clauses: &ChunkedTermVec,
code: &mut CodeDeque, code: &mut CodeDeque,
) -> Result<(), CompilationError> { ) -> Result<(), CompilationError> {
@@ -1108,7 +1039,7 @@ impl<'b> CodeGenerator<'b> {
.. ..
}, },
) => self.compile_is_call( ) => self.compile_is_call(
focused_heap, &mut focused_heap,
clause.term_loc(), clause.term_loc(),
branch_code_stack.code(code), branch_code_stack.code(code),
context, context,
@@ -1121,7 +1052,7 @@ impl<'b> CodeGenerator<'b> {
}, },
) => self.compile_inlined( ) => self.compile_inlined(
ct, ct,
focused_heap, &mut focused_heap,
clause.term_loc(), clause.term_loc(),
context, context,
branch_code_stack.code(code), branch_code_stack.code(code),
@@ -1132,15 +1063,13 @@ impl<'b> CodeGenerator<'b> {
&QueryTerm::Succeed => { &QueryTerm::Succeed => {
let code = branch_code_stack.code(code); let code = branch_code_stack.code(code);
if self.marker.in_tail_position { if self.marker.in_tail_position && self.marker.var_data.allocates {
if self.marker.var_data.allocates { code.push_back(instr!("deallocate"));
code.push_back(instr!("deallocate"));
}
} }
code.push_back( code.push_back(
if self.marker.in_tail_position { if self.marker.in_tail_position {
instr!("$succeed").to_execute() instr!("$succeed").into_execute()
} else { } else {
instr!("$succeed") instr!("$succeed")
}, },
@@ -1148,7 +1077,7 @@ impl<'b> CodeGenerator<'b> {
} }
QueryTerm::Clause(clause) => { QueryTerm::Clause(clause) => {
self.compile_query_line( self.compile_query_line(
focused_heap, &mut focused_heap,
clause, clause,
context, context,
branch_code_stack.code(code), branch_code_stack.code(code),
@@ -1208,24 +1137,23 @@ impl<'b> CodeGenerator<'b> {
pub(crate) fn compile_rule( pub(crate) fn compile_rule(
&mut self, &mut self,
heap: &mut Heap,
rule: &mut Rule, rule: &mut Rule,
var_data: VarData, var_data: VarData,
) -> Result<Code, CompilationError> { ) -> Result<Code, CompilationError> {
let Rule { let Rule { term_loc, clauses } = rule;
ref mut term,
clauses,
} = rule;
self.marker.var_data = var_data; self.marker.var_data = var_data;
let term = FocusedHeapRefMut { heap, focus: *term_loc };
let mut code = VecDeque::new(); let mut code = VecDeque::new();
let head_loc = term.nth_arg(term.focus, 1).unwrap(); let head_loc = term.nth_arg(term.focus, 1).unwrap();
self.marker.reset_at_head(term, head_loc); self.marker.reset_at_head(term.heap, head_loc);
let mut stack = Stack::uninitialized(); let mut stack = Stack::uninitialized();
let iter = fact_iterator::<true>( let iter = fact_iterator::<true>(term.heap, &mut stack, head_loc);
&mut term.heap, &mut stack, head_loc,
);
let fact = self.compile_target::<FactInstruction, _>( let fact = self.compile_target::<FactInstruction, _>(
iter, iter,
@@ -1247,20 +1175,18 @@ impl<'b> CodeGenerator<'b> {
pub(crate) fn compile_fact( pub(crate) fn compile_fact(
&mut self, &mut self,
heap: &mut Heap,
fact: &mut Fact, fact: &mut Fact,
var_data: VarData, var_data: VarData,
) -> Result<Code, CompilationError> { ) -> Result<Code, CompilationError> {
let mut code = Vec::new(); let mut code = Vec::new();
let fact_focus = fact.term.focus;
let mut stack = Stack::uninitialized(); let mut stack = Stack::uninitialized();
self.marker.var_data = var_data; self.marker.var_data = var_data;
self.marker.reset_at_head(&mut fact.term, fact_focus); self.marker.reset_at_head(heap, fact.term_loc);
let iter = fact_iterator::<true>( let iter = fact_iterator::<true>(heap, &mut stack, fact.term_loc);
&mut fact.term.heap, &mut stack, fact_focus,
);
let compiled_fact = self.compile_target::<FactInstruction, _>( let compiled_fact = self.compile_target::<FactInstruction, _>(
iter, iter,
@@ -1280,7 +1206,7 @@ impl<'b> CodeGenerator<'b> {
fn compile_query_line( fn compile_query_line(
&mut self, &mut self,
term: &mut FocusedHeap, term: &mut FocusedHeapRefMut,
clause: &QueryClause, clause: &QueryClause,
context: GenContext, context: GenContext,
code: &mut CodeDeque, code: &mut CodeDeque,
@@ -1300,15 +1226,16 @@ impl<'b> CodeGenerator<'b> {
self.add_call(code, clause.ct.to_instr(), clause.call_policy); self.add_call(code, clause.ct.to_instr(), clause.call_policy);
} }
fn split_predicate(clauses: &[PredicateClause]) -> Vec<ClauseSpan> { fn split_predicate(heap: &mut Heap, clauses: &[PredicateClause]) -> Vec<ClauseSpan> {
let mut subseqs = Vec::new(); let mut subseqs = Vec::new();
let mut left = 0; let mut left = 0;
let mut optimal_index = 0; let mut optimal_index = 0;
'outer: for (right, clause) in clauses.iter().enumerate() { 'outer: for (right, clause) in clauses.iter().enumerate() {
if let Some(args) = clause.args() { if let Some(args) = clause.args(heap) {
for (instantiated_arg_index, arg) in args.iter().cloned().enumerate() { for (instantiated_arg_index, arg_idx) in args.enumerate() {
let arg = heap_bound_store(clause.heap(), heap_bound_deref(clause.heap(), arg)); let arg = heap[arg_idx];
let arg = heap_bound_store(heap, heap_bound_deref(heap, arg));
if !arg.is_var() { if !arg.is_var() {
if optimal_index != instantiated_arg_index { if optimal_index != instantiated_arg_index {
@@ -1364,6 +1291,7 @@ impl<'b> CodeGenerator<'b> {
fn compile_pred_subseq<I: Indexer>( fn compile_pred_subseq<I: Indexer>(
&mut self, &mut self,
heap: &mut Heap,
clauses: &mut [PredicateClause], clauses: &mut [PredicateClause],
optimal_index: usize, optimal_index: usize,
) -> Result<Code, CompilationError> { ) -> Result<Code, CompilationError> {
@@ -1382,11 +1310,11 @@ impl<'b> CodeGenerator<'b> {
let clause_code = match clause { let clause_code = match clause {
PredicateClause::Fact(fact, var_data) => { PredicateClause::Fact(fact, var_data) => {
let var_data = std::mem::take(var_data); let var_data = std::mem::take(var_data);
self.compile_fact(fact, var_data)? self.compile_fact(heap, fact, var_data)?
} }
PredicateClause::Rule(rule, var_data) => { PredicateClause::Rule(rule, var_data) => {
let var_data = std::mem::take(var_data); let var_data = std::mem::take(var_data);
self.compile_rule(rule, var_data)? self.compile_rule(heap, rule, var_data)?
} }
}; };
@@ -1414,19 +1342,19 @@ impl<'b> CodeGenerator<'b> {
skip_stub_try_me_else = !self.settings.is_dynamic(); skip_stub_try_me_else = !self.settings.is_dynamic();
} }
let arg = clause.args().and_then(|args| args.get(optimal_index)); let arg = clause.args(heap)
.map(|r| heap[r.start() + optimal_index]);
if let Some(arg) = arg.cloned() { if let Some(arg) = arg {
let index = code.len(); let index = code.len();
if clauses_len > 1 || self.settings.is_extensible { if clauses_len > 1 || self.settings.is_extensible {
let arg = heap_bound_store(clause.heap(), heap_bound_deref(clause.heap(), arg)); let arg = heap_bound_store(heap, heap_bound_deref(heap, arg));
code_offsets.index_term( code_offsets.index_term(
clause.heap(), heap,
arg, arg,
index, index,
&mut clause_index_info, &mut clause_index_info,
self.atom_tbl,
); );
} }
} }
@@ -1457,11 +1385,12 @@ impl<'b> CodeGenerator<'b> {
pub(crate) fn compile_predicate( pub(crate) fn compile_predicate(
&mut self, &mut self,
heap: &mut Heap,
mut clauses: Vec<PredicateClause>, mut clauses: Vec<PredicateClause>,
) -> Result<Code, CompilationError> { ) -> Result<Code, CompilationError> {
let mut code = Code::new(); let mut code = Code::new();
let split_pred = Self::split_predicate(&clauses); let split_pred = Self::split_predicate(heap, &clauses);
let multi_seq = split_pred.len() > 1; let multi_seq = split_pred.len() > 1;
for ClauseSpan { for ClauseSpan {
@@ -1473,11 +1402,13 @@ impl<'b> CodeGenerator<'b> {
let skel_lower_bound = self.skeleton.clauses.len(); let skel_lower_bound = self.skeleton.clauses.len();
let code_segment = if self.settings.is_dynamic() { let code_segment = if self.settings.is_dynamic() {
self.compile_pred_subseq::<DynamicCodeIndices>( self.compile_pred_subseq::<DynamicCodeIndices>(
heap,
&mut clauses[left..right], &mut clauses[left..right],
instantiated_arg_index, instantiated_arg_index,
)? )?
} else { } else {
self.compile_pred_subseq::<StaticCodeIndices>( self.compile_pred_subseq::<StaticCodeIndices>(
heap,
&mut clauses[left..right], &mut clauses[left..right],
instantiated_arg_index, instantiated_arg_index,
)? )?

View File

@@ -4,7 +4,7 @@ use crate::codegen::SubsumedBranchHits;
use crate::forms::{GenContext, Level}; use crate::forms::{GenContext, Level};
use crate::instructions::*; use crate::instructions::*;
use crate::machine::disjuncts::*; use crate::machine::disjuncts::*;
use crate::machine::heap::{heap_bound_deref, heap_bound_store}; use crate::machine::heap::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::targets::*; use crate::targets::*;
use crate::types::*; use crate::types::*;
@@ -920,19 +920,24 @@ impl Allocator for DebrayAllocator {
self.arg_c += 1; self.arg_c += 1;
} }
fn reset_at_head(&mut self, term: &mut FocusedHeap, head_loc: usize) { fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize) {
read_heap_cell!(term.deref_loc(head_loc), let head_cell = heap_bound_store(
heap,
heap_bound_deref(heap, heap_loc_as_cell!(head_loc)),
);
read_heap_cell!(head_cell,
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let arity = cell_as_atom_cell!(term.heap[s]).get_arity(); let arity = cell_as_atom_cell!(heap[s]).get_arity();
self.reset_arg(arity); self.reset_arg(arity);
self.arity = arity; self.arity = arity;
for (idx, arg) in term.heap[s+1 .. s+arity+1].iter().cloned().enumerate() { for (idx, arg) in heap.splice(s+1 ..= s+arity).enumerate() {
if arg.is_var() { if arg.is_var() {
let var = heap_bound_store( let var = heap_bound_store(
&term.heap, heap,
heap_bound_deref(&term.heap, arg), heap_bound_deref(heap, arg),
); );
if !var.is_var() { if !var.is_var() {

View File

@@ -1,9 +1,10 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::instructions::*; use crate::instructions::*;
use crate::functor_macro::*;
use crate::machine::disjuncts::VarData; use crate::machine::disjuncts::VarData;
use crate::machine::heap::*; use crate::machine::heap::*;
use crate::machine::loader::PredicateQueue; // use crate::machine::loader::PredicateQueue;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::parser::ast::*; use crate::parser::ast::*;
@@ -25,18 +26,6 @@ use std::path::PathBuf;
pub type PredicateKey = (Atom, usize); // name, arity. pub type PredicateKey = (Atom, usize); // name, arity.
/*
// vars of predicate, toplevel offset. Vec<Term> is always a vector
// of vars (we get their adjoining cells this way).
pub type JumpStub = Vec<Term>;
*/
#[derive(Debug)]
pub enum TopLevel {
Fact(Fact, VarData), // Term, line_num, col_num
Rule(Rule, VarData), // Rule, line_num, col_num
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum AppendOrPrepend { pub enum AppendOrPrepend {
Append, Append,
@@ -171,17 +160,6 @@ impl ChunkedTermVec {
.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity))); .push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
} }
pub fn push_branch_arm(&mut self, branch: VecDeque<ChunkedTerms>) {
match self.chunk_vec.back_mut().unwrap() {
ChunkedTerms::Branch(branches) => {
branches.push(branch);
}
ChunkedTerms::Chunk { .. } => {
self.chunk_vec.push_back(ChunkedTerms::Branch(vec![branch]));
}
}
}
pub fn try_set_chunk_at_inlined_boundary(&mut self) -> bool { pub fn try_set_chunk_at_inlined_boundary(&mut self) -> bool {
if self.current_chunk_type.is_last() { if self.current_chunk_type.is_last() {
self.current_chunk_type = ChunkType::Mid; self.current_chunk_type = ChunkType::Mid;
@@ -243,7 +221,6 @@ impl ChunkedTermVec {
#[derive(Debug)] #[derive(Debug)]
pub struct QueryClause { pub struct QueryClause {
pub ct: ClauseType, pub ct: ClauseType,
pub arity: usize,
pub term: HeapCellValue, pub term: HeapCellValue,
pub code_indices: IndexMap<usize, CodeIndex, FxBuildHasher>, pub code_indices: IndexMap<usize, CodeIndex, FxBuildHasher>,
pub call_policy: CallPolicy, pub call_policy: CallPolicy,
@@ -266,14 +243,14 @@ pub enum QueryTerm {
GetLevel(usize), // var_num GetLevel(usize), // var_num
} }
#[derive(Debug)] #[derive(Clone, Copy, Debug)]
pub struct Fact { pub struct Fact {
pub(crate) term: FocusedHeap, pub(crate) term_loc: usize,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Rule { pub struct Rule {
pub(crate) term: FocusedHeap, pub(crate) term_loc: usize,
pub(crate) clauses: ChunkedTermVec, pub(crate) clauses: ChunkedTermVec,
} }
@@ -290,138 +267,34 @@ impl ListingSource {
} }
} }
pub trait ClauseInfo { pub fn clause_predicate_key_from_heap(
fn is_consistent(&self, clauses: &PredicateQueue) -> bool { heap: &impl SizedHeap,
match clauses.first() { value: HeapCellValue,
Some(cl) => { ) -> Option<PredicateKey> {
self.name() == ClauseInfo::name(cl) && self.arity() == ClauseInfo::arity(cl) read_heap_cell!(value,
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
Some((name, 0))
}
_ => {
if value.is_ref() {
clause_predicate_key(heap, value.get_value() as usize)
} else {
None
} }
None => true,
} }
} )
fn name(&self) -> Option<Atom>;
fn arity(&self) -> usize;
} }
impl ClauseInfo for PredicateKey { pub fn clause_predicate_key(heap: &impl SizedHeap, term_loc: usize) -> Option<PredicateKey> {
#[inline] let key_opt = term_predicate_key(heap, term_loc);
fn name(&self) -> Option<Atom> {
Some(self.0)
}
#[inline] if Some((atom!(":-"), 2)) == key_opt {
fn arity(&self) -> usize { term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| {
self.1 term_predicate_key(heap, arg_loc)
} })
}
fn clause_name(heap: &[HeapCellValue], term_loc: usize) -> Option<Atom> {
let name = term_name(heap, term_loc);
if Some(atom!(":-")) == name && 2 == term_arity(heap, term_loc) {
term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| term_name(heap, arg_loc))
} else { } else {
name key_opt
}
}
fn clause_arity(heap: &[HeapCellValue], term_loc: usize) -> usize {
let name = term_name(heap, term_loc);
if Some(atom!(":-")) == name && 2 == term_arity(heap, term_loc) {
term_nth_arg(heap, term_loc, 1)
.map(|arg_loc| term_arity(heap, arg_loc))
.unwrap_or(0)
} else {
term_arity(heap, term_loc)
}
}
impl ClauseInfo for FocusedHeap {
#[inline]
fn name(&self) -> Option<Atom> {
clause_name(&self.heap, self.focus)
}
#[inline]
fn arity(&self) -> usize {
clause_arity(&self.heap, self.focus)
}
}
impl<'a> ClauseInfo for FocusedHeapRefMut<'a> {
#[inline]
fn name(&self) -> Option<Atom> {
clause_name(self.heap, self.focus)
}
#[inline]
fn arity(&self) -> usize {
clause_arity(self.heap, self.focus)
}
}
/*
impl ClauseInfo for Term {
fn name(&self) -> Option<Atom> {
match self {
Term::Clause(_, name, terms) => {
match name {
atom!(":-") => {
match terms.len() {
1 => None, // a declaration.
2 => terms[0].name(),
_ => Some(*name),
}
}
_ => Some(*name), //str_buf),
}
}
Term::Literal(_, Literal::Atom(name)) => Some(*name),
_ => None,
}
}
fn arity(&self) -> usize {
match self {
Term::Clause(_, name, terms) => match &*name.as_str() {
":-" => match terms.len() {
1 => 0,
2 => terms[0].arity(),
_ => terms.len(),
},
_ => terms.len(),
},
_ => 0,
}
}
}
*/
impl ClauseInfo for Rule {
fn name(&self) -> Option<Atom> {
self.term.name(self.term.focus)
}
fn arity(&self) -> usize {
self.term.arity(self.term.focus)
}
}
impl ClauseInfo for PredicateClause {
fn name(&self) -> Option<Atom> {
match self {
PredicateClause::Fact(ref fact, ..) => fact.term.name(fact.term.focus),
PredicateClause::Rule(ref rule, ..) => rule.term.name(rule.term.focus),
}
}
fn arity(&self) -> usize {
match self {
PredicateClause::Fact(ref fact, ..) => fact.term.arity(fact.term.focus),
PredicateClause::Rule(ref rule, ..) => rule.term.arity(rule.term.focus),
}
} }
} }
@@ -432,33 +305,27 @@ pub enum PredicateClause {
} }
impl PredicateClause { impl PredicateClause {
pub(crate) fn args(&self) -> Option<&[HeapCellValue]> { pub(crate) fn args<'a>(&self, heap: &'a Heap) -> Option<std::ops::RangeInclusive<usize>> {
let (term, focus) = match self { let focus = match self {
PredicateClause::Fact(Fact { term }, _) => (term, term.focus), &PredicateClause::Fact(Fact { term_loc }, _) => term_loc,
PredicateClause::Rule(Rule { term, .. }, _) => { &PredicateClause::Rule(Rule { term_loc, .. }, _) => {
let focus = term.nth_arg(term.focus, 1).unwrap(); term_nth_arg(heap, term_loc, 1).unwrap()
(term, focus)
} }
}; };
let arity = term.arity(focus); let arity = clause_predicate_key(heap, focus)
.map(|(_name, arity)| arity)
.unwrap_or(0);
read_heap_cell!(term.deref_loc(focus), read_heap_cell!(heap_bound_store(heap, heap_bound_deref(heap, heap[focus])),
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
Some(&term.heap[s+1 .. s+arity+1]) Some(s+1 ..= s+arity)
} }
_ => { _ => {
None None
} }
) )
} }
pub(crate) fn heap(&self) -> &[HeapCellValue] {
match self {
PredicateClause::Fact(ref fact, ..) => &fact.term.heap,
PredicateClause::Rule(ref rule, ..) => &rule.term.heap,
}
}
} }
#[derive(Debug)] #[derive(Debug)]
@@ -477,10 +344,10 @@ pub enum ModuleSource {
impl ModuleSource { impl ModuleSource {
pub(crate) fn as_functor_stub(&self) -> MachineStub { pub(crate) fn as_functor_stub(&self) -> MachineStub {
match self { match self {
ModuleSource::Library(name) => { &ModuleSource::Library(name) => {
functor!(atom!("library"), [atom(name)]) functor!(atom!("library"), [atom_as_cell(name)])
} }
ModuleSource::File(name) => { &ModuleSource::File(name) => {
functor!(name) functor!(name)
} }
} }
@@ -813,6 +680,7 @@ impl ArenaFrom<i32> for Number {
} }
} }
/*
impl ArenaFrom<Number> for Literal { impl ArenaFrom<Number> for Literal {
#[inline] #[inline]
fn arena_from(value: Number, arena: &mut Arena) -> Literal { fn arena_from(value: Number, arena: &mut Arena) -> Literal {
@@ -824,6 +692,21 @@ impl ArenaFrom<Number> for Literal {
} }
} }
} }
*/
impl ArenaFrom<u64> for HeapCellValue {
#[inline]
fn arena_from(value: u64, arena: &mut Arena) -> HeapCellValue {
fixnum!(value as i64, arena)
}
}
impl ArenaFrom<usize> for HeapCellValue {
#[inline]
fn arena_from(value: usize, arena: &mut Arena) -> HeapCellValue {
HeapCellValue::arena_from(value as u64, arena)
}
}
impl ArenaFrom<Number> for HeapCellValue { impl ArenaFrom<Number> for HeapCellValue {
#[inline] #[inline]
@@ -896,8 +779,8 @@ impl Number {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) enum OptArgIndexKey { pub(crate) enum OptArgIndexKey {
Literal(usize, usize, Literal, Vec<Literal>), // index, IndexingCode location, opt arg, alternatives Literal(usize, usize, HeapCellValue, Vec<HeapCellValue>), // index, IndexingCode location, opt arg, alternatives
List(usize, usize), // index, IndexingCode location List(usize, usize), // index, IndexingCode location
None, None,
Structure(usize, usize, Atom, usize), // index, IndexingCode location, name, arity Structure(usize, usize, Atom, usize), // index, IndexingCode location, name, arity
} }

616
src/functor_macro.rs Normal file
View File

@@ -0,0 +1,616 @@
use crate::atom_table::*;
use crate::instructions::IndexingCodePtr;
use crate::machine::heap::Heap;
use crate::parser::ast::Fixnum;
use crate::types::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FunctorElement {
AbsoluteCell(HeapCellValue),
Cell(HeapCellValue),
InnerFunctor(u64, Vec<FunctorElement>),
String(u64, String),
}
// helper macros
macro_rules! count {
() => (0);
( $x:tt $($xs:tt)* ) => (1 + count!($($xs)*));
}
// core macros
/*
* functor! is more declarative now, with fewer effects and more
* work done at compile time using const functions. With these
* advantages come new quirks: expressions must generally be wrapped
* in round parentheses for rustc to parse them. See the tests module
* below for examples, especially those involving atom!
* subexpressions.
*/
macro_rules! functor {
($name:expr) => ({
vec![FunctorElement::Cell(atom_as_cell!($name))]
});
($name:expr, [$($dt:ident($($value:tt),*)),+]) => ({
build_functor!([$($dt($($value),*)),*],
[FunctorElement::Cell(atom_as_cell!($name, count!($($dt) *)))],
1,
[])
});
}
macro_rules! inner_functor {
($name:expr, $res_len:expr, [$($dt:ident($($value:tt),*)),+]) => ({
build_functor!([$($dt($($value),*)),*],
[FunctorElement::Cell(atom_as_cell!($name, count!($($dt) *)))],
1 + $res_len,
[])
});
}
macro_rules! build_functor {
([], [$($res:expr),*], $res_len:expr, [$($subfunctor:expr),*]) => ({
vec![$($res,)* $($subfunctor),*]
});
([indexing_code_ptr($e:expr) $(, $dt:ident($($value:tt),*))*],
[$($res:expr),*],
$res_len:expr,
[$($subfunctor:expr),*]) => ({
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(str_loc_as_cell!(1u64 + count!($($dt)*) + $res_len))],
3 + $res_len,
[$($subfunctor, )* FunctorElement::InnerFunctor(2, indexing_code_ptr($e))])
});
([fixnum($e:expr) $(, $dt:ident($($value:tt),*))*],
[$($res:expr),*],
$res_len:expr,
[$($subfunctor:expr),*]) => ({
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(fixnum_as_cell!(Fixnum::build_with($e as i64)))],
1 + $res_len,
[$($subfunctor),*])
});
([cell($e:expr) $(, $dt:ident($($value:tt),*))*],
[$($res:expr),*],
$res_len:expr,
[$($subfunctor:expr),*]) => ({
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::AbsoluteCell($e)],
1 + $res_len,
[$($subfunctor),*])
});
([number($n:expr, $arena:expr) $(, $dt:ident($($value:tt),*))*],
[$($res:expr),*],
$res_len:expr,
[$($subfunctor:expr),*]) => ({
let number_cell = HeapCellValue::arena_from($n, $arena);
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(number_cell)],
1 + $res_len,
[$($subfunctor),*])
});
([list([]) $(, $dt:ident($($value:tt),*))*],
[$($res:expr),*],
$res_len:expr,
[$($subfunctor:expr),*]) => ({
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(empty_list_as_cell!())],
1 + $res_len,
[$($subfunctor),*])
});
([list([$id:ident($($id_value:tt),*) $(, $in_dt:ident($($in_value:tt),*))*]) $(, $dt:ident($($value:tt),*))*],
[$($res:expr),*],
$res_len:expr,
[$($subfunctor:expr),*]) => ({
build_functor!([functor((atom!(".")), [$id($($id_value),*), list([$($in_dt($($in_value),*)),*])])
$(, $dt($($value),*))*],
[$($res),*],
$res_len,
[$($subfunctor),*])
});
([string($s:expr) $(, $dt:ident($($value:tt),*))*], [$($res:expr),*], $res_len:expr, [$($subfunctor:expr),*]) => ({
let string = $s;
let pstr_len = cell_index!(Heap::compute_pstr_size(&string)) as u64;
let result_len = 1 + count!($($dt)*) + $res_len;
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(pstr_loc_as_cell!(heap_index!(result_len as usize) as u64))],
1 + $res_len + pstr_len,
[$($subfunctor, )* FunctorElement::String(pstr_len, string)])
});
([atom_as_cell($n:expr) $(, $dt:ident($($value:tt),*))*], [$($res:expr),*], $res_len:expr, [$($subfunctor:expr),*]) => ({
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(atom_as_cell!($n))],
1 + $res_len,
[$($subfunctor),*])
});
([functor($stub:expr) $(, $dt:ident($($value:tt),*))*], [$($res:expr),*], $res_len:expr, [$($subfunctor:expr),*]) => ({
let result_len = 1u64 + count!($($dt)*) + $res_len;
let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&$stub)) as u64;
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(str_loc_as_cell!(result_len))],
1 + $res_len + inner_functor_size,
[$($subfunctor, )*
FunctorElement::InnerFunctor(inner_functor_size, $stub)])
});
([$id:ident($n:expr) $(, $dt:ident($($value:tt),*))*], [$($res:expr),*], $res_len:expr, [$($subfunctor:expr),*]) => ({
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell($id!($n))],
1 + $res_len,
[$($subfunctor),*])
});
([functor($name:expr, [$($in_dt:ident($($in_value:tt),*)),+]) $(, $dt:ident($($value:tt),*))*],
[$($res:expr),*],
$res_len:expr,
[$($subfunctor:expr),*]) => ({
let result_len = 1u64 + count!($($dt)*) + $res_len;
let inner_functor = inner_functor!($name, 0, [$($in_dt($($in_value),*)),*]);
let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&inner_functor)) as u64;
build_functor!([$($dt($($value),*)),*],
[$($res, )* FunctorElement::Cell(str_loc_as_cell!(result_len))],
1 + $res_len + inner_functor_size,
[$($subfunctor, )*
FunctorElement::InnerFunctor(inner_functor_size, inner_functor)])
});
}
pub(crate) fn indexing_code_ptr(code_ptr: IndexingCodePtr) -> Vec<FunctorElement> {
match code_ptr {
IndexingCodePtr::DynamicExternal(o) => {
functor!(atom!("dynamic_external"), [fixnum(o)])
}
IndexingCodePtr::External(o) => {
functor!(atom!("external"), [fixnum(o)])
}
IndexingCodePtr::Internal(o) => {
functor!(atom!("internal"), [fixnum(o)])
}
IndexingCodePtr::Fail => {
vec![FunctorElement::Cell(atom_as_cell!(atom!("fail")))]
}
}
}
pub(crate) fn variadic_functor(
name: Atom,
arity: usize,
iter: impl Iterator<Item = Vec<FunctorElement>>,
) -> Vec<FunctorElement> {
let mut arg_vec = vec![
FunctorElement::Cell(atom_as_cell!(name, arity)),
FunctorElement::Cell(list_loc_as_cell!(2)),
];
let key_value_pairs: Vec<_> = iter.collect();
let num_items = key_value_pairs.len();
for (idx, _) in key_value_pairs.iter().enumerate() {
arg_vec.push(FunctorElement::Cell(str_loc_as_cell!(2 + num_items * 2 + idx)));
arg_vec.push(FunctorElement::Cell(list_loc_as_cell!(5 + idx)));
}
arg_vec.pop();
arg_vec.push(FunctorElement::Cell(empty_list_as_cell!()));
arg_vec.extend(key_value_pairs
.into_iter()
.map(|kv_func| {
let inner_functor_size = cell_index!(Heap::compute_functor_byte_size(&kv_func));
FunctorElement::InnerFunctor(inner_functor_size as u64, kv_func)
}));
arg_vec
}
#[cfg(test)]
#[allow(unused_parens)]
mod tests {
use super::*;
use FunctorElement::*;
use std::string::String;
#[test]
fn basic_terms() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
char_as_cell('c')]);
assert_eq!(functor.len(), 3);
assert_eq!(functor[0], Cell(atom_as_cell!(atom!("first"), 2)));
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(char_as_cell!('c')));
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1),
fixnum(2)]),
char_as_cell('c')]);
assert_eq!(functor.len(), 5);
assert_eq!(functor[0], Cell(atom_as_cell!(atom!("second"), 3)));
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(str_loc_as_cell!(4)));
assert_eq!(functor[3], Cell(char_as_cell!('c')));
assert_eq!(functor[4], InnerFunctor(3, functor!(atom!("b"), [fixnum(1),
fixnum(2)])));
let functor = functor!(atom!("third"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1), fixnum(2)]),
char_as_cell('c')]);
assert_eq!(functor.len(), 7);
assert_eq!(functor[0], Cell(atom_as_cell!(atom!("third"), 4)));
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
assert_eq!(functor[3], Cell(str_loc_as_cell!(8)));
assert_eq!(functor[4], Cell(char_as_cell!('c')));
assert_eq!(functor[5], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("c"), [fixnum(1), fixnum(2)])));
let functor = functor!(atom!("fourth"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1)]),
functor((atom!("d")), [fixnum(453), fixnum(2)]),
char_as_cell('c')]);
assert_eq!(functor.len(), 9);
assert_eq!(functor[0], Cell(atom_as_cell!(atom!("fourth"), 5)));
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(str_loc_as_cell!(6)));
assert_eq!(functor[3], Cell(str_loc_as_cell!(9)));
assert_eq!(functor[4], Cell(str_loc_as_cell!(11)));
assert_eq!(functor[5], Cell(char_as_cell!('c')));
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("b"), [fixnum(1), fixnum(2)])));
assert_eq!(functor[7], InnerFunctor(2, functor!(atom!("c"), [fixnum(1)])));
assert_eq!(functor[8], InnerFunctor(3, functor!(atom!("d"), [fixnum(453), fixnum(2)])));
}
#[test]
fn basic_terms_in_heap() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))), char_as_cell('b')]);
assert_eq!(functor.len(), 3);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(functor);
let loc = functor_writer(&mut heap).unwrap();
assert_eq!(loc, str_loc_as_cell!(0));
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2));
assert_eq!(heap[1], atom_as_cell!(atom!("a")));
assert_eq!(heap[2], char_as_cell!('b'));
heap.truncate(2);
let functor = functor!(atom!("second"), [atom_as_cell((atom!("a"))),
functor((atom!("b")), [fixnum(1), fixnum(2)]),
functor((atom!("c")), [fixnum(1), fixnum(2)]),
char_as_cell('b')]);
assert_eq!(functor.len(), 7);
let mut functor_writer = Heap::functor_writer(functor);
let loc = functor_writer(&mut heap).unwrap();
assert_eq!(loc, str_loc_as_cell!(2));
assert_eq!(heap[2], atom_as_cell!(atom!("second"), 4));
assert_eq!(heap[3], atom_as_cell!(atom!("a")));
assert_eq!(heap[4], str_loc_as_cell!(7));
assert_eq!(heap[5], str_loc_as_cell!(10));
assert_eq!(heap[6], char_as_cell!('b'));
assert_eq!(heap[7], atom_as_cell!(atom!("b"), 2));
assert_eq!(heap[8], fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(heap[9], fixnum_as_cell!(Fixnum::build_with(2)));
assert_eq!(heap[10], atom_as_cell!(atom!("c"), 2));
assert_eq!(heap[11], fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(heap[12], fixnum_as_cell!(Fixnum::build_with(2)));
}
#[test]
fn nested_functors() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
functor((atom!("d")), [fixnum(1),
functor((atom!("b")),
[atom_as_cell((atom!("c"))),
char_as_cell('c')])]),
functor((atom!("e")), [fixnum(453),
fixnum(2)]),
char_as_cell('b')]);
assert_eq!(functor.len(), 7);
assert_eq!(functor[0], Cell(atom_as_cell!(atom!("first"), 4)));
assert_eq!(functor[1], Cell(atom_as_cell!(atom!("a"))));
assert_eq!(functor[2], Cell(str_loc_as_cell!(5)));
assert_eq!(functor[3], Cell(str_loc_as_cell!(11)));
assert_eq!(functor[4], Cell(char_as_cell!('b')));
assert_eq!(functor[5], InnerFunctor(6, vec![Cell(atom_as_cell!(atom!("d"), 2)),
Cell(fixnum_as_cell!(Fixnum::build_with(1))),
Cell(str_loc_as_cell!(3)),
InnerFunctor(3, functor!(atom!("b"), [atom_as_cell((atom!("c"))),
char_as_cell('c')]))]));
assert_eq!(functor[6], InnerFunctor(3, functor!(atom!("e"), [fixnum(453),
fixnum(2)])));
}
#[test]
fn nested_functors_in_heap() {
let functor = functor!(atom!("first"), [atom_as_cell((atom!("a"))),
functor((atom!("second")), [fixnum(1),
functor((atom!("third")), [atom_as_cell((atom!("b"))),
char_as_cell('c')])]),
functor((atom!("fourth")), [fixnum(453), fixnum(2)]),
char_as_cell('b')]);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(functor);
let loc = functor_writer(&mut heap).unwrap();
assert_eq!(loc, str_loc_as_cell!(0));
assert_eq!(heap.cell_len(), 14);
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 4));
assert_eq!(heap[1], atom_as_cell!(atom!("a")));
assert_eq!(heap[2], str_loc_as_cell!(5));
assert_eq!(heap[3], str_loc_as_cell!(11));
assert_eq!(heap[4], char_as_cell!('b'));
assert_eq!(heap[5], atom_as_cell!(atom!("second"), 2));
assert_eq!(heap[6], fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(heap[7], str_loc_as_cell!(8));
assert_eq!(heap[8], atom_as_cell!(atom!("third"), 2));
assert_eq!(heap[9], atom_as_cell!(atom!("b")));
assert_eq!(heap[10], char_as_cell!('c'));
assert_eq!(heap[11], atom_as_cell!(atom!("fourth"), 2));
assert_eq!(heap[12], fixnum_as_cell!(Fixnum::build_with(453)));
assert_eq!(heap[13], fixnum_as_cell!(Fixnum::build_with(2)));
}
#[test]
fn functors_with_strings_in_heap() {
let functor = functor!(atom!("first"), [string((String::from("a string")))]);
assert_eq!(functor.len(), 3);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(functor);
let loc = functor_writer(&mut heap).unwrap();
assert_eq!(loc, str_loc_as_cell!(0));
assert_eq!(heap.cell_len(), 5);
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 1));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!(heap.slice_to_str(heap_index!(2), "a string".len()), "a string");
assert_eq!(heap[4], empty_list_as_cell!());
heap.truncate(0);
let functor = functor!(atom!("second"), [string((String::from("a stuttered\0 string")))]);
let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
assert_eq!(heap.cell_len(), 7);
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 1));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!(heap.slice_to_str(heap_index!(2), "a stuttered".len()), "a stuttered");
assert_eq!(heap[4], pstr_loc_as_cell!(heap_index!(5)));
assert_eq!(heap.slice_to_str(heap_index!(5), " string".len()), " string");
assert_eq!(heap[6], empty_list_as_cell!());
}
#[test]
fn functors_with_lists_in_heap() {
let functor = functor!(
atom!("first"),
[list([fixnum(1),
atom_as_cell((atom!("a"))),
fixnum(2)])]
);
assert_eq!(functor.len(), 3);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
assert_eq!(heap.cell_len(), 11);
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 1));
assert_eq!(heap[1], str_loc_as_cell!(2));
assert_eq!(heap[2], atom_as_cell!(atom!("."), 2));
assert_eq!(heap[3], fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(heap[4], str_loc_as_cell!(5));
assert_eq!(heap[5], atom_as_cell!(atom!("."), 2));
assert_eq!(heap[6], atom_as_cell!(atom!("a")));
assert_eq!(heap[7], str_loc_as_cell!(8));
assert_eq!(heap[8], atom_as_cell!(atom!("."), 2));
assert_eq!(heap[9], fixnum_as_cell!(Fixnum::build_with(2)));
assert_eq!(heap[10], empty_list_as_cell!());
}
#[test]
fn inlined_atoms() {
let atom_table = AtomTable::new();
let inlined = AtomTable::build_with(&atom_table, "inline");
assert!(inlined.is_inlined());
assert_eq!(&*inlined.as_str(), "inline");
let non_inlined = AtomTable::build_with(&atom_table, "longer non-inlined atom");
assert!(!non_inlined.is_inlined());
assert_eq!(&*non_inlined.as_str(), "longer non-inlined atom");
}
#[test]
fn functors_with_indexing_code_ptr() {
let code_ptr = IndexingCodePtr::Internal(0);
let functor = functor!(
atom!("first"),
[string((String::from("a string"))),
indexing_code_ptr(code_ptr)]
);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
assert_eq!(heap.cell_len(), 8);
assert_eq!(heap[0], atom_as_cell!(atom!("first"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6));
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
assert_eq!(heap[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[7], fixnum_as_cell!(Fixnum::build_with(0)));
heap.truncate(0);
let functor = functor!(atom!("second"),
[string((String::from("a string"))),
functor((atom!("third")), [atom_as_cell((atom!("a"))),
string((String::from("another string"))),
indexing_code_ptr(code_ptr)])]);
let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
assert_eq!(heap.cell_len(), 15);
assert_eq!(heap[0], atom_as_cell!(atom!("second"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6));
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
assert_eq!(heap[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("third"), 3));
assert_eq!(heap[7], atom_as_cell!(atom!("a")));
assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(10)));
assert_eq!(heap[9], str_loc_as_cell!(13));
assert_eq!(heap.slice_to_str(heap_index!(10), "another string".len()), "another string");
assert_eq!(heap[12], empty_list_as_cell!());
assert_eq!(heap[13], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[14], fixnum_as_cell!(Fixnum::build_with(0)));
let functor = functor!(atom!("fourth"),
[string((String::from("a string"))),
functor((atom!("a")),
[functor((atom!("fifth")), [fixnum(5),
string((String::from("another string"))),
indexing_code_ptr(code_ptr)]),
string((String::from("and another")))])]);
heap.truncate(0);
let mut functor_writer = Heap::functor_writer(functor);
functor_writer(&mut heap).unwrap();
assert_eq!(heap.cell_len(), 21);
assert_eq!(heap[0], atom_as_cell!(atom!("fourth"), 2));
assert_eq!(heap[1], pstr_loc_as_cell!(heap_index!(3)));
assert_eq!(heap[2], str_loc_as_cell!(6));
assert_eq!(heap.slice_to_str(heap_index!(3), "a string".len()), "a string");
assert_eq!(heap[5], empty_list_as_cell!());
assert_eq!(heap[6], atom_as_cell!(atom!("a"), 2));
assert_eq!(heap[7], str_loc_as_cell!(9));
assert_eq!(heap[8], pstr_loc_as_cell!(heap_index!(18))); // <-- wrong!
assert_eq!(heap[9], atom_as_cell!(atom!("fifth"), 3));
assert_eq!(heap[10], fixnum_as_cell!(Fixnum::build_with(5)));
assert_eq!(heap[11], pstr_loc_as_cell!(heap_index!(13)));
assert_eq!(heap[12], str_loc_as_cell!(16));
assert_eq!(heap.slice_to_str(heap_index!(13), "another string".len()), "another string");
assert_eq!(heap[15], empty_list_as_cell!());
assert_eq!(heap[16], atom_as_cell!(atom!("internal"), 1));
assert_eq!(heap[17], fixnum_as_cell!(Fixnum::build_with(0)));
assert_eq!(heap.slice_to_str(heap_index!(18), "and another".len()), "and another");
assert_eq!(heap[20], empty_list_as_cell!());
}
#[test]
fn undefined_procedure_functor() {
// existence_error
let culprit = functor!(atom!("/"), [atom_as_cell((atom!("a"))), fixnum(1)]);
let stub = functor!(
atom!("existence_error"),
[atom_as_cell((atom!("procedure"))), functor((culprit.clone()))]
);
println!("{:?}", stub);
// now the error form
let lineless_error_form = functor!(
atom!("error"),
[functor(stub),
functor(culprit)]
);
println!("{:?}", lineless_error_form);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(lineless_error_form);
functor_writer(&mut heap).unwrap();
assert_eq!(heap[0], atom_as_cell!(atom!("error"), 2));
assert_eq!(heap[1], str_loc_as_cell!(3));
assert_eq!(heap[2], str_loc_as_cell!(9));
assert_eq!(heap[3], atom_as_cell!(atom!("existence_error"), 2));
assert_eq!(heap[4], atom_as_cell!(atom!("procedure")));
assert_eq!(heap[5], str_loc_as_cell!(6)); // is str_loc_as_cell!(3)
assert_eq!(heap[6], atom_as_cell!(atom!("/"), 2));
assert_eq!(heap[7], atom_as_cell!(atom!("a")));
assert_eq!(heap[8], fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(heap[9], atom_as_cell!(atom!("/"), 2));
assert_eq!(heap[10], atom_as_cell!(atom!("a")));
assert_eq!(heap[11], fixnum_as_cell!(Fixnum::build_with(1)));
}
#[test]
fn argless_functor() {
let name = functor!(atom!("[]"));
assert_eq!(name.len(), 1);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(name);
let loc = functor_writer(&mut heap).unwrap();
assert_eq!(loc, heap_loc_as_cell!(0));
}
#[test]
fn predefined_subfunctors() {
let stub = functor!(atom!("sub"), [atom_as_cell((atom!("[]")))]);
let name = functor!(atom!("super"), [functor(stub)]);
let mut heap = Heap::new();
let mut functor_writer = Heap::functor_writer(name);
functor_writer(&mut heap).unwrap();
assert_eq!(heap.cell_len(), 4);
assert_eq!(heap[0], atom_as_cell!(atom!("super"), 1));
assert_eq!(heap[1], str_loc_as_cell!(2));
assert_eq!(heap[2], atom_as_cell!(atom!("sub"), 1));
assert_eq!(heap[3], empty_list_as_cell!());
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,6 @@ use crate::forms::*;
use crate::heap_iter::*; use crate::heap_iter::*;
use crate::machine::heap::*; use crate::machine::heap::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::machine_state::pstr_loc_and_offset;
use crate::machine::partial_string::*; use crate::machine::partial_string::*;
use crate::machine::stack::*; use crate::machine::stack::*;
use crate::machine::streams::*; use crate::machine::streams::*;
@@ -25,7 +24,6 @@ use std::convert::TryFrom;
use std::iter::once; use std::iter::once;
use std::net::{IpAddr, TcpListener}; use std::net::{IpAddr, TcpListener};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
/* contains the location, name, precision and Specifier of the parent op. */ /* contains the location, name, precision and Specifier of the parent op. */
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@@ -206,11 +204,12 @@ impl NumberFocus {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
struct CommaSeparatedCharList { struct CommaSeparatedCharList {
pstr: PartialString, // pstr: PartialString,
offset: usize, // offset: usize,
pstr_loc: usize,
max_depth: usize, max_depth: usize,
end_cell: HeapCellValue, // end_cell: HeapCellValue,
end_h: Option<usize>, // end_h: Option<usize>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -473,7 +472,6 @@ pub fn fmt_float(mut fl: f64) -> String {
pub struct HCPrinter<'a, Outputter> { pub struct HCPrinter<'a, Outputter> {
outputter: Outputter, outputter: Outputter,
iter: StackfulPreOrderHeapIter<'a, ListElider>, iter: StackfulPreOrderHeapIter<'a, ListElider>,
atom_tbl: Arc<AtomTable>,
op_dir: &'a OpDir, op_dir: &'a OpDir,
state_stack: Vec<TokenOrRedirect>, state_stack: Vec<TokenOrRedirect>,
toplevel_spec: Option<DirectedOp>, toplevel_spec: Option<DirectedOp>,
@@ -488,9 +486,19 @@ pub struct HCPrinter<'a, Outputter> {
pub double_quotes: bool, pub double_quotes: bool,
} }
fn ambiguity_check(outputter: &impl HCValueOutputter, quoted: bool, last_item_idx: usize, atom: &str) -> bool {
let tail = &outputter.as_str()[last_item_idx..];
if atom == "," || !quoted || non_quoted_token(atom.chars()) {
requires_space(tail, atom)
} else {
requires_space(tail, "'")
}
}
macro_rules! push_space_if_amb { macro_rules! push_space_if_amb {
($self:expr, $atom:expr, $action:block) => { ($self:expr, $atom:expr, $action:block) => {
if $self.ambiguity_check($atom) { if ambiguity_check(&$self.outputter, $self.quoted, $self.last_item_idx, $atom) {
$self.outputter.push_char(' '); $self.outputter.push_char(' ');
$action; $action;
} else { } else {
@@ -528,7 +536,6 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option<String>
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
pub fn new( pub fn new(
heap: &'a mut Heap, heap: &'a mut Heap,
atom_tbl: Arc<AtomTable>,
stack: &'a mut Stack, stack: &'a mut Stack,
op_dir: &'a OpDir, op_dir: &'a OpDir,
output: Outputter, output: Outputter,
@@ -537,7 +544,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
HCPrinter { HCPrinter {
outputter: output, outputter: output,
iter: stackful_preorder_iter(heap, stack, root_loc), iter: stackful_preorder_iter(heap, stack, root_loc),
atom_tbl,
op_dir, op_dir,
state_stack: vec![], state_stack: vec![],
toplevel_spec: None, toplevel_spec: None,
@@ -553,17 +559,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} }
} }
#[inline]
fn ambiguity_check(&self, atom: &str) -> bool {
let tail = &self.outputter.as_str()[self.last_item_idx..];
if atom == "," || !self.quoted || non_quoted_token(atom.chars()) {
requires_space(tail, atom)
} else {
requires_space(tail, "'")
}
}
fn set_parent_of_first_op(&mut self, parent_op: Option<DirectedOp>) { fn set_parent_of_first_op(&mut self, parent_op: Option<DirectedOp>) {
if let Some(op) = parent_op { if let Some(op) = parent_op {
if op.is_left() && op.is_prefix() { if op.is_left() && op.is_prefix() {
@@ -1123,9 +1118,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
// returns true if max_depth limit is reached and ellipsis is printed. // returns true if max_depth limit is reached and ellipsis is printed.
fn print_string_as_functor(&mut self, focus: usize, max_depth: &mut usize) -> bool { fn print_string_as_functor(&mut self, focus: usize, max_depth: &mut usize) -> bool {
let iter = HeapPStrIter::new(self.iter.heap, focus); let mut iter = HeapPStrIter::new(self.iter.heap, focus);
let mut char_count = 0;
for (char_count, c) in iter.chars().enumerate() { while let Some(iteratee) = iter.next() {
if self.check_max_depth(max_depth) { if self.check_max_depth(max_depth) {
if char_count > 0 { if char_count > 0 {
self.state_stack.push(TokenOrRedirect::Close); self.state_stack.push(TokenOrRedirect::Close);
@@ -1135,13 +1131,31 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
return true; return true;
} }
append_str!(self, "'.'"); macro_rules! emit_char {
push_char!(self, '('); ($c:expr) => ({
append_str!(self, "'.'");
push_char!(self, '(');
print_char!(self, self.quoted, c); print_char!(self, self.quoted, $c);
push_char!(self, ','); push_char!(self, ',');
self.state_stack.push(TokenOrRedirect::Close); self.state_stack.push(TokenOrRedirect::Close);
char_count += 1;
});
}
match iteratee {
PStrIteratee::Char { value, .. } => {
emit_char!(value);
}
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
let s = iter.heap.slice_to_str(slice_loc, slice_len);
for c in s.chars() {
emit_char!(c);
}
}
}
} }
false false
@@ -1152,7 +1166,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
fn print_proper_string(&mut self, focus: usize, max_depth: usize) { fn print_proper_string(&mut self, focus: usize, max_depth: usize) {
push_char!(self, '"'); push_char!(self, '"');
let iter = HeapPStrIter::new(self.iter.heap, focus); let mut iter = HeapPStrIter::new(self.iter.heap, focus);
let char_to_string = |c: char| { let char_to_string = |c: char| {
// refrain from quoting characters other than '"' and '\' // refrain from quoting characters other than '"' and '\'
// unless self.quoted is true. // unless self.quoted is true.
@@ -1164,19 +1179,43 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
}; };
if max_depth == 0 { if max_depth == 0 {
for c in iter.chars() { while let Some(iteratee) = iter.next() {
for c in char_to_string(c).chars() { let iter: Box<dyn Iterator<Item = char>> = match iteratee {
push_char!(self, c); PStrIteratee::Char { value: c, .. } => {
Box::new(std::iter::once(c))
}
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
let s = iter.heap.slice_to_str(slice_loc, slice_len);
Box::new(s.chars())
}
};
for c in iter {
for c in char_to_string(c).chars() {
push_char!(self, c);
}
} }
} }
} else { } else {
let mut char_count = 0; let mut char_count = 0;
for c in iter.chars().take(max_depth) { while let Some(iteratee) = iter.next() {
char_count += 1; let iter: Box<dyn Iterator<Item = char>> = match iteratee {
PStrIteratee::Char { value: c, .. } => {
Box::new(std::iter::once(c))
}
PStrIteratee::PStrSlice { slice_loc, slice_len } => {
let s = iter.heap.slice_to_str(slice_loc, slice_len);
Box::new(s.chars())
}
};
for c in char_to_string(c).chars() { for c in iter.take(max_depth - char_count) {
push_char!(self, c); char_count += 1;
for c in char_to_string(c).chars() {
push_char!(self, c);
}
} }
} }
@@ -1194,10 +1233,10 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
self.iter.pop_stack(); self.iter.pop_stack();
self.iter.pop_stack(); self.iter.pop_stack();
} }
HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset => { HeapCellValueTag::PStrLoc => {
self.iter.pop_stack(); self.iter.pop_stack();
} }
HeapCellValueTag::CStr => {} // HeapCellValueTag::CStr => {}
_ => { _ => {
unreachable!(); unreachable!();
} }
@@ -1208,19 +1247,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let focus = self.iter.focus(); let focus = self.iter.focus();
let mut heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus.value() as usize); let mut heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus.value() as usize);
let next_h; let is_cyclic = if heap_pstr_iter.next().is_some() {
let next_hare;
if heap_pstr_iter.next().is_some() {
next_h = heap_pstr_iter.focus;
next_hare = heap_pstr_iter.focus();
for _ in heap_pstr_iter.by_ref() {} for _ in heap_pstr_iter.by_ref() {}
heap_pstr_iter.is_cyclic()
} else { } else {
return self.push_list(max_depth); return self.push_list(max_depth);
} };
let end_h = heap_pstr_iter.focus(); let end_h = heap_pstr_iter.focus();
let end_cell = heap_pstr_iter.focus; let end_cell = heap_pstr_iter.heap[end_h]; // heap_pstr_iter.focus;
if self.check_max_depth(&mut max_depth) { if self.check_max_depth(&mut max_depth) {
self.remove_list_children(focus.value() as usize); self.remove_list_children(focus.value() as usize);
@@ -1230,9 +1265,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
let at_cdr = self.outputter.ends_with("|"); let at_cdr = self.outputter.ends_with("|");
if self.double_quotes && !self.ignore_ops && end_cell.is_string_terminator(self.iter.heap) { if self.double_quotes && !self.ignore_ops && !is_cyclic {
self.remove_list_children(focus.value() as usize); if end_cell.is_string_terminator(self.iter.heap) {
return self.print_proper_string(focus.value() as usize, max_depth); self.remove_list_children(focus.value() as usize);
return self.print_proper_string(focus.value() as usize, max_depth);
}
} }
if self.ignore_ops { if self.ignore_ops {
@@ -1261,37 +1298,27 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
(HeapCellValueTag::Lis) => { (HeapCellValueTag::Lis) => {
self.push_list(max_depth) self.push_list(max_depth)
} }
_ => { (HeapCellValueTag::PStrLoc, h) => {
let switch = Rc::new(Cell::new((!at_cdr, 0))); let switch = Rc::new(Cell::new((!at_cdr, 0)));
let switch = self.close_list(switch); let switch = self.close_list(switch);
let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus.value() as usize);
let offset = offset.get_num() as usize;
let tag = value.get_tag();
let end_h = if tag == HeapCellValueTag::PStrOffset {
// remove the fixnum offset from the iterator stack so we don't
// print an extraneous number. pstr offset value cells are never
// used by the iterator to mark cyclic terms so the removal is safe.
self.iter.pop_stack();
Some(next_hare)
// Some(end_h)
} else {
None
};
if !self.max_depth_exhausted(max_depth) { if !self.max_depth_exhausted(max_depth) {
let pstr = cell_as_string!(self.iter.heap[h]); self.state_stack.push(
self.state_stack.push(TokenOrRedirect::CommaSeparatedCharList(CommaSeparatedCharList { TokenOrRedirect::CommaSeparatedCharList(
pstr, offset, max_depth, end_cell: next_h, end_h, CommaSeparatedCharList {
})); pstr_loc: h, max_depth,
}
),
);
} else { } else {
self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
} }
self.open_list(switch); self.open_list(switch);
} }
_ => {
unreachable!()
}
); );
} }
} }
@@ -1521,32 +1548,29 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
fn print_comma_separated_char_list(&mut self, char_list: CommaSeparatedCharList) { fn print_comma_separated_char_list(&mut self, char_list: CommaSeparatedCharList) {
let CommaSeparatedCharList { let CommaSeparatedCharList {
pstr, pstr_loc,
offset,
max_depth, max_depth,
end_cell,
end_h,
} = char_list; } = char_list;
let pstr_str = pstr.as_str_from(offset);
if let Some(c) = pstr_str.chars().next() { let c = self.iter.heap.char_at(pstr_loc);
let offset = offset + c.len_utf8();
if c != '\u{0}' || pstr_loc % std::mem::size_of::<HeapCellValue>() == 0 {
// if a null character in a pstr has location aligned
// to a cell boundary, the string is ['\\x0\\'].
if !self.max_depth_exhausted(max_depth) { if !self.max_depth_exhausted(max_depth) {
self.state_stack self.state_stack
.push(TokenOrRedirect::CommaSeparatedCharList( .push(TokenOrRedirect::CommaSeparatedCharList(
CommaSeparatedCharList { CommaSeparatedCharList {
pstr, pstr_loc: pstr_loc + c.len_utf8(),
offset,
max_depth: max_depth.saturating_sub(1), max_depth: max_depth.saturating_sub(1),
end_cell,
end_h,
}, },
)); ));
let max_depth_allows = self.max_depth == 0 || max_depth > 1; let max_depth_allows = self.max_depth == 0 || max_depth > 1;
let next_c = self.iter.heap.char_at(pstr_loc + c.len_utf8());
if max_depth_allows && pstr_str.chars().nth(1).is_some() { if max_depth_allows && next_c != '\u{0}' {
self.state_stack.push(TokenOrRedirect::Comma); self.state_stack.push(TokenOrRedirect::Comma);
} }
@@ -1558,14 +1582,23 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
} else if self.max_depth_exhausted(max_depth) { } else if self.max_depth_exhausted(max_depth) {
self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
} else if end_cell != empty_list_as_cell!() { } else {
if let Some(end_h) = end_h { /*
self.iter let end_cell_h = Heap::neighboring_cell_offset(pstr_loc);
.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap)); let end_cell = self.iter.heap[end_cell_h];
} let end_cell = heap_bound_store(
self.iter.heap,
heap_bound_deref(self.iter.heap, end_cell),
);
self.state_stack if end_cell != empty_list_as_cell!() {
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1)); self.iter.push_stack(
IterStackLoc::iterable_loc(end_cell_h, HeapOrStackTag::Heap),
);
}
*/
self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
} }
} }
@@ -1658,10 +1691,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
print_struct(self, name, arity); print_struct(self, name, arity);
} }
(HeapCellValueTag::Char, c) => {
let name = AtomTable::build_with(&self.atom_tbl, &String::from(c));
print_struct(self, name, 0);
}
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.iter.heap[s]) let (name, arity) = cell_as_atom_cell!(self.iter.heap[s])
.get_name_and_arity(); .get_name_and_arity();
@@ -1688,7 +1717,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
(HeapCellValueTag::F64, f) => { (HeapCellValueTag::F64, f) => {
self.print_number(max_depth, NumberFocus::Unfocused(Number::Float(*f)), &op); self.print_number(max_depth, NumberFocus::Unfocused(Number::Float(*f)), &op);
} }
(HeapCellValueTag::CStr | HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => { (HeapCellValueTag::PStrLoc) => { // HeapCellValueTag::CStr | HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
self.print_list_like(max_depth); self.print_list_like(max_depth);
} }
(HeapCellValueTag::Lis) => { (HeapCellValueTag::Lis) => {
@@ -1825,6 +1854,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
mod tests { mod tests {
use super::*; use super::*;
use crate::functor_macro::*;
use crate::machine::mock_wam::*; use crate::machine::mock_wam::*;
#[test] #[test]
@@ -1832,25 +1862,30 @@ mod tests {
fn term_printing_tests() { fn term_printing_tests() {
let mut wam = MockWAM::new(); let mut wam = MockWAM::new();
// clear the heap of resource error data etc
wam.machine_st.heap.clear();
let f_atom = atom!("f"); let f_atom = atom!("f");
let a_atom = atom!("a"); let a_atom = atom!("a");
let b_atom = atom!("b"); let b_atom = atom!("b");
let c_atom = atom!("c"); let c_atom = atom!("c");
wam.machine_st let mut functor_writer = Heap::functor_writer(functor!(
.heap f_atom,
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); [atom_as_cell(a_atom),
atom_as_cell(b_atom)]),
);
wam.machine_st.heap.push(str_loc_as_cell!(0)); let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push_cell(cell).unwrap();
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
0, 3,
); );
let output = printer.print(); let output = printer.print();
@@ -1858,31 +1893,31 @@ mod tests {
assert_eq!(output.result(), "f(a,b)"); assert_eq!(output.result(), "f(a,b)");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
wam.machine_st.heap.extend(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[ [
atom(a_atom), atom_as_cell(a_atom),
atom(b_atom), atom_as_cell(b_atom),
atom(a_atom), atom_as_cell(a_atom),
cell(str_loc_as_cell!(0)) str_loc_as_cell(0)
] ]
)); ));
let h = wam.machine_st.heap.len(); let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
wam.machine_st.heap.push(str_loc_as_cell!(0));
wam.machine_st.heap.push_cell(cell).unwrap();
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
h, 5,
); );
let output = printer.print(); let output = printer.print();
@@ -1890,19 +1925,22 @@ mod tests {
assert_eq!(output.result(), "f(a,b,a,...)"); assert_eq!(output.result(), "f(a,b,a,...)");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let mut writer = wam.machine_st.heap.reserve(96).unwrap();
// print L = [L|L]. // print L = [L|L].
wam.machine_st.heap.push(list_loc_as_cell!(1)); writer.write_with(|section| {
wam.machine_st.heap.push(list_loc_as_cell!(1)); section.push_cell(list_loc_as_cell!(1));
wam.machine_st.heap.push(list_loc_as_cell!(1)); section.push_cell(list_loc_as_cell!(1));
section.push_cell(list_loc_as_cell!(1));
});
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -1915,7 +1953,6 @@ mod tests {
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -1931,24 +1968,32 @@ mod tests {
assert_eq!(output.result(), "[L|L]"); assert_eq!(output.result(), "[L|L]");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]); let mut writer = wam.machine_st.heap.reserve(96).unwrap();
wam.machine_st.heap.push(list_loc_as_cell!(1)); writer.write_with(|section| {
wam.machine_st.heap.push(str_loc_as_cell!(5)); section.push_cell(list_loc_as_cell!(1));
wam.machine_st.heap.push(list_loc_as_cell!(3)); section.push_cell(str_loc_as_cell!(5));
wam.machine_st.heap.push(str_loc_as_cell!(5)); section.push_cell(list_loc_as_cell!(3));
wam.machine_st.heap.push(empty_list_as_cell!()); section.push_cell(str_loc_as_cell!(5));
section.push_cell(empty_list_as_cell!());
});
wam.machine_st.heap.extend(functor); let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[atom_as_cell(a_atom),
atom_as_cell(b_atom),
atom_as_cell(b_atom)]
));
functor_writer(&mut wam.machine_st.heap).unwrap();
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -1960,14 +2005,13 @@ mod tests {
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)]"); assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)]");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap[4] = list_loc_as_cell!(1); wam.machine_st.heap[4] = list_loc_as_cell!(1);
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -1979,12 +2023,11 @@ mod tests {
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|...]"); assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|...]");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
{ {
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -2000,23 +2043,27 @@ mod tests {
assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|L]"); assert_eq!(output.result(), "[f(a,b,b),f(a,b,b)|L]");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
// issue #382 // issue #382
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
wam.machine_st.heap.push(list_loc_as_cell!(1));
for idx in 0..3000 { let mut writer = wam.machine_st.heap.reserve(6002).unwrap();
wam.machine_st.heap.push(heap_loc_as_cell!(2 * idx + 1));
wam.machine_st.heap.push(list_loc_as_cell!(2 * idx + 2 + 1));
}
wam.machine_st.heap.push(empty_list_as_cell!()); writer.write_with(|section| {
section.push_cell(list_loc_as_cell!(1));
for idx in 0..3000 {
section.push_cell(heap_loc_as_cell!(2 * idx + 1));
section.push_cell(list_loc_as_cell!(2 * idx + 2 + 1));
}
section.push_cell(empty_list_as_cell!());
});
{ {
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
@@ -2030,24 +2077,22 @@ mod tests {
assert_eq!(output.result(), "[_1,_3,_5,_7,_9|...]"); assert_eq!(output.result(), "[_1,_3,_5,_7,_9|...]");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
put_partial_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl); wam.machine_st.allocate_pstr("abc").unwrap();
wam.machine_st.heap.push(pstr_loc_as_cell!(0)); wam.machine_st.heap.push_cell(heap_loc_as_cell!(1)).unwrap();
wam.machine_st.heap.push_cell(pstr_loc_as_cell!(0)).unwrap();
let h = wam.machine_st.heap.len() - 1;
{ {
let printer = HCPrinter::new( let printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
h, 2,
); );
let output = printer.print(); let output = printer.print();
@@ -2055,28 +2100,28 @@ mod tests {
assert_eq!(output.result(), "[a,b,c|_1]"); assert_eq!(output.result(), "[a,b,c|_1]");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.pop(); let mut writer = wam.machine_st.heap.reserve(96).unwrap();
wam.machine_st.heap.pop();
wam.machine_st.heap.push(list_loc_as_cell!(2)); writer.write_with(|section| {
section.push_cell(atom_as_cell!(a_atom));
section.push_cell(list_loc_as_cell!(5));
section.push_cell(atom_as_cell!(b_atom));
section.push_cell(list_loc_as_cell!(7));
section.push_cell(atom_as_cell!(c_atom));
section.push_cell(empty_list_as_cell!());
});
wam.machine_st.heap.push(atom_as_cell!(a_atom)); wam.machine_st.heap[1] = list_loc_as_cell!(3);
wam.machine_st.heap.push(list_loc_as_cell!(4));
wam.machine_st.heap.push(atom_as_cell!(b_atom));
wam.machine_st.heap.push(list_loc_as_cell!(6));
wam.machine_st.heap.push(atom_as_cell!(c_atom));
wam.machine_st.heap.push(empty_list_as_cell!());
{ {
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut wam.machine_st.heap, &mut wam.machine_st.heap,
Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack, &mut wam.machine_st.stack,
&wam.op_dir, &wam.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
0, 2,
); );
printer.double_quotes = true; printer.double_quotes = true;
@@ -2086,7 +2131,7 @@ mod tests {
assert_eq!(output.result(), "\"abcabc\""); assert_eq!(output.result(), "\"abcabc\"");
} }
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
@@ -2095,14 +2140,14 @@ mod tests {
"=(X,[a,b,c|X])" "=(X,[a,b,c|X])"
); );
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!( assert_eq!(
&wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(), &wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(),
"[a,b,[a],[a,b,c]]" "[a,b,[a],[a,b,c]]"
); );
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!( assert_eq!(
&wam.parse_and_print_term("[\"abc\",e,f,[g,e,h,Y,v|[X,Y]]].") &wam.parse_and_print_term("[\"abc\",e,f,[g,e,h,Y,v|[X,Y]]].")
@@ -2110,11 +2155,11 @@ mod tests {
"[[a,b,c],e,f,[g,e,h,Y,v,X,Y]]" "[[a,b,c],e,f,[g,e,h,Y,v,X,Y]]"
); );
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(&wam.parse_and_print_term("f((a,b)).").unwrap(), "f((a,b))"); assert_eq!(&wam.parse_and_print_term("f((a,b)).").unwrap(), "f((a,b))");
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.op_dir wam.op_dir
.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX)); .insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
@@ -2126,14 +2171,14 @@ mod tests {
"[a|[]+b]" "[a|[]+b]"
); );
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!( assert_eq!(
&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(), &wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
"[a|[b|c]*d]" "[a|[b|c]*d]"
); );
all_cells_unmarked(&wam.machine_st.heap); all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.op_dir wam.op_dir
.insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY)); .insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY));

View File

@@ -1,7 +1,8 @@
use crate::atom_table::*; use crate::atom_table::*;
use crate::forms::*; use crate::forms::*;
use crate::instructions::*; use crate::instructions::*;
use crate::parser::ast::*; use crate::machine::heap::*;
use crate::parser::ast::Fixnum;
use crate::types::*; use crate::types::*;
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
@@ -144,7 +145,7 @@ impl<'a> IndexingCodeMergingPtr<'a> {
fn add_static_indexed_choice_for_constant( fn add_static_indexed_choice_for_constant(
&mut self, &mut self,
external: usize, external: usize,
constant: Literal, constant: HeapCellValue,
index: usize, index: usize,
) { ) {
let third_level_index = if self.append_or_prepend.is_append() { let third_level_index = if self.append_or_prepend.is_append() {
@@ -181,7 +182,7 @@ impl<'a> IndexingCodeMergingPtr<'a> {
fn add_dynamic_indexed_choice_for_constant( fn add_dynamic_indexed_choice_for_constant(
&mut self, &mut self,
external: usize, external: usize,
constant: Literal, constant: HeapCellValue,
index: usize, index: usize,
) { ) {
let third_level_index = if self.append_or_prepend.is_append() { let third_level_index = if self.append_or_prepend.is_append() {
@@ -235,8 +236,8 @@ impl<'a> IndexingCodeMergingPtr<'a> {
fn index_overlapping_constant( fn index_overlapping_constant(
&mut self, &mut self,
orig_constant: Literal, orig_constant: HeapCellValue,
overlapping_constant: Literal, overlapping_constant: HeapCellValue,
index: usize, index: usize,
) { ) {
loop { loop {
@@ -316,7 +317,7 @@ impl<'a> IndexingCodeMergingPtr<'a> {
} }
} }
fn index_constant(&mut self, constant: Literal, index: usize) { fn index_constant(&mut self, constant: HeapCellValue, index: usize) {
loop { loop {
let indexing_code_len = self.indexing_code.len(); let indexing_code_len = self.indexing_code.len();
@@ -663,8 +664,8 @@ pub(crate) fn merge_clause_index(
} }
pub(crate) fn remove_constant_indices( pub(crate) fn remove_constant_indices(
constant: Literal, constant: HeapCellValue,
overlapping_constants: &[Literal], overlapping_constants: &[HeapCellValue],
indexing_code: &mut [IndexingLine], indexing_code: &mut [IndexingLine],
offset: usize, offset: usize,
) { ) {
@@ -1096,12 +1097,28 @@ fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) {
} }
pub(crate) fn constant_key_alternatives( pub(crate) fn constant_key_alternatives(
constant: Literal, constant: HeapCellValue,
atom_tbl: &AtomTable, // atom_tbl: &AtomTable,
// arena: &mut Arena, // arena: &mut Arena,
) -> Vec<Literal> { ) -> Vec<HeapCellValue> {
let mut constants = vec![]; let mut constants = vec![];
match Number::try_from(constant) {
Ok(Number::Integer(n)) => {
let result = (&*n).try_into();
if let Ok(value) = result {
constants.push(
Fixnum::build_with_checked(value)
.map(|n| fixnum_as_cell!(n))
.unwrap()
);
}
}
_ => {
}
}
/*
match constant { match constant {
Literal::Atom(ref name) => { Literal::Atom(ref name) => {
if let Some(c) = name.as_char() { if let Some(c) = name.as_char() {
@@ -1131,20 +1148,21 @@ pub(crate) fn constant_key_alternatives(
} }
_ => {} _ => {}
} }
*/
constants constants
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct StaticCodeIndices { pub(crate) struct StaticCodeIndices {
constants: IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher>, constants: IndexMap<HeapCellValue, VecDeque<IndexedChoiceInstruction>, FxBuildHasher>,
lists: VecDeque<IndexedChoiceInstruction>, lists: VecDeque<IndexedChoiceInstruction>,
structures: IndexMap<(Atom, usize), VecDeque<IndexedChoiceInstruction>, FxBuildHasher>, structures: IndexMap<(Atom, usize), VecDeque<IndexedChoiceInstruction>, FxBuildHasher>,
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct DynamicCodeIndices { pub(crate) struct DynamicCodeIndices {
constants: IndexMap<Literal, VecDeque<usize>, FxBuildHasher>, constants: IndexMap<HeapCellValue, VecDeque<usize>, FxBuildHasher>,
lists: VecDeque<usize>, lists: VecDeque<usize>,
structures: IndexMap<(Atom, usize), VecDeque<usize>, FxBuildHasher>, structures: IndexMap<(Atom, usize), VecDeque<usize>, FxBuildHasher>,
} }
@@ -1156,7 +1174,7 @@ pub(crate) trait Indexer {
fn constants( fn constants(
&mut self, &mut self,
) -> &mut IndexMap<Literal, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>; ) -> &mut IndexMap<HeapCellValue, VecDeque<Self::ThirdLevelIndex>, FxBuildHasher>;
fn lists(&mut self) -> &mut VecDeque<Self::ThirdLevelIndex>; fn lists(&mut self) -> &mut VecDeque<Self::ThirdLevelIndex>;
fn structures( fn structures(
&mut self, &mut self,
@@ -1204,7 +1222,7 @@ impl Indexer for StaticCodeIndices {
#[inline] #[inline]
fn constants( fn constants(
&mut self, &mut self,
) -> &mut IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> { ) -> &mut IndexMap<HeapCellValue, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
&mut self.constants &mut self.constants
} }
@@ -1328,7 +1346,7 @@ impl Indexer for DynamicCodeIndices {
} }
#[inline] #[inline]
fn constants(&mut self) -> &mut IndexMap<Literal, VecDeque<usize>, FxBuildHasher> { fn constants(&mut self) -> &mut IndexMap<HeapCellValue, VecDeque<usize>, FxBuildHasher> {
&mut self.constants &mut self.constants
} }
@@ -1449,11 +1467,10 @@ impl<I: Indexer> CodeOffsets<I> {
fn index_constant( fn index_constant(
&mut self, &mut self,
atom_tbl: &AtomTable, constant: HeapCellValue,
constant: Literal,
index: usize, index: usize,
) -> Vec<Literal> { ) -> Vec<HeapCellValue> {
let overlapping_constants = constant_key_alternatives(constant, atom_tbl); let overlapping_constants = constant_key_alternatives(constant);
let code = self.indices.constants().entry(constant).or_default(); let code = self.indices.constants().entry(constant).or_default();
let is_initial_index = code.is_empty(); let is_initial_index = code.is_empty();
@@ -1491,11 +1508,10 @@ impl<I: Indexer> CodeOffsets<I> {
pub(crate) fn index_term( pub(crate) fn index_term(
&mut self, &mut self,
heap: &[HeapCellValue], heap: &Heap,
optimal_arg: HeapCellValue, optimal_arg: HeapCellValue,
index: usize, index: usize,
clause_index_info: &mut ClauseIndexInfo, clause_index_info: &mut ClauseIndexInfo,
atom_tbl: &AtomTable,
) { ) {
read_heap_cell!(optimal_arg, read_heap_cell!(optimal_arg,
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
@@ -1514,36 +1530,32 @@ impl<I: Indexer> CodeOffsets<I> {
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0); debug_assert_eq!(arity, 0);
let overlapping_constants = self.index_constant(atom_tbl, Literal::Atom(name), index); let overlapping_constants = self.index_constant(atom_as_cell!(name), index);
clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal( clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal(
self.optimal_index, self.optimal_index,
0, 0,
Literal::Atom(name), atom_as_cell!(name),
overlapping_constants, overlapping_constants,
); );
} }
(HeapCellValueTag::Lis (HeapCellValueTag::Lis
| HeapCellValueTag::CStr // | HeapCellValueTag::CStr
| HeapCellValueTag::PStrLoc) => { | HeapCellValueTag::PStrLoc) => {
clause_index_info.opt_arg_index_key = OptArgIndexKey::List(self.optimal_index, 0); clause_index_info.opt_arg_index_key = OptArgIndexKey::List(self.optimal_index, 0);
self.index_list(index); self.index_list(index);
} }
_ => { _ if optimal_arg.is_constant() => {
match Literal::try_from(optimal_arg) { let overlapping_constants = self.index_constant(optimal_arg, index);
Ok(lit) => {
let overlapping_constants = self.index_constant(atom_tbl, lit, index);
clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal( clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal(
self.optimal_index, self.optimal_index,
0, 0,
lit, optimal_arg,
overlapping_constants, overlapping_constants,
); );
}
_ => {}
}
} }
_ => {}
); );
} }

View File

@@ -14,9 +14,7 @@ use std::iter::*;
use std::ops::Deref; use std::ops::Deref;
use std::vec::Vec; use std::vec::Vec;
pub(crate) trait TermIterator: pub(crate) trait TermIterator: Deref<Target = Heap> + Iterator<Item = HeapCellValue> {
Deref<Target = [HeapCellValue]> + Iterator<Item = HeapCellValue>
{
fn focus(&self) -> IterStackLoc; fn focus(&self) -> IterStackLoc;
fn level(&mut self) -> Level; fn level(&mut self) -> Level;
} }
@@ -30,7 +28,7 @@ pub(crate) struct TargetIterator<I: FocusedHeapIter, const SKIP_ROOT: bool> {
} }
fn record_path( fn record_path(
heap: &[HeapCellValue], heap: &impl SizedHeap,
root_terms: &mut BitSet<usize>, root_terms: &mut BitSet<usize>,
mut root_loc: usize, mut root_loc: usize,
) -> usize { ) -> usize {
@@ -47,9 +45,9 @@ fn record_path(
} }
} }
(HeapCellValueTag::Lis) => { (HeapCellValueTag::Lis) => {
root_terms.insert(root_loc); root_terms.insert(root_loc);
break; break;
} }
_ => { _ => {
if cell.is_ref() { if cell.is_ref() {
root_terms.insert(cell.get_value() as usize); root_terms.insert(cell.get_value() as usize);
@@ -63,14 +61,14 @@ fn record_path(
root_loc root_loc
} }
fn find_root_terms(heap: &[HeapCellValue], root_loc: usize) -> (usize, BitSet<usize>) { fn find_root_terms(heap: &impl SizedHeap, root_loc: usize) -> (usize, BitSet<usize>) {
let mut root_terms = BitSet::<usize>::default(); let mut root_terms = BitSet::<usize>::default();
let root_loc = record_path(heap, &mut root_terms, root_loc); let root_loc = record_path(heap, &mut root_terms, root_loc);
(root_loc, root_terms) (root_loc, root_terms)
} }
fn find_shallow_terms( fn find_shallow_terms(
heap: &[HeapCellValue], heap: &impl SizedHeap,
root_loc: usize, root_loc: usize,
) -> IndexMap<usize, BitSet<usize>, FxBuildHasher> { ) -> IndexMap<usize, BitSet<usize>, FxBuildHasher> {
let mut shallow_terms_map = IndexMap::with_hasher(FxBuildHasher::default()); let mut shallow_terms_map = IndexMap::with_hasher(FxBuildHasher::default());
@@ -101,8 +99,8 @@ fn find_shallow_terms(
impl<I: FocusedHeapIter, const SKIP_ROOT: bool> TargetIterator<I, SKIP_ROOT> { impl<I: FocusedHeapIter, const SKIP_ROOT: bool> TargetIterator<I, SKIP_ROOT> {
fn new(iter: I, root_loc: usize, arg_c: usize) -> Self { fn new(iter: I, root_loc: usize, arg_c: usize) -> Self {
let (derefed_root_loc, root_terms) = find_root_terms(&iter, root_loc); let (derefed_root_loc, root_terms) = find_root_terms(iter.deref(), root_loc);
let shallow_terms = find_shallow_terms(&iter, derefed_root_loc); let shallow_terms = find_shallow_terms(iter.deref(), derefed_root_loc);
Self { Self {
shallow_terms, shallow_terms,
@@ -184,7 +182,7 @@ impl<I: FocusedHeapIter, const SKIP_ROOT: bool> Iterator for TargetIterator<I, S
} }
impl<I: FocusedHeapIter, const SKIP_ROOT: bool> Deref for TargetIterator<I, SKIP_ROOT> { impl<I: FocusedHeapIter, const SKIP_ROOT: bool> Deref for TargetIterator<I, SKIP_ROOT> {
type Target = [HeapCellValue]; type Target = Heap;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.iter.deref() self.iter.deref()
@@ -205,7 +203,6 @@ pub(crate) fn fact_iterator<'a, const SKIP_ROOT: bool>(
stack: &'a mut Stack, stack: &'a mut Stack,
root_loc: usize, root_loc: usize,
) -> FactIterator<'a, SKIP_ROOT> { ) -> FactIterator<'a, SKIP_ROOT> {
// let cell = heap[root_loc];
TargetIterator::new(stackful_preorder_iter(heap, stack, root_loc), root_loc, 0) TargetIterator::new(stackful_preorder_iter(heap, stack, root_loc), root_loc, 0)
} }
@@ -217,7 +214,6 @@ pub(crate) fn query_iterator<'a, const SKIP_ROOT: bool>(
stack: &'a mut Stack, stack: &'a mut Stack,
root_loc: usize, root_loc: usize,
) -> QueryIterator<'a, SKIP_ROOT> { ) -> QueryIterator<'a, SKIP_ROOT> {
// let cell = heap[root_loc];
TargetIterator::new(stackful_post_order_iter(heap, stack, root_loc), root_loc, 1) TargetIterator::new(stackful_post_order_iter(heap, stack, root_loc), root_loc, 1)
} }

View File

@@ -2,6 +2,7 @@
#![recursion_limit = "4112"] #![recursion_limit = "4112"]
#![deny(missing_docs)] #![deny(missing_docs)]
#[macro_use] #[macro_use]
extern crate static_assertions; extern crate static_assertions;
@@ -13,6 +14,8 @@ pub(crate) mod atom_table;
pub(crate) mod arena; pub(crate) mod arena;
#[macro_use] #[macro_use]
pub(crate) mod parser; pub(crate) mod parser;
#[macro_use]
pub(crate) mod functor_macro;
mod allocator; mod allocator;
mod arithmetic; mod arithmetic;
pub(crate) mod codegen; pub(crate) mod codegen;

View File

@@ -125,7 +125,7 @@ call(_, _, _, _, _, _, _, _, _).
% %
% The flags that Scryer Prolog support are: % The flags that Scryer Prolog support are:
% %
% * `max_arity`: The max arity a predicate can have in Prolog. On Scryer is set to 1023. Read only. % * `max_arity`: The max arity a predicate can have in Prolog. On Scryer is set to 255. Read only.
% * `bounded`: `true` if integer arithmethic is bounded between some min/max values. On Scryer is always set % * `bounded`: `true` if integer arithmethic is bounded between some min/max values. On Scryer is always set
% to `false` since it supports unbounded integer arithmethic. Read only. % to `false` since it supports unbounded integer arithmethic. Read only.
% * `integer_rounding_function`: Describes the rounding donde by `//` and `rem` functions. On Scryer is % * `integer_rounding_function`: Describes the rounding donde by `//` and `rem` functions. On Scryer is
@@ -145,8 +145,8 @@ call(_, _, _, _, _, _, _, _, _).
% `fail` (the call silently fails) and `warn` (the call fails and a warning about the undefined predicate is printed). % `fail` (the call silently fails) and `warn` (the call fails and a warning about the undefined predicate is printed).
% * `answer_write_options`: Additional write options used by the top level for writing answers. % * `answer_write_options`: Additional write options used by the top level for writing answers.
% %
current_prolog_flag(Flag, Value) :- Flag == max_arity, !, Value = 1023. current_prolog_flag(Flag, Value) :- Flag == max_arity, !, Value = 255.
current_prolog_flag(max_arity, 1023). current_prolog_flag(max_arity, 255).
current_prolog_flag(Flag, Value) :- Flag == bounded, !, Value = false. current_prolog_flag(Flag, Value) :- Flag == bounded, !, Value = false.
current_prolog_flag(bounded, false). current_prolog_flag(bounded, false).
current_prolog_flag(Flag, Value) :- Flag == integer_rounding_function, !, Value == toward_zero. current_prolog_flag(Flag, Value) :- Flag == integer_rounding_function, !, Value == toward_zero.

View File

@@ -205,7 +205,6 @@ load_loop(Stream, Evacuable) :-
read_term(Stream, Term, [singletons(Singletons)]) read_term(Stream, Term, [singletons(Singletons)])
; Term = end_of_file ; Term = end_of_file
), ),
% write('Term: '), writeq(Term), nl,
( Term == end_of_file -> ( Term == end_of_file ->
close(Stream), close(Stream),
'$conclude_load'(Evacuable) '$conclude_load'(Evacuable)
@@ -220,7 +219,6 @@ load_loop(Stream, Evacuable) :-
compile_term(Term, Evacuable) :- compile_term(Term, Evacuable) :-
expand_terms_and_goals(Term, Terms), expand_terms_and_goals(Term, Terms),
% write('Terms: '), writeq(Terms),nl,
!, !,
( var(Terms) -> ( var(Terms) ->
instantiation_error(load/1) instantiation_error(load/1)
@@ -301,7 +299,7 @@ expand_term_goals(Terms0, Terms) :-
( atom(Module) -> ( atom(Module) ->
prolog_load_context(module, Target), prolog_load_context(module, Target),
module_expanded_head_variables(Head2, HeadVars), module_expanded_head_variables(Head2, HeadVars),
catch(expand_goal(Body0, Target, Body1, HeadVars, []), catch('$call'(loader:expand_goal(Body0, Target, Body1, HeadVars, [])),
error(type_error(callable, Pred), _), error(type_error(callable, Pred), _),
( loader:print_goal_expansion_warning(Pred), ( loader:print_goal_expansion_warning(Pred),
builtins:(Body1 = Body0) builtins:(Body1 = Body0)
@@ -311,7 +309,7 @@ expand_term_goals(Terms0, Terms) :-
) )
; module_expanded_head_variables(Head1, HeadVars), ; module_expanded_head_variables(Head1, HeadVars),
prolog_load_context(module, Target), prolog_load_context(module, Target),
catch(expand_goal(Body0, Target, Body1, HeadVars, []), catch('$call'(loader:expand_goal(Body0, Target, Body1, HeadVars, [])),
error(type_error(callable, Pred), _), error(type_error(callable, Pred), _),
( loader:print_goal_expansion_warning(Pred), ( loader:print_goal_expansion_warning(Pred),
builtins:(Body1 = Body0) builtins:(Body1 = Body0)

View File

@@ -48,7 +48,7 @@ macro_rules! drop_iter_on_err {
}; };
} }
fn zero_divisor_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen { fn zero_divisor_eval_error(stub_gen: impl Fn() -> MachineStub + 'static) -> MachineStubGen {
Box::new(move |machine_st| { Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::ZeroDivisor); let eval_error = machine_st.evaluation_error(EvalError::ZeroDivisor);
let stub = stub_gen(); let stub = stub_gen();
@@ -57,7 +57,7 @@ fn zero_divisor_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> Mach
}) })
} }
fn undefined_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> MachineStubGen { fn undefined_eval_error(stub_gen: impl Fn() -> MachineStub + 'static) -> MachineStubGen {
Box::new(move |machine_st| { Box::new(move |machine_st| {
let eval_error = machine_st.evaluation_error(EvalError::Undefined); let eval_error = machine_st.evaluation_error(EvalError::Undefined);
let stub = stub_gen(); let stub = stub_gen();
@@ -69,7 +69,7 @@ fn undefined_eval_error(stub_gen: impl Fn() -> FunctorStub + 'static) -> Machine
fn numerical_type_error( fn numerical_type_error(
valid_type: ValidType, valid_type: ValidType,
n: Number, n: Number,
stub_gen: impl Fn() -> FunctorStub + 'static, stub_gen: impl Fn() -> MachineStub + 'static,
) -> MachineStubGen { ) -> MachineStubGen {
Box::new(move |machine_st| { Box::new(move |machine_st| {
let type_error = machine_st.type_error(valid_type, n); let type_error = machine_st.type_error(valid_type, n);
@@ -528,7 +528,7 @@ pub(crate) fn min(n1: Number, n2: Number) -> Result<Number, MachineStubGen> {
pub fn rational_from_number( pub fn rational_from_number(
n: Number, n: Number,
stub_gen: impl Fn() -> FunctorStub + 'static, stub_gen: impl Fn() -> MachineStub + 'static,
arena: &mut Arena, arena: &mut Arena,
) -> Result<TypedArenaPtr<Rational>, MachineStubGen> { ) -> Result<TypedArenaPtr<Rational>, MachineStubGen> {
match n { match n {
@@ -1140,7 +1140,7 @@ impl MachineState {
pub fn get_rational( pub fn get_rational(
&mut self, &mut self,
at: &ArithmeticTerm, at: &ArithmeticTerm,
caller: impl Fn() -> FunctorStub + 'static, caller: impl Fn() -> MachineStub + 'static,
) -> Result<TypedArenaPtr<Rational>, MachineStub> { ) -> Result<TypedArenaPtr<Rational>, MachineStub> {
let n = self.get_number(at)?; let n = self.get_number(at)?;
@@ -1154,6 +1154,8 @@ impl MachineState {
&mut self, &mut self,
value: HeapCellValue, value: HeapCellValue,
) -> Result<Number, MachineStub> { ) -> Result<Number, MachineStub> {
debug_assert!(value.is_ref());
let stub_gen = || functor_stub(atom!("is"), 2); let stub_gen = || functor_stub(atom!("is"), 2);
let root_loc = if value.is_ref() && !value.is_stack_var() { let root_loc = if value.is_ref() && !value.is_stack_var() {
@@ -1178,7 +1180,7 @@ impl MachineState {
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
cell_as_atom_cell!(self.heap[s]).get_name_and_arity() cell_as_atom_cell!(self.heap[s]).get_name_and_arity()
} }
(HeapCellValueTag::Lis | HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset | (HeapCellValueTag::Lis | // HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset |
HeapCellValueTag::PStrLoc) => { HeapCellValueTag::PStrLoc) => {
(atom!("."), 2) (atom!("."), 2)
} }
@@ -1458,7 +1460,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();
assert_eq!( assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.heap_loc)), wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
Ok(Number::Fixnum(Fixnum::build_with(8))), Ok(Number::Fixnum(Fixnum::build_with(8))),
); );
@@ -1468,7 +1470,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "5 * 4 - 1.", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "5 * 4 - 1.", &op_dir).unwrap();
assert_eq!( assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.heap_loc)), wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
Ok(Number::Fixnum(Fixnum::build_with(19))), Ok(Number::Fixnum(Fixnum::build_with(19))),
); );
@@ -1478,7 +1480,7 @@ mod tests {
parse_and_write_parsed_term_to_heap(&mut wam, "sign(-1).", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "sign(-1).", &op_dir).unwrap();
assert_eq!( assert_eq!(
wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.heap_loc)), wam.arith_eval_by_metacall(heap_loc_as_cell!(term_write_result.focus)),
Ok(Number::Fixnum(Fixnum::build_with(-1))) Ok(Number::Fixnum(Fixnum::build_with(-1)))
); );
} }

View File

@@ -38,6 +38,7 @@ verify_attrs([], _, _, []).
call_goals([ListOfGoalLists | ListsCubed]) :- call_goals([ListOfGoalLists | ListsCubed]) :-
'$debug_hook',
call_goals_0(ListOfGoalLists), call_goals_0(ListOfGoalLists),
call_goals(ListsCubed). call_goals(ListsCubed).
call_goals([]). call_goals([]).

View File

@@ -6,7 +6,6 @@ use crate::types::*;
use indexmap::IndexSet; use indexmap::IndexSet;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::vec::IntoIter;
pub(super) type Bindings = Vec<(usize, HeapCellValue)>; pub(super) type Bindings = Vec<(usize, HeapCellValue)>;
@@ -55,32 +54,36 @@ impl MachineState {
self.attr_var_init.bindings.push((h, addr)); self.attr_var_init.bindings.push((h, addr));
} }
fn populate_var_and_value_lists(&mut self) -> (HeapCellValue, HeapCellValue) { fn populate_var_and_value_lists(&mut self) -> Result<(HeapCellValue, HeapCellValue), usize> {
let size = self.attr_var_init.bindings.len();
let iter = self let iter = self
.attr_var_init .attr_var_init
.bindings .bindings
.iter() .iter()
.map(|(ref h, _)| attr_var_as_cell!(*h)); .map(|(ref h, _)| attr_var_as_cell!(*h));
let var_list_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, iter)); let var_list_addr = sized_iter_to_heap_list(&mut self.heap, size, iter)?;
let iter = self.attr_var_init.bindings.drain(0..).map(|(_, ref v)| *v); let iter = self.attr_var_init.bindings.drain(0..).map(|(_, ref v)| *v);
let value_list_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, iter)); let value_list_addr = sized_iter_to_heap_list(&mut self.heap, size, iter)?;
(var_list_addr, value_list_addr) Ok((var_list_addr, value_list_addr))
} }
fn verify_attributes(&mut self) { fn verify_attributes(&mut self) -> Result<(), usize> {
for (h, _) in &self.attr_var_init.bindings { for (h, _) in &self.attr_var_init.bindings {
self.heap[*h] = attr_var_as_cell!(*h); self.heap[*h] = attr_var_as_cell!(*h);
} }
let (var_list_addr, value_list_addr) = self.populate_var_and_value_lists(); let (var_list_addr, value_list_addr) = self.populate_var_and_value_lists()?;
self[temp_v!(1)] = var_list_addr; self[temp_v!(1)] = var_list_addr;
self[temp_v!(2)] = value_list_addr; self[temp_v!(2)] = value_list_addr;
Ok(())
} }
pub(super) fn gather_attr_vars_created_since(&mut self, b: usize) -> IntoIter<HeapCellValue> { pub(super) fn gather_attr_vars_created_since(&mut self, b: usize) -> Vec<HeapCellValue> {
let mut attr_vars: Vec<_> = if b >= self.attr_var_init.attr_var_queue.len() { let mut attr_vars: Vec<_> = if b >= self.attr_var_init.attr_var_queue.len() {
vec![] vec![]
} else { } else {
@@ -104,10 +107,10 @@ impl MachineState {
}); });
attr_vars.dedup(); attr_vars.dedup();
attr_vars.into_iter() attr_vars
} }
pub(super) fn verify_attr_interrupt(&mut self, p: usize, arity: usize) { pub(super) fn verify_attr_interrupt(&mut self, p: usize, arity: usize) -> Result<(), usize> {
self.allocate(arity + 3); self.allocate(arity + 3);
let e = self.e; let e = self.e;
@@ -121,14 +124,18 @@ impl MachineState {
and_frame[arity + 2] = fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64)); and_frame[arity + 2] = fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
and_frame[arity + 3] = fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64)); and_frame[arity + 3] = fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
self.verify_attributes(); self.verify_attributes()?;
self.num_of_args = 3; self.num_of_args = 3;
self.b0 = self.b; self.b0 = self.b;
self.p = p; self.p = p;
Ok(())
} }
pub(super) fn attr_vars_of_term(&mut self, cell: HeapCellValue) -> Vec<HeapCellValue> { pub(super) fn attr_vars_of_term(&mut self, cell: HeapCellValue) -> Vec<HeapCellValue> {
debug_assert!(cell.is_ref());
let mut seen_set = IndexSet::new(); let mut seen_set = IndexSet::new();
let mut seen_vars = vec![]; let mut seen_vars = vec![];
let root_loc = if cell.is_ref() { let root_loc = if cell.is_ref() {

View File

@@ -1232,15 +1232,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
fn compile_standalone_clause( fn compile_standalone_clause(
&mut self, &mut self,
term: FocusedHeap, term: TermWriteResult,
settings: CodeGenSettings, settings: CodeGenSettings,
) -> Result<StandaloneCompileResult, SessionError> { ) -> Result<StandaloneCompileResult, SessionError> {
let mut preprocessor = Preprocessor::new(settings); let mut preprocessor = Preprocessor::new(settings);
let clause = self.try_term_to_tl(term, &mut preprocessor)?; let clause = preprocessor.try_term_to_tl(self, term)?;
let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings); let machine_st = LS::machine_st(&mut self.payload);
let mut cg = CodeGenerator::new(settings);
let clause_code = cg.compile_predicate(vec![clause])?; let clause_code = cg.compile_predicate(&mut machine_st.heap, vec![clause])?;
Ok(StandaloneCompileResult { Ok(StandaloneCompileResult {
clause_code, clause_code,
@@ -1265,11 +1266,13 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let mut preprocessor = Preprocessor::new(settings); let mut preprocessor = Preprocessor::new(settings);
for term in predicates.predicates.drain(0..) { for term in predicates.predicates.drain(0..) {
clauses.push(self.try_term_to_tl(term, &mut preprocessor)?); clauses.push(preprocessor.try_term_to_tl(self, term)?);
} }
let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings); let machine_st = LS::machine_st(&mut self.payload);
let mut code = cg.compile_predicate(clauses)?;
let mut cg = CodeGenerator::new(settings);
let mut code = cg.compile_predicate(&mut machine_st.heap, clauses)?;
if settings.is_extensible { if settings.is_extensible {
let mut clause_clause_locs = VecDeque::new(); let mut clause_clause_locs = VecDeque::new();
@@ -1466,7 +1469,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
pub(super) fn incremental_compile_clause( pub(super) fn incremental_compile_clause(
&mut self, &mut self,
key: PredicateKey, key: PredicateKey,
clause: FocusedHeap, clause: TermWriteResult,
compilation_target: CompilationTarget, compilation_target: CompilationTarget,
non_counted_bt: bool, non_counted_bt: bool,
append_or_prepend: AppendOrPrepend, append_or_prepend: AppendOrPrepend,
@@ -2005,7 +2008,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
&mut self, &mut self,
key: PredicateKey, key: PredicateKey,
compilation_target: CompilationTarget, compilation_target: CompilationTarget,
clause_clauses: Vec<FocusedHeap>, clause_clauses: Vec<TermWriteResult>,
append_or_prepend: AppendOrPrepend, append_or_prepend: AppendOrPrepend,
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let clause_clause_compilation_target = match compilation_target { let clause_clause_compilation_target = match compilation_target {
@@ -2099,15 +2102,19 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> { pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
let key = self let key = match self
.payload .payload
.predicates .predicates
.first() .first()
.and_then(|cl| { .map(|term| term.focus) {
let arity = ClauseInfo::arity(cl); Some(focus) => {
ClauseInfo::name(cl).map(|name| (name, arity)) clause_predicate_key(self.machine_heap(), focus)
}) .ok_or(SessionError::NamelessEntry)?
.ok_or(SessionError::NamelessEntry)?; }
None => {
return Err(SessionError::NamelessEntry);
}
};
let listing_src_file_name = self.listing_src_file_name(); let listing_src_file_name = self.listing_src_file_name();
@@ -2285,34 +2292,40 @@ impl Machine {
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg])); let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
let new_header_loc = self.machine_st.heap.len(); let new_header_loc = self.machine_st.heap.cell_len();
let arity = vars.len(); let arity = vars.len();
let term_loc = self.machine_st.heap.cell_len() + 1 + arity;
self.machine_st.heap.push(atom_as_cell!(atom!(""), arity)); let mut writer = self.machine_st.heap.reserve(4 + arity)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
for var in vars { writer.write_with(move |section| {
self.machine_st.heap.push(var); section.push_cell(atom_as_cell!(atom!(""), arity));
}
let head_loc = if arity > 0 { for var in vars {
str_loc_as_cell!(new_header_loc) section.push_cell(var);
} else { }
heap_loc_as_cell!(new_header_loc)
};
let term_loc = self.machine_st.heap.len(); let head_loc = if arity > 0 {
str_loc_as_cell!(new_header_loc)
} else {
heap_loc_as_cell!(new_header_loc)
};
self.machine_st.heap.push(atom_as_cell!(atom!(":-"), 2)); section.push_cell(atom_as_cell!(atom!(":-"), 2));
self.machine_st.heap.push(head_loc); section.push_cell(head_loc);
self.machine_st.heap.push(body_cell); section.push_cell(body_cell);
});
let mut compile = || { let mut compile = || {
use crate::heap_iter::eager_stackful_preorder_iter;
let mut loader: Loader<'_, InlineLoadState<'_>> = let mut loader: Loader<'_, InlineLoadState<'_>> =
Loader::new(self, InlineTermStream {}); Loader::new(self, InlineTermStream {});
let mut term = loader.copy_term_from_heap(str_loc_as_cell!(term_loc)); let machine_st = InlineLoadState::machine_st(&mut loader.payload);
let term_loc = str_loc_as_cell!(term_loc);
let term = TermWriteResult::from(&mut machine_st.heap, term_loc)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
let settings = CodeGenSettings { let settings = CodeGenSettings {
global_clock_tick: None, global_clock_tick: None,
@@ -2320,12 +2333,6 @@ impl Machine {
non_counted_bt: true, non_counted_bt: true,
}; };
let value = term.heap[term.focus];
term.inverse_var_locs = inverse_var_locs_from_iter(
eager_stackful_preorder_iter(&mut term.heap, value),
);
loader.compile_standalone_clause(term, settings) loader.compile_standalone_clause(term, settings)
}; };

View File

@@ -1,10 +1,11 @@
use crate::atom_table::*; use crate::atom_table::*;
use crate::machine::get_structure_index; use crate::machine::get_structure_index;
use crate::machine::heap::*;
use crate::machine::stack::*; use crate::machine::stack::*;
use crate::types::*; use crate::types::*;
use std::mem; use std::mem;
use std::ops::IndexMut; use std::ops::{IndexMut, Range};
type Trail = Vec<(Ref, HeapCellValue)>; type Trail = Vec<(Ref, HeapCellValue)>;
@@ -17,22 +18,31 @@ pub enum AttrVarPolicy {
pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> { pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
fn store(&self, value: HeapCellValue) -> HeapCellValue; fn store(&self, value: HeapCellValue) -> HeapCellValue;
fn deref(&self, value: HeapCellValue) -> HeapCellValue; fn deref(&self, value: HeapCellValue) -> HeapCellValue;
fn push(&mut self, value: HeapCellValue); // fn push_cell(&mut self, value: HeapCellValue) -> Result<(), usize>;
fn push_attr_var_queue(&mut self, attr_var_loc: usize); fn push_attr_var_queue(&mut self, attr_var_loc: usize);
fn stack(&mut self) -> &mut Stack; fn stack(&mut self) -> &mut Stack;
fn threshold(&self) -> usize; fn threshold(&self) -> usize;
// returns the tail location of the pstr on success
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize>;
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize;
fn pstr_at(&self, loc: usize) -> bool;
fn next_non_pstr_cell_index(&self, loc: usize) -> usize;
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize>;
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize>;
} }
pub(crate) fn copy_term<T: CopierTarget>( pub(crate) fn copy_term<T: CopierTarget>(
target: T, target: T,
addr: HeapCellValue, addr: HeapCellValue,
attr_var_policy: AttrVarPolicy, attr_var_policy: AttrVarPolicy,
) { ) -> Result<(), usize> {
let mut copy_term_state = CopyTermState::new(target, attr_var_policy); let mut copy_term_state = CopyTermState::new(target, attr_var_policy);
copy_term_state.copy_term_impl(addr); copy_term_state.copy_term_impl(addr)?;
copy_term_state.copy_attr_var_lists(); copy_term_state.copy_attr_var_lists()?;
copy_term_state.unwind_trail(); copy_term_state.unwind_trail();
Ok(())
} }
#[derive(Debug)] #[derive(Debug)]
@@ -67,14 +77,14 @@ impl<T: CopierTarget> CopyTermState<T> {
self.trail.push((Ref::heap_cell(addr), trail_item)); self.trail.push((Ref::heap_cell(addr), trail_item));
} }
fn copy_list(&mut self, addr: usize) { fn copy_list(&mut self, addr: usize) -> Result<(), usize> {
for offset in 0..2 { for offset in 0..2 {
read_heap_cell!(self.target[addr + offset], read_heap_cell!(self.target[addr + offset],
(HeapCellValueTag::Lis, h) => { (HeapCellValueTag::Lis, h) => {
if h >= self.old_h { if h >= self.old_h {
*self.value_at_scan() = list_loc_as_cell!(h); *self.value_at_scan() = list_loc_as_cell!(h);
self.scan += 1; self.scan += 1;
return; return Ok(());
} }
} }
_ => { _ => {
@@ -83,14 +93,10 @@ impl<T: CopierTarget> CopyTermState<T> {
} }
let threshold = self.target.threshold(); let threshold = self.target.threshold();
self.target.copy_slice_to_end(addr .. addr + 2)?;
*self.value_at_scan() = list_loc_as_cell!(threshold); *self.value_at_scan() = list_loc_as_cell!(threshold);
for i in 0..2 {
let hcv = self.target[addr + i];
self.target.push(hcv);
}
let cdr = self let cdr = self
.target .target
.store(self.target.deref(heap_loc_as_cell!(addr + 1))); .store(self.target.deref(heap_loc_as_cell!(addr + 1)));
@@ -113,80 +119,72 @@ impl<T: CopierTarget> CopyTermState<T> {
} }
self.scan += 1; self.scan += 1;
Ok(())
} }
fn copy_partial_string(&mut self, scan_tag: HeapCellValueTag, pstr_loc: usize) { /*
read_heap_cell!(self.target[pstr_loc], * write a null byte to the first word of a partial string to
(HeapCellValueTag::PStrLoc, h) => { * flag that it has been copied followed by the copied
debug_assert!(h >= self.old_h); * string's index in the next 7 bytes. write the bytes in big
* endian order so that the null byte is at index 0.
*/
fn write_pstr_index(&mut self, head_cell_idx: usize, threshold: usize) {
let bytes = u64::to_be_bytes(threshold as u64);
debug_assert_eq!(bytes[0], 0);
self.target[head_cell_idx] = HeapCellValue::from_bytes(bytes);
}
*self.value_at_scan() = match scan_tag { fn copy_partial_string(&mut self, pstr_loc: usize) -> Result<(), usize> {
HeapCellValueTag::PStrLoc => { let head_cell_idx = self.target.pstr_head_cell_index(pstr_loc);
pstr_loc_as_cell!(h) let head_byte_idx = heap_index!(head_cell_idx);
} let pstr_offset = pstr_loc - head_byte_idx;
tag => {
debug_assert_eq!(tag, HeapCellValueTag::PStrOffset);
pstr_offset_as_cell!(h)
}
};
self.scan += 1; // if a partial string has been copied previously, we
return; // track it by writing a null byte to its first word, which is trailed,
} // and then the new pstr_loc in the word's remaining 7 bytes. see write_pstr_index
(HeapCellValueTag::Var, h) => { // comment.
debug_assert!(h >= self.old_h);
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
*self.value_at_scan() = pstr_offset_as_cell!(h); if self.target[head_cell_idx].into_bytes()[0] == 0u8 {
self.scan += 1; let head_bytes = self.target[head_cell_idx].into_bytes();
let new_pstr_loc = u64::from_be_bytes(head_bytes) as usize;
return; *self.value_at_scan() = pstr_loc_as_cell!(heap_index!(new_pstr_loc) + pstr_offset);
} self.scan += 1;
_ => {} return Ok(());
); }
let threshold = self.target.threshold(); let threshold = self.target.threshold();
let tail_loc = self.target.copy_pstr_to_threshold(head_byte_idx)?;
let replacement = read_heap_cell!(self.target[pstr_loc], *self.value_at_scan() = pstr_loc_as_cell!(heap_index!(threshold) + pstr_offset);
(HeapCellValueTag::CStr) => {
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
*self.value_at_scan() = pstr_offset_as_cell!(threshold); self.trail.push((Ref::heap_cell(head_cell_idx), self.target[head_cell_idx]));
self.target.push(self.target[pstr_loc]); self.write_pstr_index(head_cell_idx, threshold);
heap_loc_as_cell!(threshold) let tail_cell = self.target[tail_loc];
} let mut writer = self.target.reserve(1)?;
_ => {
*self.value_at_scan() = if scan_tag == HeapCellValueTag::PStrLoc {
pstr_loc_as_cell!(threshold)
} else {
debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
pstr_offset_as_cell!(threshold)
};
self.target.push(self.target[pstr_loc]); writer.write_with(|section| {
self.target.push(self.target[pstr_loc + 1]); section.push_cell(tail_cell);
});
pstr_loc_as_cell!(threshold)
}
);
self.scan += 1; self.scan += 1;
let trail_item = mem::replace(&mut self.target[pstr_loc], replacement); Ok(())
self.trail.push((Ref::heap_cell(pstr_loc), trail_item));
} }
fn copy_attr_var_lists(&mut self) { fn copy_attr_var_lists(&mut self) -> Result<(), usize> {
while !self.attr_var_list_locs.is_empty() { while !self.attr_var_list_locs.is_empty() {
let iter = std::mem::take(&mut self.attr_var_list_locs); let mut list_loc_vec = std::mem::take(&mut self.attr_var_list_locs);
for (threshold, list_loc) in iter { while let Some((threshold, list_loc)) = list_loc_vec.pop() {
self.target[threshold] = list_loc_as_cell!(self.target.threshold()); self.target[threshold] = list_loc_as_cell!(self.target.threshold());
self.target.push_attr_var_queue(threshold - 1); self.target.push_attr_var_queue(threshold - 1);
self.copy_attr_var_list(list_loc); self.copy_attr_var_list(list_loc)?;
} }
} }
Ok(())
} }
/* /*
@@ -194,36 +192,36 @@ impl<T: CopierTarget> CopyTermState<T> {
* structure which is ensured by this function and not at all by * structure which is ensured by this function and not at all by
* the vanilla copier. * the vanilla copier.
*/ */
fn copy_attr_var_list(&mut self, mut list_addr: HeapCellValue) { fn copy_attr_var_list(&mut self, mut list_addr: HeapCellValue) -> Result<(), usize> {
while let HeapCellValueTag::Lis = list_addr.get_tag() { while let HeapCellValueTag::Lis = list_addr.get_tag() {
let threshold = self.target.threshold(); let threshold = self.target.threshold();
let heap_loc = list_addr.get_value() as usize; let heap_loc = list_addr.get_value() as usize;
let str_loc = self.target[heap_loc].get_value() as usize; let str_loc = self.target[heap_loc].get_value() as usize;
let str_cell = self.target[str_loc];
let mut writer = self.target.reserve(3).unwrap();
self.target.push(heap_loc_as_cell!(threshold + 2)); writer.write_with(|section| {
self.target.push(heap_loc_as_cell!(threshold + 1)); section.push_cell(heap_loc_as_cell!(threshold + 2));
section.push_cell(heap_loc_as_cell!(threshold + 1));
read_heap_cell!(self.target[str_loc], if str_cell.to_atom().is_some() {
(HeapCellValueTag::Atom) => { section.push_cell(str_cell);
self.target.push(self.target[str_loc]);
} }
(HeapCellValueTag::Str) => { });
self.copy_term_impl(self.target[str_loc]);
}
_ => {
unreachable!();
}
);
debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str);
self.copy_term_impl(str_cell)?;
list_addr = self.target[heap_loc + 1]; list_addr = self.target[heap_loc + 1];
if HeapCellValueTag::Lis == list_addr.get_tag() { if HeapCellValueTag::Lis == list_addr.get_tag() {
self.target[threshold + 1] = list_loc_as_cell!(self.target.threshold()); self.target[threshold + 1] = list_loc_as_cell!(self.target.threshold());
} }
} }
Ok(())
} }
fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) { fn reinstantiate_var(&mut self, addr: HeapCellValue, frontier: usize) -> Result<(), usize> {
read_heap_cell!(addr, read_heap_cell!(addr,
(HeapCellValueTag::Var, h) => { (HeapCellValueTag::Var, h) => {
self.target[frontier] = heap_loc_as_cell!(frontier); self.target[frontier] = heap_loc_as_cell!(frontier);
@@ -250,8 +248,12 @@ impl<T: CopierTarget> CopyTermState<T> {
self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h))); self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h)));
if let AttrVarPolicy::DeepCopy = self.attr_var_policy { if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
self.target.push(attr_var_as_cell!(threshold)); let mut writer = self.target.reserve(2).unwrap();
self.target.push(heap_loc_as_cell!(threshold + 1));
writer.write_with(|section| {
section.push_cell(attr_var_as_cell!(threshold));
section.push_cell(heap_loc_as_cell!(threshold + 1));
});
let old_list_link = self.target[h + 1]; let old_list_link = self.target[h + 1];
self.trail.push((Ref::heap_cell(h + 1), old_list_link)); self.trail.push((Ref::heap_cell(h + 1), old_list_link));
@@ -266,9 +268,11 @@ impl<T: CopierTarget> CopyTermState<T> {
unreachable!() unreachable!()
} }
); );
Ok(())
} }
fn copy_var(&mut self, addr: HeapCellValue) { fn copy_var(&mut self, addr: HeapCellValue) -> Result<(), usize> {
let index = addr.get_value() as usize; let index = addr.get_value() as usize;
let rd = self.target.deref(addr); let rd = self.target.deref(addr);
let ra = self.target.store(rd); let ra = self.target.store(rd);
@@ -278,7 +282,7 @@ impl<T: CopierTarget> CopyTermState<T> {
if h >= self.old_h { if h >= self.old_h {
*self.value_at_scan() = ra; *self.value_at_scan() = ra;
self.scan += 1; self.scan += 1;
return; return Ok(());
} }
} }
(HeapCellValueTag::Lis, h) => { (HeapCellValueTag::Lis, h) => {
@@ -292,46 +296,57 @@ impl<T: CopierTarget> CopyTermState<T> {
); );
self.scan += 1; self.scan += 1;
return; return Ok(());
} }
} }
_ => {} _ => {}
); );
if rd == ra { if rd == ra {
self.reinstantiate_var(ra, self.scan); self.reinstantiate_var(ra, self.scan)?;
self.scan += 1; self.scan += 1;
} else { } else {
*self.value_at_scan() = ra; *self.value_at_scan() = ra;
} }
Ok(())
} }
fn copy_structure(&mut self, addr: usize) { fn copy_structure(&mut self, addr: usize) -> Result<(), usize> {
read_heap_cell!(self.target[addr], read_heap_cell!(self.target[addr],
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (_name, arity)) => {
let threshold = self.target.threshold(); let threshold = self.target.threshold();
*self.value_at_scan() = str_loc_as_cell!(threshold); *self.value_at_scan() = str_loc_as_cell!(threshold);
self.target.copy_slice_to_end(addr .. addr + 1 + arity)?;
let trail_item = mem::replace( let trail_item = mem::replace(
&mut self.target[addr], &mut self.target[addr],
str_loc_as_cell!(threshold), str_loc_as_cell!(threshold),
); );
self.trail.push((Ref::heap_cell(addr), trail_item)); self.trail.push((Ref::heap_cell(addr), trail_item));
/*
self.target.push(atom_as_cell!(name, arity)); self.target.push(atom_as_cell!(name, arity));
for i in 0..arity { for i in 0..arity {
let hcv = self.target[addr + 1 + i]; let hcv = self.target[addr + 1 + i];
self.target.push(hcv); self.target.push(hcv);
} }
*/
if !self.target.pstr_at(addr + 1 + arity) {
let index_cell = self.target[addr + 1 + arity];
let index_cell = self.target[addr + 1 + arity]; if get_structure_index(index_cell).is_some() {
// copy the index pointer trailing this
// inlined or expanded goal.
let mut writer = self.target.reserve(1).unwrap();
if get_structure_index(index_cell).is_some() { writer.write_with(|section| {
// copy the index pointer trailing this section.push_cell(index_cell);
// inlined or expanded goal. });
self.target.push(index_cell); }
} }
} }
(HeapCellValueTag::Str, h) => { (HeapCellValueTag::Str, h) => {
@@ -343,37 +358,51 @@ impl<T: CopierTarget> CopyTermState<T> {
); );
self.scan += 1; self.scan += 1;
Ok(())
} }
fn copy_term_impl(&mut self, addr: HeapCellValue) { fn copy_term_impl(&mut self, addr: HeapCellValue) -> Result<(), usize> {
self.scan = self.target.threshold(); self.scan = self.target.threshold();
self.target.push(addr); let mut writer = self.target.reserve(1)?;
writer.write_with(|section| {
section.push_cell(addr);
});
while self.scan < self.target.threshold() { while self.scan < self.target.threshold() {
if self.target.pstr_at(self.scan) {
self.scan = self.target.next_non_pstr_cell_index(self.scan);
continue;
}
let addr = *self.value_at_scan(); let addr = *self.value_at_scan();
read_heap_cell!(addr, read_heap_cell!(addr,
(HeapCellValueTag::Lis, h) => { (HeapCellValueTag::Lis, h) => {
if h >= self.old_h { if h >= self.old_h {
self.scan += 1; self.scan += 1;
continue;
} else { } else {
self.copy_list(h); self.copy_list(h)
} }
} }
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var) => {
self.copy_var(addr); self.copy_var(addr)
} }
(HeapCellValueTag::Str, h) => { (HeapCellValueTag::Str, h) => {
self.copy_structure(h); self.copy_structure(h)
} }
(HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrOffset, pstr_loc) => { (HeapCellValueTag::PStrLoc, pstr_loc) => {
self.copy_partial_string(addr.get_tag(), pstr_loc); self.copy_partial_string(pstr_loc)
} }
_ => { _ => {
self.scan += 1; self.scan += 1;
continue;
} }
); )?;
} }
Ok(())
} }
fn unwind_trail(mut self) { fn unwind_trail(mut self) {
@@ -395,19 +424,25 @@ impl<T: CopierTarget> CopyTermState<T> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::functor_macro::*;
use crate::machine::mock_wam::*; use crate::machine::mock_wam::*;
#[test] #[test]
fn copier_tests() { fn copier_tests() {
let mut wam = MockWAM::new(); let mut wam = MockWAM::new();
// clear the heap of resource error data etc
wam.machine_st.heap.clear();
let f_atom = atom!("f"); let f_atom = atom!("f");
let a_atom = atom!("a"); let a_atom = atom!("a");
let b_atom = atom!("b"); let b_atom = atom!("b");
wam.machine_st let mut functor_writer = Heap::functor_writer(
.heap functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom)]),
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); );
functor_writer(&mut wam.machine_st.heap).unwrap();
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 2)); assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 2));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom)); assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
@@ -415,7 +450,7 @@ mod tests {
{ {
let wam = TermCopyingMockWAM { wam: &mut wam }; let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy); copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
} }
// check that the original heap state is still intact. // check that the original heap state is still intact.
@@ -430,69 +465,62 @@ mod tests {
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
let pstr_var_cell = let mut writer = wam.machine_st.heap.reserve(4).unwrap();
put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
wam.machine_st.heap.pop(); writer.write_with(|section| {
wam.machine_st.heap.push(pstr_loc_as_cell!(2)); section.push_pstr("abc ");
section.push_cell(pstr_loc_as_cell!(heap_index!(2)));
let pstr_second_var_cell = section.push_pstr("def");
put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl); section.push_cell(pstr_loc_as_cell!(0));
let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; });
wam.machine_st.heap.pop();
wam.machine_st
.heap
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
wam.machine_st
.heap
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
{ {
let wam = TermCopyingMockWAM { wam: &mut wam }; let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy); copy_term(wam, pstr_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
} }
print_heap_terms(wam.machine_st.heap[6..].iter(), 6);
assert_eq!(wam.machine_st.heap[0], pstr_cell);
assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(2));
assert_eq!(wam.machine_st.heap[2], pstr_second_cell);
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(4));
assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0));
assert_eq!( assert_eq!(
wam.machine_st.heap[5], wam.machine_st.heap.slice_to_str(0, "abc ".len()),
fixnum_as_cell!(Fixnum::build_with(0i64)) "abc "
); );
assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(heap_index!(2)));
assert_eq!(wam.machine_st.heap[7], pstr_cell);
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(9));
assert_eq!(wam.machine_st.heap[9], pstr_second_cell);
assert_eq!(wam.machine_st.heap[10], pstr_loc_as_cell!(11));
assert_eq!(wam.machine_st.heap[11], pstr_offset_as_cell!(7));
assert_eq!( assert_eq!(
wam.machine_st.heap[12], wam.machine_st.heap.slice_to_str(heap_index!(2), "def".len()),
fixnum_as_cell!(Fixnum::build_with(0i64)) "def"
); );
assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(0));
assert_eq!(wam.machine_st.heap[4], pstr_loc_as_cell!(heap_index!(5)));
assert_eq!(
wam.machine_st.heap.slice_to_str(heap_index!(5), "abc ".len()),
"abc "
);
assert_eq!(wam.machine_st.heap[6], pstr_loc_as_cell!(heap_index!(7)));
assert_eq!(
wam.machine_st.heap.slice_to_str(heap_index!(7), "def".len()),
"def"
);
assert_eq!(wam.machine_st.heap[8], pstr_loc_as_cell!(heap_index!(5)));
wam.machine_st.heap.clear(); wam.machine_st.heap.clear();
wam.machine_st.heap.extend(functor!( let mut functor_writer = Heap::functor_writer(functor!(
f_atom, f_atom,
[ [
atom(a_atom), atom_as_cell(a_atom),
atom(b_atom), atom_as_cell(b_atom),
atom(a_atom), atom_as_cell(a_atom),
cell(str_loc_as_cell!(0)) str_loc_as_cell(0)
] ]
)); ));
functor_writer(&mut wam.machine_st.heap).unwrap();
{ {
let wam = TermCopyingMockWAM { wam: &mut wam }; let wam = TermCopyingMockWAM { wam: &mut wam };
copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy); copy_term(wam, str_loc_as_cell!(0), AttrVarPolicy::DeepCopy).unwrap();
} }
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 4)); assert_eq!(wam.machine_st.heap[0], atom_as_cell!(f_atom, 4));

View File

@@ -1,4 +1,5 @@
use crate::atom_table::*; use crate::atom_table::*;
use crate::machine::heap::*;
use crate::types::*; use crate::types::*;
/* Use the pointer reversal technique of the Deutsch-Schorr-Waite /* Use the pointer reversal technique of the Deutsch-Schorr-Waite
@@ -11,7 +12,7 @@ use crate::types::*;
* - Cells are only marked during the backward phase * - Cells are only marked during the backward phase
* - Visiting subterms of a visited compound does not immediately shift to the backward phase * - Visiting subterms of a visited compound does not immediately shift to the backward phase
* - The heads of LIS structures are both marked and forwarded rather * - The heads of LIS structures are both marked and forwarded rather
* than just forwarded to distinguish them from tails; * than just forwarded to distinguish them from tails
* continue_forwarding() checks for this before entering the forward * continue_forwarding() checks for this before entering the forward
* phase * phase
* *
@@ -22,7 +23,7 @@ use crate::types::*;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct CycleDetectingIter<'a, const STOP_AT_CYCLES: bool> { pub(crate) struct CycleDetectingIter<'a, const STOP_AT_CYCLES: bool> {
pub(crate) heap: &'a mut [HeapCellValue], pub(crate) heap: &'a mut Heap,
start: usize, start: usize,
current: usize, current: usize,
next: u64, next: u64,
@@ -31,7 +32,7 @@ pub(crate) struct CycleDetectingIter<'a, const STOP_AT_CYCLES: bool> {
} }
impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> { impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self { pub(crate) fn new(heap: &'a mut Heap, start: usize) -> Self {
heap[start].set_forwarding_bit(true); heap[start].set_forwarding_bit(true);
let next = heap[start].get_value(); let next = heap[start].get_value();
@@ -127,7 +128,7 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
self.current = next; self.current = next;
self.next = temp; self.next = temp;
if self.next < self.heap.len() as u64 { if self.next < self.heap.cell_len() as u64 {
return Some(HeapCellValue::build_with(tag, next as u64)); return Some(HeapCellValue::build_with(tag, next as u64));
} }
} }
@@ -205,8 +206,7 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
} }
HeapCellValueTag::PStrLoc => { HeapCellValueTag::PStrLoc => {
let h = self.next as usize; let h = self.next as usize;
let cell = self.heap[h]; let (_, last_cell_loc) = self.heap.scan_slice_to_str(h);
let last_cell_loc = h + 1;
if self.heap[last_cell_loc].get_forwarding_bit() { if self.heap[last_cell_loc].get_forwarding_bit() {
if self.cycle_detection_active() { if self.cycle_detection_active() {
@@ -225,39 +225,7 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
self.heap[last_cell_loc].set_value(self.current as u64); self.heap[last_cell_loc].set_value(self.current as u64);
self.current = last_cell_loc; self.current = last_cell_loc;
return Some(cell); return Some(pstr_loc_as_cell!(h));
}
HeapCellValueTag::PStrOffset => {
let h = self.next as usize;
let cell = self.heap[h];
let last_cell_loc = h + 1;
if self.heap[h].get_tag() == HeapCellValueTag::PStr {
if self.heap[last_cell_loc].get_forwarding_bit() {
if self.cycle_detection_active() {
self.cycle_found = true;
return None;
} else if self.backward() {
return None;
}
continue;
}
self.heap[last_cell_loc].set_forwarding_bit(true);
self.next = self.heap[last_cell_loc].get_value();
self.heap[last_cell_loc].set_value(self.current as u64);
self.current = last_cell_loc;
} else {
debug_assert!(self.heap[h].get_tag() == HeapCellValueTag::CStr);
self.next = self.heap[h].get_value();
self.heap[h].set_value(self.current as u64);
self.current = h;
}
return Some(cell);
} }
tag @ HeapCellValueTag::Atom => { tag @ HeapCellValueTag::Atom => {
let cell = HeapCellValue::build_with(tag, self.next); let cell = HeapCellValue::build_with(tag, self.next);
@@ -269,11 +237,6 @@ impl<'a, const STOP_AT_CYCLES: bool> CycleDetectingIter<'a, STOP_AT_CYCLES> {
return None; return None;
} }
} }
HeapCellValueTag::PStr => {
if self.backward() {
return None;
}
}
_ => { _ => {
return Some(self.backward_and_return()); return Some(self.backward_and_return());
} }

View File

@@ -3,6 +3,7 @@ use crate::forms::*;
use crate::instructions::*; use crate::instructions::*;
use crate::iterators::fact_iterator; use crate::iterators::fact_iterator;
use crate::machine::Stack; use crate::machine::Stack;
use crate::machine::heap::*;
use crate::machine::loader::*; use crate::machine::loader::*;
use crate::machine::machine_errors::CompilationError; use crate::machine::machine_errors::CompilationError;
use crate::machine::preprocessor::*; use crate::machine::preprocessor::*;
@@ -320,13 +321,12 @@ impl VariableClassifier {
} }
} }
pub fn classify_fact( pub fn classify_fact<'a, LS: LoadState<'a>>(
mut self, mut self,
term: &mut FocusedHeap, loader: &mut Loader<'a, LS>,
term: &TermWriteResult,
) -> Result<ClassifyFactResult, CompilationError> { ) -> Result<ClassifyFactResult, CompilationError> {
let focus = term.focus; self.classify_head_variables(loader, &term, term.focus)?;
self.classify_head_variables(term, focus)?;
Ok(self.branch_map.separate_and_classify_variables( Ok(self.branch_map.separate_and_classify_variables(
self.var_num, self.var_num,
self.global_cut_var_num, self.global_cut_var_num,
@@ -337,12 +337,14 @@ impl VariableClassifier {
pub fn classify_rule<'a, LS: LoadState<'a>>( pub fn classify_rule<'a, LS: LoadState<'a>>(
mut self, mut self,
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
term: &mut FocusedHeap, term: &TermWriteResult,
) -> Result<ClassifyRuleResult, CompilationError> { ) -> Result<ClassifyRuleResult, CompilationError> {
let head_loc = term.nth_arg(term.focus, 1).unwrap(); let heap = &mut LS::machine_st(&mut loader.payload).heap;
let body_loc = term.nth_arg(term.focus, 2).unwrap();
self.classify_head_variables(term, head_loc)?; let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
let body_loc = term_nth_arg(heap, term.focus, 2).unwrap();
self.classify_head_variables(loader, &term, head_loc)?;
self.root_set.insert(self.current_branch_num.clone()); self.root_set.insert(self.current_branch_num.clone());
let mut query_terms = self.classify_body_variables(loader, term, body_loc)?; let mut query_terms = self.classify_body_variables(loader, term, body_loc)?;
@@ -385,8 +387,8 @@ impl VariableClassifier {
&mut self, &mut self,
arg_c: usize, arg_c: usize,
arity: usize, arity: usize,
term: &mut FocusedHeap, term: &mut FocusedHeapRefMut,
term_loc: usize, inverse_var_locs: &InverseVarLocs,
context: GenContext, context: GenContext,
) { ) {
let classify_info = ClassifyInfo { arg_c, arity }; let classify_info = ClassifyInfo { arg_c, arity };
@@ -394,9 +396,9 @@ impl VariableClassifier {
let mut lvl = Level::Shallow; let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized(); let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>( let mut iter = fact_iterator::<false>(
&mut term.heap, term.heap,
&mut stack, &mut stack,
term_loc, term.focus,
); );
// second arg is true to iterate the root, which may be a variable // second arg is true to iterate the root, which may be a variable
@@ -407,7 +409,7 @@ impl VariableClassifier {
} }
let var_loc = subterm.get_value() as usize; let var_loc = subterm.get_value() as usize;
let var = to_classified_var(&term.inverse_var_locs, var_loc); let var = to_classified_var(inverse_var_locs, var_loc);
self.probe_body_var( self.probe_body_var(
context, context,
@@ -468,27 +470,21 @@ impl VariableClassifier {
self.probe_body_var(context, var_info); self.probe_body_var(context, var_info);
} }
fn classify_head_variables( fn classify_head_variables<'a, LS: LoadState<'a>>(
&mut self, &mut self,
term: &mut FocusedHeap, loader: &mut Loader<'a, LS>,
term: &TermWriteResult,
head_loc: usize, head_loc: usize,
) -> Result<(), CompilationError> { ) -> Result<(), CompilationError> {
let arity = read_heap_cell!(term.deref_loc(head_loc), let heap = &mut LS::machine_st(&mut loader.payload).heap;
(HeapCellValueTag::Str, s) => { let arity = term_predicate_key(heap, head_loc)
cell_as_atom_cell!(term.heap[s]).get_arity() .and_then(|(_, arity)| Some(arity))
} .ok_or(CompilationError::InvalidRuleHead)?;
(HeapCellValueTag::Atom) => {
return Ok(());
}
_ => {
return Err(CompilationError::InvalidRuleHead);
}
);
let mut classify_info = ClassifyInfo { arg_c: 1, arity }; let mut classify_info = ClassifyInfo { arg_c: 1, arity };
if arity > 0 { if arity > 0 {
let (_term_loc, value) = subterm_index(&term.heap, head_loc); let (_term_loc, value) = subterm_index(heap, head_loc);
let str_offset = value.get_value() as usize; let str_offset = value.get_value() as usize;
debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str); debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str);
@@ -497,7 +493,7 @@ impl VariableClassifier {
let mut lvl = Level::Shallow; let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized(); let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>( let mut iter = fact_iterator::<false>(
&mut term.heap, heap,
&mut stack, &mut stack,
idx, idx,
); );
@@ -571,11 +567,11 @@ impl VariableClassifier {
fn classify_body_variables<'a, LS: LoadState<'a>>( fn classify_body_variables<'a, LS: LoadState<'a>>(
&mut self, &mut self,
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
terms: &mut FocusedHeap, terms: &TermWriteResult,
term_loc: usize, term_loc: usize,
) -> Result<ChunkedTermVec, CompilationError> { ) -> Result<ChunkedTermVec, CompilationError> {
let mut state_stack = vec![TraversalState::Term { let mut state_stack = vec![TraversalState::Term {
subterm: terms.heap[term_loc], subterm: loader.machine_heap()[term_loc],
term_loc, term_loc,
}]; }];
let mut build_stack = ChunkedTermVec::new(); let mut build_stack = ChunkedTermVec::new();
@@ -684,13 +680,21 @@ impl VariableClassifier {
for (arg_c, term_loc) in for (arg_c, term_loc) in
($term_loc + 1 ..= $term_loc + $key.1).enumerate() ($term_loc + 1 ..= $term_loc + $key.1).enumerate()
{ {
self.probe_body_term(arg_c + 1, $key.1, terms, term_loc, context); let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
self.probe_body_term(
arg_c + 1,
$key.1,
&mut term,
&terms.inverse_var_locs,
context,
);
} }
build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term( build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
loader, loader,
$key, $key,
terms.as_ref_mut($term_loc), &terms,
HeapCellValue::build_with($tag, $term_loc as u64), HeapCellValue::build_with($tag, $term_loc as u64),
self.call_policy, self.call_policy,
))); )));
@@ -706,9 +710,17 @@ impl VariableClassifier {
let context = build_stack.current_gen_context(); let context = build_stack.current_gen_context();
for (arg_c, term_loc) in for (arg_c, term_loc) in
($term_loc + 1..$term_loc + $key.1 + 1).enumerate() ($term_loc + 1 ..= $term_loc + $key.1).enumerate()
{ {
self.probe_body_term(arg_c + 1, $key.1, terms, term_loc, context); let mut term = FocusedHeapRefMut::from(loader.machine_heap(), term_loc);
self.probe_body_term(
arg_c + 1,
$key.1,
&mut term,
&terms.inverse_var_locs,
context,
);
} }
build_stack.push_chunk_term(QueryTerm::Clause( build_stack.push_chunk_term(QueryTerm::Clause(
@@ -716,7 +728,7 @@ impl VariableClassifier {
loader, loader,
$key, $key,
$module_name, $module_name,
terms.as_ref_mut($term_loc), &terms,
HeapCellValue::build_with($tag, $term_loc as u64), HeapCellValue::build_with($tag, $term_loc as u64),
self.call_policy, self.call_policy,
), ),
@@ -725,26 +737,28 @@ impl VariableClassifier {
} }
loop { loop {
let heap = loader.machine_heap();
read_heap_cell!(subterm, read_heap_cell!(subterm,
(HeapCellValueTag::Str, subterm_loc) => { (HeapCellValueTag::Str, subterm_loc) => {
let (name, arity) = cell_as_atom_cell!(terms.heap[subterm_loc]) let (name, arity) = cell_as_atom_cell!(heap[subterm_loc])
.get_name_and_arity(); .get_name_and_arity();
match (name, arity) { match (name, arity) {
(atom!("->") | atom!(";") | atom!(","), 3) => { (atom!("->") | atom!(";") | atom!(","), 3) => {
if blunt_index_ptr(&mut terms.heap, (name, 2), subterm_loc) { if blunt_index_ptr(heap, (name, 2), subterm_loc) {
subterm = terms.heap[subterm_loc]; subterm = heap[subterm_loc];
continue; continue;
} }
add_chunk!((name, 2), HeapCellValueTag::Str, subterm_loc); add_chunk!((name, 2), HeapCellValueTag::Str, subterm_loc);
} }
(atom!(","), 2) => { (atom!(","), 2) => {
let head_loc = terms.nth_arg(subterm_loc, 1).unwrap(); let head_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap(); let tail_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let head = terms.heap[head_loc]; let head = heap[head_loc];
let iter = unfold_by_str_locs(&mut terms.heap, tail_loc, atom!(",")) let iter = unfold_by_str_locs(heap, tail_loc, atom!(","))
.into_iter() .into_iter()
.rev() .rev()
.chain(std::iter::once((head, head_loc))) .chain(std::iter::once((head, head_loc)))
@@ -754,15 +768,15 @@ impl VariableClassifier {
state_stack.extend(iter); state_stack.extend(iter);
} }
(atom!(";"), 2) => { (atom!(";"), 2) => {
let head_loc = terms.nth_arg(subterm_loc, 1).unwrap(); let head_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap(); let tail_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let head = terms.heap[head_loc]; let head = heap[head_loc];
let first_branch_num = self.current_branch_num.split(); let first_branch_num = self.current_branch_num.split();
let branches: Vec<_> = std::iter::once((head, head_loc)) let branches: Vec<_> = std::iter::once((head, head_loc))
.chain( .chain(
unfold_by_str_locs(&mut terms.heap, tail_loc, atom!(";")) unfold_by_str_locs(heap, tail_loc, atom!(";"))
.into_iter(), .into_iter(),
) )
.collect(); .collect();
@@ -807,11 +821,11 @@ impl VariableClassifier {
build_stack.current_chunk_num += 1; build_stack.current_chunk_num += 1;
} }
(atom!("->"), 2) => { (atom!("->"), 2) => {
let if_term_loc = terms.nth_arg(subterm_loc, 1).unwrap(); let if_term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let then_term_loc = terms.nth_arg(subterm_loc, 2).unwrap(); let then_term_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let if_term = terms.heap[if_term_loc]; let if_term = heap[if_term_loc];
let then_term = terms.heap[then_term_loc]; let then_term = heap[then_term_loc];
let prev_b = if matches!( let prev_b = if matches!(
state_stack.last(), state_stack.last(),
@@ -851,8 +865,8 @@ impl VariableClassifier {
self.var_num += 1; self.var_num += 1;
} }
(atom!("\\+"), 1) => { (atom!("\\+"), 1) => {
let not_term_loc = terms.nth_arg(subterm_loc, 1).unwrap(); let not_term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let not_term = terms.heap[not_term_loc]; let not_term = heap[not_term_loc];
let build_stack_len = build_stack.len(); let build_stack_len = build_stack.len();
build_stack.reserve_branch(2); build_stack.reserve_branch(2);
@@ -886,18 +900,19 @@ impl VariableClassifier {
self.var_num += 1; self.var_num += 1;
} }
(atom!(":"), 2) => { (atom!(":"), 2) => {
let module_name_loc = terms.nth_arg(subterm_loc, 1).unwrap(); let module_name_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let predicate_term_loc = terms.nth_arg(subterm_loc, 2).unwrap(); let predicate_term_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
let mut focused = FocusedHeapRefMut::from(heap, module_name_loc);
let module_name = terms.deref_loc(module_name_loc); let module_name = focused.deref_loc(module_name_loc);
let predicate_term = terms.deref_loc(predicate_term_loc); let predicate_term = focused.deref_loc(predicate_term_loc);
read_heap_cell!(module_name, read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => { (HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 { if arity == 0 {
read_heap_cell!(predicate_term, read_heap_cell!(predicate_term,
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let key = cell_as_atom_cell!(terms.heap[s]) let key = cell_as_atom_cell!(heap[s])
.get_name_and_arity(); .get_name_and_arity();
add_qualified_chunk!( add_qualified_chunk!(
@@ -933,25 +948,40 @@ impl VariableClassifier {
let context = build_stack.current_gen_context(); let context = build_stack.current_gen_context();
self.probe_body_term(1, 0, terms, module_name_loc, context); focused.focus = module_name_loc;
self.probe_body_term(2, 0, terms, predicate_term_loc, context);
let h = terms.heap.len(); self.probe_body_term(
1, 0, &mut focused, &terms.inverse_var_locs, context,
);
terms.heap.push(atom_as_cell!(atom!("call"), 1)); focused.focus = predicate_term_loc;
terms.heap.push(str_loc_as_cell!(subterm_loc));
self.probe_body_term(
2, 0, &mut focused, &terms.inverse_var_locs, context,
);
let h = heap.cell_len();
heap.push_cell(atom_as_cell!(atom!("call"), 1))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
heap.push_cell(str_loc_as_cell!(subterm_loc))
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term( build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
loader, loader,
(atom!("call"), 1), (atom!("call"), 1),
terms.as_ref_mut(h), terms,
str_loc_as_cell!(h), str_loc_as_cell!(h),
self.call_policy, self.call_policy,
))); )));
} }
(atom!("$call_with_inference_counting"), 1) => { (atom!("$call_with_inference_counting"), 1) => {
let term_loc = terms.nth_arg(subterm_loc, 1).unwrap(); let term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
let subterm = terms.deref_loc(term_loc); let heap = loader.machine_heap();
let subterm = heap_bound_store(
heap,
heap_bound_deref(heap, heap[term_loc]),
);
state_stack.push(TraversalState::ResetCallPolicy(self.call_policy)); state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
state_stack.push(TraversalState::Term { subterm, term_loc }); state_stack.push(TraversalState::Term { subterm, term_loc });
@@ -973,17 +1003,9 @@ impl VariableClassifier {
add_chunk!((name, 0), HeapCellValueTag::Var, term_loc); add_chunk!((name, 0), HeapCellValueTag::Var, term_loc);
} }
} }
(HeapCellValueTag::Char, c) => {
if c == '!' {
let context = build_stack.current_gen_context();
state_stack.push(self.new_cut_state(context));
} else {
return Err(CompilationError::InadmissibleQueryTerm);
}
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h != term_loc { if h != term_loc {
subterm = terms.heap[h]; subterm = heap[h];
term_loc = h; term_loc = h;
continue; continue;
} }

View File

@@ -1,5 +1,6 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::functor_macro::*;
use crate::instructions::*; use crate::instructions::*;
use crate::machine::arithmetic_ops::*; use crate::machine::arithmetic_ops::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
@@ -24,7 +25,10 @@ macro_rules! try_or_throw {
match $e { match $e {
Ok(val) => val, Ok(val) => val,
Err(msg) => { Err(msg) => {
$s.throw_exception(msg); if !msg.is_empty() {
$s.throw_exception(msg);
}
$s.backtrack(); $s.backtrack();
continue; continue;
} }
@@ -32,6 +36,15 @@ macro_rules! try_or_throw {
}}; }};
} }
macro_rules! backtrack_on_resource_error {
($machine_st:expr, $val:expr) => {
step_or_resource_error!($machine_st, $val, {
$machine_st.backtrack();
continue;
})
};
}
macro_rules! increment_call_count { macro_rules! increment_call_count {
($s:expr) => {{ ($s:expr) => {{
if !$s.increment_call_count() { if !$s.increment_call_count() {
@@ -55,6 +68,15 @@ macro_rules! try_or_throw_gen {
}}; }};
} }
macro_rules! push_cell {
($machine_st:expr, $cell:expr) => {{
step_or_resource_error!($machine_st, $machine_st.heap.push_cell($cell), {
$machine_st.backtrack();
continue;
})
}};
}
static INSTRUCTIONS_PER_INTERRUPT_POLL: usize = 256; static INSTRUCTIONS_PER_INTERRUPT_POLL: usize = 256;
impl MachineState { impl MachineState {
@@ -113,12 +135,15 @@ impl MachineState {
} }
pub fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) { pub fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) {
let old_h = self.heap.len(); let old_h = self.heap.cell_len();
let a1 = self.registers[1]; let a1 = self.registers[1];
let a2 = self.registers[2]; let a2 = self.registers[2];
copy_term(CopyTerm::new(self), a1, attr_var_policy); step_or_resource_error!(
self,
copy_term(CopyTerm::new(self), a1, attr_var_policy)
);
unify_fn!(*self, heap_loc_as_cell!(old_h), a2); unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
} }
@@ -135,10 +160,16 @@ impl MachineState {
list.dedup_by(|v1, v2| compare_term_test!(self, *v1, *v2) == Some(Ordering::Equal)); list.dedup_by(|v1, v2| compare_term_test!(self, *v1, *v2) == Some(Ordering::Equal));
let heap_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, list.into_iter())); let heap_addr = resource_error_call_result!(
self,
sized_iter_to_heap_list(
&mut self.heap,
list.len(),
list.into_iter(),
)
);
let target_addr = self.registers[2]; let target_addr = self.registers[2];
unify_fn!(*self, target_addr, heap_addr); unify_fn!(*self, target_addr, heap_addr);
Ok(()) Ok(())
} }
@@ -160,8 +191,14 @@ impl MachineState {
compare_term_test!(self, a1.0, a2.0, var_comparison).unwrap_or(Ordering::Less) compare_term_test!(self, a1.0, a2.0, var_comparison).unwrap_or(Ordering::Less)
}); });
let key_pairs = key_pairs.into_iter().map(|kp| kp.1); let heap_addr = resource_error_call_result!(
let heap_addr = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, key_pairs)); self,
sized_iter_to_heap_list(
&mut self.heap,
key_pairs.len(),
key_pairs.into_iter().map(|kp| kp.1),
)
);
let target_addr = self.registers[2]; let target_addr = self.registers[2];
@@ -201,13 +238,13 @@ impl MachineState {
v v
} }
(HeapCellValueTag::PStrLoc | (HeapCellValueTag::PStrLoc |
HeapCellValueTag::Lis | HeapCellValueTag::Lis) => {
HeapCellValueTag::CStr) => { // HeapCellValueTag::CStr) => {
l l
} }
(HeapCellValueTag::Fixnum | (HeapCellValueTag::Fixnum |
HeapCellValueTag::CutPoint | HeapCellValueTag::CutPoint |
HeapCellValueTag::Char | // HeapCellValueTag::Char |
HeapCellValueTag::F64) => { HeapCellValueTag::F64) => {
c c
} }
@@ -242,6 +279,7 @@ impl MachineState {
) )
} }
/*
#[inline(always)] #[inline(always)]
pub(crate) fn constant_to_literal(&self, addr: HeapCellValue) -> Literal { pub(crate) fn constant_to_literal(&self, addr: HeapCellValue) -> Literal {
read_heap_cell!(addr, read_heap_cell!(addr,
@@ -288,6 +326,7 @@ impl MachineState {
} }
) )
} }
*/
#[inline(always)] #[inline(always)]
pub(crate) fn select_switch_on_structure_index( pub(crate) fn select_switch_on_structure_index(
@@ -464,9 +503,9 @@ impl Machine {
} }
} }
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
let lit = self.machine_st.constant_to_literal(addr); // let lit = self.machine_st.constant_to_literal(addr);
let offset = match hm.get(&lit) { let offset = match hm.get(&addr) {
Some(offset) => *offset, Some(offset) => *offset,
_ => IndexingCodePtr::Fail, _ => IndexingCodePtr::Fail,
}; };
@@ -1245,22 +1284,32 @@ impl Machine {
self.machine_st.allocate(num_cells); self.machine_st.allocate(num_cells);
} }
&Instruction::DefaultCallAcyclicTerm => { &Instruction::DefaultCallAcyclicTerm => {
let addr = self.machine_st.registers[1]; let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) { if addr.is_ref() {
self.machine_st.backtrack(); self.machine_st.heap[0] = addr;
} else {
self.machine_st.p += 1; if self.machine_st.is_cyclic_term(0) {
self.machine_st.backtrack();
continue;
}
} }
self.machine_st.p += 1;
} }
&Instruction::DefaultExecuteAcyclicTerm => { &Instruction::DefaultExecuteAcyclicTerm => {
let addr = self.machine_st.registers[1]; let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) { if addr.is_ref() {
self.machine_st.backtrack(); self.machine_st.heap[0] = addr;
} else {
self.machine_st.p = self.machine_st.cp; if self.machine_st.is_cyclic_term(0) {
self.machine_st.backtrack();
continue;
}
} }
self.machine_st.p = self.machine_st.cp;
} }
&Instruction::DefaultCallArg => { &Instruction::DefaultCallArg => {
try_or_throw!(self.machine_st, self.machine_st.try_arg()); try_or_throw!(self.machine_st, self.machine_st.try_arg());
@@ -1497,24 +1546,34 @@ impl Machine {
step_or_fail!(self, self.machine_st.p = self.machine_st.cp); step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
} }
&Instruction::CallAcyclicTerm => { &Instruction::CallAcyclicTerm => {
let addr = self.machine_st.registers[1]; let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) { if addr.is_ref() {
self.machine_st.backtrack(); self.machine_st.heap[0] = addr;
} else {
increment_call_count!(self.machine_st); if self.machine_st.is_cyclic_term(0) {
self.machine_st.p += 1; self.machine_st.backtrack();
continue;
}
} }
increment_call_count!(self.machine_st);
self.machine_st.p += 1;
} }
&Instruction::ExecuteAcyclicTerm => { &Instruction::ExecuteAcyclicTerm => {
let addr = self.machine_st.registers[1]; let addr = self.deref_register(1);
if self.machine_st.is_cyclic_term(addr) { if addr.is_ref() {
self.machine_st.backtrack(); self.machine_st.heap[0] = addr;
} else {
increment_call_count!(self.machine_st); if self.machine_st.is_cyclic_term(0) {
self.machine_st.p = self.machine_st.cp; self.machine_st.backtrack();
continue;
}
} }
increment_call_count!(self.machine_st);
self.machine_st.p = self.machine_st.cp;
} }
&Instruction::CallArg => { &Instruction::CallArg => {
try_or_throw!(self.machine_st, self.machine_st.try_arg()); try_or_throw!(self.machine_st, self.machine_st.try_arg());
@@ -2282,9 +2341,6 @@ impl Machine {
self.machine_st.backtrack(); self.machine_st.backtrack();
} }
} }
(HeapCellValueTag::Char) => {
self.machine_st.p += 1;
}
_ => { _ => {
self.machine_st.backtrack(); self.machine_st.backtrack();
} }
@@ -2313,9 +2369,6 @@ impl Machine {
self.machine_st.backtrack(); self.machine_st.backtrack();
} }
} }
(HeapCellValueTag::Char) => {
self.machine_st.p = self.machine_st.cp;
}
_ => { _ => {
self.machine_st.backtrack(); self.machine_st.backtrack();
} }
@@ -2327,7 +2380,7 @@ impl Machine {
.store(self.machine_st.deref(self.machine_st[r])); .store(self.machine_st.deref(self.machine_st[r]));
read_heap_cell!(d, read_heap_cell!(d,
(HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 | (HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
HeapCellValueTag::Cons) => { HeapCellValueTag::Cons) => {
self.machine_st.p += 1; self.machine_st.p += 1;
} }
@@ -2359,7 +2412,7 @@ impl Machine {
.store(self.machine_st.deref(self.machine_st[r])); .store(self.machine_st.deref(self.machine_st[r]));
read_heap_cell!(d, read_heap_cell!(d,
(HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 | (HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
HeapCellValueTag::Cons) => { HeapCellValueTag::Cons) => {
self.machine_st.p = self.machine_st.cp; self.machine_st.p = self.machine_st.cp;
} }
@@ -2392,8 +2445,8 @@ impl Machine {
read_heap_cell!(d, read_heap_cell!(d,
(HeapCellValueTag::Lis | (HeapCellValueTag::Lis |
HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrLoc) => {
HeapCellValueTag::CStr) => { // HeapCellValueTag::CStr) => {
self.machine_st.p += 1; self.machine_st.p += 1;
} }
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
@@ -2425,8 +2478,8 @@ impl Machine {
read_heap_cell!(d, read_heap_cell!(d,
(HeapCellValueTag::Lis | (HeapCellValueTag::Lis |
HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrLoc) => {
HeapCellValueTag::CStr) => { // HeapCellValueTag::CStr) => {
self.machine_st.p = self.machine_st.cp; self.machine_st.p = self.machine_st.cp;
} }
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
@@ -2664,8 +2717,6 @@ impl Machine {
&Instruction::CallNamed(arity, name, ref idx) => { &Instruction::CallNamed(arity, name, ref idx) => {
let idx = idx.get(); let idx = idx.get();
// println!("calling {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_call(name, arity, idx)); try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
if self.machine_st.fail { if self.machine_st.fail {
@@ -2677,8 +2728,6 @@ impl Machine {
&Instruction::ExecuteNamed(arity, name, ref idx) => { &Instruction::ExecuteNamed(arity, name, ref idx) => {
let idx = idx.get(); let idx = idx.get();
// println!("executing {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx)); try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
if self.machine_st.fail { if self.machine_st.fail {
@@ -2690,8 +2739,6 @@ impl Machine {
&Instruction::DefaultCallNamed(arity, name, ref idx) => { &Instruction::DefaultCallNamed(arity, name, ref idx) => {
let idx = idx.get(); let idx = idx.get();
// println!("calling {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_call(name, arity, idx)); try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
if self.machine_st.fail { if self.machine_st.fail {
@@ -2701,8 +2748,6 @@ impl Machine {
&Instruction::DefaultExecuteNamed(arity, name, ref idx) => { &Instruction::DefaultExecuteNamed(arity, name, ref idx) => {
let idx = idx.get(); let idx = idx.get();
// println!("executing {}/{}", name.as_str(), arity);
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx)); try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
if self.machine_st.fail { if self.machine_st.fail {
@@ -2720,8 +2765,7 @@ impl Machine {
self.machine_st.p = self.machine_st.cp; self.machine_st.p = self.machine_st.cp;
} }
&Instruction::GetConstant(_, c, reg) => { &Instruction::GetConstant(_, c, reg) => {
let value = self.machine_st.deref(self.machine_st[reg]); unify!(self.machine_st, self.machine_st[reg], c);
self.machine_st.write_literal_to_var(value, c);
step_or_fail!(self, self.machine_st.p += 1); step_or_fail!(self, self.machine_st.p += 1);
} }
&Instruction::GetList(_, reg) => { &Instruction::GetList(_, reg) => {
@@ -2730,17 +2774,7 @@ impl Machine {
read_heap_cell!(store_v, read_heap_cell!(store_v,
(HeapCellValueTag::PStrLoc, h) => { (HeapCellValueTag::PStrLoc, h) => {
let (h, n) = pstr_loc_and_offset(&self.machine_st.heap, h); self.machine_st.s = HeapPtr::PStr(h);
self.machine_st.s = HeapPtr::PStrChar(h, n.get_num() as usize);
self.machine_st.s_offset = 0;
self.machine_st.mode = MachineMode::Read;
}
(HeapCellValueTag::CStr) => {
let h = self.machine_st.heap.len();
self.machine_st.heap.push(store_v);
self.machine_st.s = HeapPtr::PStrChar(h, 0);
self.machine_st.s_offset = 0; self.machine_st.s_offset = 0;
self.machine_st.mode = MachineMode::Read; self.machine_st.mode = MachineMode::Read;
} }
@@ -2763,9 +2797,9 @@ impl Machine {
self.machine_st.mode = MachineMode::Read; self.machine_st.mode = MachineMode::Read;
} }
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(list_loc_as_cell!(h+1)); push_cell!(self.machine_st, list_loc_as_cell!(h+1));
self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h)); self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
self.machine_st.mode = MachineMode::Write; self.machine_st.mode = MachineMode::Write;
@@ -2778,29 +2812,61 @@ impl Machine {
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::GetPartialString(_, string, reg, has_tail) => { &Instruction::GetPartialString(_, ref string, reg) => {
use crate::machine::partial_string::{HeapPStrIter, PStrCmpResult};
let deref_v = self.machine_st.deref(self.machine_st[reg]); let deref_v = self.machine_st.deref(self.machine_st[reg]);
let store_v = self.machine_st.store(deref_v); let store_v = self.machine_st.store(deref_v);
read_heap_cell!(store_v, read_heap_cell!(store_v,
(HeapCellValueTag::Str | (HeapCellValueTag::Str |
HeapCellValueTag::Lis | HeapCellValueTag::Lis |
HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrLoc) => {
HeapCellValueTag::CStr) => { debug_assert!(store_v.is_ref());
self.machine_st.match_partial_string(store_v, string, has_tail);
self.machine_st.heap[0] = store_v;
let heap_pstr_iter = HeapPStrIter::new(&self.machine_st.heap, 0);
match heap_pstr_iter.compare_pstr_to_string(string) {
Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc }) => {
self.machine_st.s_offset = chars_matched;
self.machine_st.s = HeapPtr::PStr(pstr_loc);
self.machine_st.mode = MachineMode::Read;
}
Some(PStrCmpResult::PartialPStrMatch { string, var_loc }) => {
let cell = backtrack_on_resource_error!(
self.machine_st,
self.machine_st.allocate_pstr(string)
);
self.machine_st.mode = MachineMode::Write;
unify!(self.machine_st, cell, heap_loc_as_cell!(var_loc));
}
Some(PStrCmpResult::ListMatch { list_loc }) => {
self.machine_st.s_offset = 0;
self.machine_st.s = HeapPtr::HeapCell(list_loc);
self.machine_st.mode = MachineMode::Read;
}
None => {
self.machine_st.backtrack();
continue;
}
}
} }
(HeapCellValueTag::AttrVar | (HeapCellValueTag::AttrVar |
HeapCellValueTag::StackVar | HeapCellValueTag::StackVar |
HeapCellValueTag::Var) => { HeapCellValueTag::Var) => {
let target_cell = self.machine_st.push_str_to_heap( let target_cell = backtrack_on_resource_error!(
&string.as_str(), self.machine_st,
has_tail, self.machine_st.allocate_pstr(string)
); );
self.machine_st.bind( self.machine_st.bind(
store_v.as_var().unwrap(), store_v.as_var().unwrap(),
target_cell, target_cell,
); );
self.machine_st.mode = MachineMode::Write;
} }
_ => { _ => {
self.machine_st.backtrack(); self.machine_st.backtrack();
@@ -2833,10 +2899,10 @@ impl Machine {
); );
} }
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(str_loc_as_cell!(h+1)); push_cell!(self.machine_st, str_loc_as_cell!(h+1));
self.machine_st.heap.push(atom_as_cell!(name, arity)); push_cell!(self.machine_st, atom_as_cell!(name, arity));
self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h)); self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
self.machine_st.mode = MachineMode::Write; self.machine_st.mode = MachineMode::Write;
@@ -2870,8 +2936,7 @@ impl Machine {
match self.machine_st.mode { match self.machine_st.mode {
MachineMode::Read => { MachineMode::Read => {
let addr = self.machine_st.read_s(); let addr = self.machine_st.read_s();
unify!(&mut self.machine_st, addr, v);
self.machine_st.write_literal_to_var(addr, v);
if self.machine_st.fail { if self.machine_st.fail {
self.machine_st.backtrack(); self.machine_st.backtrack();
@@ -2881,7 +2946,7 @@ impl Machine {
} }
} }
MachineMode::Write => { MachineMode::Write => {
self.machine_st.heap.push(v); push_cell!(self.machine_st, v);
} }
} }
@@ -2906,17 +2971,17 @@ impl Machine {
let value = self let value = self
.machine_st .machine_st
.store(self.machine_st.deref(self.machine_st[reg])); .store(self.machine_st.deref(self.machine_st[reg]));
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
read_heap_cell!(value, read_heap_cell!(value,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, hc) => { (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, hc) => {
let value = self.machine_st.heap[hc]; let value = self.machine_st.heap[hc];
self.machine_st.heap.push(value); push_cell!(self.machine_st, value);
self.machine_st.s_offset += 1; self.machine_st.s_offset += 1;
} }
_ => { _ => {
self.machine_st.heap.push(heap_loc_as_cell!(h)); push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)( (self.machine_st.bind_fn)(
&mut self.machine_st, &mut self.machine_st,
Ref::heap_cell(h), Ref::heap_cell(h),
@@ -2932,13 +2997,14 @@ impl Machine {
&Instruction::UnifyVariable(reg) => { &Instruction::UnifyVariable(reg) => {
match self.machine_st.mode { match self.machine_st.mode {
MachineMode::Read => { MachineMode::Read => {
self.machine_st[reg] = self.machine_st.read_s(); let value = self.machine_st.read_s();
self.machine_st[reg] = value;
self.machine_st.s_offset += 1; self.machine_st.s_offset += 1;
} }
MachineMode::Write => { MachineMode::Write => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h)); push_cell!(self.machine_st, heap_loc_as_cell!(h));
self.machine_st[reg] = heap_loc_as_cell!(h); self.machine_st[reg] = heap_loc_as_cell!(h);
} }
} }
@@ -2961,8 +3027,8 @@ impl Machine {
} }
} }
MachineMode::Write => { MachineMode::Write => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h)); push_cell!(self.machine_st, heap_loc_as_cell!(h));
let addr = self.machine_st.store(self.machine_st[reg]); let addr = self.machine_st.store(self.machine_st[reg]);
(self.machine_st.bind_fn)( (self.machine_st.bind_fn)(
@@ -2974,7 +3040,7 @@ impl Machine {
// the former code of this match arm was: // the former code of this match arm was:
// let addr = self.machine_st.store(self.machine_st[reg]); // let addr = self.machine_st.store(self.machine_st[reg]);
// self.machine_st.heap.push(HeapCellValue::Addr(addr)); // push_cell!(self.machine_st, HeapCellValue::Addr(addr));
// the old code didn't perform the occurs // the old code didn't perform the occurs
// check when enabled and so it was changed to // check when enabled and so it was changed to
@@ -2991,10 +3057,10 @@ impl Machine {
self.machine_st.s_offset += n; self.machine_st.s_offset += n;
} }
MachineMode::Write => { MachineMode::Write => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
for i in h..h + n { for i in h..h + n {
self.machine_st.heap.push(heap_loc_as_cell!(i)); push_cell!(self.machine_st, heap_loc_as_cell!(i));
} }
} }
} }
@@ -3126,38 +3192,26 @@ impl Machine {
} }
} }
} }
&Instruction::PutConstant(_, c, reg) => { &Instruction::PutConstant(_, cell, reg) => {
self.machine_st[reg] = c; self.machine_st[reg] = cell;
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::PutList(_, reg) => { &Instruction::PutList(_, reg) => {
self.machine_st[reg] = list_loc_as_cell!(self.machine_st.heap.len()); self.machine_st[reg] = list_loc_as_cell!(self.machine_st.heap.cell_len());
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::PutPartialString(_, string, reg, has_tail) => { &Instruction::PutPartialString(_, ref string, reg) => {
let pstr_addr = if has_tail { self.machine_st[reg] = backtrack_on_resource_error!(
if string != atom!("") { self.machine_st,
let h = self.machine_st.heap.len(); self.machine_st.allocate_pstr(&string)
self.machine_st.heap.push(string_as_pstr_cell!(string)); );
// the tail will be pushed by the next
// instruction, so don't push one here.
pstr_loc_as_cell!(h)
} else {
empty_list_as_cell!()
}
} else {
string_as_cstr_cell!(string)
};
self.machine_st[reg] = pstr_addr;
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::PutStructure(name, arity, reg) => { &Instruction::PutStructure(name, arity, reg) => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(atom_as_cell!(name, arity)); push_cell!(self.machine_st, atom_as_cell!(name, arity));
self.machine_st[reg] = str_loc_as_cell!(h); self.machine_st[reg] = str_loc_as_cell!(h);
self.machine_st.p += 1; self.machine_st.p += 1;
@@ -3171,9 +3225,9 @@ impl Machine {
if addr.is_protected(self.machine_st.e) { if addr.is_protected(self.machine_st.e) {
self.machine_st.registers[arg] = addr; self.machine_st.registers[arg] = addr;
} else { } else {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h)); push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)( (self.machine_st.bind_fn)(
&mut self.machine_st, &mut self.machine_st,
Ref::heap_cell(h), Ref::heap_cell(h),
@@ -3197,8 +3251,8 @@ impl Machine {
self.machine_st.registers[arg] = self.machine_st[norm]; self.machine_st.registers[arg] = self.machine_st[norm];
} }
RegType::Temp(_) => { RegType::Temp(_) => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h)); push_cell!(self.machine_st, heap_loc_as_cell!(h));
self.machine_st[norm] = heap_loc_as_cell!(h); self.machine_st[norm] = heap_loc_as_cell!(h);
self.machine_st.registers[arg] = heap_loc_as_cell!(h); self.machine_st.registers[arg] = heap_loc_as_cell!(h);
@@ -3208,7 +3262,7 @@ impl Machine {
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::SetConstant(c) => { &Instruction::SetConstant(c) => {
self.machine_st.heap.push(c); push_cell!(self.machine_st, c);
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::SetLocalValue(reg) => { &Instruction::SetLocalValue(reg) => {
@@ -3216,37 +3270,37 @@ impl Machine {
let stored_v = self.machine_st.store(addr); let stored_v = self.machine_st.store(addr);
if stored_v.is_stack_var() { if stored_v.is_stack_var() {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h)); push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)( (self.machine_st.bind_fn)(
&mut self.machine_st, &mut self.machine_st,
Ref::heap_cell(h), Ref::heap_cell(h),
stored_v, stored_v,
); );
} else { } else {
self.machine_st.heap.push(stored_v); push_cell!(self.machine_st, stored_v);
} }
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::SetVariable(reg) => { &Instruction::SetVariable(reg) => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
self.machine_st.heap.push(heap_loc_as_cell!(h)); push_cell!(self.machine_st, heap_loc_as_cell!(h));
self.machine_st[reg] = heap_loc_as_cell!(h); self.machine_st[reg] = heap_loc_as_cell!(h);
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::SetValue(reg) => { &Instruction::SetValue(reg) => {
let heap_val = self.machine_st.store(self.machine_st[reg]); let heap_val = self.machine_st.store(self.machine_st[reg]);
self.machine_st.heap.push(heap_val); push_cell!(self.machine_st, heap_val);
self.machine_st.p += 1; self.machine_st.p += 1;
} }
&Instruction::SetVoid(n) => { &Instruction::SetVoid(n) => {
let h = self.machine_st.heap.len(); let h = self.machine_st.heap.cell_len();
for i in h..h + n { for i in h..h + n {
self.machine_st.heap.push(heap_loc_as_cell!(i)); push_cell!(self.machine_st, heap_loc_as_cell!(i));
} }
self.machine_st.p += 1; self.machine_st.p += 1;
@@ -3363,11 +3417,11 @@ impl Machine {
} }
&Instruction::CallCopyToLiftedHeap => { &Instruction::CallCopyToLiftedHeap => {
self.copy_to_lifted_heap(); self.copy_to_lifted_heap();
self.machine_st.p += 1; step_or_fail!(self, self.machine_st.p += 1);
} }
&Instruction::ExecuteCopyToLiftedHeap => { &Instruction::ExecuteCopyToLiftedHeap => {
self.copy_to_lifted_heap(); self.copy_to_lifted_heap();
self.machine_st.p = self.machine_st.cp; step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
} }
&Instruction::CallCreatePartialString => { &Instruction::CallCreatePartialString => {
self.create_partial_string(); self.create_partial_string();
@@ -3519,15 +3573,6 @@ impl Machine {
self.dynamic_module_resolution(arity - 2) self.dynamic_module_resolution(arity - 2)
); );
/*
println!(
"(slow) calling {}:{}/{}",
module_name.as_str(),
key.0.as_str(),
key.1,
);
*/
try_or_throw!(self.machine_st, self.call_clause(module_name, key)); try_or_throw!(self.machine_st, self.call_clause(module_name, key));
if self.machine_st.fail { if self.machine_st.fail {
@@ -3540,15 +3585,6 @@ impl Machine {
self.dynamic_module_resolution(arity - 2) self.dynamic_module_resolution(arity - 2)
); );
/*
println!(
"(slow) executing {}:{}/{}",
module_name.as_str(),
key.0.as_str(),
key.1,
);
*/
try_or_throw!(self.machine_st, self.execute_clause(module_name, key)); try_or_throw!(self.machine_st, self.execute_clause(module_name, key));
if self.machine_st.fail { if self.machine_st.fail {
@@ -4291,11 +4327,11 @@ impl Machine {
} }
&Instruction::CallSetBall => { &Instruction::CallSetBall => {
self.set_ball(); self.set_ball();
self.machine_st.p += 1; step_or_fail!(self, self.machine_st.p += 1);
} }
&Instruction::ExecuteSetBall => { &Instruction::ExecuteSetBall => {
self.set_ball(); self.set_ball();
self.machine_st.p = self.machine_st.cp; step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
} }
&Instruction::CallPushBallStack => { &Instruction::CallPushBallStack => {
self.push_ball_stack(); self.push_ball_stack();
@@ -4630,19 +4666,19 @@ impl Machine {
step_or_fail!(self, self.machine_st.p = self.machine_st.cp); step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
} }
&Instruction::CallLoadHTML => { &Instruction::CallLoadHTML => {
self.load_html(); backtrack_on_resource_error!(self.machine_st, self.load_html());
step_or_fail!(self, self.machine_st.p += 1); step_or_fail!(self, self.machine_st.p += 1);
} }
&Instruction::ExecuteLoadHTML => { &Instruction::ExecuteLoadHTML => {
self.load_html(); backtrack_on_resource_error!(self.machine_st, self.load_html());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp); step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
} }
&Instruction::CallLoadXML => { &Instruction::CallLoadXML => {
self.load_xml(); backtrack_on_resource_error!(self.machine_st, self.load_xml());
step_or_fail!(self, self.machine_st.p += 1); step_or_fail!(self, self.machine_st.p += 1);
} }
&Instruction::ExecuteLoadXML => { &Instruction::ExecuteLoadXML => {
self.load_xml(); backtrack_on_resource_error!(self.machine_st, self.load_xml());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp); step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
} }
&Instruction::CallGetEnv => { &Instruction::CallGetEnv => {
@@ -5119,13 +5155,18 @@ impl Machine {
let r = self.machine_st.registers[2]; let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r)); let r = self.machine_st.store(self.machine_st.deref(r));
let h = self.machine_st.heap.len(); let mut writer = Heap::functor_writer(
self.machine_st functor!(atom!("-"), [fixnum(n), fixnum(p)]),
.heap );
.extend(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
let str_cell = backtrack_on_resource_error!(
&mut self.machine_st,
writer(&mut self.machine_st.heap)
);
let r = r.as_var().unwrap(); let r = r.as_var().unwrap();
self.machine_st.bind(r, str_loc_as_cell!(h));
self.machine_st.bind(r, str_cell);
step_or_fail!(self, self.machine_st.p += 1); step_or_fail!(self, self.machine_st.p += 1);
} }
@@ -5137,13 +5178,18 @@ impl Machine {
let r = self.machine_st.registers[2]; let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r)); let r = self.machine_st.store(self.machine_st.deref(r));
let h = self.machine_st.heap.len(); let mut writer = Heap::functor_writer(
self.machine_st functor!(atom!("-"), [fixnum(n), fixnum(p)]),
.heap );
.extend(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
let str_cell = backtrack_on_resource_error!(
&mut self.machine_st,
writer(&mut self.machine_st.heap)
);
let r = r.as_var().unwrap(); let r = r.as_var().unwrap();
self.machine_st.bind(r, str_loc_as_cell!(h));
self.machine_st.bind(r, str_cell);
step_or_fail!(self, self.machine_st.p = self.machine_st.cp); step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,15 +3,14 @@ use std::collections::BTreeMap;
use crate::atom_table; use crate::atom_table;
use crate::heap_iter::{stackful_post_order_iter, NonListElider}; use crate::heap_iter::{stackful_post_order_iter, NonListElider};
use crate::machine::machine_indices::VarKey;
use crate::machine::mock_wam::CompositeOpDir; use crate::machine::mock_wam::CompositeOpDir;
use crate::machine::{ use crate::machine::{
ArenaHeaderTag, F64Offset, F64Ptr, Fixnum, Number, BREAK_FROM_DISPATCH_LOOP_LOC, ArenaHeaderTag, F64Offset, F64Ptr, Fixnum, Number, BREAK_FROM_DISPATCH_LOOP_LOC,
LIB_QUERY_SUCCESS, LIB_QUERY_SUCCESS,
}; };
use crate::parser::ast::{Var, VarPtr}; use crate::parser::ast::{TermWriteResult, Var};
use crate::parser::parser::{Parser, Tokens}; use crate::parser::lexer::LexerParser;
use crate::read::{write_term_to_heap, TermWriteResult}; use crate::parser::parser::Tokens;
use crate::types::UntypedArenaPtr; use crate::types::UntypedArenaPtr;
use dashu::{Integer, Rational}; use dashu::{Integer, Rational};
@@ -171,29 +170,22 @@ impl Term {
pub(crate) fn from_heapcell( pub(crate) fn from_heapcell(
machine: &mut Machine, machine: &mut Machine,
heap_cell: HeapCellValue, heap_cell: HeapCellValue,
var_names: &mut IndexMap<HeapCellValue, VarPtr>, var_names: &mut IndexMap<HeapCellValue, Var>,
) -> Self { ) -> Self {
// Adapted from MachineState::read_term_from_heap // Adapted from MachineState::read_term_from_heap
let mut term_stack = vec![]; let mut term_stack = vec![];
let iter = stackful_post_order_iter::<NonListElider>(
machine.machine_st.heap[0] = heap_cell;
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut machine.machine_st.heap, &mut machine.machine_st.heap,
&mut machine.machine_st.stack, &mut machine.machine_st.stack,
heap_cell, 0,
); );
let mut anon_count: usize = 0; let mut anon_count: usize = 0;
let var_ptr_cmp = |a, b| match a {
Var::Named(name_a) => match b {
Var::Named(name_b) => name_a.cmp(&name_b),
_ => Ordering::Less,
},
_ => match b {
Var::Named(_) => Ordering::Greater,
_ => Ordering::Equal,
},
};
for addr in iter { while let Some(addr) = iter.next() {
let addr = unmark_cell_bits!(addr); let addr = unmark_cell_bits!(addr);
read_heap_cell!(addr, read_heap_cell!(addr,
@@ -242,29 +234,28 @@ impl Term {
term_stack.push(list); term_stack.push(list);
} }
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let var = var_names.get(&addr).map(|x| x.borrow().clone()); let var = var_names.get(&addr).cloned();
match var { match var {
Some(Var::Named(name)) => term_stack.push(Term::Var(name)), Some(name) => term_stack.push(Term::Var(name.to_string())),
_ => { _ => {
let anon_name = loop { let anon_name = loop {
// Generate a name for the anonymous variable // Generate a name for the anonymous variable
let anon_name = count_to_letter_code(anon_count); let anon_name = count_to_letter_code(anon_count);
// Find if this name is already being used // Find if this name is already being used
var_names.sort_by(|_, a, _, b| { var_names.sort_by(|_, a, _, b| a.cmp(b));
var_ptr_cmp(a.borrow().clone(), b.borrow().clone())
});
let binary_result = var_names.binary_search_by(|_,a| { let binary_result = var_names.binary_search_by(|_,a| {
let var_ptr = Var::Named(anon_name.clone()); let a: &String = a.as_ref();
var_ptr_cmp(a.borrow().clone(), var_ptr.clone()) a.cmp(&anon_name)
}); });
match binary_result { match binary_result {
Ok(_) => anon_count += 1, // Name already used Ok(_) => anon_count += 1, // Name already used
Err(_) => { Err(_) => {
// Name not used, assign it to this variable // Name not used, assign it to this variable
let var_ptr = VarPtr::from(Var::Named(anon_name.clone())); let var = anon_name.clone();
var_names.insert(addr, var_ptr); var_names.insert(addr, Var::from(var));
break anon_name; break anon_name;
}, },
} }
@@ -276,9 +267,6 @@ impl Term {
(HeapCellValueTag::F64, f) => { (HeapCellValueTag::F64, f) => {
term_stack.push(Term::Float((*f).into())); term_stack.push(Term::Float((*f).into()));
} }
(HeapCellValueTag::Char, c) => {
term_stack.push(Term::Atom(c.into()));
}
(HeapCellValueTag::Fixnum, n) => { (HeapCellValueTag::Fixnum, n) => {
term_stack.push(Term::Integer(n.into())); term_stack.push(Term::Integer(n.into()));
} }
@@ -310,9 +298,6 @@ impl Term {
); );
} }
} }
(HeapCellValueTag::CStr, s) => {
term_stack.push(Term::String(s.as_str().to_string()));
}
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
//let h = iter.focus().value() as usize; //let h = iter.focus().value() as usize;
//let mut arity = arity; //let mut arity = arity;
@@ -354,8 +339,9 @@ impl Term {
term_stack.push(Term::Compound(name.as_str().to_string(), subterms)); term_stack.push(Term::Compound(name.as_str().to_string(), subterms));
} }
} }
(HeapCellValueTag::PStr, atom) => { (HeapCellValueTag::PStrLoc, pstr_loc) => {
let tail = term_stack.pop().unwrap(); let tail = term_stack.pop().unwrap();
let char_iter = iter.base_iter.heap.char_iter(pstr_loc);
match tail { match tail {
Term::Atom(atom) => { Term::Atom(atom) => {
@@ -363,21 +349,18 @@ impl Term {
term_stack.push(Term::String(atom.as_str().to_string())); term_stack.push(Term::String(atom.as_str().to_string()));
} }
}, },
Term::List(l) if l.is_empty() => {
term_stack.push(Term::String(char_iter.collect()));
}
Term::List(l) => { Term::List(l) => {
let mut list: Vec<Term> = atom let mut list: Vec<Term> = char_iter
.as_str()
.to_string()
.chars()
.map(|x| Term::Atom(x.to_string())) .map(|x| Term::Atom(x.to_string()))
.collect(); .collect();
list.extend(l.into_iter()); list.extend(l.into_iter());
term_stack.push(Term::List(list)); term_stack.push(Term::List(list));
}, },
_ => { _ => {
let mut list: Vec<Term> = atom let mut list: Vec<Term> = char_iter
.as_str()
.to_string()
.chars()
.map(|x| Term::Atom(x.to_string())) .map(|x| Term::Atom(x.to_string()))
.collect(); .collect();
@@ -403,19 +386,6 @@ impl Term {
} }
} }
} }
// I dont know if this is needed here.
/*
(HeapCellValueTag::PStrLoc, h) => {
let atom = cell_as_atom_cell!(iter.heap[h]).get_name();
let tail = term_stack.pop().unwrap();
term_stack.push(Term::PartialString(
Cell::default(),
atom.as_str().to_owned(),
Box::new(tail),
));
}
*/
_ => { _ => {
unreachable!(); unreachable!();
} }
@@ -432,7 +402,7 @@ pub struct QueryState<'a> {
machine: &'a mut Machine, machine: &'a mut Machine,
term: TermWriteResult, term: TermWriteResult,
stub_b: usize, stub_b: usize,
var_names: IndexMap<HeapCellValue, VarPtr>, var_names: IndexMap<HeapCellValue, Var>,
called: bool, called: bool,
} }
@@ -472,7 +442,7 @@ impl Iterator for QueryState<'_> {
if let Err(resource_err_loc) = machine if let Err(resource_err_loc) = machine
.machine_st .machine_st
.heap .heap
.append(&machine.machine_st.ball.stub) .append(machine.machine_st.ball.stub.splice(..))
{ {
return Some(Err(Term::from_heapcell( return Some(Err(Term::from_heapcell(
machine, machine,
@@ -589,13 +559,13 @@ impl Machine {
or_frame.prelude.attr_var_queue_len = 0; or_frame.prelude.attr_var_queue_len = 0;
self.machine_st.b = stub_b; self.machine_st.b = stub_b;
self.machine_st.hb = self.machine_st.heap.len(); self.machine_st.hb = self.machine_st.heap.cell_len();
self.machine_st.block = stub_b; self.machine_st.block = stub_b;
} }
/// Runs a query. /// Runs a query.
pub fn run_query(&mut self, query: impl Into<String>) -> QueryState { pub fn run_query(&mut self, query: impl Into<String>) -> QueryState {
let mut parser = Parser::new( let mut parser = LexerParser::new(
Stream::from_owned_string(query.into(), &mut self.machine_st.arena), Stream::from_owned_string(query.into(), &mut self.machine_st.arena),
&mut self.machine_st, &mut self.machine_st,
); );

View File

@@ -2,7 +2,6 @@ use crate::forms::*;
use crate::machine::loader::*; use crate::machine::loader::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::preprocessor::*;
use crate::machine::term_stream::*; use crate::machine::term_stream::*;
use crate::machine::*; use crate::machine::*;
use crate::parser::ast::*; use crate::parser::ast::*;
@@ -434,19 +433,6 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
self.retract_local_clauses_impl(clause_clause_compilation_target, key, clause_locs); self.retract_local_clauses_impl(clause_clause_compilation_target, key, clause_locs);
} }
pub(super) fn try_term_to_tl(
&mut self,
term: FocusedHeap,
preprocessor: &mut Preprocessor,
) -> Result<PredicateClause, SessionError> {
let tl = preprocessor.try_term_to_tl(self, term)?;
Ok(match tl {
TopLevel::Fact(fact, var_data) => PredicateClause::Fact(fact, var_data),
TopLevel::Rule(rule, var_data) => PredicateClause::Rule(rule, var_data),
})
}
#[inline] #[inline]
pub(super) fn remove_module_op_exports(&mut self) { pub(super) fn remove_module_op_exports(&mut self) {
for (mut op_decl, record) in self.payload.module_op_exports.drain(0..) { for (mut op_decl, record) in self.payload.module_op_exports.drain(0..) {

View File

@@ -20,6 +20,25 @@ use std::convert::TryFrom;
use std::fmt; use std::fmt;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
impl TermWriteResult {
pub(super) fn from(heap: &mut Heap, value: HeapCellValue) -> Result<Self, usize> {
let focus = heap.index_of(value)?;
let mut stack = Stack::uninitialized();
heap[0] = value;
let inverse_var_locs = inverse_var_locs_from_iter(
stackful_preorder_iter::<NonListElider>(
heap,
&mut stack,
0,
),
);
Ok(Self { focus, inverse_var_locs })
}
}
/* /*
* The loader compiles Prolog terms read from a TermStream instance, * The loader compiles Prolog terms read from a TermStream instance,
* which may be incremental or monolithic. The monolithic term stream * which may be incremental or monolithic. The monolithic term stream
@@ -176,18 +195,18 @@ impl CompilationTarget {
} }
pub struct PredicateQueue { pub struct PredicateQueue {
pub(super) predicates: Vec<FocusedHeap>, pub predicates: Vec<TermWriteResult>,
pub(super) compilation_target: CompilationTarget, pub compilation_target: CompilationTarget,
} }
impl PredicateQueue { impl PredicateQueue {
#[inline] #[inline]
pub(super) fn push(&mut self, clause: FocusedHeap) { pub(super) fn push(&mut self, term_write_result: TermWriteResult) {
self.predicates.push(clause); self.predicates.push(term_write_result);
} }
#[inline] #[inline]
pub(crate) fn first(&self) -> Option<&FocusedHeap> { pub(crate) fn first(&self) -> Option<&TermWriteResult> {
self.predicates.first() self.predicates.first()
} }
@@ -381,7 +400,6 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
let repo_len = loader.wam_prelude.code.len(); let repo_len = loader.wam_prelude.code.len();
loader.payload.retraction_info.reset(repo_len); loader.payload.retraction_info.reset(repo_len);
loader.remove_module_op_exports(); loader.remove_module_op_exports();
Ok(loader.payload.compilation_target) Ok(loader.payload.compilation_target)
@@ -399,7 +417,7 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
#[inline(always)] #[inline(always)]
fn machine_st(loader: &mut Self::LoaderFieldType) -> &mut MachineState { fn machine_st(loader: &mut Self::LoaderFieldType) -> &mut MachineState {
loader.term_stream.parser.lexer.machine_st loader.term_stream.lexer_parser.machine_st
} }
#[inline(always)] #[inline(always)]
@@ -491,23 +509,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
} }
pub(crate) fn copy_term_from_heap(&mut self, cell: HeapCellValue) -> FocusedHeap { #[inline]
use crate::iterators::fact_iterator; pub(super) fn machine_heap(&mut self) -> &mut Heap {
&mut LS::machine_st(&mut self.payload).heap
let mut term = FocusedHeap::empty();
let mut stack = Stack::uninitialized();
let machine_st = LS::machine_st(&mut self.payload);
term.copy_term_from_machine_heap(machine_st, cell);
term.inverse_var_locs = inverse_var_locs_from_iter(
fact_iterator::<false>(
&mut term.heap,
&mut stack,
0,
),
);
term
} }
pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> { pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> {
@@ -525,14 +529,26 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target); let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target);
let mut term = load_state.term_stream.next(&composite_op_dir)?; let mut term = load_state.term_stream.next(&composite_op_dir)?;
let predicate_focus_opt = load_state.predicates.first().map(|term_write_result| {
term_write_result.focus
});
if !term.is_consistent(&load_state.predicates) { let machine_st = LS::machine_st(&mut self.payload);
self.compile_and_submit()?; let term_key_opt = clause_predicate_key(&machine_st.heap, term.focus);
if let Some(predicate_focus) = predicate_focus_opt {
let predicate_key_opt = clause_predicate_key(&machine_st.heap, predicate_focus);
debug_assert!(predicate_key_opt.is_some());
if term_key_opt != predicate_key_opt {
self.compile_and_submit()?;
}
} }
if Some(atom!(":-")) == term.name(term.focus) && term.arity(term.focus) == 1 { if Some((atom!(":-"), 1)) == term_key_opt {
let new_focus = term.nth_arg(term.focus, 1).unwrap(); let machine_st = LS::machine_st(&mut self.payload);
let term = term.as_ref_mut(new_focus); term.focus = term_nth_arg(&machine_st.heap, term.focus, 1).unwrap();
return Ok(Some(setup_declaration(self, term)?)); return Ok(Some(setup_declaration(self, term)?));
} }
@@ -1055,48 +1071,55 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
let machine_st = LS::machine_st(&mut self.payload); let machine_st = LS::machine_st(&mut self.payload);
let cell = machine_st[r]; let cell = machine_st[r];
let export_list = FocusedHeapRefMut::from_cell(&mut machine_st.heap, cell); let focus = machine_st.heap.cell_len();
machine_st.heap.push_cell(cell)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
let export_list = FocusedHeapRefMut { heap: &mut machine_st.heap, focus };
let export_list = setup_module_export_list(export_list)?; let export_list = setup_module_export_list(export_list)?;
Ok(export_list.into_iter().collect()) Ok(export_list.into_iter().collect())
} }
fn clause_clause(&mut self, cell: HeapCellValue) -> Result<FocusedHeap, CompilationError> { fn clause_clause(&mut self, cell: HeapCellValue) -> Result<TermWriteResult, CompilationError> {
let machine_st = LS::machine_st(&mut self.payload); let machine_st = LS::machine_st(&mut self.payload);
let mut term = FocusedHeap::empty(); let focus = machine_st.heap.cell_len();
read_heap_cell!(cell, read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(machine_st.heap[s]) let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
.get_name_and_arity(); .get_name_and_arity();
term.copy_term_from_machine_heap(machine_st, cell); let mut writer = machine_st.heap.reserve(4)
let focus = term.heap.len(); .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
term.heap.push(str_loc_as_cell!(focus+1)); writer.write_with(|section| {
term.heap.push(atom_as_cell!(atom!("clause"), 2)); section.push_cell(str_loc_as_cell!(focus+1));
section.push_cell(atom_as_cell!(atom!("clause"), 2));
match (name, arity) { match (name, arity) {
(atom!(":-"), 2) => { (atom!(":-"), 2) => {
term.heap.push(heap_loc_as_cell!(2)); section.push_cell(heap_loc_as_cell!(s+1));
term.heap.push(heap_loc_as_cell!(3)); section.push_cell(heap_loc_as_cell!(s+2));
}
_ => {
section.push_cell(str_loc_as_cell!(s));
section.push_cell(atom_as_cell!(atom!("true")));
}
} }
_ => { });
term.heap.push(heap_loc_as_cell!(0));
term.heap.push(atom_as_cell!(atom!("true")));
}
}
term.focus = focus;
} }
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 { if arity == 0 {
term.heap.push(str_loc_as_cell!(1)); let mut writer = machine_st.heap.reserve(4)
term.heap.push(atom_as_cell!(atom!("clause"), 2)); .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
term.heap.push(atom_as_cell!(name));
term.heap.push(atom_as_cell!(atom!("true")));
term.focus = 0; writer.write_with(|section| {
section.push_cell(str_loc_as_cell!(focus+1));
section.push_cell(atom_as_cell!(atom!("clause"), 2));
section.push_cell(atom_as_cell!(name));
section.push_cell(atom_as_cell!(atom!("true")));
});
} else { } else {
return Err(CompilationError::InadmissibleFact); return Err(CompilationError::InadmissibleFact);
} }
@@ -1106,11 +1129,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
} }
); );
let value = term.heap[term.focus]; Ok(TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
term.inverse_var_locs = inverse_var_locs_from_iter( .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?)
eager_stackful_preorder_iter(&mut term.heap, value),
);
Ok(term)
} }
fn add_extensible_predicate_declaration( fn add_extensible_predicate_declaration(
@@ -1330,18 +1350,18 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
fn add_clause_clause_if_dynamic(&mut self, value: HeapCellValue) -> Result<(), SessionError> { fn add_clause_clause_if_dynamic(&mut self, value: HeapCellValue) -> Result<(), SessionError> {
let machine_st = LS::machine_st(&mut self.payload); let machine_st = LS::machine_st(&mut self.payload);
let term = FocusedHeapRefMut::from_cell(&mut machine_st.heap, value); let key_opt = clause_predicate_key_from_heap(&machine_st.heap, value);
let name_opt = ClauseInfo::name(&term); if let Some((predicate_name, predicate_arity)) = key_opt {
if let Some(predicate_name) = name_opt {
let arity = ClauseInfo::arity(&term);
let predicates_compilation_target = self.payload.predicates.compilation_target; let predicates_compilation_target = self.payload.predicates.compilation_target;
let is_dynamic = self let is_dynamic = self
.wam_prelude .wam_prelude
.indices .indices
.get_predicate_skeleton(&predicates_compilation_target, &(predicate_name, arity)) .get_predicate_skeleton(
&predicates_compilation_target,
&(predicate_name, predicate_arity),
)
.map(|skeleton| skeleton.core.is_dynamic) .map(|skeleton| skeleton.core.is_dynamic)
.unwrap_or(false); .unwrap_or(false);
@@ -1574,11 +1594,14 @@ impl Machine {
pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult { pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult {
let value = self.machine_st.registers[1]; let value = self.machine_st.registers[1];
let term = resource_error_call_result!(
self.machine_st,
TermWriteResult::from(&mut self.machine_st.heap, value)
);
let mut loader = self.loader_from_heap_evacuable(temp_v!(2)); let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
let add_clause = || { let add_clause = || {
let term = loader.copy_term_from_heap(value);
loader.incremental_compile_clause( loader.incremental_compile_clause(
(atom!("term_expansion"), 2), (atom!("term_expansion"), 2),
term, term,
@@ -1599,31 +1622,40 @@ impl Machine {
.machine_st .machine_st
.store(self.machine_st.deref(self.machine_st.registers[1]))); .store(self.machine_st.deref(self.machine_st.registers[1])));
let value = self.machine_st.registers[2];
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
let compilation_target = match target_module_name { let compilation_target = match target_module_name {
atom!("user") => CompilationTarget::User, atom!("user") => CompilationTarget::User,
_ => CompilationTarget::Module(target_module_name), _ => CompilationTarget::Module(target_module_name),
}; };
let add_clause = || { let value = self.machine_st.registers[2];
let term = loader.copy_term_from_heap(value); let term = resource_error_call_result!(
self.machine_st,
TermWriteResult::from(&mut self.machine_st.heap, value)
);
let indexing_arg = match term.name(term.focus) { let add_clause = || {
Some(atom!(":-")) => term.nth_arg(term.focus, 1).and_then(|h| term.nth_arg(h, 1)), let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) {
Some(_) => term.nth_arg(term.focus, 1), Some((atom!(":-"), _)) => {
term_nth_arg(&self.machine_st.heap, term.focus, 1).and_then(|h| {
term_nth_arg(&self.machine_st.heap, h, 1)
})
}
Some(_) => term_nth_arg(&self.machine_st.heap, term.focus, 1),
None => None, None => None,
}; };
if let Some(indexing_term_loc) = indexing_arg { let key_opt = indexing_arg_opt.and_then(|indexing_term_loc| {
if let Some(indexing_name) = term.name(indexing_term_loc) { term_predicate_key(&self.machine_st.heap, indexing_term_loc)
loader });
.wam_prelude
.indices let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
.goal_expansion_indices
.insert((indexing_name, term.arity(indexing_term_loc))); if let Some((name, arity)) = key_opt {
} loader
.wam_prelude
.indices
.goal_expansion_indices
.insert((name, arity));
} }
loader.incremental_compile_clause( loader.incremental_compile_clause(
@@ -1929,19 +1961,16 @@ impl Machine {
let stub_gen = || functor_stub(key.0, key.1); let stub_gen = || functor_stub(key.0, key.1);
let assert_clause = self.machine_st.registers[2]; let assert_clause = self.machine_st.registers[2];
let (name, arity) = { let key_opt = clause_predicate_key_from_heap(&self.machine_st.heap, assert_clause);
let term = FocusedHeapRefMut::from_cell(&mut self.machine_st.heap, assert_clause);
(ClauseInfo::name(&term), ClauseInfo::arity(&term))
};
let mut compile_assert = |assert_clause, name, arity| { let mut compile_assert = |assert_clause, key_opt| {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> = let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
Loader::new(self, LiveTermStream::new(ListingSource::User)); Loader::new(self, LiveTermStream::new(ListingSource::User));
loader.payload.compilation_target = compilation_target; loader.payload.compilation_target = compilation_target;
let name = if let Some(name) = name { let (name, arity) = if let Some(key) = key_opt {
name key
} else { } else {
return Err(SessionError::from(CompilationError::InvalidRuleHead)); return Err(SessionError::from(CompilationError::InvalidRuleHead));
}; };
@@ -1979,11 +2008,16 @@ impl Machine {
// if a new predicate was just created, make it dynamic. // if a new predicate was just created, make it dynamic.
loader.add_dynamic_predicate(compilation_target, name, arity)?; loader.add_dynamic_predicate(compilation_target, name, arity)?;
let asserted_clause = loader.copy_term_from_heap(assert_clause);
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
// let asserted_clause = loader.copy_term_from_heap(assert_clause);
let term = TermWriteResult::from(&mut machine_st.heap, assert_clause)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
loader.incremental_compile_clause( loader.incremental_compile_clause(
(name, arity), (name, arity),
asserted_clause, term,
compilation_target, compilation_target,
false, false,
append_or_prepend, append_or_prepend,
@@ -2004,7 +2038,7 @@ impl Machine {
LiveLoadAndMachineState::evacuate(loader) LiveLoadAndMachineState::evacuate(loader)
}; };
match compile_assert(assert_clause, name, arity) { match compile_assert(assert_clause, key_opt) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(SessionError::CompilationError( Err(SessionError::CompilationError(
CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact, CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact,
@@ -2206,11 +2240,21 @@ impl Machine {
}; };
let mut loader = self.loader_from_heap_evacuable(temp_v!(4)); let mut loader = self.loader_from_heap_evacuable(temp_v!(4));
let predicate_focus_opt = loader.payload.predicates.first().map(|term_write_result| {
term_write_result.focus
});
let is_consistent = if let Some(predicate_focus) = predicate_focus_opt {
let machine_st = LiveLoadAndMachineState::machine_st(&mut loader.payload);
clause_predicate_key(&machine_st.heap, predicate_focus) == Some(key)
} else {
true
};
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail = LiveLoadAndMachineState::machine_st(&mut loader.payload).fail =
(!loader.payload.predicates.is_empty() (!loader.payload.predicates.is_empty()
&& loader.payload.predicates.compilation_target != compilation_target) && loader.payload.predicates.compilation_target != compilation_target)
|| !key.is_consistent(&loader.payload.predicates); || !is_consistent;
let result = LiveLoadAndMachineState::evacuate(loader); let result = LiveLoadAndMachineState::evacuate(loader);
self.restore_load_state_payload(result) self.restore_load_state_payload(result)
@@ -2278,29 +2322,36 @@ impl Machine {
.get_meta_predicate_spec(predicate_name, arity, &compilation_target) .get_meta_predicate_spec(predicate_name, arity, &compilation_target)
{ {
Some(meta_specs) => { Some(meta_specs) => {
let term_loc = self.machine_st.heap.len(); let term_loc = self.machine_st.heap.cell_len();
self.machine_st let mut writer = match self.machine_st.heap.reserve(3 + meta_specs.len()) {
.heap Ok(writer) => writer,
.push(atom_as_cell!(predicate_name, arity)); Err(err_loc) => {
self.machine_st self.machine_st.throw_resource_error(err_loc);
.heap return;
.extend(meta_specs.iter().map(|meta_spec| match meta_spec { }
MetaSpec::Minus => atom_as_cell!(atom!("+")), };
MetaSpec::Plus => atom_as_cell!(atom!("-")),
MetaSpec::Either => atom_as_cell!(atom!("?")),
MetaSpec::Colon => atom_as_cell!(atom!(":")),
MetaSpec::RequiresExpansionWithArgument(ref arg_num) => {
fixnum_as_cell!(Fixnum::build_with(*arg_num as i64))
}
}));
let heap_loc = self.machine_st.heap.len(); writer.write_with(|section| {
section.push_cell(atom_as_cell!(predicate_name, arity));
self.machine_st for meta_spec in meta_specs.iter() {
.heap section.push_cell(match meta_spec {
.push(atom_as_cell!(atom!("meta_predicate"), 1)); MetaSpec::Minus => atom_as_cell!(atom!("+")),
self.machine_st.heap.push(str_loc_as_cell!(term_loc)); MetaSpec::Plus => atom_as_cell!(atom!("-")),
MetaSpec::Either => atom_as_cell!(atom!("?")),
MetaSpec::Colon => atom_as_cell!(atom!(":")),
MetaSpec::RequiresExpansionWithArgument(ref arg_num) => {
fixnum_as_cell!(Fixnum::build_with(*arg_num as i64))
}
});
}
section.push_cell(atom_as_cell!(atom!("meta_predicate"), 1));
section.push_cell(str_loc_as_cell!(term_loc));
});
let heap_loc = self.machine_st.heap.cell_len() - 2;
unify!( unify!(
self.machine_st, self.machine_st,
@@ -2411,13 +2462,16 @@ impl<'a> Loader<'a, LiveLoadAndMachineState<'a>> {
} }
let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload); let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
let value = machine_st[term_reg]; let value = machine_st.store(MachineState::deref(&machine_st, machine_st[term_reg]));
self.add_clause_clause_if_dynamic(value)?; self.add_clause_clause_if_dynamic(value)?;
let term = self.copy_term_from_heap(value); let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
self.payload.term_stream.term_queue.push_back(term);
let term = TermWriteResult::from(&mut machine_st.heap, value)
.map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
self.payload.term_stream.term_queue.push_back(term);
self.load() self.load()
} }
} }

View File

@@ -5,6 +5,7 @@ use crate::parser::ast::*;
#[cfg(feature = "ffi")] #[cfg(feature = "ffi")]
use crate::ffi::FFIError; use crate::ffi::FFIError;
use crate::forms::*; use crate::forms::*;
use crate::functor_macro::*;
use crate::machine::heap::*; use crate::machine::heap::*;
use crate::machine::loader::CompilationTarget; use crate::machine::loader::CompilationTarget;
use crate::machine::machine_state::*; use crate::machine::machine_state::*;
@@ -12,20 +13,13 @@ use crate::machine::streams::*;
use crate::machine::system_calls::BrentAlgState; use crate::machine::system_calls::BrentAlgState;
use crate::types::*; use crate::types::*;
pub type MachineStub = Vec<HeapCellValue>; pub type MachineStub = Vec<FunctorElement>;
pub type MachineStubGen = Box<dyn Fn(&mut MachineState) -> MachineStub>; pub type MachineStubGen = Box<dyn Fn(&mut MachineState) -> MachineStub>;
#[derive(Debug, Clone, Copy)]
enum ErrorProvenance {
Constructed, // if constructed, offset the addresses.
Received, // otherwise, preserve the addresses.
}
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct MachineError { pub(crate) struct MachineError {
stub: MachineStub, stub: MachineStub,
location: Option<ParserErrorSrc>, location: Option<ParserErrorSrc>,
from: ErrorProvenance,
} }
// from 7.12.2 b) of 13211-1:1995 // from 7.12.2 b) of 13211-1:1995
@@ -91,45 +85,26 @@ impl TypeError for HeapCellValue {
fn type_error(self, _machine_st: &mut MachineState, valid_type: ValidType) -> MachineError { fn type_error(self, _machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
let stub = functor!( let stub = functor!(
atom!("type_error"), atom!("type_error"),
[atom(valid_type.as_atom()), cell(self)] [atom_as_cell((valid_type.as_atom())), cell(self)]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
} }
impl TypeError for MachineStub { impl TypeError for MachineStub {
fn type_error(self, machine_st: &mut MachineState, valid_type: ValidType) -> MachineError { fn type_error(self, _machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
let stub = functor!( let stub = functor!(
atom!("type_error"), atom!("type_error"),
[atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)], [atom_as_cell((valid_type.as_atom())), functor(self)]
[self]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Constructed,
}
}
}
impl TypeError for FunctorStub {
fn type_error(self, machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
let stub = functor!(
atom!("type_error"),
[atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)],
[self]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
} }
} }
} }
@@ -139,15 +114,14 @@ impl TypeError for Number {
let stub = functor!( let stub = functor!(
atom!("type_error"), atom!("type_error"),
[ [
atom(valid_type.as_atom()), atom_as_cell((valid_type.as_atom())),
number(&mut machine_st.arena, self) number(self, (&mut machine_st.arena))
] ]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
} }
@@ -171,16 +145,15 @@ impl PermissionError for Atom {
let stub = functor!( let stub = functor!(
atom!("permission_error"), atom!("permission_error"),
[ [
atom(perm.as_atom()), atom_as_cell((perm.as_atom())),
atom(index_atom), atom_as_cell(index_atom),
cell(atom_as_cell!(self)) atom_as_cell(self)
] ]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
} }
@@ -214,13 +187,12 @@ impl PermissionError for HeapCellValue {
let stub = functor!( let stub = functor!(
atom!("permission_error"), atom!("permission_error"),
[atom(perm.as_atom()), atom(index_atom), cell(cell)] [atom_as_cell((perm.as_atom())), atom_as_cell(index_atom), cell(cell)]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
} }
@@ -228,24 +200,22 @@ impl PermissionError for HeapCellValue {
impl PermissionError for MachineStub { impl PermissionError for MachineStub {
fn permission_error( fn permission_error(
self, self,
machine_st: &mut MachineState, _machine_st: &mut MachineState,
index_atom: Atom, index_atom: Atom,
perm: Permission, perm: Permission,
) -> MachineError { ) -> MachineError {
let stub = functor!( let stub = functor!(
atom!("permission_error"), atom!("permission_error"),
[ [
atom(perm.as_atom()), atom_as_cell((perm.as_atom())),
atom(index_atom), atom_as_cell(index_atom),
str(machine_st.heap.len(), 0) functor(self)
], ]
[self]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Constructed,
} }
} }
} }
@@ -256,32 +226,11 @@ pub(super) trait DomainError {
impl DomainError for HeapCellValue { impl DomainError for HeapCellValue {
fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError { fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(atom!("domain_error"), [atom(error.as_atom()), cell(self)]); let stub = functor!(atom!("domain_error"), [atom_as_cell((error.as_atom())), cell(self)]);
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
}
}
}
impl DomainError for FunctorStub {
fn domain_error(
self,
machine_st: &mut MachineState,
valid_type: DomainErrorType,
) -> MachineError {
let stub = functor!(
atom!("domain_error"),
[atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)],
[self]
);
MachineError {
stub,
location: None,
from: ErrorProvenance::Constructed,
} }
} }
} }
@@ -290,26 +239,33 @@ impl DomainError for Number {
fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError { fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!( let stub = functor!(
atom!("domain_error"), atom!("domain_error"),
[atom(error.as_atom()), number(&mut machine_st.arena, self)] [atom_as_cell((error.as_atom())), number(self, (&mut machine_st.arena))]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
} }
pub(super) type FunctorStub = [HeapCellValue; 3]; impl DomainError for MachineStub {
fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(
atom!("domain_error"),
[atom_as_cell((error.as_atom())), functor(self)]
);
MachineError {
stub,
location: None,
}
}
}
#[inline(always)] #[inline(always)]
pub(super) fn functor_stub(name: Atom, arity: usize) -> FunctorStub { pub(super) fn functor_stub(name: Atom, arity: usize) -> MachineStub {
[ functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)])
atom_as_cell!(atom!("/"), 2),
atom_as_cell!(name),
fixnum_as_cell!(Fixnum::build_with(arity as i64)),
]
} }
impl MachineState { impl MachineState {
@@ -320,17 +276,15 @@ impl MachineState {
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError { pub(super) fn evaluation_error(&mut self, eval_error: EvalError) -> MachineError {
let stub = functor!(atom!("evaluation_error"), [atom(eval_error.as_atom())]); let stub = functor!(atom!("evaluation_error"), [atom_as_cell((eval_error.as_atom()))]);
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
@@ -339,18 +293,17 @@ impl MachineState {
ResourceError::FiniteMemory(size_requested) => { ResourceError::FiniteMemory(size_requested) => {
functor!( functor!(
atom!("resource_error"), atom!("resource_error"),
[atom(atom!("finite_memory")), cell(size_requested)] [atom_as_cell((atom!("finite_memory"))), cell(size_requested)]
) )
} }
ResourceError::OutOfFiles => { ResourceError::OutOfFiles => {
functor!(atom!("resource_error"), [atom(atom!("file_descriptors"))]) functor!(atom!("resource_error"), [atom_as_cell((atom!("file_descriptors")))])
} }
}; };
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
@@ -367,13 +320,12 @@ impl MachineState {
ExistenceError::Module(name) => { ExistenceError::Module(name) => {
let stub = functor!( let stub = functor!(
atom!("existence_error"), atom!("existence_error"),
[atom(atom!("source_sink")), atom(name)] [atom_as_cell((atom!("source_sink"))), atom_as_cell(name)]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
ExistenceError::QualifiedProcedure { ExistenceError::QualifiedProcedure {
@@ -381,36 +333,30 @@ impl MachineState {
name, name,
arity, arity,
} => { } => {
let h = self.heap.len(); let ind_stub = functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]);
let res_stub = functor!(atom!(":"), [atom_as_cell(module_name), functor(ind_stub)]);
let ind_stub = functor!(atom!("/"), [atom(name), fixnum(arity)]);
let res_stub = functor!(atom!(":"), [atom(module_name), str(h + 3, 0)], [ind_stub]);
let stub = functor!( let stub = functor!(
atom!("existence_error"), atom!("existence_error"),
[atom(atom!("procedure")), str(h, 0)], [atom_as_cell((atom!("procedure"))), functor(res_stub)]
[res_stub]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Constructed,
} }
} }
ExistenceError::Procedure(name, arity) => { ExistenceError::Procedure(name, arity) => {
let culprit = functor!(atom!("/"), [atom(name), fixnum(arity)]); let culprit = functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]);
let stub = functor!( let stub = functor!(
atom!("existence_error"), atom!("existence_error"),
[atom(atom!("procedure")), str(self.heap.len(), 0)], [atom_as_cell((atom!("procedure"))), functor(culprit)]
[culprit]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Constructed,
} }
} }
ExistenceError::ModuleSource(source) => { ExistenceError::ModuleSource(source) => {
@@ -418,43 +364,75 @@ impl MachineState {
let stub = functor!( let stub = functor!(
atom!("existence_error"), atom!("existence_error"),
[atom(atom!("source_sink")), str(self.heap.len(), 0)], [atom_as_cell((atom!("source_sink"))), functor(source_stub)]
[source_stub]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Constructed,
} }
} }
ExistenceError::SourceSink(culprit) => { ExistenceError::SourceSink(culprit) => {
let stub = functor!( let stub = functor!(
atom!("existence_error"), atom!("existence_error"),
[atom(atom!("source_sink")), cell(culprit)] [atom_as_cell((atom!("source_sink"))), cell(culprit)]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
ExistenceError::Stream(culprit) => { ExistenceError::Stream(culprit) => {
let stub = functor!( let stub = functor!(
atom!("existence_error"), atom!("existence_error"),
[atom(atom!("stream")), cell(culprit)] [atom_as_cell((atom!("stream"))), cell(culprit)]
); );
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
} }
} }
pub(crate) fn directive_error(&mut self, err: DirectiveError) -> MachineError {
match err {
DirectiveError::ExpectedDirective(_term) => self.domain_error(
DomainErrorType::Directive,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidDirective(name, arity) => {
self.domain_error(DomainErrorType::Directive, functor_stub(name, arity))
}
DirectiveError::InvalidOpDeclNameType(_term) => self.type_error(
ValidType::List,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecDomain(_term) => self.domain_error(
DomainErrorType::OperatorSpecifier,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecValue(atom) => {
self.domain_error(DomainErrorType::OperatorSpecifier, atom_as_cell!(atom))
}
DirectiveError::InvalidOpDeclPrecType(_term) => self.type_error(
ValidType::Integer,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclPrecDomain(num) => {
self.domain_error(DomainErrorType::OperatorPriority, fixnum_as_cell!(num))
}
DirectiveError::ShallNotCreate(atom) => {
self.permission_error(Permission::Create, atom!("operator"), atom)
}
DirectiveError::ShallNotModify(atom) => {
self.permission_error(Permission::Modify, atom!("operator"), atom)
}
}
}
pub(super) fn permission_error<T: PermissionError>( pub(super) fn permission_error<T: PermissionError>(
&mut self, &mut self,
err: Permission, err: Permission,
@@ -471,7 +449,6 @@ impl MachineState {
fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError { fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError {
match err { match err {
ArithmeticError::UninstantiatedVar => self.instantiation_error(),
ArithmeticError::NonEvaluableFunctor(cell, arity) => { ArithmeticError::NonEvaluableFunctor(cell, arity) => {
let culprit = functor!(atom!("/"), [cell(cell), fixnum(arity)]); let culprit = functor!(atom!("/"), [cell(cell), fixnum(arity)]);
@@ -495,7 +472,6 @@ impl MachineState {
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
@@ -505,15 +481,11 @@ impl MachineState {
Permission::Modify, Permission::Modify,
atom!("static_procedure"), atom!("static_procedure"),
functor_stub(key.0, key.1) functor_stub(key.0, key.1)
.into_iter()
.collect::<MachineStub>(),
), ),
SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error( SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
Permission::Modify, Permission::Modify,
atom!("static_procedure"), atom!("static_procedure"),
functor_stub(key.0, key.1) functor_stub(key.0, key.1)
.into_iter()
.collect::<MachineStub>(),
), ),
SessionError::CannotOverwriteBuiltInModule(module) => { SessionError::CannotOverwriteBuiltInModule(module) => {
self.permission_error(Permission::Modify, atom!("static_module"), module) self.permission_error(Permission::Modify, atom!("static_module"), module)
@@ -524,8 +496,7 @@ impl MachineState {
let stub = functor!( let stub = functor!(
atom!("module_does_not_contain_claimed_export"), atom!("module_does_not_contain_claimed_export"),
[atom(module_name), str(self.heap.len() + 4, 0)], [atom_as_cell(module_name), functor(functor_stub)]
[functor_stub]
); );
self.permission_error(Permission::Access, atom!("private_procedure"), stub) self.permission_error(Permission::Access, atom!("private_procedure"), stub)
@@ -536,7 +507,7 @@ impl MachineState {
self.permission_error( self.permission_error(
Permission::Modify, Permission::Modify,
atom!("module"), atom!("module"),
functor!(error_atom, [atom(module_name)]), functor!(error_atom, [atom_as_cell(module_name)]),
) )
} }
SessionError::NamelessEntry => { SessionError::NamelessEntry => {
@@ -555,15 +526,12 @@ impl MachineState {
} }
SessionError::CompilationError(err) => self.syntax_error(err), SessionError::CompilationError(err) => self.syntax_error(err),
SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key) => { SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key) => {
let functor_stub = functor_stub(key.0, key.1);
let stub = functor!( let stub = functor!(
atom!(":"), atom!(":"),
[ [
atom(compilation_target.module_name()), atom_as_cell((compilation_target.module_name())),
str(self.heap.len() + 4, 0) functor((key.0), [fixnum((key.1))])
], ]
[functor_stub]
); );
self.permission_error( self.permission_error(
@@ -587,30 +555,27 @@ impl MachineState {
} }
let location = err.line_and_col_num(); let location = err.line_and_col_num();
let len = self.heap.len();
let stub = err.as_functor(); let stub = err.as_functor();
let stub = functor!(atom!("syntax_error"), [str(len, 0)], [stub]); let stub = functor!(atom!("syntax_error"), [functor(stub)]);
MachineError { MachineError {
stub, stub,
location, location,
from: ErrorProvenance::Constructed,
} }
} }
pub(super) fn representation_error(&mut self, flag: RepFlag) -> MachineError { pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError {
let stub = functor!(atom!("representation_error"), [atom(flag.as_atom())]); let stub = functor!(atom!("representation_error"), [atom_as_cell((flag.as_atom()))]);
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Received,
} }
} }
#[cfg(feature = "ffi")] #[cfg(feature = "ffi")]
pub(super) fn ffi_error(&mut self, err: FFIError) -> MachineError { pub(super) fn ffi_error(&self, err: FFIError) -> MachineError {
let error_atom = match err { let error_atom = match err {
FFIError::ValueCast => atom!("value_cast"), FFIError::ValueCast => atom!("value_cast"),
FFIError::ValueDontFit => atom!("value_dont_fit"), FFIError::ValueDontFit => atom!("value_dont_fit"),
@@ -619,62 +584,44 @@ impl MachineState {
FFIError::FunctionNotFound => atom!("function_not_found"), FFIError::FunctionNotFound => atom!("function_not_found"),
FFIError::StructNotFound => atom!("struct_not_found"), FFIError::StructNotFound => atom!("struct_not_found"),
}; };
let stub = functor!(atom!("ffi_error"), [atom(error_atom)]); let stub = functor!(atom!("ffi_error"), [atom_as_cell(error_atom)]);
MachineError { MachineError {
stub, stub,
location: None, location: None,
from: ErrorProvenance::Constructed,
} }
} }
pub(super) fn error_form(&mut self, err: MachineError, src: FunctorStub) -> MachineStub { pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
let h = self.heap.len(); if let Some(ParserErrorSrc { line_num, .. }) = err.location {
let location = err.location; functor!(atom!("error"), [functor((err.stub)),
let stub_addition_len = if err.len() == 1 { functor((atom!(":")), [functor(src),
0 // if err contains 1 cell, it can be inlined at stub[1]. number(line_num, (&mut self.arena))])])
} else { } else {
err.len() functor!(atom!("error"), [functor((err.stub)),
}; functor(src)])
let mut stub = vec![
atom_as_cell!(atom!("error"), 2),
str_loc_as_cell!(h + 3),
str_loc_as_cell!(h + 3 + stub_addition_len),
];
if stub_addition_len > 0 {
stub.extend(err.into_iter(3));
} else {
stub[1] = err.stub[0];
} }
}
if let Some(ParserErrorSrc { line_num, .. }) = location { // throw an error pre-allocated in the heap
stub.push(atom_as_cell!(atom!(":"), 2)); pub(super) fn throw_resource_error(&mut self, err_loc: usize) {
stub.push(str_loc_as_cell!(h + 6 + stub_addition_len)); self.registers[1] = str_loc_as_cell!(err_loc);
stub.push(integer_as_cell!(Number::arena_from( self.set_ball();
line_num, self.unwind_stack();
&mut self.arena
)));
}
stub.extend(src.iter());
stub
} }
pub(super) fn throw_exception(&mut self, err: MachineStub) { pub(super) fn throw_exception(&mut self, err: MachineStub) {
let h = self.heap.len();
let err_len = err.len();
self.ball.boundary = 0; self.ball.boundary = 0;
self.ball.stub.truncate(0); self.ball.stub.truncate(0);
self.heap.extend(err); let mut writer = Heap::functor_writer(err);
self.registers[1] = if err_len == 1 { self.registers[1] = match writer(&mut self.heap) {
heap_loc_as_cell!(h) Ok(loc) => loc,
} else { Err(resource_err_loc) => {
str_loc_as_cell!(h) self.throw_resource_error(resource_err_loc);
return;
}
}; };
self.set_ball(); self.set_ball();
@@ -682,21 +629,6 @@ impl MachineState {
} }
} }
impl MachineError {
fn into_iter(self, offset: usize) -> Box<dyn Iterator<Item = HeapCellValue>> {
match self.from {
ErrorProvenance::Constructed => {
Box::new(self.stub.into_iter().map(move |hcv| hcv + offset))
}
ErrorProvenance::Received => Box::new(self.stub.into_iter()),
}
}
fn len(&self) -> usize {
self.stub.len()
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum CompilationError { pub enum CompilationError {
Arithmetic(ArithmeticError), Arithmetic(ArithmeticError),
@@ -715,12 +647,12 @@ pub enum CompilationError {
#[derive(Debug)] #[derive(Debug)]
pub enum DirectiveError { pub enum DirectiveError {
ExpectedDirective(Term), ExpectedDirective(HeapCellValue),
InvalidDirective(Atom, usize /* arity */), InvalidDirective(Atom, usize /* arity */),
InvalidOpDeclNameType(Term), InvalidOpDeclNameType(HeapCellValue),
InvalidOpDeclSpecDomain(Term), InvalidOpDeclSpecDomain(HeapCellValue),
InvalidOpDeclSpecValue(Atom), InvalidOpDeclSpecValue(Atom),
InvalidOpDeclPrecType(Term), InvalidOpDeclPrecType(HeapCellValue),
InvalidOpDeclPrecDomain(Fixnum), InvalidOpDeclPrecDomain(Fixnum),
ShallNotCreate(Atom), ShallNotCreate(Atom),
ShallNotModify(Atom), ShallNotModify(Atom),
@@ -757,11 +689,9 @@ impl CompilationError {
functor!(atom!("exceeded_max_arity")) functor!(atom!("exceeded_max_arity"))
} }
CompilationError::InadmissibleFact => { CompilationError::InadmissibleFact => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_fact")) functor!(atom!("inadmissible_fact"))
} }
CompilationError::InadmissibleQueryTerm => { CompilationError::InadmissibleQueryTerm => {
// TODO: type_error(callable, _).
functor!(atom!("inadmissible_query_term")) functor!(atom!("inadmissible_query_term"))
} }
CompilationError::InvalidDirective(_) => { CompilationError::InvalidDirective(_) => {
@@ -776,8 +706,8 @@ impl CompilationError {
CompilationError::InvalidModuleExport => { CompilationError::InvalidModuleExport => {
functor!(atom!("invalid_module_export")) functor!(atom!("invalid_module_export"))
} }
CompilationError::InvalidModuleResolution(ref module_name) => { &CompilationError::InvalidModuleResolution(module_name) => {
functor!(atom!("no_such_module"), [atom(module_name)]) functor!(atom!("no_such_module"), [atom_as_cell(module_name)])
} }
CompilationError::InvalidRuleHead => { CompilationError::InvalidRuleHead => {
functor!(atom!("invalid_head_of_rule")) // TODO: type_error(callable, _). functor!(atom!("invalid_head_of_rule")) // TODO: type_error(callable, _).
@@ -896,14 +826,13 @@ impl EvalError {
// used by '$skip_max_list'. // used by '$skip_max_list'.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CycleSearchResult { pub enum CycleSearchResult {
Cyclic(usize), Cyclic { lambda: usize }, // number of steps
EmptyList, EmptyList,
NotList(usize, HeapCellValue), // the list length until the second argument in the heap NotList { num_steps: usize, heap_loc: HeapCellValue },
PartialList(usize, Ref), // the list length (up to max), and an offset into the heap. PartialList { num_steps: usize, heap_loc: HeapCellValue },
ProperList(usize), // the list length. ProperList { num_steps: usize },
PStrLocation(usize, usize, usize), // list length (up to max), the heap address of the PStr, the offset PStrLocation { num_steps: usize, pstr_loc: HeapCellValue },
UntouchedList(usize, usize), // list length (up to max), the address of an uniterated Addr::Lis(address). UntouchedList { num_steps: usize, list_loc: usize },
UntouchedCStr(Atom, usize),
} }
impl MachineState { impl MachineState {
@@ -915,11 +844,11 @@ impl MachineState {
let sorted = self.store(self.deref(self.registers[2])); let sorted = self.store(self.deref(self.registers[2]));
match BrentAlgState::detect_cycles(&self.heap, list) { match BrentAlgState::detect_cycles(&self.heap, list) {
CycleSearchResult::PartialList(..) => { CycleSearchResult::PartialList { .. } => {
let err = self.instantiation_error(); let err = self.instantiation_error();
return Err(self.error_form(err, stub_gen())); return Err(self.error_form(err, stub_gen()));
} }
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => { CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } => {
let err = self.type_error(ValidType::List, list); let err = self.type_error(ValidType::List, list);
return Err(self.error_form(err, stub_gen())); return Err(self.error_form(err, stub_gen()));
} }
@@ -927,7 +856,7 @@ impl MachineState {
}; };
match BrentAlgState::detect_cycles(&self.heap, sorted) { match BrentAlgState::detect_cycles(&self.heap, sorted) {
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) if !sorted.is_var() => { CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !sorted.is_var() => {
let err = self.type_error(ValidType::List, sorted); let err = self.type_error(ValidType::List, sorted);
Err(self.error_form(err, stub_gen())) Err(self.error_form(err, stub_gen()))
} }
@@ -939,7 +868,7 @@ impl MachineState {
let stub_gen = || functor_stub(atom!("keysort"), 2); let stub_gen = || functor_stub(atom!("keysort"), 2);
match BrentAlgState::detect_cycles(&self.heap, list) { match BrentAlgState::detect_cycles(&self.heap, list) {
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) if !list.is_var() => { CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } if !list.is_var() => {
let err = self.type_error(ValidType::List, list); let err = self.type_error(ValidType::List, list);
Err(self.error_form(err, stub_gen())) Err(self.error_form(err, stub_gen()))
} }
@@ -1001,11 +930,11 @@ impl MachineState {
let sorted = self.store(self.deref(self[temp_v!(2)])); let sorted = self.store(self.deref(self[temp_v!(2)]));
match BrentAlgState::detect_cycles(&self.heap, pairs) { match BrentAlgState::detect_cycles(&self.heap, pairs) {
CycleSearchResult::PartialList(..) => { CycleSearchResult::PartialList { .. } => {
let err = self.instantiation_error(); let err = self.instantiation_error();
Err(self.error_form(err, stub_gen())) Err(self.error_form(err, stub_gen()))
} }
CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => { CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } => {
let err = self.type_error(ValidType::List, pairs); let err = self.type_error(ValidType::List, pairs);
Err(self.error_form(err, stub_gen())) Err(self.error_form(err, stub_gen()))
} }

View File

@@ -169,6 +169,13 @@ impl From<TypedArenaPtr<IndexPtr>> for CodeIndex {
} }
} }
impl From<CodeIndex> for HeapCellValue {
#[inline(always)]
fn from(idx: CodeIndex) -> HeapCellValue {
untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx))
}
}
impl CodeIndex { impl CodeIndex {
#[inline] #[inline]
pub(crate) fn new(ptr: IndexPtr, arena: &mut Arena) -> Self { pub(crate) fn new(ptr: IndexPtr, arena: &mut Arena) -> Self {
@@ -208,10 +215,12 @@ impl CodeIndex {
std::mem::replace(self.0.deref_mut(), value) std::mem::replace(self.0.deref_mut(), value)
} }
/*
#[inline(always)] #[inline(always)]
pub(crate) fn as_ptr(&self) -> *const IndexPtr { pub(crate) fn as_ptr(&self) -> *const IndexPtr {
self.0.as_ptr() self.0.as_ptr()
} }
*/
} }
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>; pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;

View File

@@ -1,6 +1,7 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::forms::*; use crate::forms::*;
use crate::functor_macro::*;
use crate::heap_iter::*; use crate::heap_iter::*;
use crate::heap_print::*; use crate::heap_print::*;
use crate::machine::attributed_variables::*; use crate::machine::attributed_variables::*;
@@ -12,7 +13,6 @@ use crate::machine::stack::*;
use crate::machine::streams::*; use crate::machine::streams::*;
use crate::machine::Machine; use crate::machine::Machine;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::read::TermWriteResult;
use crate::types::*; use crate::types::*;
use crate::parser::dashu::Integer; use crate::parser::dashu::Integer;
@@ -21,7 +21,7 @@ use indexmap::IndexMap;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; use std::fmt;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut, Range};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@@ -36,8 +36,8 @@ pub(super) enum MachineMode {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(super) enum HeapPtr { pub(super) enum HeapPtr {
HeapCell(usize), HeapCell(usize),
PStrChar(usize, usize), PStr(usize), // Char(usize),
PStrLocation(usize, usize), // PStrLocation(usize),
} }
impl Default for HeapPtr { impl Default for HeapPtr {
@@ -184,8 +184,9 @@ impl IndexMut<RegType> for MachineState {
} }
} }
pub type CallResult = Result<(), Vec<HeapCellValue>>; pub type CallResult = Result<(), Vec<FunctorElement>>;
/*
#[inline(always)] #[inline(always)]
pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixnum) { pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixnum) {
read_heap_cell!(heap[index], read_heap_cell!(heap[index],
@@ -200,30 +201,44 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
} }
) )
} }
*/
fn push_var_eq_functors( fn push_var_eq_functors(
heap: &mut Heap, heap: &mut Heap,
size: usize,
iter: impl Iterator<Item = (usize, Var)>, iter: impl Iterator<Item = (usize, Var)>,
atom_tbl: &AtomTable, atom_tbl: &AtomTable,
) -> Vec<HeapCellValue> { ) -> Result<HeapCellValue, usize> {
let mut list_of_var_eqs = vec![]; let src_h = heap.cell_len();
for (var_loc, var) in iter { // (var, binding) in iter { if size > 0 {
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string()); let mut writer = heap.reserve(1 + 5 * size)?;
let h = heap.len();
let binding = heap[var_loc];
heap.push(atom_as_cell!(atom!("="), 2)); writer.write_with(|section| {
heap.push(atom_as_cell!(var_atom)); for (var_loc, var) in iter { // (var, binding) in iter {
heap.push(binding); let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
let binding = heap_loc_as_cell!(var_loc);
list_of_var_eqs.push(str_loc_as_cell!(h)); section.push_cell(atom_as_cell!(atom!("="), 2));
section.push_cell(atom_as_cell!(var_atom));
section.push_cell(binding);
}
for idx in 0 .. size {
section.push_cell(list_loc_as_cell!(section.cell_len() + 1));
section.push_cell(str_loc_as_cell!(src_h + 3 * idx));
}
section.push_cell(empty_list_as_cell!());
});
Ok(heap_loc_as_cell!(src_h + 3 * size))
} else {
Ok(empty_list_as_cell!())
} }
list_of_var_eqs
} }
/*
pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>( pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
iter: Iter, iter: Iter,
boundary: i64, boundary: i64,
@@ -232,6 +247,7 @@ pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
let diff = boundary - h; let diff = boundary - h;
iter.map(move |heap_value| heap_value - diff) iter.map(move |heap_value| heap_value - diff)
} }
*/
#[derive(Debug)] #[derive(Debug)]
pub struct Ball { pub struct Ball {
@@ -252,8 +268,17 @@ impl Ball {
self.stub.clear(); self.stub.clear();
} }
pub(super) fn copy_and_align(&self, h: usize) -> Heap { pub(super) fn copy_and_align_to(&self, dest: &mut Heap) -> Result<usize, usize> {
copy_and_align_iter(self.stub.iter().cloned(), self.boundary as i64, h as i64).collect() let h = dest.cell_len();
let diff = self.boundary as i64 - h as i64;
dest.append(self.stub.splice(..))?;
for cell in &mut dest.splice_mut(h ..) {
*cell = *cell - diff;
}
Ok(h)
} }
} }
@@ -285,21 +310,6 @@ impl<'a> IndexMut<usize> for CopyTerm<'a> {
} }
impl<'a> CopierTarget for CopyTerm<'a> { impl<'a> CopierTarget for CopyTerm<'a> {
#[inline(always)]
fn threshold(&self) -> usize {
self.state.heap.len()
}
#[inline(always)]
fn push(&mut self, hcv: HeapCellValue) {
self.state.heap.push(hcv);
}
#[inline(always)]
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.state.attr_var_init.attr_var_queue.push(attr_var_loc);
}
#[inline(always)] #[inline(always)]
fn store(&self, value: HeapCellValue) -> HeapCellValue { fn store(&self, value: HeapCellValue) -> HeapCellValue {
self.state.store(value) self.state.store(value)
@@ -310,10 +320,56 @@ impl<'a> CopierTarget for CopyTerm<'a> {
self.state.deref(value) self.state.deref(value)
} }
#[inline(always)]
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.state.attr_var_init.attr_var_queue.push(attr_var_loc);
}
#[inline(always)] #[inline(always)]
fn stack(&mut self) -> &mut Stack { fn stack(&mut self) -> &mut Stack {
&mut self.state.stack &mut self.state.stack
} }
#[inline(always)]
fn threshold(&self) -> usize {
self.state.heap.cell_len()
}
#[inline(always)]
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
self.state.heap.copy_pstr_within(pstr_loc)
}
#[inline(always)]
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
self.state.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
}
#[inline(always)]
fn pstr_at(&self, loc: usize) -> bool {
self.state.heap.pstr_vec()[loc]
}
#[inline(always)]
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
// unwrap is safe here because a partial string is always
// followed by a tail cell, i.e. a non-pstr cell, supposing
// self.state.heap[loc] is a pstr cell
self.state.heap.pstr_vec()[loc ..].first_zero().unwrap()
}
#[inline(always)]
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
self.state.heap.reserve(num_cells)
}
#[inline(always)]
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
self.state.heap.copy_slice_to_end(bounds)
}
} }
#[derive(Debug)] #[derive(Debug)]
@@ -321,7 +377,6 @@ pub(crate) struct CopyBallTerm<'a> {
attr_var_queue: &'a mut Vec<usize>, attr_var_queue: &'a mut Vec<usize>,
stack: &'a mut Stack, stack: &'a mut Stack,
heap: &'a mut Heap, heap: &'a mut Heap,
heap_boundary: usize,
stub: &'a mut Heap, stub: &'a mut Heap,
} }
@@ -332,13 +387,10 @@ impl<'a> CopyBallTerm<'a> {
heap: &'a mut Heap, heap: &'a mut Heap,
stub: &'a mut Heap, stub: &'a mut Heap,
) -> Self { ) -> Self {
let hb = heap.len();
CopyBallTerm { CopyBallTerm {
attr_var_queue, attr_var_queue,
stack, stack,
heap, heap,
heap_boundary: hb,
stub, stub,
} }
} }
@@ -348,10 +400,10 @@ impl<'a> Index<usize> for CopyBallTerm<'a> {
type Output = HeapCellValue; type Output = HeapCellValue;
fn index(&self, index: usize) -> &Self::Output { fn index(&self, index: usize) -> &Self::Output {
if index < self.heap_boundary { if index < self.heap.cell_len() {
&self.heap[index] &self.heap[index]
} else { } else {
let index = index - self.heap_boundary; let index = index - self.heap.cell_len();
&self.stub[index] &self.stub[index]
} }
} }
@@ -359,10 +411,10 @@ impl<'a> Index<usize> for CopyBallTerm<'a> {
impl<'a> IndexMut<usize> for CopyBallTerm<'a> { impl<'a> IndexMut<usize> for CopyBallTerm<'a> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output { fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index < self.heap_boundary { if index < self.heap.cell_len() {
&mut self.heap[index] &mut self.heap[index]
} else { } else {
let index = index - self.heap_boundary; let index = index - self.heap.cell_len();
&mut self.stub[index] &mut self.stub[index]
} }
} }
@@ -370,11 +422,7 @@ impl<'a> IndexMut<usize> for CopyBallTerm<'a> {
impl<'a> CopierTarget for CopyBallTerm<'a> { impl<'a> CopierTarget for CopyBallTerm<'a> {
fn threshold(&self) -> usize { fn threshold(&self) -> usize {
self.heap_boundary + self.stub.len() self.heap.cell_len() + self.stub.cell_len()
}
fn push(&mut self, value: HeapCellValue) {
self.stub.push(value);
} }
#[inline(always)] #[inline(always)]
@@ -385,10 +433,10 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
fn store(&self, value: HeapCellValue) -> HeapCellValue { fn store(&self, value: HeapCellValue) -> HeapCellValue {
read_heap_cell!(value, read_heap_cell!(value,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => { (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => {
if h < self.heap_boundary { if h < self.heap.cell_len() {
self.heap[h] self.heap[h]
} else { } else {
let index = h - self.heap_boundary; let index = h - self.heap.cell_len();
self.stub[index] self.stub[index]
} }
} }
@@ -417,6 +465,67 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
fn stack(&mut self) -> &mut Stack { fn stack(&mut self) -> &mut Stack {
self.stack self.stack
} }
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
debug_assert!(pstr_loc < self.heap.byte_len());
let (string, tail_loc) = self.heap.scan_slice_to_str(pstr_loc);
self.stub.allocate_pstr(string)?;
Ok(tail_loc)
}
#[inline]
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
self.stub.reserve(num_cells)
}
#[inline]
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
if pstr_loc >= self.heap.byte_len() {
self.stub.pstr_vec()[0 .. cell_index!(pstr_loc - self.heap.byte_len())]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
} else {
self.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
}
}
#[inline]
fn pstr_at(&self, loc: usize) -> bool {
if loc >= self.heap.cell_len() {
self.stub.pstr_vec()[loc - self.heap.cell_len()]
} else {
self.heap.pstr_vec()[loc]
}
}
#[inline]
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
let zero_from_loc = if loc >= self.heap.cell_len() {
self.stub.pstr_vec()[loc - self.heap.cell_len() ..].first_zero().unwrap()
} else {
self.heap.pstr_vec()[loc ..].first_zero().unwrap()
};
zero_from_loc + loc
}
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
let len = bounds.end - bounds.start;
let mut stub_writer = self.stub.reserve(len)?;
stub_writer.write_with(|section| {
for idx in bounds {
section.push_cell(self.heap[idx]);
}
});
Ok(())
}
} }
impl MachineState { impl MachineState {
@@ -467,10 +576,6 @@ impl MachineState {
let addr = self.store(self.deref(addr)); let addr = self.store(self.deref(addr));
read_heap_cell!(addr, read_heap_cell!(addr,
(HeapCellValueTag::Char, c) => {
chars.push(c);
continue;
}
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 { if arity == 0 {
if let Some(c) = name.as_char() { if let Some(c) = name.as_char() {
@@ -543,35 +648,37 @@ impl MachineState {
pub fn write_read_term_options( pub fn write_read_term_options(
&mut self, &mut self,
mut var_list: Vec<(Var, HeapCellValue, usize)>, mut var_list: Vec<(Var, HeapCellValue, usize)>,
singleton_var_list: Vec<HeapCellValue>, singletons_heap_list: HeapCellValue,
) -> CallResult { ) -> CallResult {
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2)); var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
/*
let list_of_var_eqs = push_var_eq_functors( let list_of_var_eqs = push_var_eq_functors(
&mut self.heap, &mut self.heap,
var_list.iter().map(|(var_name, var, _)| { var_list.iter().map(|(var_name, var, _)| {
(var.get_value() as usize, var_name.clone()) (var.get_value() as usize, var_name.clone())
}), }),
num_vars,
&self.atom_tbl, &self.atom_tbl,
); );
*/
let singleton_addr = self.registers[3]; let singleton_addr = self.registers[3];
let singletons_offset = heap_loc_as_cell!(iter_to_heap_list( unify_fn!(*self, singletons_heap_list, singleton_addr);
&mut self.heap,
singleton_var_list.into_iter()
));
unify_fn!(*self, singletons_offset, singleton_addr);
if self.fail { if self.fail {
return Ok(()); return Ok(());
} }
let vars_addr = self.registers[4]; let vars_addr = self.registers[4];
let vars_offset = heap_loc_as_cell!(iter_to_heap_list( let vars_offset = resource_error_call_result!(
&mut self.heap, self,
var_list.into_iter().map(|(_, cell, _)| cell) sized_iter_to_heap_list(
)); &mut self.heap,
var_list.len(),
var_list.iter().map(|(_, cell, _)| *cell),
)
);
unify_fn!(*self, vars_offset, vars_addr); unify_fn!(*self, vars_offset, vars_addr);
@@ -580,23 +687,41 @@ impl MachineState {
} }
let var_names_addr = self.registers[5]; let var_names_addr = self.registers[5];
/*
let var_names_offset = heap_loc_as_cell!(iter_to_heap_list( let var_names_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap, &mut self.heap,
list_of_var_eqs.into_iter() list_of_var_eqs.into_iter()
)); ));
*/
let var_names_offset = resource_error_call_result!(
self,
push_var_eq_functors(
&mut self.heap,
var_list.len(),
var_list.iter().map(|(var_name, var, _)| {
(var.get_value() as usize, var_name.clone())
}),
&self.atom_tbl,
)
);
Ok(unify_fn!(*self, var_names_offset, var_names_addr)) Ok(unify_fn!(*self, var_names_offset, var_names_addr))
} }
pub fn read_term_body(&mut self, term: TermWriteResult) -> CallResult { pub fn read_term_body(&mut self, term: TermWriteResult) -> CallResult {
let heap_loc = read_heap_cell!(self.heap[term.heap_loc], let heap_loc = self.heap[term.focus];
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
/*
read_heap_cell!(self.heap[term.heap_loc],
(HeapCellValueTag::PStr) => { // | HeapCellValueTag::PStrOffset) => {
pstr_loc_as_cell!(term.heap_loc) pstr_loc_as_cell!(term.heap_loc)
} }
_ => { _ => {
heap_loc_as_cell!(term.heap_loc) heap_loc_as_cell!(term.heap_loc)
} }
); );
*/
unify_fn!(*self, heap_loc, self.registers[2]); unify_fn!(*self, heap_loc, self.registers[2]);
@@ -612,7 +737,7 @@ impl MachineState {
let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new(); let mut singleton_var_set: IndexMap<Ref, bool> = IndexMap::new();
for cell in eager_stackful_preorder_iter(&mut self.heap, heap_loc) { for cell in stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, term.focus) {
let cell = unmark_cell_bits!(cell); let cell = unmark_cell_bits!(cell);
if let Some(var) = cell.as_var() { if let Some(var) = cell.as_var() {
@@ -624,29 +749,33 @@ impl MachineState {
} }
} }
let singleton_var_list = push_var_eq_functors( let singleton_var_list = resource_error_call_result!(
&mut self.heap, self,
term.inverse_var_locs push_var_eq_functors(
.iter() &mut self.heap,
.filter_map(|(var_loc, var_name)| { singleton_var_set
// add h to offset the term variable into its heap location. .iter()
let r = Ref::heap_cell(*var_loc); .filter(|(var, is_singleton)| {
**is_singleton && term.inverse_var_locs.contains_key(
&(var.get_value() as usize)
)
})
.count(),
term.inverse_var_locs
.iter()
.filter_map(|(var_loc, var_name)| {
let r = Ref::heap_cell(*var_loc);
if singleton_var_set.get(&r).cloned().unwrap_or(false) { if singleton_var_set.get(&r).cloned().unwrap_or(false) {
Some((*var_loc, var_name.clone())) Some((*var_loc, var_name.clone()))
} else { } else {
None None
} }
}), }),
&self.atom_tbl, &self.atom_tbl,
)
); );
/*
for var in term_write_result.var_dict.values_mut() {
*var = heap_bound_deref(&self.heap, *var);
}
*/
let mut var_list = Vec::with_capacity(singleton_var_set.len()); let mut var_list = Vec::with_capacity(singleton_var_set.len());
for (var_loc, var_name) in term.inverse_var_locs { for (var_loc, var_name) in term.inverse_var_locs {
@@ -744,7 +873,7 @@ impl MachineState {
CompilationError::ParserError(e) if e.is_unexpected_eof() => { CompilationError::ParserError(e) if e.is_unexpected_eof() => {
match eof_handler(self, stream)? { match eof_handler(self, stream)? {
OnEOF::Return => { OnEOF::Return => {
return self.write_read_term_options(vec![], vec![]) return self.write_read_term_options(vec![], empty_list_as_cell!());
} }
OnEOF::Continue => continue, OnEOF::Continue => continue,
} }
@@ -793,9 +922,6 @@ impl MachineState {
} }
read_heap_cell!(atom, read_heap_cell!(atom,
(HeapCellValueTag::Char, c) => {
var_names.insert(var, Rc::new(c.to_string()));
}
(HeapCellValueTag::Atom, (name, _arity)) => { (HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0); debug_assert_eq!(_arity, 0);
var_names.insert(var, Rc::new(name.as_str().to_owned())); var_names.insert(var, Rc::new(name.as_str().to_owned()));
@@ -884,16 +1010,20 @@ impl MachineState {
} }
); );
let h = self.heap.len(); let term_loc = self.heap.cell_len();
self.heap.push(term_to_be_printed);
step_or_resource_error!(
self,
self.heap.push_cell(term_to_be_printed),
{ return Ok(None); }
);
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut self.heap, &mut self.heap,
Arc::clone(&self.atom_tbl),
&mut self.stack, &mut self.stack,
op_dir, op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
h, term_loc,
); );
printer.ignore_ops = ignore_ops; printer.ignore_ops = ignore_ops;
@@ -984,42 +1114,6 @@ impl MachineState {
} }
); );
} }
pub(crate) fn directive_error(&mut self, err: DirectiveError) -> MachineError {
match err {
DirectiveError::ExpectedDirective(_term) => self.domain_error(
DomainErrorType::Directive,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidDirective(name, arity) => {
self.domain_error(DomainErrorType::Directive, functor_stub(name, arity))
}
DirectiveError::InvalidOpDeclNameType(_term) => self.type_error(
ValidType::List,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecDomain(_term) => self.domain_error(
DomainErrorType::OperatorSpecifier,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclSpecValue(atom) => {
self.domain_error(DomainErrorType::OperatorSpecifier, atom_as_cell!(atom))
}
DirectiveError::InvalidOpDeclPrecType(_term) => self.type_error(
ValidType::Integer,
atom_as_cell!(atom!("todo_insert_invalid_term_here")),
),
DirectiveError::InvalidOpDeclPrecDomain(num) => {
self.domain_error(DomainErrorType::OperatorPriority, fixnum_as_cell!(num))
}
DirectiveError::ShallNotCreate(atom) => {
self.permission_error(Permission::Create, atom!("operator"), atom)
}
DirectiveError::ShallNotModify(atom) => {
self.permission_error(Permission::Modify, atom!("operator"), atom)
}
}
}
} }
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]

File diff suppressed because it is too large Load Diff

View File

@@ -4,16 +4,12 @@ pub use crate::machine::machine_state::*;
pub use crate::machine::streams::*; pub use crate::machine::streams::*;
pub use crate::machine::*; pub use crate::machine::*;
pub use crate::parser::ast::*; pub use crate::parser::ast::*;
use crate::read::*;
pub use crate::types::*;
use std::sync::Arc;
#[cfg(test)] #[cfg(test)]
use crate::machine::copier::CopierTarget; use crate::machine::copier::CopierTarget;
#[cfg(test)] #[cfg(test)]
use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
// a mini-WAM for test purposes. // a mini-WAM for test purposes.
@@ -31,7 +27,6 @@ impl MockWAM {
Self { Self {
machine_st: MachineState::new(), machine_st: MachineState::new(),
op_dir, op_dir,
//flags: MachineFlags::default(),
} }
} }
@@ -56,7 +51,7 @@ impl MockWAM {
) -> Result<String, CompilationError> { ) -> Result<String, CompilationError> {
let term_write_result = self.parse_and_write_parsed_term_to_heap(term_string)?; let term_write_result = self.parse_and_write_parsed_term_to_heap(term_string)?;
print_heap_terms(self.machine_st.heap.iter(), term_write_result.heap_loc); print_heap_terms(self.machine_st.heap.splice(..), term_write_result.focus);
let var_names = term_write_result let var_names = term_write_result
.inverse_var_locs .inverse_var_locs
@@ -68,11 +63,10 @@ impl MockWAM {
let mut printer = HCPrinter::new( let mut printer = HCPrinter::new(
&mut self.machine_st.heap, &mut self.machine_st.heap,
Arc::clone(&self.machine_st.atom_tbl),
&mut self.machine_st.stack, &mut self.machine_st.stack,
&self.op_dir, &self.op_dir,
PrinterOutputter::new(), PrinterOutputter::new(),
term_write_result.heap_loc, term_write_result.focus,
); );
printer.var_names = var_names; printer.var_names = var_names;
@@ -154,10 +148,6 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
} }
} }
fn push(&mut self, val: HeapCellValue) {
self.wam.machine_st.heap.push(val);
}
fn push_attr_var_queue(&mut self, attr_var_loc: usize) { fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.wam self.wam
.machine_st .machine_st
@@ -171,43 +161,123 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
} }
fn threshold(&self) -> usize { fn threshold(&self) -> usize {
self.wam.machine_st.heap.len() self.wam.machine_st.heap.cell_len()
}
#[inline(always)]
fn copy_pstr_to_threshold(&mut self, pstr_loc: usize) -> Result<usize, usize> {
self.wam.machine_st.heap.copy_pstr_within(pstr_loc)
}
#[inline(always)]
fn pstr_head_cell_index(&self, pstr_loc: usize) -> usize {
self.wam.machine_st.heap.pstr_vec()[0 .. cell_index!(pstr_loc)]
.last_zero()
.map(|idx| idx + 1)
.unwrap_or(0)
}
#[inline(always)]
fn pstr_at(&self, loc: usize) -> bool {
self.wam.machine_st.heap.pstr_vec()[loc]
}
#[inline(always)]
fn next_non_pstr_cell_index(&self, loc: usize) -> usize {
// unwrap is safe here because a partial string is always
// followed by a tail cell, i.e. a non-pstr cell, supposing
// self.machine_st.heap[loc] is a pstr cell
self.wam.machine_st.heap.pstr_vec()[loc ..].first_zero()
.map(|idx| idx + loc)
.unwrap()
}
#[inline(always)]
fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
self.wam.machine_st.heap.reserve(num_cells)
}
#[inline(always)]
fn copy_slice_to_end(&mut self, bounds: Range<usize>) -> Result<(), usize> {
self.wam.machine_st.heap.copy_slice_to_end(bounds)
} }
} }
#[cfg(test)] #[cfg(test)]
pub fn all_cells_marked_and_unforwarded(heap: &[HeapCellValue]) { pub fn all_cells_marked_and_unforwarded(iter: impl SizedHeap) {
for (idx, cell) in heap.iter().enumerate() { let mut idx = 0;
let cell_len = iter.cell_len();
while idx < cell_len {
let curr_idx = idx;
let cell = if iter.pstr_at(idx) {
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
idx = last_cell_loc;
iter[last_cell_loc - 1]
} else {
idx += 1;
iter[curr_idx]
};
assert!( assert!(
cell.get_mark_bit(), cell.get_mark_bit(),
"cell {:?} at index {} is not marked", "cell {:?} at index {} is not marked",
cell, cell,
idx curr_idx
); );
assert!( assert!(
!cell.get_forwarding_bit(), !cell.get_forwarding_bit(),
"cell {:?} at index {} is forwarded", "cell {:?} at index {} is forwarded",
cell, cell,
idx curr_idx
); );
} }
} }
#[cfg(test)] #[cfg(test)]
pub fn all_cells_unmarked(heap: &Heap) { pub fn unmark_all_cells(mut iter: impl SizedHeapMut) {
for (idx, cell) in heap.iter().enumerate() { let mut idx = 0;
let cell_len = iter.cell_len();
while idx < cell_len {
if iter.pstr_at(idx) {
iter[idx].set_mark_bit(false);
let last_cell_loc = {
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
last_cell_loc
};
iter[last_cell_loc].set_mark_bit(false);
idx = last_cell_loc;
} else {
iter[idx].set_mark_bit(false);
idx += 1;
}
}
}
#[cfg(test)]
pub fn all_cells_unmarked(iter: impl SizedHeap) {
let mut idx = 0;
let cell_len = iter.cell_len();
while idx < cell_len {
let curr_idx = idx;
let cell = if iter.pstr_at(idx) {
let (_s, last_cell_loc) = iter.scan_slice_to_str(heap_index!(idx));
idx = last_cell_loc;
iter[last_cell_loc - 1]
} else {
idx += 1;
iter[curr_idx]
};
assert!( assert!(
!cell.get_mark_bit(), !cell.get_mark_bit(),
"cell {:?} at index {} is still marked", "cell {:?} at index {} is still marked",
cell, cell,
idx curr_idx
);
assert!(
!cell.get_forwarding_bit(),
"cell {:?} at index {} is still forwarded",
cell,
idx
); );
} }
} }
@@ -256,6 +326,8 @@ impl Machine {
mod tests { mod tests {
use super::*; use super::*;
use crate::functor_macro::FunctorElement;
#[test] #[test]
fn unify_tests() { fn unify_tests() {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
@@ -276,13 +348,13 @@ mod tests {
unify!( unify!(
wam, wam,
str_loc_as_cell!(0), str_loc_as_cell!(0),
str_loc_as_cell!(term_write_result_2.heap_loc) str_loc_as_cell!(term_write_result_2.focus)
); );
assert!(wam.fail); assert!(wam.fail);
} }
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.fail = false; wam.fail = false;
wam.heap.clear(); wam.heap.clear();
@@ -296,14 +368,14 @@ mod tests {
unify!( unify!(
wam, wam,
heap_loc_as_cell!(term_write_result_1.heap_loc), heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.heap_loc) heap_loc_as_cell!(term_write_result_2.focus)
); );
assert!(!wam.fail); assert!(!wam.fail);
} }
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.fail = false; wam.fail = false;
wam.heap.clear(); wam.heap.clear();
@@ -317,14 +389,14 @@ mod tests {
unify!( unify!(
wam, wam,
heap_loc_as_cell!(term_write_result_1.heap_loc), heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.heap_loc) heap_loc_as_cell!(term_write_result_2.focus)
); );
assert!(!wam.fail); assert!(!wam.fail);
} }
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.fail = false; wam.fail = false;
wam.heap.clear(); wam.heap.clear();
@@ -338,14 +410,14 @@ mod tests {
unify!( unify!(
wam, wam,
heap_loc_as_cell!(term_write_result_1.heap_loc), heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.heap_loc) heap_loc_as_cell!(term_write_result_2.focus)
); );
assert!(!wam.fail); assert!(!wam.fail);
} }
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.fail = false; wam.fail = false;
wam.heap.clear(); wam.heap.clear();
@@ -359,14 +431,14 @@ mod tests {
unify!( unify!(
wam, wam,
heap_loc_as_cell!(term_write_result_1.heap_loc), heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.heap_loc) heap_loc_as_cell!(term_write_result_2.focus)
); );
assert!(!wam.fail); assert!(!wam.fail);
} }
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.fail = false; wam.fail = false;
wam.heap.clear(); wam.heap.clear();
@@ -378,95 +450,119 @@ mod tests {
let term_write_result_2 = let term_write_result_2 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
unify!( unify!(
wam, wam,
heap_loc_as_cell!(term_write_result_1.heap_loc), heap_loc_as_cell!(term_write_result_1.focus),
heap_loc_as_cell!(term_write_result_2.heap_loc) heap_loc_as_cell!(term_write_result_2.focus)
); );
assert!(!wam.fail); assert!(!wam.fail);
} }
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear(); wam.heap.clear();
wam.heap.push(pstr_as_cell!(atom!("this is a string"))); let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(heap_loc_as_cell!(1));
wam.heap.push(pstr_as_cell!(atom!("this is a string"))); writer.write_with(|section| {
wam.heap.push(pstr_loc_as_cell!(4)); section.push_pstr("this is a string"); // 0
wam.heap.push(pstr_offset_as_cell!(0)); let h = section.cell_len();
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(6))); assert_eq!(h, 3);
unify!(wam, pstr_loc_as_cell!(0), pstr_loc_as_cell!(2)); section.push_cell(heap_loc_as_cell!(h)); // 3
section.push_pstr("this is a string"); // 4
let h = section.cell_len();
assert_eq!(h + 1, 8);
section.push_cell(pstr_loc_as_cell!(heap_index!(h + 1))); // 7
section.push_pstr("this is a string"); // 8
section.push_cell(pstr_loc_as_cell!(heap_index!(h + 1)));
});
unify!(wam, pstr_loc_as_cell!(0), pstr_loc_as_cell!(heap_index!(4)));
assert!(!wam.fail); assert!(!wam.fail);
assert_eq!(wam.heap[1], pstr_loc_as_cell!(4)); assert_eq!(wam.heap[3], pstr_loc_as_cell!(heap_index!(8)));
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear(); wam.heap.clear();
wam.heap.push(list_loc_as_cell!(1)); let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(atom_as_cell!(atom!("a")));
wam.heap.push(list_loc_as_cell!(3));
wam.heap.push(atom_as_cell!(atom!("b")));
wam.heap.push(heap_loc_as_cell!(0));
wam.heap.push(list_loc_as_cell!(6)); writer.write_with(|section| {
wam.heap.push(atom_as_cell!(atom!("a"))); section.push_cell(list_loc_as_cell!(1));
wam.heap.push(list_loc_as_cell!(8)); section.push_cell(atom_as_cell!(atom!("a")));
wam.heap.push(atom_as_cell!(atom!("b"))); section.push_cell(list_loc_as_cell!(3));
wam.heap.push(heap_loc_as_cell!(5)); section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(0));
section.push_cell(list_loc_as_cell!(6));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(8));
section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(5));
});
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5)); unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
assert!(!wam.fail); assert!(!wam.fail);
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear(); wam.heap.clear();
wam.heap.push(list_loc_as_cell!(1)); let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(atom_as_cell!(atom!("a")));
wam.heap.push(list_loc_as_cell!(3));
wam.heap.push(atom_as_cell!(atom!("b")));
wam.heap.push(heap_loc_as_cell!(0));
wam.heap.push(list_loc_as_cell!(6)); writer.write_with(|section| {
wam.heap.push(atom_as_cell!(atom!("a"))); section.push_cell(list_loc_as_cell!(1));
wam.heap.push(list_loc_as_cell!(8)); section.push_cell(atom_as_cell!(atom!("a")));
wam.heap.push(atom_as_cell!(atom!("c"))); section.push_cell(list_loc_as_cell!(3));
wam.heap.push(heap_loc_as_cell!(5)); section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(0));
section.push_cell(list_loc_as_cell!(6));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(8));
section.push_cell(atom_as_cell!(atom!("c")));
section.push_cell(heap_loc_as_cell!(5));
});
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5)); unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
assert!(wam.fail); assert!(wam.fail);
wam.fail = false; wam.fail = false;
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear(); wam.heap.clear();
wam.heap.push(list_loc_as_cell!(1)); let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(atom_as_cell!(atom!("a")));
wam.heap.push(list_loc_as_cell!(3));
wam.heap.push(atom_as_cell!(atom!("b")));
wam.heap.push(heap_loc_as_cell!(5));
wam.heap.push(list_loc_as_cell!(6)); writer.write_with(|section| {
wam.heap.push(atom_as_cell!(atom!("a"))); section.push_cell(list_loc_as_cell!(1));
wam.heap.push(list_loc_as_cell!(8)); section.push_cell(atom_as_cell!(atom!("a")));
wam.heap.push(atom_as_cell!(atom!("b"))); section.push_cell(list_loc_as_cell!(3));
wam.heap.push(heap_loc_as_cell!(0)); section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(5));
section.push_cell(list_loc_as_cell!(6));
section.push_cell(atom_as_cell!(atom!("a")));
section.push_cell(list_loc_as_cell!(8));
section.push_cell(atom_as_cell!(atom!("b")));
section.push_cell(heap_loc_as_cell!(0));
});
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5)); unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
assert!(!wam.fail); assert!(!wam.fail);
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
} }
#[test] #[test]
@@ -485,12 +581,12 @@ mod tests {
let term_write_result_2 = let term_write_result_2 =
parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap(); parse_and_write_parsed_term_to_heap(&mut wam, "f(A,f(A)).", &op_dir).unwrap();
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
unify_with_occurs_check!( unify_with_occurs_check!(
wam, wam,
heap_loc_as_cell!(0), heap_loc_as_cell!(0),
heap_loc_as_cell!(term_write_result_2.heap_loc) heap_loc_as_cell!(term_write_result_2.focus)
); );
assert!(wam.fail); assert!(wam.fail);
@@ -503,8 +599,15 @@ mod tests {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
wam.heap.push(heap_loc_as_cell!(0)); // clear the heap of resource error data etc
wam.heap.push(heap_loc_as_cell!(1)); wam.heap.clear();
let mut writer = wam.heap.reserve(96).unwrap();
writer.write_with(|section| {
section.push_cell(heap_loc_as_cell!(0));
section.push_cell(heap_loc_as_cell!(1));
});
assert_eq!( assert_eq!(
compare_term_test!(wam, wam.heap[0], wam.heap[1]), compare_term_test!(wam, wam.heap[0], wam.heap[1]),
@@ -526,11 +629,13 @@ mod tests {
Some(Ordering::Equal) Some(Ordering::Equal)
); );
let cstr_cell = wam.allocate_cstr("string").unwrap();
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(
wam, wam,
atom_as_cell!(atom!("atom")), atom_as_cell!(atom!("atom")),
atom_as_cstr_cell!(atom!("string")) cstr_cell
), ),
Some(Ordering::Less) Some(Ordering::Less)
); );
@@ -564,8 +669,12 @@ mod tests {
wam.heap.clear(); wam.heap.clear();
wam.heap.push(atom_as_cell!(atom!("f"), 1)); let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(heap_loc_as_cell!(1));
writer.write_with(|section| {
section.push_cell(atom_as_cell!(atom!("f"), 1));
section.push_cell(heap_loc_as_cell!(1));
});
assert_eq!( assert_eq!(
compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)), compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)),
@@ -579,21 +688,25 @@ mod tests {
wam.heap.clear(); wam.heap.clear();
// [1,2,3] let mut writer = wam.heap.reserve(96).unwrap();
wam.heap.push(list_loc_as_cell!(1));
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(1)));
wam.heap.push(list_loc_as_cell!(3));
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(2)));
wam.heap.push(list_loc_as_cell!(5));
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(3)));
wam.heap.push(empty_list_as_cell!());
// [1,2] writer.write_with(|section| {
wam.heap.push(list_loc_as_cell!(8)); // [1,2,3]
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(1))); section.push_cell(list_loc_as_cell!(1));
wam.heap.push(list_loc_as_cell!(10)); section.push_cell(fixnum_as_cell!(Fixnum::build_with(1)));
wam.heap.push(fixnum_as_cell!(Fixnum::build_with(2))); section.push_cell(list_loc_as_cell!(3));
wam.heap.push(empty_list_as_cell!()); section.push_cell(fixnum_as_cell!(Fixnum::build_with(2)));
section.push_cell(list_loc_as_cell!(5));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(3)));
section.push_cell(empty_list_as_cell!());
// [1,2]
section.push_cell(list_loc_as_cell!(8));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(1)));
section.push_cell(list_loc_as_cell!(10));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(2)));
section.push_cell(empty_list_as_cell!());
});
assert_eq!( assert_eq!(
compare_term_test!(wam, heap_loc_as_cell!(7), heap_loc_as_cell!(7)), compare_term_test!(wam, heap_loc_as_cell!(7), heap_loc_as_cell!(7)),
@@ -619,11 +732,13 @@ mod tests {
Some(Ordering::Greater) Some(Ordering::Greater)
); );
let cstr_cell = wam.allocate_cstr("string").unwrap();
assert_eq!( assert_eq!(
compare_term_test!( compare_term_test!(
wam, wam,
empty_list_as_cell!(), empty_list_as_cell!(),
atom_as_cstr_cell!(atom!("string")) cstr_cell
), ),
Some(Ordering::Less) Some(Ordering::Less)
); );
@@ -655,55 +770,66 @@ mod tests {
fn is_cyclic_term_tests() { fn is_cyclic_term_tests() {
let mut wam = MachineState::new(); let mut wam = MachineState::new();
assert!(!wam.is_cyclic_term(atom_as_cell!(atom!("f")))); let mut writer = wam.heap.reserve(96).unwrap();
assert!(!wam.is_cyclic_term(fixnum_as_cell!(Fixnum::build_with(555))));
wam.heap.push(heap_loc_as_cell!(0)); writer.write_with(|section| {
section.push_cell(atom_as_cell!(atom!("f")));
section.push_cell(fixnum_as_cell!(Fixnum::build_with(555)));
section.push_cell(heap_loc_as_cell!(0));
});
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(0))); assert!(!wam.is_cyclic_term(0));
assert!(!wam.is_cyclic_term(1));
assert!(!wam.is_cyclic_term(2));
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear(); wam.heap.clear();
wam.heap let mut functor_writer = Heap::functor_writer(
.extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))])); functor!(
atom!("f"),
[atom_as_cell((atom!("a"))),
atom_as_cell((atom!("b")))]
),
);
assert!(!wam.is_cyclic_term(str_loc_as_cell!(0))); functor_writer(&mut wam.heap).unwrap();
all_cells_unmarked(&wam.heap); let h = wam.heap.cell_len();
wam.heap.push_cell(str_loc_as_cell!(0)).unwrap();
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(1))); assert!(!wam.is_cyclic_term(h));
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
assert!(!wam.is_cyclic_term(heap_loc_as_cell!(2))); assert!(!wam.is_cyclic_term(1));
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
assert!(!wam.is_cyclic_term(2));
all_cells_unmarked(wam.heap.splice(..));
wam.heap[2] = str_loc_as_cell!(0); wam.heap[2] = str_loc_as_cell!(0);
print_heap_terms(wam.heap.iter(), 0); print_heap_terms(wam.heap.iter(), 0);
assert!(wam.is_cyclic_term(str_loc_as_cell!(0))); assert!(wam.is_cyclic_term(2));
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
wam.heap[2] = atom_as_cell!(atom!("b")); wam.heap[2] = atom_as_cell!(atom!("b"));
wam.heap[1] = str_loc_as_cell!(0); wam.heap[1] = str_loc_as_cell!(0);
assert!(wam.is_cyclic_term(str_loc_as_cell!(0))); assert!(wam.is_cyclic_term(1));
all_cells_unmarked(&wam.heap); all_cells_unmarked(wam.heap.splice(..));
assert!(wam.is_cyclic_term(heap_loc_as_cell!(1)));
all_cells_unmarked(&wam.heap);
wam.heap.clear(); wam.heap.clear();
wam.heap.push(pstr_as_cell!(atom!("a string"))); let h = wam.heap.cell_len();
wam.heap.push(empty_list_as_cell!()); wam.allocate_cstr("a string").unwrap();
assert!(!wam.is_cyclic_term(pstr_loc_as_cell!(0))); assert!(!wam.is_cyclic_term(h));
} }
} }

View File

@@ -485,7 +485,10 @@ impl Machine {
#[inline(always)] #[inline(always)]
pub(crate) fn run_verify_attr_interrupt(&mut self, arity: usize) { pub(crate) fn run_verify_attr_interrupt(&mut self, arity: usize) {
let p = self.machine_st.attr_var_init.verify_attrs_loc; let p = self.machine_st.attr_var_init.verify_attrs_loc;
self.machine_st.verify_attr_interrupt(p, arity); step_or_resource_error!(
self.machine_st,
self.machine_st.verify_attr_interrupt(p, arity)
);
} }
fn next_clause_applicable(&mut self, mut offset: usize) -> bool { fn next_clause_applicable(&mut self, mut offset: usize) -> bool {
@@ -505,12 +508,11 @@ impl Machine {
s, s,
)) => { )) => {
cell = self.deref_register(arg); cell = self.deref_register(arg);
self.machine_st self.machine_st.select_switch_on_term_index(cell, v, c, l, s)
.select_switch_on_term_index(cell, v, c, l, s)
} }
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
let lit = self.machine_st.constant_to_literal(cell); // let lit = self.machine_st.constant_to_literal(cell);
hm.get(&lit).cloned().unwrap_or(IndexingCodePtr::Fail) hm.get(&cell).cloned().unwrap_or(IndexingCodePtr::Fail)
} }
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(hm)) => { IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(hm)) => {
self.machine_st.select_switch_on_structure_index(cell, hm) self.machine_st.select_switch_on_structure_index(cell, hm)
@@ -536,6 +538,7 @@ impl Machine {
if cell.is_var() { if cell.is_var() {
offset += 1; offset += 1;
/*
} else if lit.get_tag() == HeapCellValueTag::CStr { } else if lit.get_tag() == HeapCellValueTag::CStr {
read_heap_cell!(cell, read_heap_cell!(cell,
(HeapCellValueTag::CStr) => { (HeapCellValueTag::CStr) => {
@@ -562,8 +565,10 @@ impl Machine {
return false; return false;
} }
); );
*/
} else { } else {
self.machine_st.write_literal_to_var(cell, lit); unify!(self.machine_st, cell, lit);
// self.machine_st.write_literal_to_var(cell, lit);
if self.machine_st.fail { if self.machine_st.fail {
self.machine_st.fail = false; self.machine_st.fail = false;
@@ -577,7 +582,7 @@ impl Machine {
let cell = self.deref_register(t); let cell = self.deref_register(t);
read_heap_cell!(cell, read_heap_cell!(cell,
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => { (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {// | HeapCellValueTag::CStr) => {
offset += 1; offset += 1;
} }
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
@@ -618,25 +623,32 @@ impl Machine {
} }
&Instruction::GetPartialString( &Instruction::GetPartialString(
Level::Shallow, Level::Shallow,
string, ref string,
RegType::Temp(t), RegType::Temp(t),
has_tail, // has_tail,
) => { ) => {
use crate::machine::partial_string::HeapPStrIter;
let cell = self.deref_register(t); let cell = self.deref_register(t);
read_heap_cell!(cell, read_heap_cell!(cell,
(HeapCellValueTag::CStr, cstr) => { (HeapCellValueTag::PStrLoc) => {
if !has_tail && string != cstr { self.machine_st.heap[0] = cell;
let iter = HeapPStrIter::new(&self.machine_st.heap, 0);
if iter.compare_pstr_to_string(&string).is_none() {
return false; return false;
} }
offset += 1; offset += 1;
} }
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => { (HeapCellValueTag::Lis) => {
offset += 1; offset += 1;
} }
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity(); let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
.get_name_and_arity();
if name == atom!(".") && arity == 2 { if name == atom!(".") && arity == 2 {
offset += 1; offset += 1;
@@ -759,7 +771,7 @@ impl Machine {
or_frame.prelude.boip = 0; or_frame.prelude.boip = 0;
or_frame.prelude.biip = 0; or_frame.prelude.biip = 0;
or_frame.prelude.tr = self.machine_st.tr; or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len(); or_frame.prelude.h = self.machine_st.heap.cell_len();
or_frame.prelude.b0 = self.machine_st.b0; or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len = or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len(); self.machine_st.attr_var_init.attr_var_queue.len();
@@ -770,7 +782,7 @@ impl Machine {
or_frame[i] = self.machine_st.registers[i + 1]; or_frame[i] = self.machine_st.registers[i + 1];
} }
self.machine_st.hb = self.machine_st.heap.len(); self.machine_st.hb = self.machine_st.heap.cell_len();
} }
self.machine_st.p += 1; self.machine_st.p += 1;
@@ -791,7 +803,7 @@ impl Machine {
or_frame.prelude.boip = self.machine_st.oip; or_frame.prelude.boip = self.machine_st.oip;
or_frame.prelude.biip = self.machine_st.iip + iip_offset; // 1 or_frame.prelude.biip = self.machine_st.iip + iip_offset; // 1
or_frame.prelude.tr = self.machine_st.tr; or_frame.prelude.tr = self.machine_st.tr;
or_frame.prelude.h = self.machine_st.heap.len(); or_frame.prelude.h = self.machine_st.heap.cell_len();
or_frame.prelude.b0 = self.machine_st.b0; or_frame.prelude.b0 = self.machine_st.b0;
or_frame.prelude.attr_var_queue_len = or_frame.prelude.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len(); self.machine_st.attr_var_init.attr_var_queue.len();
@@ -802,7 +814,7 @@ impl Machine {
or_frame[i] = self.machine_st.registers[i + 1]; or_frame[i] = self.machine_st.registers[i + 1];
} }
self.machine_st.hb = self.machine_st.heap.len(); self.machine_st.hb = self.machine_st.heap.cell_len();
// self.machine_st.oip = 0; // self.machine_st.oip = 0;
// self.machine_st.iip = 0; // self.machine_st.iip = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ use crate::codegen::CodeGenSettings;
use crate::forms::*; use crate::forms::*;
use crate::instructions::*; use crate::instructions::*;
use crate::machine::disjuncts::*; use crate::machine::disjuncts::*;
use crate::machine::heap::*;
use crate::machine::loader::*; use crate::machine::loader::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::CodeIndex; use crate::machine::CodeIndex;
@@ -27,25 +28,42 @@ pub(crate) fn to_op_decl_spec(spec: Atom) -> Result<OpDeclSpec, CompilationError
fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> { fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
let (focus, _cell) = subterm_index(term.heap, term.focus); let (focus, _cell) = subterm_index(term.heap, term.focus);
let name = match term.name(focus+3) { let name = match term_predicate_key(term.heap, focus+3) {
Some(name) => name, Some((name, 0)) => name,
None => return Err(CompilationError::InconsistentEntry), _ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclNameType(term.heap[focus+3]),
));
}
}; };
let spec = match term.name(focus+2) { let spec = match term_predicate_key(term.heap, focus+2) {
Some(name) => name, Some((name, _)) => name,
None => return Err(CompilationError::InconsistentEntry), None => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclSpecDomain(term.heap[focus+2]),
));
}
}; };
let prec = read_heap_cell!(term.deref_loc(focus+1), let spec = to_op_decl_spec(spec)?;
let prec = term.deref_loc(focus+1);
let prec = read_heap_cell!(prec,
(HeapCellValueTag::Fixnum, n) => { (HeapCellValueTag::Fixnum, n) => {
match u16::try_from(n.get_num()) { match u16::try_from(n.get_num()) {
Ok(n) if n <= 1200 => n, Ok(n) if n <= 1200 => n,
_ => return Err(CompilationError::InconsistentEntry), _ => {
return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecDomain(n),
));
}
} }
} }
_ => { _ => {
return Err(CompilationError::InconsistentEntry); return Err(CompilationError::InvalidDirective(
DirectiveError::InvalidOpDeclPrecType(prec),
));
} }
); );
@@ -71,10 +89,9 @@ fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
} }
fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, CompilationError> { fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, CompilationError> {
let name_opt = term.name(term.focus); let key_opt = term_predicate_key(term.heap, term.focus);
let arity = term.arity(term.focus);
if let (Some(atom!("/") | atom!("//")), 2) = (name_opt, arity) { if let Some((atom!("/") | atom!("//"), 2)) = key_opt {
let arity_loc = term.nth_arg(term.focus, 2).unwrap(); let arity_loc = term.nth_arg(term.focus, 2).unwrap();
let arity = match Number::try_from(term.deref_loc(arity_loc)) { let arity = match Number::try_from(term.deref_loc(arity_loc)) {
@@ -85,11 +102,11 @@ fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, C
.ok_or(CompilationError::InvalidModuleExport)?; .ok_or(CompilationError::InvalidModuleExport)?;
let name_loc = term.nth_arg(term.focus, 1).unwrap(); let name_loc = term.nth_arg(term.focus, 1).unwrap();
let name = term let name = term_predicate_key(term.heap, name_loc)
.name(name_loc) .map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleExport)?; .ok_or(CompilationError::InvalidModuleExport)?;
if name_opt == Some(atom!("/")) { if matches!(key_opt, Some((atom!("/"), _))) {
Ok((name, arity)) Ok((name, arity))
} else { } else {
Ok((name, arity + 2)) Ok((name, arity + 2))
@@ -103,10 +120,9 @@ fn setup_module_export(term: &FocusedHeapRefMut) -> Result<ModuleExport, Compila
setup_predicate_indicator(term) setup_predicate_indicator(term)
.map(ModuleExport::PredicateKey) .map(ModuleExport::PredicateKey)
.or_else(|_| { .or_else(|_| {
let name_opt = term.name(term.focus); let key_opt = term_predicate_key(term.heap, term.focus);
let arity = term.arity(term.focus);
if let (Some(atom!("op")), 3) = (name_opt, arity) { if let Some((atom!("op"), 3)) = key_opt {
Ok(ModuleExport::OpDecl(setup_op_decl(term)?)) Ok(ModuleExport::OpDecl(setup_op_decl(term)?))
} else { } else {
Err(CompilationError::InvalidModuleDecl) Err(CompilationError::InvalidModuleDecl)
@@ -131,48 +147,46 @@ pub(super) fn setup_module_export_list(
let mut focus = term.focus; let mut focus = term.focus;
loop { loop {
read_heap_cell!(term.heap[focus], read_heap_cell!(term.heap[focus],
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h == focus { if h == focus {
break; break;
} else { } else {
focus = h; focus = h;
} }
} }
(HeapCellValueTag::Lis, l) => { (HeapCellValueTag::Lis, l) => {
let term = FocusedHeapRefMut { let term = FocusedHeapRefMut {
heap: term.heap, heap: term.heap,
focus: l, focus: l,
}; };
exports.push(setup_module_export(&term)?);
focus = l + 1; exports.push(setup_module_export(&term)?);
} focus = l + 1;
(HeapCellValueTag::Atom, (name, _arity)) => { }
if name == atom!("[]") { (HeapCellValueTag::Atom, (name, _arity)) => {
return Ok(exports); if name == atom!("[]") {
} else { return Ok(exports);
break; } else {
} break;
} }
_ => { }
break; _ => {
} break;
); }
);
} }
Err(CompilationError::InvalidModuleDecl) Err(CompilationError::InvalidModuleDecl)
} }
fn setup_module_decl(term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> { fn setup_module_decl(mut term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
let name = term let name = term_predicate_key(term.heap, term.focus + 1)
.name(term.focus + 1) .map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleDecl)?; .ok_or(CompilationError::InvalidModuleDecl)?;
let export_list = FocusedHeapRefMut {
heap: term.heap, term.focus = term.focus + 2;
focus: term.focus + 2, let exports = setup_module_export_list(term)?;
};
let exports = setup_module_export_list(export_list)?;
Ok(ModuleDecl { name, exports }) Ok(ModuleDecl { name, exports })
} }
@@ -224,8 +238,8 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
heap: term.heap, heap: term.heap,
focus, focus,
}; };
exports.insert(setup_module_export(&term)?);
exports.insert(setup_module_export(&term)?);
focus = focus + 1; focus = focus + 1;
} }
@@ -276,7 +290,7 @@ fn setup_qualified_import(term: FocusedHeapRefMut) -> Result<UseModuleExport, Co
*/ */
fn setup_meta_predicate<'a, LS: LoadState<'a>>( fn setup_meta_predicate<'a, LS: LoadState<'a>>(
term: FocusedHeapRefMut, term: TermWriteResult,
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> { ) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> {
fn get_meta_specs( fn get_meta_specs(
@@ -319,24 +333,27 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
Ok(meta_specs) Ok(meta_specs)
} }
read_heap_cell!(term.deref_loc(term.focus+1), let heap = loader.machine_heap();
let cell = heap_bound_store(heap, heap_bound_deref(heap, heap[term.focus+1]));
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(term.heap[s]).get_name_and_arity(); let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
match (name, arity) { match (name, arity) {
(atom!(":"), 2) => { (atom!(":"), 2) => {
let module_name = term.heap[s+1]; let module_name = heap[s+1];
let spec = term.heap[s+2]; let spec = heap[s+2];
read_heap_cell!(module_name, read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => { (HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 { if arity == 0 {
read_heap_cell!(spec, read_heap_cell!(spec,
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(term.heap[s]) let (name, arity) = cell_as_atom_cell!(heap[s])
.get_name_and_arity(); .get_name_and_arity();
let term = FocusedHeapRefMut { heap: term.heap, focus: s }; let term = FocusedHeapRefMut { heap, focus: s };
return Ok((module_name, name, get_meta_specs(term, arity)?)); return Ok((module_name, name, get_meta_specs(term, arity)?));
} }
_ => { _ => {
@@ -351,9 +368,11 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
); );
} }
_ => { _ => {
let term = FocusedHeapRefMut { heap: term.heap, focus: s }; let term = FocusedHeapRefMut { heap, focus: s };
let specs = get_meta_specs(term, arity)?;
let module_name = loader.payload.compilation_target.module_name(); let module_name = loader.payload.compilation_target.module_name();
return Ok((module_name, name, get_meta_specs(term, arity)?));
return Ok((module_name, name, specs));
} }
} }
@@ -367,38 +386,41 @@ fn setup_meta_predicate<'a, LS: LoadState<'a>>(
pub(super) fn setup_declaration<'a, LS: LoadState<'a>>( pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
term: FocusedHeapRefMut, mut term: TermWriteResult,
) -> Result<Declaration, CompilationError> { ) -> Result<Declaration, CompilationError> {
let mut focus = term.focus; let mut focus = term.focus;
let machine_st = LS::machine_st(&mut loader.payload);
loop { loop {
read_heap_cell!(term.heap[focus], let decl = machine_st.heap[focus];
read_heap_cell!(decl,
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
let term = FocusedHeapRefMut { heap: term.heap, focus }; let mut focused = FocusedHeapRefMut::from(&mut machine_st.heap, focus);
return match (name, arity) { return match (name, arity) {
(atom!("dynamic"), 1) => { (atom!("dynamic"), 1) => {
let (name, arity) = setup_predicate_indicator(&term)?; let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::Dynamic(name, arity)) Ok(Declaration::Dynamic(name, arity))
} }
(atom!("module"), 2) => { (atom!("module"), 2) => {
Ok(Declaration::Module(setup_module_decl(term)?)) Ok(Declaration::Module(setup_module_decl(focused)?))
} }
(atom!("op"), 3) => { (atom!("op"), 3) => {
Ok(Declaration::Op(setup_op_decl(&term)?)) Ok(Declaration::Op(setup_op_decl(&focused)?))
} }
(atom!("non_counted_backtracking"), 1) => { (atom!("non_counted_backtracking"), 1) => {
let focus = term.nth_arg(term.focus, 1).unwrap(); focused.focus = focused.nth_arg(focused.focus, 1).unwrap();
let (name, arity) = setup_predicate_indicator(&FocusedHeapRefMut { heap: term.heap, focus })?; let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::NonCountedBacktracking(name, arity)) Ok(Declaration::NonCountedBacktracking(name, arity))
} }
(atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(&term)?)), (atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(&focused)?)),
(atom!("use_module"), 2) => { (atom!("use_module"), 2) => {
let (name, exports) = setup_qualified_import(term)?; let (name, exports) = setup_qualified_import(focused)?;
Ok(Declaration::UseQualifiedModule(name, exports)) Ok(Declaration::UseQualifiedModule(name, exports))
} }
(atom!("meta_predicate"), 1) => { (atom!("meta_predicate"), 1) => {
term.focus = focus;
let (module_name, name, meta_specs) = setup_meta_predicate(term, loader)?; let (module_name, name, meta_specs) = setup_meta_predicate(term, loader)?;
Ok(Declaration::MetaPredicate(module_name, name, meta_specs)) Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
} }
@@ -415,13 +437,13 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
focus = h; focus = h;
} else { } else {
return Err(CompilationError::InvalidDirective( return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(heap_loc_as_cell!(h)), DirectiveError::ExpectedDirective(decl),
)); ));
} }
} }
_ => { _ => {
return Err(CompilationError::InvalidDirective( return Err(CompilationError::InvalidDirective(
DirectiveError::ExpectedDirective(term.heap[focus]) DirectiveError::ExpectedDirective(decl),
)); ));
} }
); );
@@ -432,41 +454,44 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
module_name: Atom, module_name: Atom,
arity: usize, arity: usize,
term: &FocusedHeapRefMut, term: &TermWriteResult,
meta_specs: Vec<MetaSpec>, meta_specs: Vec<MetaSpec>,
) -> IndexMap<usize, CodeIndex, FxBuildHasher> { ) -> IndexMap<usize, CodeIndex, FxBuildHasher> {
use crate::machine::heap::Heap;
let mut index_ptrs = IndexMap::with_hasher(FxBuildHasher::default()); let mut index_ptrs = IndexMap::with_hasher(FxBuildHasher::default());
for (subterm_loc, meta_spec) in (term.focus + 1..term.focus + arity + 1).zip(meta_specs) { for (subterm_loc, meta_spec) in (term.focus + 1..term.focus + arity + 1).zip(meta_specs) {
if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec { if let MetaSpec::RequiresExpansionWithArgument(supp_args) = meta_spec {
if let Some(name) = term.name(subterm_loc) { let predicate_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
if let Some((name, arity)) = predicate_key_opt {
if name == atom!("$call") { if name == atom!("$call") {
continue; continue;
} }
let arity = term.arity(subterm_loc);
struct QualifiedNameInfo { struct QualifiedNameInfo {
module_name: Atom, module_name: Atom,
name: Atom, name: Atom,
arity: usize,
qualified_term_loc: usize, qualified_term_loc: usize,
} }
fn get_qualified_name( fn get_qualified_name(
term: &FocusedHeapRefMut, heap: &Heap,
module_term_loc: usize, module_term_loc: usize,
qualified_term_loc: usize, qualified_term_loc: usize,
) -> Option<QualifiedNameInfo> { ) -> Option<QualifiedNameInfo> {
let (module_term_loc, _) = subterm_index(term.heap, module_term_loc); let (module_term_loc, _) = subterm_index(heap, module_term_loc);
let (qualified_term_loc, _) = subterm_index(term.heap, qualified_term_loc); let (qualified_term_loc, _) = subterm_index(heap, qualified_term_loc);
read_heap_cell!(term.heap[module_term_loc], read_heap_cell!(heap[module_term_loc],
(HeapCellValueTag::Atom, (module_name, arity)) => { (HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 { if arity == 0 {
if let Some(name) = term.name(qualified_term_loc) { if let Some((name, arity)) = term_predicate_key(heap, qualified_term_loc) {
return Some(QualifiedNameInfo { return Some(QualifiedNameInfo {
module_name, module_name,
name, name,
arity,
qualified_term_loc, qualified_term_loc,
}); });
} }
@@ -478,23 +503,20 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
None None
} }
let (subterm_loc, _) = subterm_index(term.heap, subterm_loc); let (subterm_loc, _) = subterm_index(loader.machine_heap(), subterm_loc);
let subterm_key_opt = term_predicate_key(loader.machine_heap(), subterm_loc);
let subterm_arity = term.arity(subterm_loc);
let subterm_name_opt = term.name(subterm_loc);
let (module_name, key, term_loc) = let (module_name, key, term_loc) =
if subterm_name_opt == Some(atom!(":")) && subterm_arity == 2 { if subterm_key_opt == Some((atom!(":"), 2)) {
debug_assert_eq!(term.heap[subterm_loc].get_tag(), HeapCellValueTag::Atom); match get_qualified_name(loader.machine_heap(), subterm_loc + 1, subterm_loc + 2) {
match get_qualified_name(term, subterm_loc + 1, subterm_loc + 2) {
Some(QualifiedNameInfo { Some(QualifiedNameInfo {
module_name, module_name,
name, name,
arity,
qualified_term_loc, qualified_term_loc,
}) => ( }) => (
module_name, module_name,
(name, term.arity(qualified_term_loc) + supp_args), (name, arity + supp_args),
qualified_term_loc, qualified_term_loc,
), ),
None => { None => {
@@ -505,7 +527,7 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
(module_name, (name, arity + supp_args), subterm_loc) (module_name, (name, arity + supp_args), subterm_loc)
}; };
if let Some(index_ptr) = fetch_index_ptr(term.heap, key.1, term_loc) { if let Some(index_ptr) = fetch_index_ptr(loader.machine_heap(), key.1, term_loc) {
index_ptrs.insert(term_loc, index_ptr); index_ptrs.insert(term_loc, index_ptr);
continue; continue;
} }
@@ -525,13 +547,13 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>(
pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>( pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
key: PredicateKey, key: PredicateKey,
terms: FocusedHeapRefMut, terms: &TermWriteResult,
term: HeapCellValue, term: HeapCellValue,
call_policy: CallPolicy, call_policy: CallPolicy,
) -> QueryClause { ) -> QueryClause {
// supplementary code vector indices are unnecessary for // supplementary code vector indices are unnecessary for
// root-level clauses. // root-level clauses.
blunt_index_ptr(terms.heap, key, terms.focus); blunt_index_ptr(loader.machine_heap(), key, terms.focus);
let mut ct = loader.get_clause_type(key.0, key.1); let mut ct = loader.get_clause_type(key.0, key.1);
@@ -539,11 +561,10 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() { if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name(); let module_name = loader.payload.compilation_target.module_name();
let code_indices = let code_indices =
build_meta_predicate_clause(loader, module_name, arity, &terms, meta_specs); build_meta_predicate_clause(loader, module_name, arity, terms, meta_specs);
return QueryClause { return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx), ct: ClauseType::Named(key.1, key.0, idx),
arity,
term, term,
code_indices, code_indices,
call_policy, call_policy,
@@ -555,7 +576,6 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
QueryClause { QueryClause {
ct, ct,
arity: key.1,
term, term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()), code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy, call_policy,
@@ -567,13 +587,13 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
key: PredicateKey, key: PredicateKey,
module_name: Atom, module_name: Atom,
terms: FocusedHeapRefMut, terms: &TermWriteResult,
term: HeapCellValue, term: HeapCellValue,
call_policy: CallPolicy, call_policy: CallPolicy,
) -> QueryClause { ) -> QueryClause {
// supplementary code vector indices are unnecessary for // supplementary code vector indices are unnecessary for
// root-level clauses. // root-level clauses.
blunt_index_ptr(terms.heap, key, terms.focus); blunt_index_ptr(loader.machine_heap(), key, terms.focus);
let mut ct = loader.get_qualified_clause_type(module_name, key.0, key.1); let mut ct = loader.get_qualified_clause_type(module_name, key.0, key.1);
@@ -584,7 +604,6 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
return QueryClause { return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx), ct: ClauseType::Named(key.1, key.0, idx),
arity,
term, term,
code_indices, code_indices,
call_policy, call_policy,
@@ -596,7 +615,6 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>(
QueryClause { QueryClause {
ct, ct,
arity: key.1,
term, term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()), code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy, call_policy,
@@ -613,15 +631,18 @@ impl Preprocessor {
Preprocessor { settings } Preprocessor { settings }
} }
pub fn setup_fact( pub fn setup_fact<'a, LS: LoadState<'a>>(
&mut self, &mut self,
mut term: FocusedHeap, loader: &mut Loader<'a, LS>,
term: TermWriteResult,
) -> Result<(Fact, VarData), CompilationError> { ) -> Result<(Fact, VarData), CompilationError> {
if term.name(term.focus).is_some() { let heap = loader.machine_heap();
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let var_data = classifier.classify_fact(&mut term)?;
Ok((Fact { term }, var_data)) if term_predicate_key(heap, term.focus).is_some() {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
let var_data = classifier.classify_fact(loader, &term)?;
Ok((Fact { term_loc: term.focus }, var_data))
} else { } else {
Err(CompilationError::InadmissibleFact) Err(CompilationError::InadmissibleFact)
} }
@@ -630,14 +651,16 @@ impl Preprocessor {
fn setup_rule<'a, LS: LoadState<'a>>( fn setup_rule<'a, LS: LoadState<'a>>(
&mut self, &mut self,
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
mut term: FocusedHeap, term: TermWriteResult,
) -> Result<(Rule, VarData), CompilationError> { ) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new(self.settings.default_call_policy()); let classifier = VariableClassifier::new(self.settings.default_call_policy());
let (clauses, var_data) = classifier.classify_rule(loader, &mut term)?; let (clauses, var_data) = classifier.classify_rule(loader, &term)?;
let head_loc = term.nth_arg(term.focus, 1).unwrap();
if term.name(head_loc).is_some() { let heap = loader.machine_heap();
Ok((Rule { term, clauses }, var_data)) let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
if term_predicate_key(heap, head_loc).is_some() {
Ok((Rule { term_loc: term.focus, clauses }, var_data))
} else { } else {
Err(CompilationError::InvalidRuleHead) Err(CompilationError::InvalidRuleHead)
} }
@@ -646,19 +669,18 @@ impl Preprocessor {
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>( pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
&mut self, &mut self,
loader: &mut Loader<'a, LS>, loader: &mut Loader<'a, LS>,
term: FocusedHeap, term: TermWriteResult,
) -> Result<TopLevel, CompilationError> { ) -> Result<PredicateClause, CompilationError> {
let name = term.name(term.focus); let heap = &LS::machine_st(&mut loader.payload).heap;
let arity = term.arity(term.focus);
match (name, arity) { match term_predicate_key(heap, term.focus) {
(Some(atom!(":-")), 2) => { Some((atom!(":-"), 2)) => {
let (rule, var_data) = self.setup_rule(loader, term)?; let (rule, var_data) = self.setup_rule(loader, term)?;
Ok(TopLevel::Rule(rule, var_data)) Ok(PredicateClause::Rule(rule, var_data))
} }
_ => { _ => {
let (fact, var_data) = self.setup_fact(term)?; let (fact, var_data) = self.setup_fact(loader, term)?;
Ok(TopLevel::Fact(fact, var_data)) Ok(PredicateClause::Fact(fact, var_data))
} }
} }
} }

View File

@@ -1,12 +1,12 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::functor_macro::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::char_reader::*; use crate::parser::char_reader::*;
use crate::read::*; use crate::read::*;
#[cfg(feature = "http")] #[cfg(feature = "http")]
use crate::http::HttpResponse; use crate::http::HttpResponse;
use crate::machine::heap::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::machine_state::*; use crate::machine::machine_state::*;
@@ -476,7 +476,7 @@ impl StreamOptions {
#[inline] #[inline]
pub fn get_alias(self) -> Option<Atom> { pub fn get_alias(self) -> Option<Atom> {
if self.has_alias() { if self.has_alias() {
Some(Atom::from(self.alias() << 3)) Some(Atom::from(self.alias()))
} else { } else {
None None
} }
@@ -487,7 +487,7 @@ impl StreamOptions {
self.set_has_alias(alias.is_some()); self.set_has_alias(alias.is_some());
if let Some(alias) = alias { if let Some(alias) = alias {
self.set_alias(alias.flat_index()); self.set_alias(alias.index);
} }
} }
} }
@@ -1953,7 +1953,7 @@ impl MachineState {
let err = self.permission_error( let err = self.permission_error(
Permission::Open, Permission::Open,
atom!("source_sink"), atom!("source_sink"),
functor!(atom!("alias"), [atom(alias)]), functor!(atom!("alias"), [atom_as_cell(alias)]),
); );
self.error_form(err, stub) self.error_form(err, stub)
@@ -1961,7 +1961,7 @@ impl MachineState {
pub(crate) fn reposition_error(&mut self, stub_name: Atom, stub_arity: usize) -> MachineStub { pub(crate) fn reposition_error(&mut self, stub_name: Atom, stub_arity: usize) -> MachineStub {
let stub = functor_stub(stub_name, stub_arity); let stub = functor_stub(stub_name, stub_arity);
let rep_stub = functor!(atom!("reposition"), [atom(atom!("true"))]); let rep_stub = functor!(atom!("reposition"), [atom_as_cell((atom!("true")))]);
let err = self.permission_error(Permission::Open, atom!("source_sink"), rep_stub); let err = self.permission_error(Permission::Open, atom!("source_sink"), rep_stub);
self.error_form(err, stub) self.error_form(err, stub)

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@ use crate::machine::loader::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::*; use crate::machine::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::lexer::*;
use crate::parser::parser::*; use crate::parser::parser::*;
use crate::read::devour_whitespace; use crate::read::devour_whitespace;
@@ -20,11 +21,11 @@ pub struct LoadStatePayload<TS> {
pub(super) module_op_exports: ModuleOpExports, pub(super) module_op_exports: ModuleOpExports,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey, FxBuildHasher>, pub(super) non_counted_bt_preds: IndexSet<PredicateKey, FxBuildHasher>,
pub(super) predicates: PredicateQueue, pub(super) predicates: PredicateQueue,
pub(super) clause_clauses: Vec<FocusedHeap>, pub(super) clause_clauses: Vec<TermWriteResult>,
} }
pub trait TermStream: Sized { pub trait TermStream: Sized {
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<FocusedHeap, CompilationError>; fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError>;
fn eof(&mut self) -> Result<bool, CompilationError>; fn eof(&mut self) -> Result<bool, CompilationError>;
fn listing_src(&self) -> &ListingSource; fn listing_src(&self) -> &ListingSource;
} }
@@ -32,7 +33,7 @@ pub trait TermStream: Sized {
#[derive(Debug)] #[derive(Debug)]
pub struct BootstrappingTermStream<'a> { pub struct BootstrappingTermStream<'a> {
listing_src: ListingSource, listing_src: ListingSource,
pub(super) parser: Parser<'a, Stream>, pub(super) lexer_parser: LexerParser<'a, Stream>,
} }
impl<'a> BootstrappingTermStream<'a> { impl<'a> BootstrappingTermStream<'a> {
@@ -42,26 +43,23 @@ impl<'a> BootstrappingTermStream<'a> {
machine_st: &'a mut MachineState, machine_st: &'a mut MachineState,
listing_src: ListingSource, listing_src: ListingSource,
) -> Self { ) -> Self {
let parser = Parser::new(stream, machine_st); let lexer_parser = LexerParser::new(stream, machine_st);
Self { Self { lexer_parser, listing_src }
parser,
listing_src,
}
} }
} }
impl<'a> TermStream for BootstrappingTermStream<'a> { impl<'a> TermStream for BootstrappingTermStream<'a> {
#[inline] #[inline]
fn next(&mut self, op_dir: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> { fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
self.parser.reset(); let result = self.lexer_parser.read_term(op_dir, Tokens::Default)
self.parser .map_err(CompilationError::from);
.read_term(op_dir, Tokens::Default)
.map_err(CompilationError::from) result
} }
#[inline] #[inline]
fn eof(&mut self) -> Result<bool, CompilationError> { fn eof(&mut self) -> Result<bool, CompilationError> {
devour_whitespace(&mut self.parser) // eliminate dangling comments before checking for EOF. devour_whitespace(&mut self.lexer_parser) // eliminate dangling comments before checking for EOF.
.map_err(CompilationError::from) .map_err(CompilationError::from)
} }
@@ -72,7 +70,7 @@ impl<'a> TermStream for BootstrappingTermStream<'a> {
} }
pub struct LiveTermStream { pub struct LiveTermStream {
pub(super) term_queue: VecDeque<FocusedHeap>, pub(super) term_queue: VecDeque<TermWriteResult>,
pub(super) listing_src: ListingSource, pub(super) listing_src: ListingSource,
} }
@@ -108,7 +106,7 @@ impl<TS> LoadStatePayload<TS> {
impl TermStream for LiveTermStream { impl TermStream for LiveTermStream {
#[inline] #[inline]
fn next(&mut self, _: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> { fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
Ok(self.term_queue.pop_front().unwrap()) Ok(self.term_queue.pop_front().unwrap())
} }
@@ -126,7 +124,7 @@ impl TermStream for LiveTermStream {
pub struct InlineTermStream {} pub struct InlineTermStream {}
impl TermStream for InlineTermStream { impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> { fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default()))) Err(CompilationError::from(ParserError::unexpected_eof(ParserErrorSrc::default())))
} }

View File

@@ -2,11 +2,9 @@ use crate::arena::*;
use crate::forms::*; use crate::forms::*;
use crate::heap_iter::{stackful_preorder_iter, NonListElider}; use crate::heap_iter::{stackful_preorder_iter, NonListElider};
use crate::machine::machine_state::*; use crate::machine::machine_state::*;
use crate::machine::partial_string::*;
use crate::machine::*; use crate::machine::*;
use crate::types::*; use crate::types::*;
use std::cmp::Ordering;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use derive_more::*; use derive_more::*;
@@ -14,6 +12,18 @@ use fxhash::FxBuildHasher;
use indexmap::IndexSet; use indexmap::IndexSet;
use num_order::NumOrd; use num_order::NumOrd;
impl MachineState {
pub(crate) fn partial_string_to_pdl(&mut self, pstr_loc: usize, l: usize) {
let (c, succ_cell) = self.heap.last_str_char_and_tail(pstr_loc);
self.pdl.push(heap_loc_as_cell!(l + 1));
self.pdl.push(succ_cell);
self.pdl.push(heap_loc_as_cell!(l));
self.pdl.push(char_as_cell!(c));
}
}
pub(crate) trait Unifier: DerefMut<Target = MachineState> { pub(crate) trait Unifier: DerefMut<Target = MachineState> {
fn unify_structure(&mut self, s1: usize, value: HeapCellValue) { fn unify_structure(&mut self, s1: usize, value: HeapCellValue) {
// s1 is the value of a STR cell. // s1 is the value of a STR cell.
@@ -82,8 +92,8 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = true; self.fail = true;
} }
} }
(HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr | HeapCellValueTag::PStr) => { (HeapCellValueTag::PStrLoc, l) => {
Self::unify_partial_string(self, list_loc_as_cell!(l1), value) Self::unify_partial_string(self, l, list_loc_as_cell!(l1))
} }
(HeapCellValueTag::AttrVar, h) => { (HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), list_loc_as_cell!(l1)); Self::bind(self, Ref::attr_var(h), list_loc_as_cell!(l1));
@@ -100,261 +110,40 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
); );
} }
fn unify_complete_string(&mut self, atom: Atom, value: HeapCellValue) { fn unify_partial_string(&mut self, pstr_loc: usize, value: HeapCellValue) {
if let Some(r) = value.as_var() { if let Some(r) = value.as_var() {
if atom == atom!("") { Self::bind(self, r, pstr_loc_as_cell!(pstr_loc));
Self::bind(self, r, atom_as_cell!(atom!("[]")));
} else {
Self::bind(self, r, atom_as_cstr_cell!(atom));
}
return;
}
read_heap_cell!(value,
(HeapCellValueTag::Atom, (cstr_atom, arity)) if atom == atom!("") => {
debug_assert_eq!(arity, 0);
self.fail = cstr_atom != atom!("[]");
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
if arity == 0 {
self.fail = atom == atom!("") && name != atom!("[]");
} else {
// this is intentionally the same policy for
// value.tag() == Lis and PStrLoc. they're not
// grouped together to allow for arity == 0.
Self::unify_partial_string(self, atom_as_cstr_cell!(atom), value);
if !self.pdl.is_empty() {
Self::unify_internal(self);
}
}
}
(HeapCellValueTag::CStr, cstr_atom) => {
self.fail = atom != cstr_atom;
}
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
Self::unify_partial_string(self, atom_as_cstr_cell!(atom), value);
if !self.pdl.is_empty() {
Self::unify_internal(self);
}
}
_ => {
self.fail = true;
}
);
}
// the return value of unify_partial_string is interpreted as
// follows:
//
// Some(None) -- the strings are equal, nothing to unify
// Some(Some(f2,f1)) -- prefixes equal, try to unify focus values f2, f1
// None -- prefixes not equal, unification fails
//
// d1's tag is assumed to be one of LIS, STR or PSTRLOC.
fn unify_partial_string(&mut self, value_1: HeapCellValue, value_2: HeapCellValue) {
if let Some(r) = value_2.as_var() {
Self::bind(self, r, value_1);
return; return;
} }
let machine_st = self.deref_mut(); let machine_st = self.deref_mut();
let s1 = machine_st.heap.len(); read_heap_cell!(value,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
.get_name_and_arity();
machine_st.heap.push(value_1); if name == atom!(".") && arity == 2 {
machine_st.heap.push(value_2); machine_st.partial_string_to_pdl(pstr_loc, s+1);
let mut pstr_iter1 = HeapPStrIter::new(&machine_st.heap, s1);
let mut pstr_iter2 = HeapPStrIter::new(&machine_st.heap, s1 + 1);
fn unify_sequence(
machine_st: &mut MachineState,
iter: PStrIteratee,
source_cell: HeapCellValue,
) -> bool {
match iter {
PStrIteratee::Char(focus, _) => {
machine_st.pdl.push(machine_st.heap[focus]);
machine_st.pdl.push(source_cell);
}
PStrIteratee::PStrSegment(focus, _, n) => {
read_heap_cell!(machine_st.heap[focus],
(HeapCellValueTag::CStr | HeapCellValueTag::PStr, pstr_atom) => {
if focus < machine_st.heap.len() - 2 {
machine_st.heap.pop();
machine_st.heap.pop();
}
if n == 0 {
let target_cell = match machine_st.heap[focus].get_tag() {
HeapCellValueTag::CStr => {
atom_as_cstr_cell!(pstr_atom)
}
HeapCellValueTag::PStr => {
pstr_loc_as_cell!(focus)
}
_ => {
unreachable!()
}
};
machine_st.pdl.push(target_cell);
machine_st.pdl.push(source_cell);
} else {
let h_len = machine_st.heap.len();
machine_st.heap.push(pstr_offset_as_cell!(focus));
machine_st.heap.push(fixnum_as_cell!(
Fixnum::build_with(n as i64)
));
machine_st.pdl.push(pstr_loc_as_cell!(h_len));
machine_st.pdl.push(source_cell);
}
return true;
}
(HeapCellValueTag::PStrOffset, pstr_loc) => {
let n0 = cell_as_fixnum!(machine_st.heap[focus+1])
.get_num() as usize;
if pstr_loc < machine_st.heap.len() - 2 {
machine_st.heap.pop();
machine_st.heap.pop();
}
if n == n0 {
machine_st.pdl.push(pstr_loc_as_cell!(focus));
machine_st.pdl.push(source_cell);
} else {
let h_len = machine_st.heap.len();
machine_st.heap.push(pstr_offset_as_cell!(pstr_loc));
machine_st.heap.push(fixnum_as_cell!(
Fixnum::build_with(n as i64)
));
machine_st.pdl.push(pstr_loc_as_cell!(h_len));
machine_st.pdl.push(source_cell);
}
return true;
}
_ => {
}
);
if focus < machine_st.heap.len() - 2 {
machine_st.heap.pop();
machine_st.heap.pop();
}
machine_st.pdl.push(machine_st.heap[focus]);
machine_st.pdl.push(source_cell);
return true;
}
}
false
}
match compare_pstr_prefixes(&mut pstr_iter1, &mut pstr_iter2) {
PStrCmpResult::Ordered(Ordering::Equal) => {}
PStrCmpResult::Ordered(Ordering::Less) => {
if pstr_iter2.focus.as_var().is_none() {
machine_st.fail = true;
} else { } else {
machine_st.pdl.push(empty_list_as_cell!());
machine_st.pdl.push(pstr_iter2.focus);
}
}
PStrCmpResult::Ordered(Ordering::Greater) => {
if pstr_iter1.focus.as_var().is_none() {
machine_st.fail = true; machine_st.fail = true;
} else {
machine_st.pdl.push(empty_list_as_cell!());
machine_st.pdl.push(pstr_iter1.focus);
} }
} }
continuable @ PStrCmpResult::FirstIterContinuable(iteratee) (HeapCellValueTag::Lis, l) => {
| continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => { machine_st.partial_string_to_pdl(pstr_loc, l);
if continuable.is_second_iter() { }
std::mem::swap(&mut pstr_iter1, &mut pstr_iter2); (HeapCellValueTag::PStrLoc, other_pstr_loc) => {
} let cmp_result = machine_st.heap.compare_pstr_segments(pstr_loc, other_pstr_loc);
let mut chars_iter = PStrCharsIter { if cmp_result.continue_pstr_compare(&mut machine_st.pdl).is_some() {
iter: pstr_iter1, debug_assert!(matches!(cmp_result, PStrSegmentCmpResult::Mismatch { .. }));
item: Some(iteratee), machine_st.fail = true;
};
let mut focus = pstr_iter2.focus;
'outer: {
while let Some(c) = chars_iter.peek() {
read_heap_cell!(focus,
(HeapCellValueTag::Lis, l) => {
let val = pstr_iter2.heap[l];
machine_st.pdl.push(val);
machine_st.pdl.push(char_as_cell!(c));
focus = pstr_iter2.heap[l+1];
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(pstr_iter2.heap[s])
.get_name_and_arity();
if name == atom!(".") && arity == 2 {
machine_st.pdl.push(pstr_iter2.heap[s+1]);
machine_st.pdl.push(char_as_cell!(c));
focus = pstr_iter2.heap[s+2];
} else {
machine_st.fail = true;
break 'outer;
}
}
(HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
unify_sequence(machine_st, chars_iter.item.unwrap(), focus);
return;
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if unify_sequence(machine_st, chars_iter.item.unwrap(), heap_loc_as_cell!(h)) {
return;
}
break 'outer;
}
_ => {
machine_st.fail = true;
break 'outer;
}
);
chars_iter.next();
}
chars_iter.iter.next();
machine_st.pdl.push(focus);
machine_st.pdl.push(chars_iter.iter.focus);
} }
} }
PStrCmpResult::Unordered => { _ => {
machine_st.pdl.push(pstr_iter1.focus); machine_st.fail = true;
machine_st.pdl.push(pstr_iter2.focus);
} }
} );
machine_st.heap.pop();
machine_st.heap.pop();
} }
fn unify_atom(&mut self, atom: Atom, value: HeapCellValue) { fn unify_atom(&mut self, atom: Atom, value: HeapCellValue) {
@@ -368,6 +157,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = !(arity == 0 && name == atom); self.fail = !(arity == 0 && name == atom);
} }
/*
(HeapCellValueTag::CStr, cstr_atom) if atom == atom!("[]") => { (HeapCellValueTag::CStr, cstr_atom) if atom == atom!("[]") => {
self.fail = cstr_atom != atom!(""); self.fail = cstr_atom != atom!("");
} }
@@ -378,6 +168,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = true; self.fail = true;
} }
} }
*/
(HeapCellValueTag::AttrVar, h) => { (HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), atom_as_cell!(atom)); Self::bind(self, Ref::attr_var(h), atom_as_cell!(atom));
} }
@@ -412,11 +203,13 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
self.fail = true; self.fail = true;
} }
} }
/*
(HeapCellValueTag::Char, c2) => { (HeapCellValueTag::Char, c2) => {
if c != c2 { if c != c2 {
self.fail = true; self.fail = true;
} }
} }
*/
(HeapCellValueTag::AttrVar, h) => { (HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), char_as_cell!(c)); Self::bind(self, Ref::attr_var(h), char_as_cell!(c));
} }
@@ -610,7 +403,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
tabu_list.insert((d1, d2)); tabu_list.insert((d1, d2));
} }
} }
(HeapCellValueTag::PStrLoc) => { (HeapCellValueTag::PStrLoc, l) => {
read_heap_cell!(d2, read_heap_cell!(d2,
(HeapCellValueTag::PStrLoc | (HeapCellValueTag::PStrLoc |
HeapCellValueTag::Lis | HeapCellValueTag::Lis |
@@ -619,8 +412,7 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
continue; continue;
} }
} }
(HeapCellValueTag::CStr | (HeapCellValueTag::AttrVar |
HeapCellValueTag::AttrVar |
HeapCellValueTag::Var | HeapCellValueTag::Var |
HeapCellValueTag::StackVar) => { HeapCellValueTag::StackVar) => {
} }
@@ -630,13 +422,14 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
} }
); );
Self::unify_partial_string(self, d1, d2); Self::unify_partial_string(self, l, d2);
if !self.fail && !d2.is_constant() { if !self.fail && !d2.is_constant() {
let d2 = self.store(d2); let d2 = self.store(d2);
tabu_list.insert((d1, d2)); tabu_list.insert((d1, d2));
} }
} }
/*
(HeapCellValueTag::CStr) => { (HeapCellValueTag::CStr) => {
read_heap_cell!(d2, read_heap_cell!(d2,
(HeapCellValueTag::AttrVar, h) => { (HeapCellValueTag::AttrVar, h) => {
@@ -667,15 +460,18 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
Self::unify_partial_string(self, d2, d1); Self::unify_partial_string(self, d2, d1);
} }
*/
(HeapCellValueTag::F64, f1) => { (HeapCellValueTag::F64, f1) => {
Self::unify_f64(self, f1, d2); Self::unify_f64(self, f1, d2);
} }
(HeapCellValueTag::Fixnum, n1) => { (HeapCellValueTag::Fixnum, n1) => {
Self::unify_fixnum(self, n1, d2); Self::unify_fixnum(self, n1, d2);
} }
/*
(HeapCellValueTag::Char, c1) => { (HeapCellValueTag::Char, c1) => {
Self::unify_char(self, c1, d2); Self::unify_char(self, c1, d2);
} }
*/
(HeapCellValueTag::Cons, ptr_1) => { (HeapCellValueTag::Cons, ptr_1) => {
Self::unify_constant(self, ptr_1, d2); Self::unify_constant(self, ptr_1, d2);
} }
@@ -709,12 +505,12 @@ fn bind_with_occurs_check<U: Unifier>(unifier: &mut U, r: Ref, value: HeapCellVa
let value = machine_st.store(MachineState::deref(machine_st, value)); let value = machine_st.store(MachineState::deref(machine_st, value));
if value.is_ref() && !value.is_stack_var() { if value.is_ref() && !value.is_stack_var() {
let root_loc = value.get_value() as usize; machine_st.heap[0] = value;
for cell in stackful_preorder_iter::<NonListElider>( for cell in stackful_preorder_iter::<NonListElider>(
&mut machine_st.heap, &mut machine_st.heap,
&mut machine_st.stack, &mut machine_st.stack,
root_loc, // value, 0,
) { ) {
let cell = unmark_cell_bits!(cell); let cell = unmark_cell_bits!(cell);

View File

@@ -1,15 +1,10 @@
/* A simple macro to count the arguments in a variadic list /* A simple macro to count the arguments in a variadic list
* of token trees. * of token trees.
*/ */
macro_rules! count_tt {
() => { 0 };
($odd:tt $($a:tt $b:tt)*) => { (count_tt!($($a)*) << 1) | 1 };
($($a:tt $even:tt)*) => { count_tt!($($a)*) << 1 };
}
macro_rules! char_as_cell { macro_rules! char_as_cell {
($c: expr) => { ($c: expr) => {
HeapCellValue::build_with(HeapCellValueTag::Char, $c as u64) HeapCellValue::from_bytes(AtomCell::new_char_inlined($c).into_bytes())
}; };
} }
@@ -45,31 +40,17 @@ macro_rules! empty_list_as_cell {
macro_rules! atom_as_cell { macro_rules! atom_as_cell {
($atom:expr) => { ($atom:expr) => {
HeapCellValue::from_bytes( HeapCellValue::from_bytes(AtomCell::build_with($atom.index, 0).into_bytes())
AtomCell::build_with($atom.flat_index(), 0, HeapCellValueTag::Atom).into_bytes(),
)
}; };
($atom:expr, $arity:expr) => { ($atom:expr, $arity:expr) => {
HeapCellValue::from_bytes( HeapCellValue::from_bytes(AtomCell::build_with($atom.index, $arity as u8).into_bytes())
AtomCell::build_with($atom.flat_index(), $arity as u16, HeapCellValueTag::Atom)
.into_bytes(),
)
};
}
macro_rules! cell_as_string {
($cell:expr) => {
PartialString::from(cell_as_atom!($cell))
}; };
} }
macro_rules! cell_as_atom { macro_rules! cell_as_atom {
($cell:expr) => {{ ($cell:expr) => {
let cell = AtomCell::from_bytes($cell.into_bytes()); AtomCell::from_bytes($cell.into_bytes()).get_name()
let name = (cell.get_index() as u64) << 3; };
Atom::from(name)
}};
} }
macro_rules! cell_as_atom_cell { macro_rules! cell_as_atom_cell {
@@ -91,26 +72,12 @@ macro_rules! cell_as_untyped_arena_ptr {
}; };
} }
macro_rules! pstr_as_cell {
($atom:expr) => {
HeapCellValue::from_bytes(
AtomCell::build_with($atom.flat_index(), 0, HeapCellValueTag::PStr).into_bytes(),
)
};
}
macro_rules! pstr_loc_as_cell { macro_rules! pstr_loc_as_cell {
($h:expr) => { ($h:expr) => {
HeapCellValue::build_with(HeapCellValueTag::PStrLoc, $h as u64) HeapCellValue::build_with(HeapCellValueTag::PStrLoc, $h as u64)
}; };
} }
macro_rules! pstr_offset_as_cell {
($h:expr) => {
HeapCellValue::build_with(HeapCellValueTag::PStrOffset, $h as u64)
};
}
macro_rules! list_loc_as_cell { macro_rules! list_loc_as_cell {
($h:expr) => { ($h:expr) => {
HeapCellValue::build_with(HeapCellValueTag::Lis, $h as u64) HeapCellValue::build_with(HeapCellValueTag::Lis, $h as u64)
@@ -186,36 +153,10 @@ macro_rules! untyped_arena_ptr_as_cell {
}; };
} }
macro_rules! atom_as_cstr_cell { macro_rules! stream_as_cell {
($atom:expr) => {{ ($ptr:expr) => {
let offset = $atom.flat_index(); raw_ptr_as_cell!($ptr.as_ptr())
};
HeapCellValue::from_bytes(
AtomCell::build_with(offset as u64, 0, HeapCellValueTag::CStr).into_bytes(),
)
}};
}
macro_rules! string_as_cstr_cell {
($ptr:expr) => {{
let atom: Atom = $ptr.into();
let offset = atom.flat_index();
HeapCellValue::from_bytes(
AtomCell::build_with(offset as u64, 0, HeapCellValueTag::CStr).into_bytes(),
)
}};
}
macro_rules! string_as_pstr_cell {
($ptr:expr) => {{
let atom: Atom = $ptr.into();
let offset = atom.flat_index();
HeapCellValue::from_bytes(
AtomCell::build_with(offset as u64, 0, HeapCellValueTag::PStr).into_bytes(),
)
}};
} }
macro_rules! cell_as_stream { macro_rules! cell_as_stream {
@@ -351,6 +292,7 @@ macro_rules! read_heap_cell_pat_body {
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}}; }};
/*
($cell:ident, PStr, $atom:ident, $code:expr) => {{ ($cell:ident, PStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell); let $atom = cell_as_atom!($cell);
#[allow(unused_braces)] #[allow(unused_braces)]
@@ -371,6 +313,7 @@ macro_rules! read_heap_cell_pat_body {
#[allow(unused_braces)] #[allow(unused_braces)]
$code $code
}}; }};
*/
($cell:ident, Fixnum, $value:ident, $code:expr) => {{ ($cell:ident, Fixnum, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes()); let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)] #[allow(unused_braces)]
@@ -437,119 +380,6 @@ macro_rules! read_heap_cell {
}); });
} }
macro_rules! functor {
($name:expr, [$($dt:ident($($value:expr),*)),+], [$($aux:ident),*]) => ({
{
#[allow(unused_variables, unused_mut)]
let mut addendum = Heap::new();
let arity: usize = count_tt!($($dt) +);
#[allow(unused_variables)]
let aux_lens: [usize; count_tt!($($aux) *)] = [$($aux.len()),*];
let mut result =
vec![ atom_as_cell!($name, arity as u16),
$(functor_term!( $dt($($value),*), arity, aux_lens, addendum ),)+ ];
$(
result.extend($aux.iter());
)*
result.extend(addendum.into_iter());
result
}
});
($name:expr, [$($dt:ident($($value:expr),*)),+]) => ({
{
let arity: usize = count_tt!($($dt) +);
#[allow(unused_variables, unused_mut)]
let mut addendum = Heap::new();
let mut result =
vec![ atom_as_cell!($name, arity as u16),
$(functor_term!( $dt($($value),*), arity, [], addendum ),)+ ];
result.extend(addendum.into_iter());
result
}
});
($name:expr) => ({
vec![ atom_as_cell!($name) ]
});
}
macro_rules! functor_term {
(str(0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
str_loc_as_cell!($arity + 1)
});
(str($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
let len: usize = $aux_lens[0 .. $e].iter().sum();
str_loc_as_cell!($arity + 1 + len)
});
(str($h:expr, 0), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
str_loc_as_cell!($arity + $h + 1)
});
(str($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
let len: usize = $aux_lens[0 .. $e].iter().sum();
str_loc_as_cell!($arity + $h + 1 + len)
});
(literal($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
HeapCellValue::from($e)
);
(integer($e:expr, $arena:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
HeapCellValue::arena_from(Number::arena_from($e, $arena), $arena)
);
(fixnum($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
fixnum_as_cell!(Fixnum::build_with($e as i64))
);
(indexing_code_ptr($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => ({
let stub =
match $e {
IndexingCodePtr::DynamicExternal(o) => functor!(atom!("dynamic_external"), [fixnum(o)]),
IndexingCodePtr::External(o) => functor!(atom!("external"), [fixnum(o)]),
IndexingCodePtr::Internal(o) => functor!(atom!("internal"), [fixnum(o)]),
IndexingCodePtr::Fail => {
vec![atom_as_cell!(atom!("fail"))]
},
};
let len: usize = $aux_lens.iter().sum();
let h = len + $arity + 1 + $addendum.len() + $h;
$addendum.extend(stub.into_iter());
str_loc_as_cell!(h)
});
(number($arena:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
HeapCellValue::from(($e, $arena))
);
(atom($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
atom_as_cell!($e)
);
(string($h:expr, $e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
let len: usize = $aux_lens.iter().sum();
let h = len + $arity + 1 + $addendum.len() + $h;
let cell = string_as_pstr_cell!($e);
$addendum.push(cell);
$addendum.push(empty_list_as_cell!());
heap_loc_as_cell!(h)
});
(boolean($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
if $e {
functor_term!(atom(atom!("true")), $arity, $aux_lens, $addendum)
} else {
functor_term!(atom(atom!("false")), $arity, $aux_lens, $addendum)
}
});
(cell($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
$e
);
}
macro_rules! compare_number_instr { macro_rules! compare_number_instr {
($cmp: expr, $at_1: expr, $at_2: expr) => {{ ($cmp: expr, $at_1: expr, $at_2: expr) => {{
$cmp.set_terms($at_1, $at_2); $cmp.set_terms($at_1, $at_2);
@@ -634,3 +464,44 @@ macro_rules! compare_term_test {
$machine_st.compare_term_test($var_comparison) $machine_st.compare_term_test($var_comparison)
}}; }};
} }
macro_rules! step_or_resource_error {
($machine_st:expr, $val:expr) => {{
match $val {
Ok(r) => r,
Err(err_loc) => {
$machine_st.throw_resource_error(err_loc);
return;
}
}
}};
($machine_st:expr, $val:expr, $fail:block) => {{
match $val {
Ok(r) => r,
Err(err_loc) => {
$machine_st.throw_resource_error(err_loc);
$fail
}
}
}};
}
macro_rules! resource_error_call_result {
($machine_st:expr, $val:expr) => {
step_or_resource_error!($machine_st, $val, {
return Err(vec![]); // TODO: return Ok(());
})
};
}
macro_rules! heap_index {
($idx:expr) => {
($idx) * std::mem::size_of::<HeapCellValue>()
};
}
macro_rules! cell_index {
($idx:expr) => {
(($idx) / std::mem::size_of::<HeapCellValue>())
};
}

View File

@@ -3,10 +3,8 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::forms::PredicateKey; use crate::forms::PredicateKey;
use crate::machine::copier::*;
use crate::machine::heap::*; use crate::machine::heap::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
use crate::types::*; use crate::types::*;
use std::fmt; use std::fmt;
@@ -14,11 +12,8 @@ use std::hash::Hash;
use std::io::{Error as IOError, ErrorKind}; use std::io::{Error as IOError, ErrorKind};
use std::ops::Neg; use std::ops::Neg;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
use std::vec::Vec; use std::vec::Vec;
use crate::parser::dashu::{Integer, Rational};
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
use indexmap::IndexMap; use indexmap::IndexMap;
use scryer_modular_bitfield::error::OutOfBounds; use scryer_modular_bitfield::error::OutOfBounds;
@@ -26,7 +21,7 @@ use scryer_modular_bitfield::prelude::*;
pub type Specifier = u32; pub type Specifier = u32;
pub const MAX_ARITY: usize = 1023; pub const MAX_ARITY: usize = 255;
#[allow(clippy::upper_case_acronyms)] #[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
@@ -143,7 +138,12 @@ pub const BTERM: u32 = 0x11000;
pub const NEGATIVE_SIGN: u32 = 0x0200; pub const NEGATIVE_SIGN: u32 = 0x0200;
macro_rules! fixnum { macro_rules! fixnum {
($wrapper:tt, $n:expr, $arena:expr) => { ($n:expr, $arena:expr) => {
Fixnum::build_with_checked($n)
.map(|n| fixnum_as_cell!(n))
.unwrap_or_else(|_| typed_arena_ptr_as_cell!(arena_alloc!(Integer::from($n), $arena) as TypedArenaPtr<Integer>))
};
($wrapper:ty, $n:expr, $arena:expr) => {
Fixnum::build_with_checked($n) Fixnum::build_with_checked($n)
.map(<$wrapper>::Fixnum) .map(<$wrapper>::Fixnum)
.unwrap_or_else(|_| <$wrapper>::Integer(arena_alloc!(Integer::from($n), $arena))) .unwrap_or_else(|_| <$wrapper>::Integer(arena_alloc!(Integer::from($n), $arena)))
@@ -272,50 +272,12 @@ impl fmt::Display for RegType {
} }
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum VarReg {
ArgAndNorm(RegType, usize),
Norm(RegType),
}
impl VarReg {
pub fn norm(self) -> RegType {
match self {
VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg,
}
}
}
impl fmt::Display for VarReg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
VarReg::Norm(RegType::Perm(reg)) => write!(f, "Y{}", reg),
VarReg::Norm(RegType::Temp(reg)) => write!(f, "X{}", reg),
VarReg::ArgAndNorm(RegType::Perm(reg), arg) => write!(f, "Y{} A{}", reg, arg),
VarReg::ArgAndNorm(RegType::Temp(reg), arg) => write!(f, "X{} A{}", reg, arg),
}
}
}
impl Default for VarReg {
fn default() -> Self {
VarReg::Norm(RegType::default())
}
}
macro_rules! temp_v { macro_rules! temp_v {
($x:expr) => { ($x:expr) => {
$crate::parser::ast::RegType::Temp($x) $crate::parser::ast::RegType::Temp($x)
}; };
} }
#[macro_export]
macro_rules! perm_v {
($x:expr) => {
$crate::parser::ast::RegType::Perm($x)
};
}
#[bitfield] #[bitfield]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct OpDesc { pub struct OpDesc {
@@ -410,7 +372,6 @@ pub fn default_op_dir() -> OpDir {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum ArithmeticError { pub enum ArithmeticError {
NonEvaluableFunctor(HeapCellValue, usize), NonEvaluableFunctor(HeapCellValue, usize),
UninstantiatedVar,
} }
#[derive(Debug, Copy, Clone, Default)] #[derive(Debug, Copy, Clone, Default)]
@@ -430,6 +391,7 @@ pub enum ParserError {
MissingQuote(ParserErrorSrc), MissingQuote(ParserErrorSrc),
NonPrologChar(ParserErrorSrc), NonPrologChar(ParserErrorSrc),
ParseBigInt(ParserErrorSrc), ParseBigInt(ParserErrorSrc),
ResourceError(ParserErrorSrc),
UnexpectedChar(char, ParserErrorSrc), UnexpectedChar(char, ParserErrorSrc),
// UnexpectedEOF, // UnexpectedEOF,
Utf8Error(ParserErrorSrc), Utf8Error(ParserErrorSrc),
@@ -447,6 +409,7 @@ impl ParserError {
| &ParserError::MissingQuote(err_src) | &ParserError::MissingQuote(err_src)
| &ParserError::NonPrologChar(err_src) | &ParserError::NonPrologChar(err_src)
| &ParserError::ParseBigInt(err_src) | &ParserError::ParseBigInt(err_src)
| &ParserError::ResourceError(err_src)
| &ParserError::UnexpectedChar(_, err_src) | &ParserError::UnexpectedChar(_, err_src)
| &ParserError::Utf8Error(err_src) => err_src, | &ParserError::Utf8Error(err_src) => err_src,
} }
@@ -475,6 +438,7 @@ impl ParserError {
ParserError::ParseBigInt(..) => atom!("cannot_parse_big_int"), ParserError::ParseBigInt(..) => atom!("cannot_parse_big_int"),
ParserError::UnexpectedChar(..) => atom!("unexpected_char"), ParserError::UnexpectedChar(..) => atom!("unexpected_char"),
ParserError::Utf8Error(..) => atom!("utf8_conversion_error"), ParserError::Utf8Error(..) => atom!("utf8_conversion_error"),
ParserError::ResourceError(..) => atom!("resource_error"),
} }
} }
@@ -492,29 +456,13 @@ impl ParserError {
} }
} }
} }
/*
impl From<lexical::Error> for ParserError { impl From<ParserErrorSrc> for ParserError {
fn from((e, err_src): (lexical::Error, ParserErrorSrc)) -> ParserError { fn from(err_src: ParserErrorSrc) -> ParserError {
ParserError::LexicalError(e, err_src) ParserError::LexicalError(err_src)
} }
} }
impl From<IOError> for ParserError {
fn from(e: IOError) -> ParserError {
ParserError::IO(e)
}
}
impl From<&IOError> for ParserError {
fn from(error: &IOError) -> ParserError {
if error.get_ref().filter(|e| e.is::<BadUtf8Error>()).is_some() {
ParserError::Utf8Error(0, 0)
} else {
ParserError::IO(error.kind().into())
}
}
}
*/
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct CompositeOpDir<'a, 'b> { pub struct CompositeOpDir<'a, 'b> {
pub primary_op_dir: Option<&'b OpDir>, pub primary_op_dir: Option<&'b OpDir>,
@@ -623,16 +571,16 @@ impl Neg for Fixnum {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] /*
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Literal { pub enum Literal {
Atom(Atom), Atom(Atom),
Char(char),
CodeIndex(CodeIndex), CodeIndex(CodeIndex),
Fixnum(Fixnum), Fixnum(Fixnum),
Integer(TypedArenaPtr<Integer>), Integer(TypedArenaPtr<Integer>),
Rational(TypedArenaPtr<Rational>), Rational(TypedArenaPtr<Rational>),
Float(F64Offset), Float(F64Offset),
String(Atom), String(Rc<String>),
} }
impl From<F64Ptr> for Literal { impl From<F64Ptr> for Literal {
@@ -648,7 +596,7 @@ impl fmt::Display for Literal {
Literal::Atom(ref atom) => { Literal::Atom(ref atom) => {
write!(f, "{}", atom.flat_index()) write!(f, "{}", atom.flat_index())
} }
Literal::Char(c) => write!(f, "'{}'", *c as u32), // Literal::Char(c) => write!(f, "'{}'", *c as u32),
Literal::CodeIndex(i) => write!(f, "{:x}", i.as_ptr() as u64), Literal::CodeIndex(i) => write!(f, "{:x}", i.as_ptr() as u64),
Literal::Fixnum(n) => write!(f, "{}", n.get_num()), Literal::Fixnum(n) => write!(f, "{}", n.get_num()),
Literal::Integer(ref n) => write!(f, "{}", n), Literal::Integer(ref n) => write!(f, "{}", n),
@@ -667,10 +615,14 @@ impl Literal {
} }
} }
} }
*/
pub type Var = Rc<String>; pub type Var = Rc<String>;
pub(crate) fn subterm_index(heap: &[HeapCellValue], subterm_loc: usize) -> (usize, HeapCellValue) { pub(crate) fn subterm_index(
heap: &impl SizedHeap,
subterm_loc: usize,
) -> (usize, HeapCellValue) {
let subterm = heap[subterm_loc]; let subterm = heap[subterm_loc];
if subterm.is_ref() { if subterm.is_ref() {
@@ -696,11 +648,12 @@ pub enum Term {
AnonVar, AnonVar,
Clause(Cell<RegType>, Atom, Vec<Term>), Clause(Cell<RegType>, Atom, Vec<Term>),
Cons(Cell<RegType>, Box<Term>, Box<Term>), Cons(Cell<RegType>, Box<Term>, Box<Term>),
Literal(Cell<RegType>, Literal), Literal(Cell<RegType>, HeapCellValue),
// Literal(Cell<RegType>, Literal),
// PartialString wraps a String in anticipation of it absorbing // PartialString wraps a String in anticipation of it absorbing
// other PartialString variants in as_partial_string. // other PartialString variants in as_partial_string.
PartialString(Cell<RegType>, String, Box<Term>), PartialString(Cell<RegType>, Rc<String>, Box<Term>),
CompleteString(Cell<RegType>, Atom), CompleteString(Cell<RegType>, Rc<String>),
Var(Cell<VarReg>, VarPtr), Var(Cell<VarReg>, VarPtr),
} }
@@ -714,8 +667,11 @@ impl Term {
pub fn name(&self) -> Option<Atom> { pub fn name(&self) -> Option<Atom> {
match self { match self {
&Term::Literal(_, Literal::Atom(ref atom)) | &Term::Clause(_, ref atom, ..) => { Term::Literal(_, cell) => {
Some(*atom) cell.to_atom()
}
&Term::Clause(_, atom, ..) => {
Some(atom)
} }
_ => None, _ => None,
} }
@@ -760,11 +716,11 @@ pub fn unfold_by_str(mut term: Term, s: Atom) -> Vec<Term> {
*/ */
pub(crate) fn fetch_index_ptr( pub(crate) fn fetch_index_ptr(
heap: &[HeapCellValue], heap: &impl SizedHeap,
arity: usize, arity: usize,
term_loc: usize, term_loc: usize,
) -> Option<CodeIndex> { ) -> Option<CodeIndex> {
if term_loc + arity + 1 >= heap.len() { if term_loc + arity + 1 >= heap.cell_len() || heap.pstr_at(term_loc + arity + 1) {
return None; return None;
} }
@@ -784,7 +740,7 @@ pub(crate) fn fetch_index_ptr(
} }
pub(crate) fn blunt_index_ptr( pub(crate) fn blunt_index_ptr(
heap: &mut [HeapCellValue], heap: &mut impl SizedHeapMut,
key: PredicateKey, key: PredicateKey,
term_loc: usize, term_loc: usize,
) -> bool { ) -> bool {
@@ -797,7 +753,7 @@ pub(crate) fn blunt_index_ptr(
} }
pub(crate) fn unfold_by_str_once( pub(crate) fn unfold_by_str_once(
heap: &mut [HeapCellValue], heap: &mut impl SizedHeapMut,
start_term: HeapCellValue, start_term: HeapCellValue,
atom: Atom, atom: Atom,
) -> Option<usize> { ) -> Option<usize> {
@@ -821,7 +777,7 @@ pub(crate) fn unfold_by_str_once(
} }
pub fn unfold_by_str( pub fn unfold_by_str(
heap: &mut [HeapCellValue], heap: &mut impl SizedHeapMut,
mut start_term: HeapCellValue, mut start_term: HeapCellValue,
atom: Atom, atom: Atom,
) -> Vec<HeapCellValue> { ) -> Vec<HeapCellValue> {
@@ -862,7 +818,7 @@ pub fn unfold_by_str_locs(
*/ */
pub fn unfold_by_str_locs( pub fn unfold_by_str_locs(
heap: &mut [HeapCellValue], heap: &mut impl SizedHeapMut,
mut term_loc: usize, mut term_loc: usize,
atom: Atom, atom: Atom,
) -> Vec<(HeapCellValue, usize)> { ) -> Vec<(HeapCellValue, usize)> {
@@ -880,11 +836,14 @@ pub fn unfold_by_str_locs(
terms terms
} }
pub fn term_name(heap: &[HeapCellValue], mut term_loc: usize) -> Option<Atom> { pub fn term_predicate_key(
heap: &impl SizedHeap,
mut term_loc: usize,
) -> Option<PredicateKey> {
loop { loop {
read_heap_cell!(heap[term_loc], read_heap_cell!(heap[term_loc],
(HeapCellValueTag::Atom, (name, _arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
return Some(name); return Some((name, arity));
} }
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
term_loc = s; term_loc = s;
@@ -903,32 +862,6 @@ pub fn term_name(heap: &[HeapCellValue], mut term_loc: usize) -> Option<Atom> {
} }
} }
pub fn term_arity(heap: &[HeapCellValue], mut term_loc: usize) -> usize {
loop {
read_heap_cell!(heap[term_loc],
(HeapCellValueTag::Atom, (_name, arity)) => {
return arity;
}
(HeapCellValueTag::Str, s) => {
term_loc = s;
}
(HeapCellValueTag::Lis) => {
return 2;
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h != term_loc {
term_loc = h;
} else {
return 0;
}
}
_ => {
return 0;
}
);
}
}
pub fn inverse_var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) -> InverseVarLocs { pub fn inverse_var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) -> InverseVarLocs {
let mut occurrence_set: IndexMap<HeapCellValue, usize, FxBuildHasher> = let mut occurrence_set: IndexMap<HeapCellValue, usize, FxBuildHasher> =
IndexMap::with_hasher(FxBuildHasher::default()); IndexMap::with_hasher(FxBuildHasher::default());
@@ -975,7 +908,7 @@ pub fn term_deref(heap: &[HeapCellValue], mut term_loc: usize) -> HeapCellValue
} }
*/ */
pub fn term_nth_arg(heap: &[HeapCellValue], mut term_loc: usize, n: usize) -> Option<usize> { pub fn term_nth_arg(heap: &impl SizedHeap, mut term_loc: usize, n: usize) -> Option<usize> {
loop { loop {
read_heap_cell!(heap[term_loc], read_heap_cell!(heap[term_loc],
(HeapCellValueTag::Str, s) => { (HeapCellValueTag::Str, s) => {
@@ -1015,108 +948,55 @@ pub fn term_nth_arg(heap: &[HeapCellValue], mut term_loc: usize, n: usize) -> Op
} }
} }
pub type VarLocs = IndexMap<Var, HeapCellValue, FxBuildHasher>;
pub type InverseVarLocs = IndexMap<usize, Var, FxBuildHasher>;
#[derive(Debug)] #[derive(Debug)]
pub struct FocusedHeap { pub struct TermWriteResult {
pub heap: Vec<HeapCellValue>,
pub focus: usize, pub focus: usize,
pub inverse_var_locs: InverseVarLocs, pub inverse_var_locs: InverseVarLocs,
} }
impl FocusedHeap { pub type VarLocs = IndexMap<Var, HeapCellValue, FxBuildHasher>;
pub fn empty() -> Self { pub type InverseVarLocs = IndexMap<usize, Var, FxBuildHasher>;
Self {
heap: vec![],
focus: 0,
inverse_var_locs: InverseVarLocs::default(),
}
}
pub fn copy_term_from_machine_heap(
&mut self,
machine_st: &mut MachineState,
cell: HeapCellValue,
) {
let hb = machine_st.heap.len();
copy_term(
CopyBallTerm::new(
&mut machine_st.attr_var_init.attr_var_queue,
&mut machine_st.stack,
&mut machine_st.heap,
&mut self.heap,
),
cell,
AttrVarPolicy::DeepCopy,
);
for cell in self.heap.iter_mut() {
*cell = *cell - hb;
}
}
pub fn as_ref_mut(&mut self, focus: usize) -> FocusedHeapRefMut {
FocusedHeapRefMut {
heap: &mut self.heap,
focus,
}
}
pub fn deref_loc(&self, term_loc: usize) -> HeapCellValue {
use crate::machine::heap::*;
let cell = self.heap[term_loc];
heap_bound_store(&self.heap, heap_bound_deref(&self.heap, cell))
}
pub fn name(&self, term_loc: usize) -> Option<Atom> {
term_name(&self.heap, term_loc)
}
pub fn arity(&self, term_loc: usize) -> usize {
term_arity(&self.heap, term_loc)
}
pub fn nth_arg(&self, term_loc: usize, n: usize) -> Option<usize> {
term_nth_arg(&self.heap, term_loc, n)
}
}
#[derive(Debug)]
pub struct FocusedHeapRefMut<'a> { pub struct FocusedHeapRefMut<'a> {
pub heap: &'a mut Vec<HeapCellValue>, pub heap: &'a mut Heap,
pub focus: usize, pub focus: usize,
} }
impl<'a> FocusedHeapRefMut<'a> { impl<'a> FocusedHeapRefMut<'a> {
pub fn name(&self, term_loc: usize) -> Option<Atom> { #[inline]
term_name(&self.heap, term_loc) pub fn from(heap: &'a mut Heap, focus: usize) -> Self {
Self { heap, focus }
}
pub fn predicate_key(&self, term_loc: usize) -> Option<PredicateKey> {
term_predicate_key(self.heap, term_loc)
} }
pub fn arity(&self, term_loc: usize) -> usize { pub fn arity(&self, term_loc: usize) -> usize {
term_arity(&self.heap, term_loc) self.predicate_key(term_loc)
.map(|(_, arity)| arity)
.unwrap_or(0)
} }
pub fn deref_loc(&self, term_loc: usize) -> HeapCellValue { pub fn deref_loc(&self, term_loc: usize) -> HeapCellValue {
use crate::machine::heap::*;
let cell = self.heap[term_loc]; let cell = self.heap[term_loc];
heap_bound_store(&self.heap, heap_bound_deref(&self.heap, cell)) heap_bound_store(self.heap, heap_bound_deref(self.heap, cell))
} }
pub fn nth_arg(&self, term_loc: usize, n: usize) -> Option<usize> { pub fn nth_arg(&self, term_loc: usize, n: usize) -> Option<usize> {
term_nth_arg(self.heap, term_loc, n) term_nth_arg(self.heap, term_loc, n)
} }
pub fn from_cell(heap: &'a mut Vec<HeapCellValue>, cell: HeapCellValue) -> Self { /*
pub fn from_cell(heap: &'a mut Heap, cell: HeapCellValue) -> Self {
let focus = read_heap_cell!(cell, let focus = read_heap_cell!(cell,
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
h h
} }
_ => { _ => {
let h = heap.len(); let h = heap.len();
heap.push(cell); heap.push_cell(cell).unwrap();
h h
} }
@@ -1124,4 +1004,5 @@ impl<'a> FocusedHeapRefMut<'a> {
Self { heap, focus } Self { heap, focus }
} }
*/
} }

View File

@@ -1,13 +1,15 @@
use crate::arena::F64Ptr; use crate::arena::F64Ptr;
use crate::arena::TypedArenaPtr; use crate::arena::TypedArenaPtr;
use lexical::{FromLexicalLossy, parse_lossy}; use lexical::{FromLexical, parse};
use crate::arena::ArenaAllocated; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::machine::heap::*;
pub use crate::machine::machine_state::*; pub use crate::machine::machine_state::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::char_reader::*; use crate::parser::char_reader::*;
use crate::parser::dashu::Integer; use crate::parser::dashu::Integer;
use crate::types::*;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt; use std::fmt;
@@ -33,8 +35,9 @@ struct LayoutInfo {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Token { pub enum Token {
Literal(Literal), Literal(HeapCellValue),
Var(String), Var(String),
String(String),
Open, // '(' Open, // '('
OpenCT, // '(' OpenCT, // '('
Close, // ')' Close, // ')'
@@ -48,6 +51,30 @@ pub enum Token {
} }
impl Token { impl Token {
pub(super) fn byte_size(&self, flags: MachineFlags) -> usize {
match self {
Token::String(string) if flags.double_quotes.is_codes() => {
2 * string.chars().count() + 1
}
Token::String(string) => {
Heap::compute_pstr_size(&string)
}
Token::Literal(_) |
Token::Comma |
Token::HeadTailSeparator |
Token::Open |
Token::OpenCT |
Token::OpenCurly |
Token::OpenList |
Token::Var(_) => {
heap_index!(1)
}
_ => {
0
}
}
}
#[inline] #[inline]
pub(super) fn is_end(&self) -> bool { pub(super) fn is_end(&self) -> bool {
matches!(self, Token::End) matches!(self, Token::End)
@@ -103,16 +130,16 @@ macro_rules! try_nt {
}}; }};
} }
pub struct Lexer<'a, R> { pub(crate) struct LexerParser<'a, R> {
pub(crate) reader: R, pub(crate) reader: R,
pub(crate) machine_st: &'a mut MachineState, pub(crate) machine_st: &'a mut MachineState,
pub(crate) line_num: usize, pub(crate) line_num: usize,
pub(crate) col_num: usize, pub(crate) col_num: usize,
} }
impl<'a, R: fmt::Debug> fmt::Debug for Lexer<'a, R> { impl<'a, R: fmt::Debug> fmt::Debug for LexerParser<'a, R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Lexer") f.debug_struct("LexerParser")
.field("reader", &"&'a mut R") // Hacky solution. .field("reader", &"&'a mut R") // Hacky solution.
.field("line_num", &self.line_num) .field("line_num", &self.line_num)
.field("col_num", &self.col_num) .field("col_num", &self.col_num)
@@ -120,9 +147,9 @@ impl<'a, R: fmt::Debug> fmt::Debug for Lexer<'a, R> {
} }
} }
impl<'a, R: CharRead> Lexer<'a, R> { impl<'a, R: CharRead> LexerParser<'a, R> {
pub fn new(src: R, machine_st: &'a mut MachineState) -> Self { pub fn new(src: R, machine_st: &'a mut MachineState) -> Self {
Lexer { LexerParser {
reader: src, reader: src,
machine_st, machine_st,
line_num: 0, line_num: 0,
@@ -144,11 +171,6 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
#[inline]
pub fn loc_to_err_src(&self) -> ParserErrorSrc {
ParserErrorSrc { line_num: self.line_num, col_num: self.col_num }
}
#[inline(always)] #[inline(always)]
fn return_char(&mut self, c: char) { fn return_char(&mut self, c: char) {
self.reader.put_back_char(c); self.reader.put_back_char(c);
@@ -631,11 +653,11 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if !token.is_empty() && token.chars().nth(1).is_none() { if !token.is_empty() && token.chars().nth(1).is_none() {
if let Some(c) = token.chars().next() { if let Some(c) = token.chars().next() {
return Ok(Token::Literal(Literal::Char(c))); return Ok(Token::Literal(char_as_cell!(c)));
} }
} }
} else { } else {
return Err(ParserError::InvalidSingleQuotedCharacter(c, self.loc_to_err_src())); return Err(ParserError::InvalidSingleQuotedCharacter(self.loc_to_err_src()));
} }
} else { } else {
match self.get_back_quoted_string() { match self.get_back_quoted_string() {
@@ -645,26 +667,29 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
if token.as_str() == "[]" { if token.as_str() == "[]" {
Ok(Token::Literal(Literal::Atom(atom!("[]")))) Ok(Token::Literal(empty_list_as_cell!()))
} else { } else {
Ok(Token::Literal(Literal::Atom(AtomTable::build_with( Ok(Token::Literal(atom_as_cell!(AtomTable::build_with(
&self.machine_st.atom_tbl, &self.machine_st.atom_tbl,
&token, &token,
)))) ))))
} }
} }
fn parse_lossy_wrapper<T: FromLexicalLossy>(&self, token: String) -> Result<T, ParserError> { fn parse_lossy_wrapper<T: FromLexical>(&self, token: &str) -> Result<T, ParserError> {
match parse_lossy::<T, _>(token.as_bytes()) { match parse::<T, _>(token.as_bytes()) {
Ok(n) => Ok(n), Ok(n) => Ok(n),
Err(e) => return Err(ParserError::LexicalError(e, self.loc_to_err_src())), Err(_) => return Err(ParserError::LexicalError(self.loc_to_err_src())),
} }
} }
fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> { fn vacate_with_float(&mut self, mut token: String) -> Result<Token, ParserError> {
self.return_char(token.pop().unwrap()); self.return_char(token.pop().unwrap());
let n = self.parse_lossy_wrapper::<f64>(token)?; let n = self.parse_lossy_wrapper::<f64>(&token)?;
Ok(Token::Literal(Literal::from(float_alloc!(n, self.machine_st.arena)))) Ok(Token::Literal(HeapCellValue::from(float_alloc!(
n,
self.machine_st.arena
))))
} }
fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> { fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> {
@@ -790,8 +815,8 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
let n = parse_float_lossy(&token)?; let n = self.parse_lossy_wrapper::<f64>(&token)?;
Ok(NumberToken::Number(Number::Float(float_alloc!( Ok(Token::Literal(HeapCellValue::from(float_alloc!(
n, n,
self.machine_st.arena self.machine_st.arena
)))) ))))
@@ -799,8 +824,8 @@ impl<'a, R: CharRead> Lexer<'a, R> {
return self.vacate_with_float(token).map(NumberToken::Number); return self.vacate_with_float(token).map(NumberToken::Number);
} }
} else { } else {
let n = parse_float_lossy(&token)?; let n = self.parse_lossy_wrapper::<f64>(&token)?;
Ok(NumberToken::Number(Number::Float(float_alloc!( Ok(Token::Literal(HeapCellValue::from(float_alloc!(
n, n,
self.machine_st.arena self.machine_st.arena
)))) ))))
@@ -1034,12 +1059,12 @@ impl<'a, R: CharRead> Lexer<'a, R> {
if c == '"' { if c == '"' {
let s = self.char_code_list_token(c)?; let s = self.char_code_list_token(c)?;
let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &s);
return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes { return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes {
Ok(Token::Literal(Literal::Atom(atom))) let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &s);
Ok(Token::Literal(atom_as_cell!(atom)))
} else { } else {
Ok(Token::Literal(Literal::String(atom))) Ok(Token::String(s))
}; };
} }
@@ -1053,13 +1078,3 @@ impl<'a, R: CharRead> Lexer<'a, R> {
} }
} }
} }
fn parse_float_lossy(token: &str) -> Result<f64, ParserError> {
const FORMAT: u128 = lexical::format::STANDARD;
let options = lexical::ParseFloatOptions::builder()
.lossy(true)
.build()
.unwrap();
let n = lexical::parse_with_options::<f64, _, FORMAT>(token.as_bytes(), &options)?;
Ok(n)
}

View File

@@ -3,14 +3,13 @@ use dashu::Rational;
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::machine::heap::{heap_bound_deref, heap_bound_store}; use crate::forms::Number;
use crate::machine::partial_string::*; use crate::machine::heap::*;
use crate::parser::ast::*; use crate::parser::ast::*;
use crate::parser::char_reader::*; use crate::parser::char_reader::*;
use crate::parser::lexer::*; use crate::parser::lexer::*;
use crate::types::*; use crate::types::*;
use std::mem;
use std::ops::Neg; use std::ops::Neg;
use std::rc::Rc; use std::rc::Rc;
@@ -53,7 +52,7 @@ provided via the Provided variant.
#[derive(Debug)] #[derive(Debug)]
pub enum Tokens { pub enum Tokens {
Default, Default,
Provided(Vec<Token>), Provided(Vec<Token>, usize),
} }
impl TokenType { impl TokenType {
@@ -176,22 +175,27 @@ pub struct CompositeOpDesc {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Parser<'a, R> { struct Parser<'a> {
pub lexer: Lexer<'a, R>,
tokens: Vec<Token>, tokens: Vec<Token>,
stack: Vec<TokenDesc>, stack: Vec<TokenDesc>,
terms: Vec<HeapCellValue>, terms: HeapWriter<'a>,
arena: &'a mut Arena,
flags: MachineFlags,
line_num: &'a mut usize,
col_num: &'a mut usize,
var_locs: VarLocs, var_locs: VarLocs,
inverse_var_locs: InverseVarLocs, inverse_var_locs: InverseVarLocs,
} }
fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserError> { pub fn read_tokens<R: CharRead>(lexer: &mut LexerParser<R>) -> Result<(Vec<Token>, usize), ParserError> {
let mut tokens = vec![]; let mut tokens = vec![];
let mut term_size = 0;
loop { loop {
match lexer.next_token() { match lexer.next_token() {
Ok(token) => { Ok(token) => {
let at_end = token.is_end(); let at_end = token.is_end();
term_size += token.byte_size(lexer.machine_st.flags);
tokens.push(token); tokens.push(token);
if at_end { if at_end {
@@ -209,19 +213,11 @@ fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserEr
tokens.reverse(); tokens.reverse();
Ok(tokens) Ok((tokens, term_size))
}
fn atomize_literal(atom_tbl: &AtomTable, c: Literal) -> Option<Atom> {
match c {
Literal::Atom(ref name) => Some(*name),
Literal::Char(c) => Some(AtomTable::build_with(atom_tbl, &c.to_string())),
_ => None,
}
} }
pub(crate) fn as_partial_string( pub(crate) fn as_partial_string(
heap: &[HeapCellValue], heap: &impl SizedHeap,
head: HeapCellValue, head: HeapCellValue,
tail: HeapCellValue, tail: HeapCellValue,
) -> Option<(String, Option<HeapCellValue>)> { ) -> Option<(String, Option<HeapCellValue>)> {
@@ -240,9 +236,6 @@ pub(crate) fn as_partial_string(
return None; return None;
} }
} }
(HeapCellValueTag::Char, c) => {
c.to_string()
}
_ => { _ => {
return None; return None;
} }
@@ -263,9 +256,6 @@ pub(crate) fn as_partial_string(
break; break;
} }
} }
(HeapCellValueTag::Char, c) => {
string.push(c);
}
_ => { _ => {
return None; return None;
} }
@@ -274,16 +264,9 @@ pub(crate) fn as_partial_string(
tail = heap[l+1]; tail = heap[l+1];
} }
(HeapCellValueTag::PStrLoc, l) => { (HeapCellValueTag::PStrLoc, l) => {
let (index, n) = pstr_loc_and_offset(&heap, l); let (pstr, tail_loc) = heap.scan_slice_to_str(l);
let n = n.get_num() as usize; string += pstr;
tail = heap[tail_loc];
string += &*cell_as_string!(heap[index]).as_str_from(n);
tail = heap[l+1];
}
(HeapCellValueTag::CStr, cstr_atom) => {
string += &*cstr_atom.as_str();
tail = empty_list_as_cell!();
break;
} }
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if heap[h] != tail { if heap[h] != tail {
@@ -316,36 +299,15 @@ pub(crate) fn as_partial_string(
) )
} }
impl<'a, R: CharRead> Parser<'a, R> { impl<'a> Parser<'a> {
pub fn new(stream: R, machine_st: &'a mut MachineState) -> Self {
Parser {
lexer: Lexer::new(stream, machine_st),
tokens: vec![],
stack: vec![],
terms: vec![],
var_locs: VarLocs::default(),
inverse_var_locs: InverseVarLocs::default(),
}
}
pub fn from_lexer(lexer: Lexer<'a, R>) -> Self {
Parser {
lexer,
tokens: vec![],
stack: vec![],
terms: vec![],
var_locs: VarLocs::default(),
inverse_var_locs: InverseVarLocs::default(),
}
}
fn get_term_name(&self, td: TokenDesc) -> Option<Atom> { fn get_term_name(&self, td: TokenDesc) -> Option<Atom> {
match td.tt { match td.tt {
TokenType::HeadTailSeparator => Some(atom!("|")), TokenType::HeadTailSeparator => Some(atom!("|")),
TokenType::Comma => Some(atom!(",")), TokenType::Comma => Some(atom!(",")),
TokenType::Term { heap_loc } => { TokenType::Term { heap_loc } => {
if heap_loc.is_ref() { if heap_loc.is_ref() {
term_name(&self.terms, heap_loc.get_value() as usize) term_predicate_key(&self.terms, heap_loc.get_value() as usize)
.map(|key| key.0)
} else { } else {
None None
} }
@@ -354,16 +316,6 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
} }
#[inline]
pub fn line_num(&self) -> usize {
self.lexer.line_num
}
#[inline]
pub fn col_num(&self) -> usize {
self.lexer.col_num
}
fn push_binary_op( fn push_binary_op(
&mut self, &mut self,
op: TokenDesc, op: TokenDesc,
@@ -382,13 +334,15 @@ impl<'a, R: CharRead> Parser<'a, R> {
} = operand_1 } = operand_1
{ {
if let Some(name) = self.get_term_name(op) { if let Some(name) = self.get_term_name(op) {
let str_loc = self.terms.len(); let str_loc = self.terms.cell_len();
self.terms.push(atom_as_cell!(name, 2)); self.terms.write_with(|section| {
self.terms.push(arg1); section.push_cell(atom_as_cell!(name, 2));
self.terms.push(arg2); section.push_cell(arg1);
section.push_cell(arg2);
self.terms.push(str_loc_as_cell!(str_loc)); section.push_cell(str_loc_as_cell!(str_loc));
});
self.stack.push(TokenDesc { self.stack.push(TokenDesc {
tt: TokenType::Term { tt: TokenType::Term {
@@ -404,10 +358,6 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
fn push_unary_op(&mut self, op: TokenDesc, operand: TokenDesc, spec: Specifier) { fn push_unary_op(&mut self, op: TokenDesc, operand: TokenDesc, spec: Specifier) {
// if is_postfix!(assoc) {
// mem::swap(&mut op, &mut operand);
// }
if let TokenDesc { if let TokenDesc {
tt: TokenType::Term { heap_loc: arg1 }, tt: TokenType::Term { heap_loc: arg1 },
.. ..
@@ -419,11 +369,13 @@ impl<'a, R: CharRead> Parser<'a, R> {
} = op } = op
{ {
if let Some(name) = self.get_term_name(op) { if let Some(name) = self.get_term_name(op) {
let str_loc = self.terms.len(); let str_loc = self.terms.cell_len();
self.terms.push(atom_as_cell!(name, 1)); self.terms.write_with(|section| {
self.terms.push(arg1); section.push_cell(atom_as_cell!(name, 1));
self.terms.push(str_loc_as_cell!(str_loc)); section.push_cell(arg1);
section.push_cell(str_loc_as_cell!(str_loc));
});
self.stack.push(TokenDesc { self.stack.push(TokenDesc {
tt: TokenType::Term { tt: TokenType::Term {
@@ -439,8 +391,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) { fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
let h = self.terms.len(); let h = self.terms.cell_len();
self.terms.push(atom_as_cell!(atom)); self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom)));
self.stack.push(TokenDesc { self.stack.push(TokenDesc {
tt: TokenType::Term { tt: TokenType::Term {
heap_loc: heap_loc_as_cell!(h), heap_loc: heap_loc_as_cell!(h),
@@ -452,51 +404,61 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
fn shift(&mut self, token: Token, priority: usize, spec: Specifier) { fn shift(&mut self, token: Token, priority: usize, spec: Specifier) {
let heap_loc = heap_loc_as_cell!(self.terms.len()); let heap_loc = heap_loc_as_cell!(self.terms.cell_len());
let tt = match token { let tt = match token {
Token::Literal(Literal::String(s)) Token::String(s) if self.flags.double_quotes.is_codes() => {
if self.lexer.machine_st.flags.double_quotes.is_codes() =>
{
let mut list = empty_list_as_cell!(); let mut list = empty_list_as_cell!();
for c in s.as_str().chars().rev() { self.terms.write_with(|section| {
let h = self.terms.len(); for c in s.as_str().chars().rev() {
let h = section.cell_len();
self.terms section.push_cell(fixnum_as_cell!(Fixnum::build_with(c as i64)));
.push(fixnum_as_cell!(Fixnum::build_with(c as i64))); section.push_cell(list);
self.terms.push(list);
list = list_loc_as_cell!(h); list = list_loc_as_cell!(h);
} }
self.terms.push(list); section.push_cell(list);
});
TokenType::Term { heap_loc: list } TokenType::Term { heap_loc: list }
} }
Token::Literal(Literal::String(s)) Token::String(s) => {
if self.lexer.machine_st.flags.double_quotes.is_chars() => debug_assert!(self.flags.double_quotes.is_chars());
{ let mut pstr_cell = heap_loc;
if s.is_empty() {
self.terms.push(empty_list_as_cell!()); if s == "\u{0}" {
let h = self.terms.cell_len();
self.terms.write_with(|section| {
section.push_cell(char_as_cell!('\u{0}'));
section.push_cell(empty_list_as_cell!());
section.push_cell(list_loc_as_cell!(h));
});
TokenType::Term { heap_loc: heap_loc_as_cell!(h + 2) }
} else { } else {
self.terms.push(string_as_cstr_cell!(s)); self.terms.write_with(|section| {
match section.push_pstr(&s) {
Some(pstr_loc_cell) => {
section.push_cell(empty_list_as_cell!());
let h = section.cell_len();
section.push_cell(pstr_loc_cell);
pstr_cell = heap_loc_as_cell!(h);
}
None => {
section.push_cell(empty_list_as_cell!());
}
}
});
TokenType::Term { heap_loc: pstr_cell }
} }
TokenType::Term { heap_loc }
}
Token::Literal(Literal::Char(c)) => {
// soon this will be gone due to chars being folded
// into atoms
self.terms.push(atom_as_cell!(atomize_literal(
&self.lexer.machine_st.atom_tbl,
Literal::Char(c),
).unwrap()));
TokenType::Term { heap_loc }
} }
Token::Literal(c) => { Token::Literal(c) => {
self.terms.push(HeapCellValue::from(c)); self.terms.write_with(|section| section.push_cell(c));
TokenType::Term { heap_loc } TokenType::Term { heap_loc }
} }
Token::Var(var_string) => { Token::Var(var_string) => {
@@ -504,11 +466,11 @@ impl<'a, R: CharRead> Parser<'a, R> {
match self.var_locs.get(&var).cloned() { match self.var_locs.get(&var).cloned() {
Some(heap_loc) => { Some(heap_loc) => {
self.terms.push(heap_loc); self.terms.write_with(|section| section.push_cell(heap_loc));
TokenType::Term { heap_loc } TokenType::Term { heap_loc }
} }
None => { None => {
self.terms.push(heap_loc); self.terms.write_with(|section| section.push_cell(heap_loc));
// if var_string == "_", it not being present // if var_string == "_", it not being present
// as a key of self.var_locs means it is // as a key of self.var_locs means it is
@@ -649,23 +611,23 @@ impl<'a, R: CharRead> Parser<'a, R> {
return false; return false;
} }
if self.terms.len() < arity { if self.terms.cell_len() < arity {
return false; return false;
} }
let stack_len = self.stack.len() - 2 * arity - 1; let stack_len = self.stack.len() - 2 * arity - 1;
let term_idx = self.terms.len(); let term_idx = self.terms.cell_len();
let push_structure = |parser: &mut Self, name: Atom| -> TokenType { let push_structure = |parser: &mut Self, name: Atom| -> TokenType {
parser.terms.push(atom_as_cell!(name, arity)); parser.terms.write_with(|section| section.push_cell(atom_as_cell!(name, arity)));
for idx in (stack_len + 2..parser.stack.len()).step_by(2) { for idx in (stack_len + 2..parser.stack.len()).step_by(2) {
let subterm = parser.term_from_stack(idx).unwrap(); let subterm = parser.term_from_stack(idx).unwrap();
parser.terms.push(subterm); parser.terms.write_with(|section| section.push_cell(subterm));
} }
let str_loc_idx = parser.terms.len(); let str_loc_idx = parser.terms.cell_len();
parser.terms.push(str_loc_as_cell!(term_idx)); parser.terms.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
TokenType::Term { TokenType::Term {
heap_loc: heap_loc_as_cell!(str_loc_idx), heap_loc: heap_loc_as_cell!(str_loc_idx),
@@ -679,39 +641,38 @@ impl<'a, R: CharRead> Parser<'a, R> {
{ {
let idx = heap_loc.get_value() as usize; let idx = heap_loc.get_value() as usize;
if let Some(name) = term_name(&self.terms, idx) { if let Some((name, arity)) = term_predicate_key(&self.terms, idx) {
// reduce the '.' functor to a cons cell if it applies. // reduce the '.' functor to a cons cell if it applies.
let new_tt = if name == atom!(".") && arity == 2 { let new_tt = if name == atom!(".") && arity == 2 {
let head = self.term_from_stack(stack_len + 2).unwrap(); let head = self.term_from_stack(stack_len + 2).unwrap();
let tail = self.term_from_stack(stack_len + 4).unwrap(); let tail = self.term_from_stack(stack_len + 4).unwrap();
let cell_len = self.terms.cell_len();
match as_partial_string(&self.terms, head, tail) { match as_partial_string(&self.terms, head, tail) {
Some((string_buf, Some(tail))) => { Some((string_buf, tail_opt)) => {
let atom = let bytes_written = self.terms.write_with(|section| {
AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf); let pstr_cell = section.push_pstr(&string_buf).unwrap();
section.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
section.push_cell(pstr_cell);
});
self.terms.push(string_as_pstr_cell!(atom)); let heap_loc = cell_index!(bytes_written) - 1 + cell_len;
self.terms.push(tail);
self.terms.push(pstr_loc_as_cell!(term_idx));
TokenType::Term { TokenType::Term {
heap_loc: heap_loc_as_cell!(term_idx + 2), heap_loc: heap_loc_as_cell!(heap_loc),
}
}
Some((string_buf, None)) => {
let atom =
AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
TokenType::Term {
heap_loc: string_as_cstr_cell!(atom),
} }
} }
None => { None => {
self.terms.push(head); let bytes_written = self.terms.write_with(|section| {
self.terms.push(tail); section.push_cell(head);
self.terms.push(list_loc_as_cell!(term_idx)); section.push_cell(tail);
section.push_cell(list_loc_as_cell!(term_idx));
});
TokenType::Term { TokenType::Term {
heap_loc: heap_loc_as_cell!(term_idx + 2), heap_loc: heap_loc_as_cell!(
cell_len + cell_index!(bytes_written) - 1
),
} }
} }
} }
@@ -747,9 +708,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
false false
} }
pub fn reset(&mut self) { fn loc_to_err_src(&self) -> ParserErrorSrc {
self.stack.clear(); ParserErrorSrc { line_num: *self.line_num, col_num: *self.col_num }
self.var_locs.clear();
} }
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize { fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
@@ -764,17 +724,17 @@ impl<'a, R: CharRead> Parser<'a, R> {
); );
if term.is_ref() && if term.is_ref() &&
0 < op_desc.priority && op_desc.priority < self.stack[index].priority 0 < op_desc.priority &&
op_desc.priority < self.stack[index].priority
{ {
/* '|' is a head-tail separator here, not /* '|' is a head-tail separator here, not
* an operator, so expand the * an operator, so expand the
* terms it compacted out again. */ * terms it compacted out again. */
let focus = term.get_value() as usize; let focus = term.get_value() as usize;
let name_opt = term_name(&self.terms, focus); let key_opt = term_predicate_key(&self.terms, focus);
let arity = term_arity(&self.terms, focus);
if name_opt == Some(atom!(",")) && arity == 2 { if key_opt == Some((atom!(","), 2)) {
let terms = if op_desc.unfold_bounds == 0 { let terms = if op_desc.unfold_bounds == 0 {
unfold_by_str(&mut self.terms, term, atom!(",")) unfold_by_str(&mut self.terms, term, atom!(","))
} else { } else {
@@ -855,8 +815,8 @@ impl<'a, R: CharRead> Parser<'a, R> {
if let Some(ref mut td) = self.stack.last_mut() { if let Some(ref mut td) = self.stack.last_mut() {
// parsed an empty list token // parsed an empty list token
if td.tt == TokenType::OpenList { if td.tt == TokenType::OpenList {
let h = self.terms.len(); let h = self.terms.cell_len();
self.terms.push(empty_list_as_cell!()); self.terms.write_with(|section| section.push_cell(empty_list_as_cell!()));
td.spec = TERM; td.spec = TERM;
td.tt = TokenType::Term { td.tt = TokenType::Term {
@@ -886,7 +846,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
Some(term) => term, Some(term) => term,
None => { None => {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), self.loc_to_err_src(),
)); ));
} }
}; };
@@ -902,13 +862,13 @@ impl<'a, R: CharRead> Parser<'a, R> {
tail_term tail_term
}; };
if arity > self.terms.len() { if arity > self.terms.cell_len() {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), self.loc_to_err_src(),
)); ));
} }
let pre_terms_len = self.terms.len(); let pre_terms_len = self.terms.cell_len();
while let Some(token_desc) = self.stack.pop() { while let Some(token_desc) = self.stack.pop() {
let subterm = match token_desc.tt { let subterm = match token_desc.tt {
@@ -922,11 +882,13 @@ impl<'a, R: CharRead> Parser<'a, R> {
arity -= 1; arity -= 1;
let link_cell = list_loc_as_cell!(self.terms.len() + 1); let link_cell = list_loc_as_cell!(self.terms.cell_len() + 1);
self.terms.push(link_cell); self.terms.write_with(|section| {
self.terms.push(subterm); section.push_cell(link_cell);
self.terms.push(tail_term); section.push_cell(subterm);
section.push_cell(tail_term);
});
tail_term = link_cell; tail_term = link_cell;
@@ -939,29 +901,22 @@ impl<'a, R: CharRead> Parser<'a, R> {
self.stack.truncate(list_start_idx); self.stack.truncate(list_start_idx);
let list_loc = self.terms.len() - 3; let list_loc = self.terms.cell_len() - 3;
let head_term = self.terms[list_loc + 1]; let head_term = self.terms[list_loc + 1];
let tail_term = self.terms[list_loc + 2]; let tail_term = self.terms[list_loc + 2];
let heap_loc = match as_partial_string(&self.terms, head_term, tail_term) { let heap_loc = match as_partial_string(&self.terms, head_term, tail_term) {
Some((string_buf, Some(tail))) => { Some((string_buf, tail_opt)) => {
self.terms.truncate(pre_terms_len); self.terms.truncate(pre_terms_len);
let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf); let bytes_written = self.terms.write_with(|section| {
let pstr_cell = section.push_pstr(&string_buf).unwrap();
section.push_cell(tail_opt.unwrap_or(empty_list_as_cell!()));
section.push_cell(pstr_cell);
});
self.terms.push(string_as_pstr_cell!(atom)); heap_loc_as_cell!(pre_terms_len + cell_index!(bytes_written) - 1)
self.terms.push(tail);
self.terms.push(pstr_loc_as_cell!(pre_terms_len));
heap_loc_as_cell!(pre_terms_len + 2)
}
Some((string_buf, None)) => {
self.terms.truncate(pre_terms_len);
let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
self.terms.push(string_as_cstr_cell!(atom));
heap_loc_as_cell!(pre_terms_len)
} }
None => { None => {
heap_loc_as_cell!(list_loc) // head_term heap_loc_as_cell!(list_loc) // head_term
@@ -975,22 +930,6 @@ impl<'a, R: CharRead> Parser<'a, R> {
unfold_bounds: 0, unfold_bounds: 0,
}); });
/*
self.terms.push(match list {
Term::Cons(_, head, tail) => match as_partial_string(*head, *tail) {
Ok((string_buf, Some(tail))) => {
Term::PartialString(Cell::default(), string_buf, tail)
}
Ok((string_buf, None)) => {
let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
Term::CompleteString(Cell::default(), atom)
}
Err(term) => term,
},
term => term,
});
*/
Ok(true) Ok(true)
} }
@@ -1001,8 +940,9 @@ impl<'a, R: CharRead> Parser<'a, R> {
if let Some(ref mut td) = self.stack.last_mut() { if let Some(ref mut td) = self.stack.last_mut() {
if td.tt == TokenType::OpenCurly { if td.tt == TokenType::OpenCurly {
let h = self.terms.len(); let h = self.terms.cell_len();
self.terms.push(atom_as_cell!(atom!("{}")));
self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom!("{}"))));
td.tt = TokenType::Term { td.tt = TokenType::Term {
heap_loc: heap_loc_as_cell!(h), heap_loc: heap_loc_as_cell!(h),
@@ -1025,7 +965,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
if oc.tt == TokenType::OpenCurly { if oc.tt == TokenType::OpenCurly {
if let TokenType::Term { heap_loc } = td.tt { if let TokenType::Term { heap_loc } = td.tt {
let curly_idx = self.terms.len(); let curly_idx = self.terms.cell_len();
oc.tt = TokenType::Term { oc.tt = TokenType::Term {
heap_loc: heap_loc_as_cell!(curly_idx + 2), heap_loc: heap_loc_as_cell!(curly_idx + 2),
@@ -1033,9 +973,11 @@ impl<'a, R: CharRead> Parser<'a, R> {
oc.priority = 0; oc.priority = 0;
oc.spec = TERM; oc.spec = TERM;
self.terms.push(atom_as_cell!(atom!("{}"), 1)); self.terms.write_with(|section| {
self.terms.push(heap_loc); section.push_cell(atom_as_cell!(atom!("{}"), 1));
self.terms.push(str_loc_as_cell!(curly_idx)); section.push_cell(heap_loc);
section.push_cell(str_loc_as_cell!(curly_idx));
});
/* /*
let term = match self.terms.pop() { let term = match self.terms.pop() {
@@ -1089,8 +1031,6 @@ impl<'a, R: CharRead> Parser<'a, R> {
let term = if self.stack[idx].tt.sep_to_atom().is_some() { let term = if self.stack[idx].tt.sep_to_atom().is_some() {
atom_as_cell!(atom!("|")) atom_as_cell!(atom!("|"))
// self.terms
// .push(Term::Literal(Cell::default(), Literal::Atom(atom)));
} else { } else {
self.term_from_stack(idx).unwrap() self.term_from_stack(idx).unwrap()
}; };
@@ -1117,7 +1057,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
match self match self
.tokens .tokens
.last() .last()
.ok_or(ParserError::unexpected_eof(self.lexer.loc_to_err_src()))? .ok_or(ParserError::unexpected_eof(self.loc_to_err_src()))?
{ {
// do this when layout hasn't been inserted, // do this when layout hasn't been inserted,
// ie. why we don't match on Token::Open. // ie. why we don't match on Token::Open.
@@ -1173,7 +1113,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
fn negate_number<N, Negator, ToLiteral>(&mut self, n: N, negator: Negator, constr: ToLiteral) fn negate_number<N, Negator, ToLiteral>(&mut self, n: N, negator: Negator, constr: ToLiteral)
where where
Negator: Fn(N, &mut Arena) -> N, Negator: Fn(N, &mut Arena) -> N,
ToLiteral: Fn(N, &mut Arena) -> Literal, ToLiteral: Fn(N, &mut Arena) -> HeapCellValue,
{ {
match self.stack.last().cloned() { match self.stack.last().cloned() {
Some( Some(
@@ -1187,7 +1127,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
if name == atom!("-") && (is_prefix!(spec) || is_negate!(spec)) { if name == atom!("-") && (is_prefix!(spec) || is_negate!(spec)) {
self.stack.pop(); self.stack.pop();
let arena = &mut self.lexer.machine_st.arena; let arena = &mut self.arena;
let literal = constr(negator(n, arena), arena); let literal = constr(negator(n, arena), arena);
self.shift(Token::Literal(literal), 0, TERM); self.shift(Token::Literal(literal), 0, TERM);
@@ -1199,7 +1139,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
_ => {} _ => {}
} }
let literal = constr(n, &mut self.lexer.machine_st.arena); let literal = constr(n, &mut self.arena);
self.shift(Token::Literal(literal), 0, TERM); self.shift(Token::Literal(literal), 0, TERM);
} }
@@ -1217,34 +1157,43 @@ impl<'a, R: CharRead> Parser<'a, R> {
} }
match token { match token {
Token::Literal(Literal::Fixnum(n)) => { Token::String(string) => {
self.negate_number(n, |n, _| -n, |n, _| Literal::Fixnum(n)) self.shift(Token::String(string), 0, TERM);
} }
Token::Literal(Literal::Integer(n)) => {
self.negate_number(n, negate_int_rc, |n, _| Literal::Integer(n))
}
Token::Literal(Literal::Rational(n)) => {
self.negate_number(n, negate_rat_rc, |r, _| Literal::Rational(r))
}
Token::Literal(Literal::Float(n)) if F64Ptr::from_offset(n).is_infinite() => {
return Err(ParserError::InfiniteFloat(
self.lexer.loc_to_err_src(),
));
}
Token::Literal(Literal::Float(n)) => self.negate_number(
**n.as_ptr(),
|n, _| -n,
|n, arena| Literal::from(float_alloc!(n, arena)),
),
Token::Literal(c) => { Token::Literal(c) => {
let atomized = atomize_literal(&self.lexer.machine_st.atom_tbl, c); match Number::try_from(c) {
Ok(Number::Integer(n)) => {
if let Some(name) = atomized { self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n))
if !self.shift_op(name, op_dir)? { }
self.shift(Token::Literal(c), 0, TERM); Ok(Number::Rational(n)) => {
self.negate_number(n, negate_rat_rc, |r, _| typed_arena_ptr_as_cell!(r))
}
Ok(Number::Float(n)) if n.is_infinite() => {
return Err(ParserError::InfiniteFloat(
self.lexer.loc_to_err_src(),
));
}
Ok(Number::Float(n)) => {
use ordered_float::OrderedFloat;
self.negate_number(
n,
|n, _| -n,
|OrderedFloat(n), arena| HeapCellValue::from(float_alloc!(n, arena)),
)
}
Ok(Number::Fixnum(n)) => {
self.negate_number(n, |n, _| -n, |n, _| fixnum_as_cell!(n))
}
Err(_) => {
if let Some(name) = c.to_atom() {
if !self.shift_op(name, op_dir)? {
self.shift(Token::Literal(c), 0, TERM);
}
} else {
self.shift(Token::Literal(c), 0, TERM);
}
} }
} else {
self.shift(Token::Literal(c), 0, TERM);
} }
} }
Token::Var(v) => self.shift(Token::Var(v), 0, TERM), Token::Var(v) => self.shift(Token::Var(v), 0, TERM),
@@ -1253,7 +1202,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
Token::Close => { Token::Close => {
if !self.reduce_term() && !self.reduce_brackets() { if !self.reduce_term() && !self.reduce_brackets() {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), self.loc_to_err_src(),
)); ));
} }
} }
@@ -1261,7 +1210,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
Token::CloseList => { Token::CloseList => {
if !self.reduce_list()? { if !self.reduce_list()? {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), self.loc_to_err_src(),
)); ));
} }
} }
@@ -1269,7 +1218,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
Token::CloseCurly => { Token::CloseCurly => {
if !self.reduce_curly()? { if !self.reduce_curly()? {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), self.loc_to_err_src(),
)); ));
} }
} }
@@ -1305,7 +1254,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
| Some(TokenType::HeadTailSeparator) | Some(TokenType::HeadTailSeparator)
| Some(TokenType::Comma) => { | Some(TokenType::Comma) => {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), self.loc_to_err_src(),
)) ))
} }
_ => {} _ => {}
@@ -1314,10 +1263,16 @@ impl<'a, R: CharRead> Parser<'a, R> {
Ok(()) Ok(())
} }
}
impl<'a, R: CharRead> LexerParser<'a, R> {
#[inline] #[inline]
pub fn lines_read(&self) -> usize { pub fn line_num(&self) -> usize {
self.lexer.line_num self.line_num
}
pub fn loc_to_err_src(&self) -> ParserErrorSrc {
ParserErrorSrc { line_num: self.line_num, col_num: self.col_num }
} }
// on success, returns the parsed term and the number of lines read. // on success, returns the parsed term and the number of lines read.
@@ -1325,35 +1280,62 @@ impl<'a, R: CharRead> Parser<'a, R> {
&mut self, &mut self,
op_dir: &CompositeOpDir, op_dir: &CompositeOpDir,
tokens: Tokens, tokens: Tokens,
) -> Result<FocusedHeap, ParserError> { ) -> Result<TermWriteResult, ParserError> {
self.tokens = match tokens { let (tokens, term_byte_size) = match tokens {
Tokens::Default => read_tokens(&mut self.lexer)?, Tokens::Default => read_tokens(self)?,
Tokens::Provided(tokens) => tokens, Tokens::Provided(tokens, size) => (tokens, size),
}; };
while let Some(token) = self.tokens.pop() { // the parser uses conditional indirection in many places so
self.shift_token(token, op_dir)?; // the reserved size should be at least 3 * term_byte_size
// so all cells are accounted for.
let writer = match self.machine_st.heap.reserve(cell_index!(3 * term_byte_size)) {
Ok(term) => term,
Err(_err_loc) => {
return Err(ParserError::ResourceError(self.loc_to_err_src()));
}
};
let before_len = writer.cell_len();
let mut parser_impl = Parser {
tokens,
stack: vec![],
terms: writer,
arena: &mut self.machine_st.arena,
flags: self.machine_st.flags,
line_num: &mut self.line_num,
col_num: &mut self.col_num,
var_locs: VarLocs::default(),
inverse_var_locs: InverseVarLocs::default(),
};
while let Some(token) = parser_impl.tokens.pop() {
parser_impl.shift_token(token, op_dir)?;
} }
self.reduce_op(1400); parser_impl.reduce_op(1400);
if self.stack.len() > 1 || self.terms.is_empty() { let after_len = parser_impl.terms.cell_len();
debug_assert!(after_len - before_len <= cell_index!(4 * term_byte_size));
if parser_impl.stack.len() > 1 || parser_impl.terms.is_empty() {
return Err(ParserError::IncompleteReduction( return Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), parser_impl.loc_to_err_src(),
)); ));
} }
match self.stack.pop() { match parser_impl.stack.pop() {
Some(TokenDesc { Some(TokenDesc {
tt: TokenType::Term { heap_loc }, tt: TokenType::Term { heap_loc },
.. ..
}) => Ok(FocusedHeap { }) => Ok(TermWriteResult {
heap: mem::replace(&mut self.terms, vec![]),
focus: heap_loc.get_value() as usize, focus: heap_loc.get_value() as usize,
inverse_var_locs: mem::replace(&mut self.inverse_var_locs, InverseVarLocs::default()), inverse_var_locs: parser_impl.inverse_var_locs,
}), }),
_ => Err(ParserError::IncompleteReduction( _ => Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(), parser_impl.loc_to_err_src(),
)), )),
} }
} }

View File

@@ -3,9 +3,10 @@ use crate::parser::parser::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::machine::machine_errors::*; use crate::machine::machine_errors::*;
use crate::machine::machine_state::{MachineState, copy_and_align_iter}; use crate::machine::machine_state::MachineState;
use crate::machine::streams::*; use crate::machine::streams::*;
use crate::parser::char_reader::*; use crate::parser::char_reader::*;
use crate::parser::lexer::LexerParser;
#[cfg(feature = "repl")] #[cfg(feature = "repl")]
use crate::repl_helper::Helper; use crate::repl_helper::Helper;
@@ -22,9 +23,9 @@ use std::io::{Error, ErrorKind};
use std::sync::Arc; use std::sync::Arc;
pub(crate) fn devour_whitespace<R: CharRead>( pub(crate) fn devour_whitespace<R: CharRead>(
parser: &mut Parser<'_, R>, lexer: &mut LexerParser<'_, R>,
) -> Result<bool, ParserError> { ) -> Result<bool, ParserError> {
match parser.lexer.scan_for_layout() { match lexer.scan_for_layout() {
Err(e) if e.is_unexpected_eof() => Ok(true), Err(e) if e.is_unexpected_eof() => Ok(true),
Err(e) => Err(e), Err(e) => Err(e),
Ok(_) => Ok(false), Ok(_) => Ok(false),
@@ -47,35 +48,17 @@ pub(crate) fn error_after_read_term(
CompilationError::from(err) CompilationError::from(err)
} }
impl FocusedHeap {
pub fn to_machine_heap(mut self, machine_st: &mut MachineState) -> TermWriteResult {
let heap_len = machine_st.heap.len();
machine_st.heap.extend(copy_and_align_iter(self.heap.drain(..), 0, heap_len as i64));
let mut inverse_var_locs = InverseVarLocs::default();
for (var_loc, var_name) in self.inverse_var_locs.drain(..) {
inverse_var_locs.insert(var_loc + heap_len, var_name);
}
TermWriteResult {
heap_loc: self.focus + heap_len,
inverse_var_locs,
}
}
}
impl MachineState { impl MachineState {
pub(crate) fn read<R: CharRead>( pub(crate) fn read<R: CharRead>(
&mut self, &mut self,
inner: R, inner: R,
op_dir: &OpDir, op_dir: &OpDir,
) -> Result<(FocusedHeap, usize), ParserError> { ) -> Result<(TermWriteResult, usize), ParserError> {
let mut parser = Parser::new(inner, self); let mut lexer_parser = LexerParser::new(inner, self);
let op_dir = CompositeOpDir::new(op_dir, None); let op_dir = CompositeOpDir::new(op_dir, None);
let term_result = parser.read_term(&op_dir, Tokens::Default); let term_result = lexer_parser.read_term(&op_dir, Tokens::Default);
let lines_read = parser.lines_read(); let lines_read = lexer_parser.line_num();
term_result.map(|term| (term, lines_read)) term_result.map(|term| (term, lines_read))
} }
@@ -96,7 +79,7 @@ impl MachineState {
} }
}; };
Ok(term.to_machine_heap(self)) Ok(term)
} }
} }
@@ -305,9 +288,3 @@ impl CharRead for ReadlineStream {
self.pending_input.put_back_char(c); self.pending_input.put_back_char(c);
} }
} }
#[derive(Debug)]
pub struct TermWriteResult {
pub heap_loc: usize,
pub inverse_var_locs: InverseVarLocs,
}

View File

@@ -6,7 +6,7 @@ use rustyline::{Context, Helper as RlHelper, Result};
use std::sync::Weak; use std::sync::Weak;
use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP}; use crate::atom_table::{AtomString, AtomTable}; //, STATIC_ATOMS_MAP};
// TODO: Maybe add validation to the helper // TODO: Maybe add validation to the helper
pub struct Helper { pub struct Helper {
@@ -74,7 +74,7 @@ impl Completer for Helper {
let mut matching = index_set let mut matching = index_set
.iter() .iter()
.chain(STATIC_ATOMS_MAP.values()) // .chain(STATIC_ATOMS_MAP.values())
.map(|a| a.as_str()) .map(|a| a.as_str())
.filter(|a| a.starts_with(sub_str)) .filter(|a| a.starts_with(sub_str))
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View File

@@ -5,22 +5,24 @@ use crate::forms::*;
use crate::instructions::*; use crate::instructions::*;
use crate::types::*; use crate::types::*;
use std::rc::Rc;
pub(crate) struct FactInstruction; pub(crate) struct FactInstruction;
pub(crate) struct QueryInstruction; pub(crate) struct QueryInstruction;
pub(crate) trait CompilationTarget<'a> { pub(crate) trait CompilationTarget<'a> {
fn to_constant(lvl: Level, literal: Literal, r: RegType) -> Instruction; fn to_constant(lvl: Level, cell: HeapCellValue, r: RegType) -> Instruction;
fn to_list(lvl: Level, r: RegType) -> Instruction; fn to_list(lvl: Level, r: RegType) -> Instruction;
fn to_structure(lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction; fn to_structure(lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction;
fn to_void(num_subterms: usize) -> Instruction; fn to_void(num_subterms: usize) -> Instruction;
fn is_void_instr(instr: &Instruction) -> bool; fn is_void_instr(instr: &Instruction) -> bool;
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction; fn to_pstr(lvl: Level, string: Rc<String>, r: RegType) -> Instruction;
fn incr_void_instr(instr: &mut Instruction); fn incr_void_instr(instr: &mut Instruction);
fn constant_subterm(literal: Literal) -> Instruction; fn constant_subterm(literal: HeapCellValue) -> Instruction;
fn argument_to_variable(r: RegType, r: usize) -> Instruction; fn argument_to_variable(r: RegType, r: usize) -> Instruction;
fn argument_to_value(r: RegType, val: usize) -> Instruction; fn argument_to_value(r: RegType, val: usize) -> Instruction;
@@ -36,8 +38,8 @@ pub(crate) trait CompilationTarget<'a> {
} }
impl<'a> CompilationTarget<'a> for FactInstruction { impl<'a> CompilationTarget<'a> for FactInstruction {
fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction { fn to_constant(lvl: Level, cell: HeapCellValue, reg: RegType) -> Instruction {
Instruction::GetConstant(lvl, HeapCellValue::from(constant), reg) Instruction::GetConstant(lvl, cell, reg)
} }
fn to_structure(lvl: Level, name: Atom, arity: usize, reg: RegType) -> Instruction { fn to_structure(lvl: Level, name: Atom, arity: usize, reg: RegType) -> Instruction {
@@ -56,8 +58,8 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
matches!(instr, &Instruction::UnifyVoid(_)) matches!(instr, &Instruction::UnifyVoid(_))
} }
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction { fn to_pstr(lvl: Level, string: Rc<String>, r: RegType) -> Instruction {
Instruction::GetPartialString(lvl, string, r, has_tail) Instruction::GetPartialString(lvl, string, r)
} }
fn incr_void_instr(instr: &mut Instruction) { fn incr_void_instr(instr: &mut Instruction) {
@@ -66,8 +68,8 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
} }
} }
fn constant_subterm(constant: Literal) -> Instruction { fn constant_subterm(constant: HeapCellValue) -> Instruction {
Instruction::UnifyConstant(HeapCellValue::from(constant)) Instruction::UnifyConstant(constant)
} }
fn argument_to_variable(arg: RegType, val: usize) -> Instruction { fn argument_to_variable(arg: RegType, val: usize) -> Instruction {
@@ -104,20 +106,20 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
} }
impl<'a> CompilationTarget<'a> for QueryInstruction { impl<'a> CompilationTarget<'a> for QueryInstruction {
fn to_structure(_lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction { fn to_constant(lvl: Level, constant: HeapCellValue, reg: RegType) -> Instruction {
Instruction::PutStructure(name, arity, r) Instruction::PutConstant(lvl, constant, reg)
} }
fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction { fn to_structure(_lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction {
Instruction::PutConstant(lvl, HeapCellValue::from(constant), reg) Instruction::PutStructure(name, arity, r)
} }
fn to_list(lvl: Level, reg: RegType) -> Instruction { fn to_list(lvl: Level, reg: RegType) -> Instruction {
Instruction::PutList(lvl, reg) Instruction::PutList(lvl, reg)
} }
fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction { fn to_pstr(lvl: Level, string: Rc<String>, r: RegType) -> Instruction {
Instruction::PutPartialString(lvl, string, r, has_tail) Instruction::PutPartialString(lvl, string, r)
} }
fn to_void(subterms: usize) -> Instruction { fn to_void(subterms: usize) -> Instruction {
@@ -134,8 +136,8 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
} }
} }
fn constant_subterm(constant: Literal) -> Instruction { fn constant_subterm(constant: HeapCellValue) -> Instruction {
Instruction::SetConstant(HeapCellValue::from(constant)) Instruction::SetConstant(constant)
} }
fn argument_to_variable(arg: RegType, val: usize) -> Instruction { fn argument_to_variable(arg: RegType, val: usize) -> Instruction {

View File

@@ -14,7 +14,7 @@ test_queries_on_call_with_inference_limit :-
error, error,
true), true),
\+ call_with_inference_limit(g(X), 5, R), \+ call_with_inference_limit(g(X), 5, R),
maplist(assertz, [g(1), g(2), g(3), g(4), g(5)]), % TODO this line fails! maplist(assertz, [g(1), g(2), g(3), g(4), g(5)]),
findall([R,X], findall([R,X],
call_with_inference_limit(g(X), 11, R), call_with_inference_limit(g(X), 11, R),
[[true, 1], [[true, 1],

View File

@@ -3,8 +3,8 @@
use crate::arena::*; use crate::arena::*;
use crate::atom_table::*; use crate::atom_table::*;
use crate::forms::*; use crate::forms::*;
use crate::machine::heap::*;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::partial_string::PartialString;
use crate::machine::streams::*; use crate::machine::streams::*;
use crate::parser::ast::Fixnum; use crate::parser::ast::Fixnum;
@@ -15,59 +15,64 @@ use std::mem;
use std::ops::{Add, Sub, SubAssign}; use std::ops::{Add, Sub, SubAssign};
#[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]
#[bits = 6] #[bits = 6]
pub enum HeapCellValueTag { pub enum HeapCellValueTag {
Str = 0b000011, Str = 0b000001,
Lis = 0b000101, Lis = 0b000101,
Var = 0b000111, Var = 0b001011,
StackVar = 0b001001, StackVar = 0b001101,
AttrVar = 0b001011, AttrVar = 0b010001,
PStrLoc = 0b001101, PStrLoc = 0b010011,
PStrOffset = 0b001111,
// constants. // constants.
Cons = 0b0, Cons = 0b0,
F64 = 0b010001, F64 = 0b010101,
Fixnum = 0b010011, Fixnum = 0b011001,
Char = 0b010101, // Char = 0b011011,
Atom = 0b010111, Atom = 0b011111,
PStr = 0b011001, CutPoint = 0b011101,
CStr = 0b011011, // trail elements.
CutPoint = 0b011111, TrailedHeapVar = 0b100001,
TrailedStackVar = 0b100011,
TrailedAttrVar = 0b100101,
TrailedAttrVarListLink = 0b101001,
TrailedAttachedValue = 0b101011,
TrailedBlackboardEntry = 0b101101,
TrailedBlackboardOffset = 0b110001,
} }
#[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]
#[bits = 6] #[bits = 6]
pub enum HeapCellValueView { pub enum HeapCellValueView {
Str = 0b000011, Str = 0b000001,
Lis = 0b000101, Lis = 0b000101,
Var = 0b000111, Var = 0b001011,
StackVar = 0b001001, StackVar = 0b001101,
AttrVar = 0b001011, AttrVar = 0b010001,
PStrLoc = 0b001101, PStrLoc = 0b010011,
PStrOffset = 0b001111,
// constants. // constants.
Cons = 0b0, Cons = 0b0,
F64 = 0b010001, F64 = 0b010101,
Fixnum = 0b010011, Fixnum = 0b011001,
Char = 0b010101, Char = 0b011011,
Atom = 0b010111, Atom = 0b011111,
PStr = 0b011001, CutPoint = 0b011101,
CStr = 0b011011,
CutPoint = 0b011111,
// trail elements. // trail elements.
TrailedHeapVar = 0b101111, TrailedHeapVar = 0b100001,
TrailedStackVar = 0b101011, TrailedStackVar = 0b100011,
TrailedAttrVar = 0b100001, TrailedAttrVar = 0b100101,
TrailedAttrVarListLink = 0b100011, TrailedAttrVarListLink = 0b101001,
TrailedAttachedValue = 0b100101, TrailedAttachedValue = 0b101011,
TrailedBlackboardEntry = 0b100111, TrailedBlackboardEntry = 0b101101,
TrailedBlackboardOffset = 0b110011, TrailedBlackboardOffset = 0b110001,
} }
#[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] #[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[bits = 1] #[bits = 1]
pub enum ConsPtrMaskTag { pub enum ConsPtrMaskTag {
Cons = 0b0, Cons = 0b0,
Atom = 0b1,
} }
#[bitfield] #[bitfield]
@@ -105,9 +110,9 @@ impl ConsPtr {
#[derive(BitfieldSpecifier, Copy, Clone, Debug)] #[derive(BitfieldSpecifier, Copy, Clone, Debug)]
#[bits = 6] #[bits = 6]
pub(crate) enum RefTag { pub(crate) enum RefTag {
HeapCell = 0b000111, HeapCell = 0b001011,
StackCell = 0b001001, StackCell = 0b001101,
AttrVar = 0b001011, AttrVar = 0b010001,
} }
#[bitfield] #[bitfield]
@@ -245,6 +250,7 @@ pub struct HeapCellValue {
val: B56, val: B56,
f: bool, f: bool,
m: bool, m: bool,
#[allow(dead_code)]
tag: HeapCellValueTag, tag: HeapCellValueTag,
} }
@@ -279,6 +285,7 @@ impl fmt::Debug for HeapCellValue {
.field("f", &self.f()) .field("f", &self.f())
.finish() .finish()
} }
/*
HeapCellValueTag::PStr => { HeapCellValueTag::PStr => {
let (name, _) = cell_as_atom_cell!(self).get_name_and_arity(); let (name, _) = cell_as_atom_cell!(self).get_name_and_arity();
@@ -289,6 +296,7 @@ impl fmt::Debug for HeapCellValue {
.field("f", &self.f()) .field("f", &self.f())
.finish() .finish()
} }
*/
tag => f tag => f
.debug_struct("HeapCellValue") .debug_struct("HeapCellValue")
.field("tag", &tag) .field("tag", &tag)
@@ -354,19 +362,15 @@ impl HeapCellValue {
} }
#[inline] #[inline]
pub fn is_string_terminator(mut self, heap: &[HeapCellValue]) -> bool { pub fn is_string_terminator(mut self, heap: &impl SizedHeap) -> bool {
use crate::machine::heap::*;
loop { loop {
return read_heap_cell!(self, return read_heap_cell!(self,
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
name == atom!("[]") && arity == 0 name == atom!("[]") && arity == 0
} }
(HeapCellValueTag::CStr) => {
true
}
(HeapCellValueTag::PStrLoc, h) => { (HeapCellValueTag::PStrLoc, h) => {
self = heap[h]; let (_s, tail_loc) = heap.scan_slice_to_str(h);
self = heap[tail_loc];
continue; continue;
} }
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => { (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
@@ -379,9 +383,6 @@ impl HeapCellValue {
self = cell; self = cell;
continue; continue;
} }
(HeapCellValueTag::PStrOffset, pstr_offset) => {
heap[pstr_offset].get_tag() == HeapCellValueTag::CStr
}
_ => { _ => {
false false
} }
@@ -399,16 +400,13 @@ impl HeapCellValue {
| HeapCellValueTag::StackVar | HeapCellValueTag::StackVar
| HeapCellValueTag::AttrVar | HeapCellValueTag::AttrVar
| HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrLoc
| HeapCellValueTag::PStrOffset // | HeapCellValueTag::PStrOffset
) )
} }
#[inline] #[inline]
pub fn as_char(self) -> Option<char> { pub fn as_char(self) -> Option<char> {
read_heap_cell!(self, read_heap_cell!(self,
(HeapCellValueTag::Char, c) => {
Some(c)
}
(HeapCellValueTag::Atom, (name, arity)) => { (HeapCellValueTag::Atom, (name, arity)) => {
if arity > 0 { if arity > 0 {
return None; return None;
@@ -428,9 +426,7 @@ impl HeapCellValue {
HeapCellValueTag::Cons HeapCellValueTag::Cons
| HeapCellValueTag::F64 | HeapCellValueTag::F64
| HeapCellValueTag::Fixnum | HeapCellValueTag::Fixnum
| HeapCellValueTag::CutPoint | HeapCellValueTag::CutPoint => true,
| HeapCellValueTag::Char
| HeapCellValueTag::CStr => true,
HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0, HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0,
_ => false, _ => false,
} }
@@ -442,16 +438,12 @@ impl HeapCellValue {
} }
#[inline] #[inline]
pub fn is_compound(self, heap: &[HeapCellValue]) -> bool { pub fn is_compound(self, heap: &Heap) -> bool {
match self.get_tag() { match self.get_tag() {
HeapCellValueTag::Str => { HeapCellValueTag::Str => {
cell_as_atom_cell!(heap[self.get_value() as usize]).get_arity() > 0 cell_as_atom_cell!(heap[self.get_value() as usize]).get_arity() > 0
} }
HeapCellValueTag::Lis HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc => true,
| HeapCellValueTag::CStr
| HeapCellValueTag::PStr
| HeapCellValueTag::PStrLoc
| HeapCellValueTag::PStrOffset => true,
HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() > 0, HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() > 0,
_ => false, _ => false,
} }
@@ -502,6 +494,7 @@ impl HeapCellValue {
match self.tag_or_err() { match self.tag_or_err() {
Ok(tag) => tag, Ok(tag) => tag,
Err(_) => match ConsPtr::from_bytes(self.into_bytes()).tag() { Err(_) => match ConsPtr::from_bytes(self.into_bytes()).tag() {
ConsPtrMaskTag::Atom => HeapCellValueTag::Atom,
ConsPtrMaskTag::Cons => HeapCellValueTag::Cons, ConsPtrMaskTag::Cons => HeapCellValueTag::Cons,
}, },
} }
@@ -509,16 +502,10 @@ impl HeapCellValue {
#[inline] #[inline]
pub fn to_atom(self) -> Option<Atom> { pub fn to_atom(self) -> Option<Atom> {
match self.tag() { match self.get_tag() {
HeapCellValueTag::Atom => Some(Atom::from(self.val() << 3)), HeapCellValueTag::Atom => {
_ => None, Some(AtomCell::from_bytes(self.into_bytes()).get_name())
} }
}
#[inline]
pub fn to_pstr(self) -> Option<PartialString> {
match self.tag() {
HeapCellValueTag::PStr => Some(PartialString::from(Atom::from(self.val() << 3))),
_ => None, _ => None,
} }
} }
@@ -593,7 +580,7 @@ impl HeapCellValue {
} }
} }
pub fn order_category(self, heap: &[HeapCellValue]) -> Option<TermOrderCategory> { pub fn order_category(self, heap: &Heap) -> Option<TermOrderCategory> {
match Number::try_from(self).ok() { match Number::try_from(self).ok() {
Some(Number::Integer(_)) | Some(Number::Fixnum(_)) | Some(Number::Rational(_)) => { Some(Number::Integer(_)) | Some(Number::Fixnum(_)) | Some(Number::Rational(_)) => {
Some(TermOrderCategory::Integer) Some(TermOrderCategory::Integer)
@@ -603,13 +590,14 @@ impl HeapCellValue {
HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar => { HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar => {
Some(TermOrderCategory::Variable) Some(TermOrderCategory::Variable)
} }
HeapCellValueTag::Char => Some(TermOrderCategory::Atom), // HeapCellValueTag::Char => Some(TermOrderCategory::Atom),
HeapCellValueTag::Atom => Some(if cell_as_atom_cell!(self).get_arity() > 0 { HeapCellValueTag::Atom => Some(if cell_as_atom_cell!(self).get_arity() > 0 {
TermOrderCategory::Compound TermOrderCategory::Compound
} else { } else {
TermOrderCategory::Atom TermOrderCategory::Atom
}), }),
HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr => { HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc => {
// | HeapCellValueTag::CStr => {
Some(TermOrderCategory::Compound) Some(TermOrderCategory::Compound)
} }
HeapCellValueTag::Str => { HeapCellValueTag::Str => {
@@ -734,12 +722,14 @@ impl Add<usize> for HeapCellValue {
match self.get_tag() { match self.get_tag() {
tag @ HeapCellValueTag::Str tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis | tag @ HeapCellValueTag::Lis
| tag @ HeapCellValueTag::PStrOffset
| tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var | tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => { | tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, (self.get_value() as usize + rhs) as u64) HeapCellValue::build_with(tag, (self.get_value() as usize + rhs) as u64)
} }
tag @ HeapCellValueTag::PStrLoc => {
let value = (self.get_value() as usize + heap_index!(rhs)) as u64;
HeapCellValue::build_with(tag, value)
}
_ => self, _ => self,
} }
} }
@@ -752,12 +742,14 @@ impl Sub<usize> for HeapCellValue {
match self.get_tag() { match self.get_tag() {
tag @ HeapCellValueTag::Str tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis | tag @ HeapCellValueTag::Lis
| tag @ HeapCellValueTag::PStrOffset
| tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var | tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => { | tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, (self.get_value() as usize - rhs) as u64) HeapCellValue::build_with(tag, (self.get_value() as usize - rhs) as u64)
} }
tag @ HeapCellValueTag::PStrLoc => {
let value = self.get_value() as usize - heap_index!(rhs);
HeapCellValue::build_with(tag, value as u64)
}
_ => self, _ => self,
} }
} }
@@ -778,12 +770,14 @@ impl Sub<i64> for HeapCellValue {
match self.get_tag() { match self.get_tag() {
tag @ HeapCellValueTag::Str tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis | tag @ HeapCellValueTag::Lis
| tag @ HeapCellValueTag::PStrOffset
| tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var | tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => { | tag @ HeapCellValueTag::AttrVar => {
HeapCellValue::build_with(tag, self.get_value() + rhs.unsigned_abs()) HeapCellValue::build_with(tag, self.get_value() + rhs.unsigned_abs())
} }
tag @ HeapCellValueTag::PStrLoc => {
let value = self.get_value() as usize + heap_index!(rhs.unsigned_abs() as usize);
HeapCellValue::build_with(tag, value as u64)
}
_ => self, _ => self,
} }
} else { } else {