introduce bespoke Heap type for in-heap partial strings
This commit is contained in:
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -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:
|
||||||
|
|||||||
@@ -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)|*
|
||||||
|
|||||||
@@ -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 } },)*
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
37
src/arena.rs
37
src/arena.rs
@@ -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!() }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
231
src/codegen.rs
231
src/codegen.rs
@@ -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,
|
||||||
)?
|
)?
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
233
src/forms.rs
233
src/forms.rs
@@ -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
616
src/functor_macro.rs
Normal 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!());
|
||||||
|
}
|
||||||
|
}
|
||||||
1221
src/heap_iter.rs
1221
src/heap_iter.rs
File diff suppressed because it is too large
Load Diff
@@ -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));
|
||||||
|
|||||||
@@ -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,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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([]).
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
1268
src/machine/gc.rs
1268
src/machine/gc.rs
File diff suppressed because it is too large
Load Diff
1444
src/machine/heap.rs
1444
src/machine/heap.rs
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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..) {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>;
|
||||||
|
|||||||
@@ -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
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
235
src/macros.rs
235
src/macros.rs
@@ -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>())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 }
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/read.rs
41
src/read.rs
@@ -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,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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<_>>();
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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],
|
||||||
|
|||||||
152
src/types.rs
152
src/types.rs
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user