# Cargo.toml rust-version
- { os: ubuntu-22.04, rust-version: "1.85", target: 'x86_64-unknown-linux-gnu'}
# 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: nightly, target: 'x86_64-unknown-linux-gnu', miri: true, components: "miri"}
defaults:
*/
use std::any::*;
+use std::rc::Rc;
use std::str::FromStr;
struct ArithmeticTerm;
struct HeapCellValue;
struct IndexingLine;
struct Level;
+// struct Literal;
struct NextOrFail;
struct RegType;
#[strum_discriminants(strum(props(Arity = "2", Name = "get_list")))]
GetList(Level, RegType),
#[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")))]
GetStructure(Level, Atom, usize, RegType),
#[strum_discriminants(strum(props(Arity = "2", Name = "get_variable")))]
#[strum_discriminants(strum(props(Arity = "2", Name = "put_list")))]
PutList(Level, RegType),
#[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")))]
PutStructure(Atom, usize, RegType),
#[strum_discriminants(strum(props(Arity = "2", Name = "put_unsafe_value")))]
use crate::arithmetic::*;
use crate::atom_table::*;
use crate::forms::*;
+ use crate::functor_macro::*;
use crate::machine::heap::*;
use crate::machine::machine_errors::MachineStub;
use crate::machine::machine_indices::CodeIndex;
use indexmap::IndexMap;
use std::collections::VecDeque;
+ use std::rc::Rc;
fn reg_type_into_functor(r: RegType) -> MachineStub {
match r {
impl Level {
fn into_functor(self) -> MachineStub {
match self {
- Level::Root => functor!(atom!("level"), [atom(atom!("root"))]),
- Level::Shallow => functor!(atom!("level"), [atom(atom!("shallow"))]),
- Level::Deep => functor!(atom!("level"), [atom(atom!("deep"))]),
+ Level::Root => functor!(atom!("level"), [atom_as_cell((atom!("root")))]),
+ Level::Shallow => functor!(atom!("level"), [atom_as_cell((atom!("shallow")))]),
+ Level::Deep => functor!(atom!("level"), [atom_as_cell((atom!("deep")))]),
}
}
}
functor!(atom!("intermediate"), [fixnum(i)])
}
ArithmeticTerm::Number(n) => {
- functor!(atom!("number"), [cell(HeapCellValue::from((n, arena)))])
+ functor!(atom!("number"), [number(n, arena)])
}
}
}
IndexingCodePtr,
IndexingCodePtr,
),
- SwitchOnConstant(IndexMap<Literal, IndexingCodePtr, FxBuildHasher>),
+ SwitchOnConstant(IndexMap<HeapCellValue, IndexingCodePtr, FxBuildHasher>),
SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr, FxBuildHasher>),
}
IndexingCodePtr::External(o) => functor!(atom!("external"), [fixnum(o)]),
IndexingCodePtr::Internal(o) => functor!(atom!("internal"), [fixnum(o)]),
IndexingCodePtr::Fail => {
- vec![atom_as_cell!(atom!("fail"))]
+ functor!(atom!("fail"))
},
}
}
}
impl IndexingInstruction {
- pub fn to_functor(&self, mut h: usize) -> MachineStub {
+ pub fn to_functor(&self) -> MachineStub {
match self {
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
functor!(
atom!("switch_on_term"),
[
fixnum(arg),
- indexing_code_ptr(h, vars),
- indexing_code_ptr(h, constants),
- indexing_code_ptr(h, lists),
- indexing_code_ptr(h, structures)
+ indexing_code_ptr(vars),
+ indexing_code_ptr(constants),
+ indexing_code_ptr(lists),
+ indexing_code_ptr(structures)
]
)
}
IndexingInstruction::SwitchOnConstant(constants) => {
- let mut key_value_list_stub = vec![];
- let orig_h = h;
-
- h += 2; // skip the 2-cell "switch_on_constant" functor.
-
- for (c, ptr) in constants.iter() {
- let key_value_pair = functor!(
- 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]
+ variadic_functor(
+ atom!("switch_on_constants"),
+ 1,
+ constants.iter().map(|(c, ptr)| {
+ functor!(
+ atom!(":"),
+ [cell((c.clone())), indexing_code_ptr((*ptr))]
+ )
+ }),
)
}
IndexingInstruction::SwitchOnStructure(structures) => {
- let mut key_value_list_stub = vec![];
- 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!(
+ variadic_functor(
atom!("switch_on_structure"),
- [str(orig_h, 0)],
- [key_value_list_stub]
+ 1,
+ structures.iter().map(|((name, arity), ptr)| {
+ functor!(
+ atom!(":"),
+ [functor((atom!("/")), [atom_as_cell(name), fixnum((*arity))]),
+ indexing_code_ptr((*ptr))]
+ )
+ }),
)
}
}
}
fn arith_instr_unary_functor(
- h: usize,
name: Atom,
arena: &mut Arena,
at: &ArithmeticTerm,
t: usize,
) -> MachineStub {
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(
- h: usize,
name: Atom,
arena: &mut Arena,
at_1: &ArithmeticTerm,
let at_1_stub = at_1.into_functor(arena);
let at_2_stub = at_2.into_functor(arena);
- functor!(
- name,
- [str(h, 0), str(h, 1), fixnum(t)],
- [at_1_stub, at_2_stub]
- )
+ functor!(name, [functor(at_1_stub),
+ functor(at_2_stub),
+ fixnum(t)])
}
pub type Code = Vec<Instruction>;
match *self {
Instruction::GetConstant(_, _, r) => vec![r],
Instruction::GetList(_, r) => vec![r],
- Instruction::GetPartialString(_, _, r, _) => vec![r],
+ Instruction::GetPartialString(_, _, r) => vec![r],
Instruction::GetStructure(_, _, _, r) => vec![r],
Instruction::GetVariable(r, t) => vec![r, temp_v!(t)],
Instruction::GetValue(r, t) => vec![r, temp_v!(t)],
Instruction::UnifyVariable(r) => vec![r],
Instruction::PutConstant(_, _, r) => vec![r],
Instruction::PutList(_, r) => vec![r],
- Instruction::PutPartialString(_, _, r, _) => vec![r],
+ Instruction::PutPartialString(_, _, r) => vec![r],
Instruction::PutStructure(_, _, r) => vec![r],
Instruction::PutValue(r, t) => vec![r, temp_v!(t)],
Instruction::PutVariable(r, t) => vec![r, temp_v!(t)],
pub fn enqueue_functors(
&self,
- mut h: usize,
arena: &mut Arena,
functors: &mut Vec<MachineStub>,
) {
for indexing_instr in indexing_instrs {
match indexing_instr {
IndexingLine::Indexing(indexing_instr) => {
- let section = indexing_instr.to_functor(h);
- h += section.len();
+ let section = indexing_instr.to_functor();
functors.push(section);
}
IndexingLine::IndexedChoice(indexed_choice_instrs) => {
for indexed_choice_instr in indexed_choice_instrs {
let section = indexed_choice_instr.to_functor();
- h += section.len();
functors.push(section);
}
}
IndexingLine::DynamicIndexedChoice(indexed_choice_instrs) => {
for indexed_choice_instr in indexed_choice_instrs {
- let section = functor!(atom!("dynamic"), [fixnum(*indexed_choice_instr)]);
-
- h += section.len();
+ let section = functor!(atom!("dynamic"),
+ [fixnum((*indexed_choice_instr))]);
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 {
&Instruction::InstallVerifyAttr => {
functor!(atom!("install_verify_attr"))
(Death::Infinity, NextOrFail::Next(i)) => {
functor!(
atom!("dynamic_else"),
- [fixnum(birth), atom(atom!("inf")), fixnum(i)]
+ [fixnum(birth), atom_as_cell((atom!("inf"))), fixnum(i)]
)
}
(Death::Infinity, NextOrFail::Fail(i)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
functor!(
atom!("dynamic_else"),
- [fixnum(birth), atom(atom!("inf")), str(h, 0)],
- [next_functor]
+ [fixnum(birth),
+ atom_as_cell((atom!("inf"))),
+ functor((atom!("fail")), [fixnum(i)])]
)
}
(Death::Finite(d), NextOrFail::Fail(i)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
functor!(
atom!("dynamic_else"),
- [fixnum(birth), fixnum(d), str(h, 0)],
- [next_functor]
+ [fixnum(birth),
+ fixnum(d),
+ functor((atom!("fail")), [fixnum(i)])]
)
}
(Death::Finite(d), NextOrFail::Next(i)) => {
(Death::Infinity, NextOrFail::Next(i)) => {
functor!(
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)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
functor!(
atom!("dynamic_internal_else"),
- [fixnum(birth), atom(atom!("inf")), str(h, 0)],
- [next_functor]
+ [fixnum(birth),
+ atom_as_cell((atom!("inf"))),
+ functor((atom!("fail")), [fixnum(i)])]
)
}
(Death::Finite(d), NextOrFail::Fail(i)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
functor!(
atom!("dynamic_internal_else"),
- [fixnum(birth), fixnum(d), str(h, 0)],
- [next_functor]
+ [fixnum(birth),
+ fixnum(d),
+ functor((atom!("fail")), [fixnum(i)])]
)
}
(Death::Finite(d), NextOrFail::Next(i)) => {
}
&Instruction::Cut(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) => {
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) => {
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) => {
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) => {
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 => {
functor!(atom!("neck_cut"))
}
&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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- 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) => {
- arith_instr_unary_functor(h, atom!("sign"), arena, at, t)
+ arith_instr_unary_functor(atom!("sign"), arena, 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) => {
- arith_instr_unary_functor(h, atom!("sin"), arena, at, t)
+ arith_instr_unary_functor(atom!("sin"), arena, 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) => {
- arith_instr_unary_functor(h, atom!("log"), arena, at, t)
+ arith_instr_unary_functor(atom!("log"), arena, 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) => {
- arith_instr_unary_functor(h, atom!("acos"), arena, at, t)
+ arith_instr_unary_functor(atom!("acos"), arena, 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) => {
- arith_instr_unary_functor(h, atom!("atan"), arena, at, t)
+ arith_instr_unary_functor(atom!("atan"), arena, 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) => {
- arith_instr_unary_functor(h, atom!("abs"), arena, at, t)
+ arith_instr_unary_functor(atom!("abs"), arena, 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) => {
- arith_instr_unary_functor(h, atom!("truncate"), arena, at, t)
+ arith_instr_unary_functor(atom!("truncate"), arena, 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) => {
- arith_instr_unary_functor(h, atom!("ceiling"), arena, at, t)
+ arith_instr_unary_functor(atom!("ceiling"), arena, 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) => {
- 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) => {
- 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(
- h,
atom!("-"),
arena,
at,
t,
),
&Instruction::Plus(ref at, t) => arith_instr_unary_functor(
- h,
atom!("+"),
arena,
at,
t,
),
&Instruction::BitwiseComplement(ref at, t) => arith_instr_unary_functor(
- h,
atom!("\\"),
arena,
at,
functor!(atom!("allocate"), [fixnum(num_frames)])
}
&Instruction::CallNamed(arity, name, ..) => {
- functor!(atom!("call"), [atom(name), fixnum(arity)])
+ functor!(atom!("call"), [atom_as_cell(name), fixnum(arity)])
}
&Instruction::ExecuteNamed(arity, name, ..) => {
- functor!(atom!("execute"), [atom(name), fixnum(arity)])
+ functor!(atom!("execute"), [atom_as_cell(name), fixnum(arity)])
}
&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, ..) => {
- functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
+ functor!(atom!("execute_default"), [atom_as_cell(name), fixnum(arity)])
}
&Instruction::CallN(arity) => {
functor!(atom!("call_n"), [fixnum(arity)])
&Instruction::CallSort |
&Instruction::CallGetNumber(_) => {
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::ExecuteSort |
&Instruction::ExecuteGetNumber(_) => {
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::DefaultCallSort |
&Instruction::DefaultCallGetNumber(_) => {
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::DefaultExecuteSort |
&Instruction::DefaultExecuteGetNumber(_) => {
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::CallIsAtomic(r) |
&Instruction::CallIsVar(r) => {
let (name, arity) = self.to_name_and_arity();
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::ExecuteIsAtomic(r) |
&Instruction::ExecuteIsVar(r) => {
let (name, arity) = self.to_name_and_arity();
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::CallEd25519VerifyRaw |
&Instruction::CallEd25519SeedToPublicKey => {
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")]
&Instruction::CallCryptoDataEncrypt |
&Instruction::CallCryptoDataDecrypt => {
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::ExecuteEd25519VerifyRaw |
&Instruction::ExecuteEd25519SeedToPublicKey => {
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")]
&Instruction::ExecuteCryptoDataEncrypt |
&Instruction::ExecuteCryptoDataDecrypt => {
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::Proceed => {
functor!(atom!("proceed"))
}
- &Instruction::GetConstant(lvl, c, r) => {
+ &Instruction::GetConstant(lvl, lit, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("get_constant"),
- [str(h, 0), cell(c), str(h, 1)],
- [lvl_stub, rt_stub]
- )
+ functor!(atom!("get_constant"), [functor(lvl_stub),
+ cell(lit),
+ functor(rt_stub)])
}
&Instruction::GetList(lvl, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("get_list"),
- [str(h, 0), str(h, 1)],
- [lvl_stub, rt_stub]
- )
+ functor!(atom!("get_list"), [functor(lvl_stub), functor(rt_stub)])
}
- &Instruction::GetPartialString(lvl, s, r, has_tail) => {
+ &Instruction::GetPartialString(lvl, ref s, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("get_partial_string"),
- [
- str(h, 0),
- string(h, s),
- str(h, 1),
- boolean(has_tail)
- ],
- [lvl_stub, rt_stub]
- )
+ functor!(atom!("get_partial_string"), [functor(lvl_stub),
+ string((s.to_string())),
+ functor(rt_stub)])
}
&Instruction::GetStructure(lvl, name, arity, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("get_structure"),
- [str(h, 0), atom(name), fixnum(arity), str(h, 1)],
- [lvl_stub, rt_stub]
- )
+ functor!(atom!("get_structure"), [functor(lvl_stub),
+ atom_as_cell(name),
+ fixnum(arity),
+ functor(rt_stub)])
}
&Instruction::GetValue(r, arg) => {
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) => {
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) => {
functor!(atom!("unify_constant"), [cell(c)])
}
&Instruction::UnifyLocalValue(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) => {
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) => {
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) => {
functor!(atom!("unify_void"), [fixnum(vars)])
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("put_constant"),
- [str(h, 0), cell(c), str(h, 1)],
- [lvl_stub, rt_stub]
- )
+ functor!(atom!("put_constant"), [functor(rt_stub), cell(c), functor(lvl_stub)])
}
&Instruction::PutList(lvl, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("put_list"),
- [str(h, 0), str(h, 1)],
- [lvl_stub, rt_stub]
- )
+ functor!(atom!("put_list"), [functor(lvl_stub), functor(rt_stub)])
}
- &Instruction::PutPartialString(lvl, s, r, has_tail) => {
+ &Instruction::PutPartialString(lvl, ref s, r) => {
let lvl_stub = lvl.into_functor();
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("put_partial_string"),
- [
- str(h, 0),
- string(h, s),
- str(h, 1),
- boolean(has_tail)
- ],
- [lvl_stub, rt_stub]
- )
+ functor!(atom!("put_partial_string"), [functor(lvl_stub),
+ string((s.to_string())),
+ functor(rt_stub)])
}
&Instruction::PutStructure(name, arity, r) => {
let rt_stub = reg_type_into_functor(r);
- functor!(
- atom!("put_structure"),
- [atom(name), fixnum(arity), str(h, 0)],
- [rt_stub]
- )
+ functor!(atom!("put_structure"), [atom_as_cell(name),
+ fixnum(arity),
+ functor(rt_stub)])
}
&Instruction::PutValue(r, arg) => {
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) => {
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) => {
functor!(atom!("set_constant"), [cell(c)])
}
&Instruction::SetLocalValue(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) => {
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) => {
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) => {
functor!(atom!("set_void"), [fixnum(vars)])
)
}
- pub fn name(&self) -> Atom {
- match self {
- #(
- #clause_type_name_arms,
- )*
- }
- }
-
pub fn is_inlined(name: Atom, arity: usize) -> bool {
matches!((name, arity),
#(#is_inlined_arms)|*
}
}
+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 {
use quote::*;
visitor.visit_file(&syntax)
}
- let indices = (0..visitor.static_strs.len()).map(|i| (i << 3) as u64);
- let indices_iter = indices.clone();
+ let mut static_str_keys = vec![];
+ let mut static_strs = vec![];
+ let mut static_str_indices = vec![];
+
+ let indices: Vec<u64> = visitor.static_strs.iter().map(|string| {
+ 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 = visitor.static_strs.len();
- let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
+ let static_strs_len = static_strs.len(); // visitor.static_strs.len();
+ //let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
quote! {
static STRINGS: [&str; #static_strs_len] = [
];
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! {
- #(#static_strs => { Atom { index: #indices } },)*
+ #(#static_strs => { Atom { index: #static_str_indices } },)*
};
}
}
use crate::forms::*;
use crate::instructions::*;
+use crate::machine::heap::Heap;
use crate::targets::*;
pub(crate) trait Allocator {
fn reset(&mut self);
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 advance_arg(&mut self);
use crate::arena::*;
use crate::atom_table::*;
use crate::machine::mock_wam::*;
- use crate::machine::partial_string::*;
+ use crate::types::*;
use crate::parser::dashu::{Integer, Rational};
use ordered_float::OrderedFloat;
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);
let untyped_arena_ptr = match cell.to_untyped_arena_ptr() {
_ => { 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
let fixnum_cell = fixnum_as_cell!(Fixnum::build_with(3));
let char_cell = char_as_cell!(c);
read_heap_cell!(char_cell,
- (HeapCellValueTag::Char, c) => {
- assert_eq!(c, 'c');
+ (HeapCellValueTag::Atom, (c, _arity)) => {
+ assert_eq!(&*c.as_str(), "c");
}
_ => { unreachable!() }
);
let cyrillic_char_cell = char_as_cell!(c);
read_heap_cell!(cyrillic_char_cell,
- (HeapCellValueTag::Char, c) => {
- assert_eq!(c, 'Ћ');
+ (HeapCellValueTag::Atom, (c, _arity)) => {
+ assert_eq!(&*c.as_str(), "Ћ");
}
_ => { unreachable!() }
);
use crate::iterators::*;
use crate::machine::disjuncts::*;
use crate::machine::stack::Stack;
-use crate::parser::ast::FocusedHeap;
use crate::targets::QueryInstruction;
use crate::types::*;
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)]
pub(crate) struct ArithmeticEvaluator<'a> {
marker: &'a mut DebrayAllocator,
interm_c: usize,
}
-fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: Literal) -> Result<(), ArithmeticError> {
- match c {
- Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(n))),
- Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(n))),
- Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))),
- Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(n))),
- Literal::Atom(name) if name == atom!("e") => interm.push(ArithmeticTerm::Number(
- Number::Float(OrderedFloat(std::f64::consts::E)),
- )),
- Literal::Atom(name) if name == atom!("pi") => interm.push(ArithmeticTerm::Number(
- Number::Float(OrderedFloat(std::f64::consts::PI)),
- )),
- Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number(
- Number::Float(OrderedFloat(f64::EPSILON)),
- )),
- _ => return Err(ArithmeticError::NonEvaluableFunctor(HeapCellValue::from(c), 0)),
- }
+fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: HeapCellValue) -> Result<(), ArithmeticError> {
+ read_heap_cell!(c,
+ (HeapCellValueTag::Fixnum, n) => {
+ interm.push(ArithmeticTerm::Number(Number::Fixnum(n)))
+ }
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::Integer, n) => {
+ interm.push(ArithmeticTerm::Number(Number::Integer(n)));
+ }
+ (ArenaHeaderTag::Rational, n) => {
+ interm.push(ArithmeticTerm::Number(Number::Rational(n)));
+ }
+ _ => return Err(ArithmeticError::NonEvaluableFunctor(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(())
}
pub(crate) fn compile_is(
&mut self,
- src: &mut FocusedHeap,
+ src: &mut FocusedHeapRefMut,
term_loc: usize,
context: GenContext,
arg: usize,
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
- push_literal(&mut self.interm, Literal::Atom(name))?;
+ push_literal(&mut self.interm, atom_as_cell!(name))?;
} else {
code.push_back(self.instr_from_clause(name, arity)?);
}
}
_ => {
- match Literal::try_from(term) {
- Ok(lit) => push_literal(&mut self.interm, lit)?,
- _ => return Err(ArithmeticError::NonEvaluableFunctor(term, 0)),
- }
+ push_literal(&mut self.interm, term)?;
}
);
}
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)]
pub struct Atom {
pub index: u64,
}
-const_assert!(mem::size_of::<Atom>() == 8);
-
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 {
#[inline]
fn from(atom: &'a Atom) -> Self {
}
}
-impl From<bool> for Atom {
- #[inline]
- fn from(value: bool) -> Self {
- if value {
- atom!("true")
- } else {
- atom!("false")
- }
- }
-}
-
impl indexmap::Equivalent<Atom> for str {
fn equivalent(&self, key: &Atom) -> bool {
&*key.as_str() == self
#[inline]
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.as_str().hash(hasher)
- // hasher.write_usize(self.index)
}
}
pub enum AtomString<'a> {
Static(&'a str),
+ Inlined([u8;8]),
Dynamic(AtomTableRef<str>),
}
-impl AtomString<'_> {
- pub fn map<F>(self, f: F) -> Self
- where
- for<'a> F: FnOnce(&'a str) -> &'a str,
- {
- match self {
- Self::Static(reference) => Self::Static(f(reference)),
- Self::Dynamic(guard) => Self::Dynamic(AtomTableRef::map(guard, f)),
- }
+fn inlined_to_str<'a>(bytes: &'a [u8;8]) -> &'a str {
+ // allow the '\0\' atom to be represented as the 0-valued inlined atom
+ let slice_len = if bytes[0] == 0 {
+ 1
+ } else {
+ bytes.iter().position(|&b| b == 0u8).unwrap_or(INLINED_ATOM_MAX_LEN)
+ };
+
+ unsafe {
+ str::from_utf8_unchecked(&bytes[..slice_len])
}
}
fn deref(&self) -> &Self::Target {
match self {
Self::Static(reference) => reference,
+ Self::Inlined(inlined) => inlined_to_str(&inlined),
Self::Dynamic(guard) => guard.deref(),
}
}
}
impl Atom {
+ #[inline]
+ fn new_inlined(string: &str) -> Self {
+ AtomCell::new_inlined(string, 0).get_name()
+ }
+
#[inline(always)]
- pub fn is_static(self) -> bool {
- (self.index as usize) < STRINGS.len() << 3
+ 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)]
- pub fn as_ptr(self) -> Option<AtomTableRef<AtomData>> {
+ fn as_ptr(self) -> Option<AtomTableRef<AtomData>> {
if self.is_static() {
None
} else {
let ptr = buf
.block
.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
let atom_data = &*(std::ptr::slice_from_raw_parts(ptr, 0) as *const AtomData);
let len = atom_data.header.len();
#[inline(always)]
pub fn len(self) -> usize {
- if self.is_static() {
- STRINGS[(self.index >> 3) as usize].len()
+ if let Some(s) = self.inlined_str() {
+ s.len()
+ } else if self.is_static() {
+ let index = self.flat_index();
+ STRINGS[index as usize].len()
} else {
let len: u64 = self.as_ptr().unwrap().header.len();
len as usize
self.len() == 0
}
- #[inline(always)]
- pub fn flat_index(self) -> u64 {
- self.index >> 3
- }
-
pub fn as_char(self) -> Option<char> {
let s = self.as_str();
let mut it = s.chars();
}
}
+ #[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]
pub fn as_str(&self) -> AtomString<'static> {
- if self.is_static() {
- AtomString::Static(STRINGS[(self.index >> 3) as usize])
+ if let Some(s) = self.inlined_str() {
+ 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() {
AtomString::Dynamic(AtomTableRef::map(ptr, |ptr| &ptr.data))
} else {
- AtomString::Static(STRINGS[(self.index >> 3) as usize])
+ AtomString::Static(STRINGS[(self.index >> 1) as usize])
}
}
}
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 {
let mut block_epoch = atom_table.inner.read();
let mut table_epoch = block_epoch.table.read();
write_to_ptr(string, len_ptr);
- let atom = Atom {
- index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
- };
+ let atom = AtomCell::new()
+ .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();
table.insert(atom);
unsafe impl Send for AtomTable {}
unsafe impl Sync for AtomTable {}
+/*
#[bitfield]
#[repr(u64)]
#[derive(Copy, Clone, Debug)]
pub struct AtomCell {
- name: B46,
+ name: B48,
arity: B10,
#[allow(unused)]
f: bool,
#[allow(unused)]
m: bool,
#[allow(unused)]
- tag: B6,
+ inlined: bool,
+ #[allow(unused)]
+ tag: B3,
}
impl AtomCell {
(Atom::from((self.get_index() as u64) << 3), self.get_arity())
}
}
+*/
use crate::indexing::*;
use crate::instructions::*;
use crate::iterators::*;
-use crate::machine::heap::{heap_bound_deref, heap_bound_store};
+use crate::machine::heap::*;
use crate::parser::ast::*;
use crate::targets::*;
use crate::types::*;
use crate::machine::disjuncts::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::CodeIndex;
-use crate::machine::machine_state::pstr_loc_and_offset;
use crate::machine::stack::Stack;
use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use std::collections::VecDeque;
+use std::rc::Rc;
#[derive(Debug)]
pub struct BranchCodeStack {
}
#[derive(Debug)]
-pub(crate) struct CodeGenerator<'a> {
- pub(crate) atom_tbl: &'a AtomTable,
+pub(crate) struct CodeGenerator {
marker: DebrayAllocator,
settings: CodeGenSettings,
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 {
pub(crate) fn mark_non_callable(
&mut self,
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) {
self.marker.add_reg_to_free_list(r);
}
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)]
fn add_term_to_free_list(&mut self, _r: RegType) {}
fn add_index_ptr<'a, Target: crate::targets::CompilationTarget<'a>>(
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
- heap: &[HeapCellValue],
+ heap: &Heap,
arity: usize,
heap_loc: usize,
) -> Option<Instruction> {
match fetch_index_ptr(heap, arity, heap_loc) {
Some(index_ptr) => {
- let subterm = Literal::CodeIndex(index_ptr);
+ let subterm = HeapCellValue::from(index_ptr);
return Some(Target::constant_subterm(subterm));
}
None => {
// if Level::Shallow == lvl {
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));
}
// }
None
}
-impl<'b> CodeGenerator<'b> {
- pub(crate) fn new(atom_tbl: &'b AtomTable, settings: CodeGenSettings) -> Self {
+impl CodeGenerator {
+ pub(crate) fn new(settings: CodeGenSettings) -> Self {
CodeGenerator {
- atom_tbl,
marker: DebrayAllocator::new(),
settings,
skeleton: PredicateSkeleton::new(),
None
}
- (HeapCellValueTag::Atom, (name, arity)) => {
- debug_assert_eq!(arity, 0);
-
+ (HeapCellValueTag::Atom, (name, _arity)) => {
if index_ptrs.contains_key(&heap_loc) {
let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target);
target.push_back(Target::clause_arg_to_instr(r));
return Some(r);
} else {
- target.push_back(Target::constant_subterm(Literal::Atom(name)));
+ target.push_back(Target::constant_subterm(atom_as_cell!(name)));
}
None
}
(HeapCellValueTag::Str
| HeapCellValueTag::Lis
- | HeapCellValueTag::PStrLoc
- | HeapCellValueTag::CStr) => {
+ | HeapCellValueTag::PStrLoc) => {
let r = self.marker.mark_non_var::<Target>(Level::Deep, heap_loc, context, target);
target.push_back(Target::clause_arg_to_instr(r));
return Some(r);
}
_ => {
- match Literal::try_from(subterm) {
- Ok(lit) => target.push_back(Target::constant_subterm(lit)),
- Err(_) => unreachable!(),
- }
-
+ target.push_back(Target::constant_subterm(subterm));
None
}
)
where
Target: crate::targets::CompilationTarget<'a>,
Iter: TermIterator,
- CodeGenerator<'b>: AddToFreeList<'a, Target>,
+ CodeGenerator: AddToFreeList<'a, Target>,
{
let mut target = CodeDeque::new();
let chunk_num = context.chunk_num();
target.push_back(instr);
} else if lvl == Level::Shallow {
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 {
let r = self.marker.mark_non_var::<Target>(lvl, heap_loc, context, &mut target);
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,
r,
);
for r_opt in free_list_regs {
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,
);
}
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,
r,
);
);
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,
);
}
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,
);
}
}
- (HeapCellValueTag::CStr, cstr_atom) => {
- 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) => {
+ (HeapCellValueTag::PStrLoc, pstr_loc) => {
let heap_loc = iter.focus().value() as usize;
let (heap_loc, _) = subterm_index(iter.deref(), heap_loc);
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));
-
- 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));
+ target.push_back(Target::to_pstr(lvl, Rc::new(pstr_str.to_owned()), r));
+ let (tail_loc, tail) = subterm_index(iter.deref(), tail_loc);
self.subterm_to_instr::<Target>(
tail, tail_loc, context, index_ptrs, &mut target,
);
}
_ 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, _) = subterm_index(iter.deref(), heap_loc);
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));
}
}
_ => {}
fn compile_inlined(
&mut self,
ct: &InlinedClauseType,
- terms: &mut FocusedHeap,
+ terms: &mut FocusedHeapRefMut,
term_loc: usize,
context: GenContext,
code: &mut CodeDeque,
instr!("$fail")
}
}
- (HeapCellValueTag::Char) => {
- instr!("$succeed")
- }
_ => {
instr!("$fail")
}
} else {
read_heap_cell!(first_arg,
(HeapCellValueTag::Fixnum |
- HeapCellValueTag::Char |
HeapCellValueTag::F64) => {
instr!("$succeed")
}
}
(HeapCellValueTag::Lis
| HeapCellValueTag::Str
- | HeapCellValueTag::PStrLoc
- | HeapCellValueTag::CStr) => {
+ | HeapCellValueTag::PStrLoc) => {
instr!("$fail")
}
_ => {
- if Literal::try_from(first_arg).is_ok() {
+ if first_arg.is_constant() {
instr!("$succeed")
} else {
instr!("$fail")
}
(HeapCellValueTag::Lis
| HeapCellValueTag::Str
- | HeapCellValueTag::PStrLoc
- | HeapCellValueTag::CStr) => {
+ | HeapCellValueTag::PStrLoc) => {
instr!("$succeed")
}
_ => {
self.marker.reset_arg(1);
if let Some(r) = variable_marker(&mut self.marker) {
instr!("number", r)
+ } else if Number::try_from(first_arg).is_ok() {
+ instr!("$succeed")
} else {
- if Number::try_from(first_arg).is_ok() {
- instr!("$succeed")
- } else {
- instr!("$fail")
- }
+ instr!("$fail")
}
}
InlinedClauseType::IsNonVar(..) => {
if let Some(r) = variable_marker(&mut self.marker) {
instr!("nonvar", r)
+ } else if first_arg.is_var() {
+ instr!("$fail")
} else {
- if first_arg.is_var() {
- instr!("$fail")
- } else {
- instr!("$succeed")
- }
+ instr!("$succeed")
}
}
InlinedClauseType::IsInteger(..) => {
if let Some(r) = variable_marker(&mut self.marker) {
instr!("var", r)
+ } else if first_arg.is_var() {
+ instr!("$succeed")
} else {
- if first_arg.is_var() {
- instr!("$succeed")
- } else {
- instr!("$fail")
- }
+ instr!("$fail")
}
},
};
fn compile_arith_expr(
&mut self,
- terms: &mut FocusedHeap,
+ terms: &mut FocusedHeapRefMut,
term_loc: usize,
target_int: usize,
context: GenContext,
fn compile_is_call(
&mut self,
- terms: &mut FocusedHeap,
+ terms: &mut FocusedHeapRefMut,
term_loc: usize,
code: &mut CodeDeque,
context: GenContext,
self.marker.reset_arg(2);
- let var = {
- let var_cell = terms.heap[term_loc + 1];
- let terms = FocusedHeapRefMut::from_cell(&mut terms.heap, var_cell);
-
- terms.deref_loc(term_loc + 1)
- };
+ let var = heap_bound_store(
+ terms.heap,
+ heap_bound_deref(terms.heap, heap_loc_as_cell!(term_loc + 1)),
+ );
let at = read_heap_cell!(var,
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
fn compile_seq(
&mut self,
- focused_heap: &mut FocusedHeap,
+ mut focused_heap: FocusedHeapRefMut,
clauses: &ChunkedTermVec,
code: &mut CodeDeque,
) -> Result<(), CompilationError> {
..
},
) => self.compile_is_call(
- focused_heap,
+ &mut focused_heap,
clause.term_loc(),
branch_code_stack.code(code),
context,
},
) => self.compile_inlined(
ct,
- focused_heap,
+ &mut focused_heap,
clause.term_loc(),
context,
branch_code_stack.code(code),
&QueryTerm::Succeed => {
let code = branch_code_stack.code(code);
- if self.marker.in_tail_position {
- if self.marker.var_data.allocates {
- code.push_back(instr!("deallocate"));
- }
+ if self.marker.in_tail_position && self.marker.var_data.allocates {
+ code.push_back(instr!("deallocate"));
}
code.push_back(
if self.marker.in_tail_position {
- instr!("$succeed").to_execute()
+ instr!("$succeed").into_execute()
} else {
instr!("$succeed")
},
}
QueryTerm::Clause(clause) => {
self.compile_query_line(
- focused_heap,
+ &mut focused_heap,
clause,
context,
branch_code_stack.code(code),
pub(crate) fn compile_rule(
&mut self,
+ heap: &mut Heap,
rule: &mut Rule,
var_data: VarData,
) -> Result<Code, CompilationError> {
- let Rule {
- ref mut term,
- clauses,
- } = rule;
+ let Rule { term_loc, clauses } = rule;
+
self.marker.var_data = var_data;
+ let term = FocusedHeapRefMut { heap, focus: *term_loc };
let mut code = VecDeque::new();
+
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 iter = fact_iterator::<true>(
- &mut term.heap, &mut stack, head_loc,
- );
+ let iter = fact_iterator::<true>(term.heap, &mut stack, head_loc);
let fact = self.compile_target::<FactInstruction, _>(
iter,
pub(crate) fn compile_fact(
&mut self,
+ heap: &mut Heap,
fact: &mut Fact,
var_data: VarData,
) -> Result<Code, CompilationError> {
let mut code = Vec::new();
- let fact_focus = fact.term.focus;
let mut stack = Stack::uninitialized();
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>(
- &mut fact.term.heap, &mut stack, fact_focus,
- );
+ let iter = fact_iterator::<true>(heap, &mut stack, fact.term_loc);
let compiled_fact = self.compile_target::<FactInstruction, _>(
iter,
fn compile_query_line(
&mut self,
- term: &mut FocusedHeap,
+ term: &mut FocusedHeapRefMut,
clause: &QueryClause,
context: GenContext,
code: &mut CodeDeque,
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 left = 0;
let mut optimal_index = 0;
'outer: for (right, clause) in clauses.iter().enumerate() {
- if let Some(args) = clause.args() {
- for (instantiated_arg_index, arg) in args.iter().cloned().enumerate() {
- let arg = heap_bound_store(clause.heap(), heap_bound_deref(clause.heap(), arg));
+ if let Some(args) = clause.args(heap) {
+ for (instantiated_arg_index, arg_idx) in args.enumerate() {
+ let arg = heap[arg_idx];
+ let arg = heap_bound_store(heap, heap_bound_deref(heap, arg));
if !arg.is_var() {
if optimal_index != instantiated_arg_index {
fn compile_pred_subseq<I: Indexer>(
&mut self,
+ heap: &mut Heap,
clauses: &mut [PredicateClause],
optimal_index: usize,
) -> Result<Code, CompilationError> {
let clause_code = match clause {
PredicateClause::Fact(fact, 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) => {
let var_data = std::mem::take(var_data);
- self.compile_rule(rule, var_data)?
+ self.compile_rule(heap, rule, var_data)?
}
};
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();
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(
- clause.heap(),
+ heap,
arg,
index,
&mut clause_index_info,
- self.atom_tbl,
);
}
}
pub(crate) fn compile_predicate(
&mut self,
+ heap: &mut Heap,
mut clauses: Vec<PredicateClause>,
) -> Result<Code, CompilationError> {
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;
for ClauseSpan {
let skel_lower_bound = self.skeleton.clauses.len();
let code_segment = if self.settings.is_dynamic() {
self.compile_pred_subseq::<DynamicCodeIndices>(
+ heap,
&mut clauses[left..right],
instantiated_arg_index,
)?
} else {
self.compile_pred_subseq::<StaticCodeIndices>(
+ heap,
&mut clauses[left..right],
instantiated_arg_index,
)?
use crate::forms::{GenContext, Level};
use crate::instructions::*;
use crate::machine::disjuncts::*;
-use crate::machine::heap::{heap_bound_deref, heap_bound_store};
+use crate::machine::heap::*;
use crate::parser::ast::*;
use crate::targets::*;
use crate::types::*;
self.arg_c += 1;
}
- fn reset_at_head(&mut self, term: &mut FocusedHeap, head_loc: usize) {
- read_heap_cell!(term.deref_loc(head_loc),
+ fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize) {
+ 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) => {
- 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.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() {
let var = heap_bound_store(
- &term.heap,
- heap_bound_deref(&term.heap, arg),
+ heap,
+ heap_bound_deref(heap, arg),
);
if !var.is_var() {
use crate::arena::*;
use crate::atom_table::*;
use crate::instructions::*;
+use crate::functor_macro::*;
use crate::machine::disjuncts::VarData;
use crate::machine::heap::*;
-use crate::machine::loader::PredicateQueue;
+// use crate::machine::loader::PredicateQueue;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::parser::ast::*;
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)]
pub enum AppendOrPrepend {
Append,
.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 {
if self.current_chunk_type.is_last() {
self.current_chunk_type = ChunkType::Mid;
#[derive(Debug)]
pub struct QueryClause {
pub ct: ClauseType,
- pub arity: usize,
pub term: HeapCellValue,
pub code_indices: IndexMap<usize, CodeIndex, FxBuildHasher>,
pub call_policy: CallPolicy,
GetLevel(usize), // var_num
}
-#[derive(Debug)]
+#[derive(Clone, Copy, Debug)]
pub struct Fact {
- pub(crate) term: FocusedHeap,
+ pub(crate) term_loc: usize,
}
#[derive(Debug)]
pub struct Rule {
- pub(crate) term: FocusedHeap,
+ pub(crate) term_loc: usize,
pub(crate) clauses: ChunkedTermVec,
}
}
}
-pub trait ClauseInfo {
- fn is_consistent(&self, clauses: &PredicateQueue) -> bool {
- match clauses.first() {
- Some(cl) => {
- self.name() == ClauseInfo::name(cl) && self.arity() == ClauseInfo::arity(cl)
- }
- None => true,
+pub fn clause_predicate_key_from_heap(
+ heap: &impl SizedHeap,
+ value: HeapCellValue,
+) -> Option<PredicateKey> {
+ read_heap_cell!(value,
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ debug_assert_eq!(_arity, 0);
+ Some((name, 0))
}
- }
-
- fn name(&self) -> Option<Atom>;
- fn arity(&self) -> usize;
-}
-
-impl ClauseInfo for PredicateKey {
- #[inline]
- fn name(&self) -> Option<Atom> {
- Some(self.0)
- }
-
- #[inline]
- fn arity(&self) -> usize {
- self.1
- }
-}
-
-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 {
- name
- }
-}
-
-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),
- }
+ _ => {
+ if value.is_ref() {
+ clause_predicate_key(heap, value.get_value() as usize)
+ } else {
+ None
}
- 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),
- }
- }
+pub fn clause_predicate_key(heap: &impl SizedHeap, term_loc: usize) -> Option<PredicateKey> {
+ let key_opt = term_predicate_key(heap, term_loc);
- 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),
- }
+ if Some((atom!(":-"), 2)) == key_opt {
+ term_nth_arg(heap, term_loc, 1).and_then(|arg_loc| {
+ term_predicate_key(heap, arg_loc)
+ })
+ } else {
+ key_opt
}
}
}
impl PredicateClause {
- pub(crate) fn args(&self) -> Option<&[HeapCellValue]> {
- let (term, focus) = match self {
- PredicateClause::Fact(Fact { term }, _) => (term, term.focus),
- PredicateClause::Rule(Rule { term, .. }, _) => {
- let focus = term.nth_arg(term.focus, 1).unwrap();
- (term, focus)
+ pub(crate) fn args<'a>(&self, heap: &'a Heap) -> Option<std::ops::RangeInclusive<usize>> {
+ let focus = match self {
+ &PredicateClause::Fact(Fact { term_loc }, _) => term_loc,
+ &PredicateClause::Rule(Rule { term_loc, .. }, _) => {
+ term_nth_arg(heap, term_loc, 1).unwrap()
}
};
- 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) => {
- Some(&term.heap[s+1 .. s+arity+1])
+ Some(s+1 ..= s+arity)
}
_ => {
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)]
impl ModuleSource {
pub(crate) fn as_functor_stub(&self) -> MachineStub {
match self {
- ModuleSource::Library(name) => {
- functor!(atom!("library"), [atom(name)])
+ &ModuleSource::Library(name) => {
+ functor!(atom!("library"), [atom_as_cell(name)])
}
- ModuleSource::File(name) => {
+ &ModuleSource::File(name) => {
functor!(name)
}
}
}
}
+/*
impl ArenaFrom<Number> for Literal {
#[inline]
fn arena_from(value: Number, arena: &mut Arena) -> 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 {
#[inline]
#[derive(Debug, Clone)]
pub(crate) enum OptArgIndexKey {
- Literal(usize, usize, Literal, Vec<Literal>), // index, IndexingCode location, opt arg, alternatives
- List(usize, usize), // index, IndexingCode location
+ Literal(usize, usize, HeapCellValue, Vec<HeapCellValue>), // index, IndexingCode location, opt arg, alternatives
+ List(usize, usize), // index, IndexingCode location
None,
Structure(usize, usize, Atom, usize), // index, IndexingCode location, name, arity
}
--- /dev/null
+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!());
+ }
+}
}
}
(HeapCellValueTag::PStrLoc, h) => {
- let h = if self.heap[h].get_tag() == HeapCellValueTag::PStr {
- h
- } else {
- debug_assert_eq!(self.heap[h].get_tag(), HeapCellValueTag::PStrOffset);
- self.heap[h].get_value() as usize
- };
-
- if self.heap[h].get_mark_bit() == self.mark_phase {
- continue;
- }
+ let (_, tail_loc) = self.heap.scan_slice_to_str(h);
- self.heap[h].set_mark_bit(self.mark_phase);
-
- if self.heap[h].get_tag() == HeapCellValueTag::PStr {
- let value = self.heap[h+1];
- self.heap[h+1].set_mark_bit(self.mark_phase);
- self.iter_stack.push(value);
- }
+ self.heap[tail_loc].set_mark_bit(self.mark_phase);
+ self.iter_stack.push(self.heap[tail_loc]);
}
_ => {
}
#[derive(Debug)]
pub struct StackfulPreOrderHeapIter<'a, ElideLists> {
- pub heap: &'a mut [HeapCellValue],
+ pub heap: &'a mut Heap,
pub machine_stack: &'a mut Stack,
stack: Vec<IterStackLoc>,
h: IterStackLoc,
cell.set_forwarding_bit(false);
cell.set_mark_bit(false);
}
-
- // self.heap.pop();
}
}
-pub trait FocusedHeapIter:
- Deref<Target = [HeapCellValue]> + Iterator<Item = HeapCellValue>
-{
+pub trait FocusedHeapIter: Deref<Target = Heap> + Iterator<Item = HeapCellValue> {
fn focus(&self) -> IterStackLoc;
}
}
impl<'a, ElideLists> Deref for StackfulPreOrderHeapIter<'a, ElideLists> {
- type Target = [HeapCellValue];
+ type Target = Heap;
fn deref(&self) -> &Self::Target {
&self.heap
impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> {
#[inline]
- fn new(heap: &'a mut [HeapCellValue], stack: &'a mut Stack, root_loc: usize) -> Self {
+ fn new(heap: &'a mut Heap, stack: &'a mut Stack, root_loc: usize) -> Self {
let h = IterStackLoc::iterable_loc(root_loc, HeapOrStackTag::Heap);
// heap.push(cell);
}
(HeapCellValueTag::Str |
HeapCellValueTag::AttrVar |
- HeapCellValueTag::Var |
- HeapCellValueTag::PStrLoc, vh) => {
+ HeapCellValueTag::Var, vh) => {
if self.heap[vh].get_mark_bit() {
self.read_cell_mut(loc).set_forwarding_bit(true);
}
}
read_heap_cell!(*cell,
- (HeapCellValueTag::Str | HeapCellValueTag::PStrLoc, vh) => {
+ (HeapCellValueTag::Str, vh) => {
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
self.push_if_unmarked(loc);
self.push_if_unmarked(loc);
self.stack.push(IterStackLoc::mark_loc(vs, HeapOrStackTag::Stack));
}
- (HeapCellValueTag::PStrOffset, offset) => {
- self.push_if_unmarked(IterStackLoc::iterable_loc(offset, HeapOrStackTag::Heap));
- self.stack.push(IterStackLoc::iterable_loc((h.value()+1) as usize, HeapOrStackTag::Heap));
+ (HeapCellValueTag::PStrLoc, vh) => {
+ let cell = *cell;
+ let (_, tail_loc) = self.heap.scan_slice_to_str(vh);
+
+ // forward the current PStrLoc cell if the zero
+ // byte at the end of the string buffer
+ // is marked
+ let buf_bytes = self.heap[tail_loc - 1].into_bytes();
+
+ if buf_bytes[7] != 0u8 {
+ let cell = self.read_cell_mut(h);
+ cell.set_forwarding_bit(true);
+ }
- return Some(self.read_cell(h));
- }
- (HeapCellValueTag::PStr) => {
- let tail_loc = IterStackLoc::iterable_loc((h.value()+1) as usize, HeapOrStackTag::Heap);
+ // now mark it as if were a HeapCellValue, even
+ // though it's not! this is fine as long as its tag
+ // is never inspected, which it isn't.
- self.push_if_unmarked(IterStackLoc::iterable_loc(h.value() as usize, HeapOrStackTag::Heap));
- self.stack.push(tail_loc);
- self.forward_if_referent_marked(tail_loc);
+ self.push_if_unmarked(
+ IterStackLoc::iterable_loc(tail_loc - 1, HeapOrStackTag::Heap),
+ );
+ self.stack.push(IterStackLoc::mark_loc(tail_loc, HeapOrStackTag::Heap));
- return Some(self.read_cell(h));
+ return Some(cell);
}
(HeapCellValueTag::Atom, (_name, arity)) => {
let l = h.value() as usize;
#[inline(always)]
pub(crate) fn cycle_detecting_stackless_preorder_iter(
- heap: &'_ mut [HeapCellValue],
+ heap: &'_ mut Heap,
start: usize,
) -> CycleDetectingIter<'_, true> {
// const generics argument of true so that cycle discovery stops
#[inline(always)]
pub(crate) fn stackful_preorder_iter<'a, ElideLists: ListElisionPolicy>(
- heap: &'a mut Vec<HeapCellValue>,
+ heap: &'a mut Heap,
stack: &'a mut Stack,
root_loc: usize,
) -> StackfulPreOrderHeapIter<'a, ElideLists> {
#[derive(Debug)]
pub(crate) struct PostOrderIterator<Iter: FocusedHeapIter> {
focus: IterStackLoc,
- base_iter: Iter,
+ pub(crate) base_iter: Iter,
base_iter_valid: bool,
parent_stack: Vec<(usize, HeapCellValue, IterStackLoc)>, // number of children, parent node, focus.
}
impl<Iter: FocusedHeapIter> Deref for PostOrderIterator<Iter> {
- type Target = [HeapCellValue];
+ type Target = Heap;
fn deref(&self) -> &Self::Target {
&self.base_iter
(HeapCellValueTag::Lis) => {
self.parent_stack.push((2, item, focus));
}
- (HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
+ (HeapCellValueTag::PStrLoc) => { // HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
self.parent_stack.push((1, item, focus));
}
_ => {
#[cfg(test)]
mod tests {
use super::*;
+
+ use crate::functor_macro::*;
use crate::machine::gc::IteratorUMP;
use crate::machine::mock_wam::*;
#[inline(always)]
pub(crate) fn stackless_preorder_iter(
- heap: &mut [HeapCellValue],
+ heap: &mut Heap,
start: usize,
) -> StacklessPreOrderHeapIter<IteratorUMP> {
StacklessPreOrderHeapIter::<IteratorUMP>::new(heap, start)
fn heap_stackless_iter_tests() {
let mut wam = MockWAM::new();
+ // clear the heap of resource error data etc
+ wam.machine_st.heap.clear();
+
let f_atom = atom!("f");
let a_atom = atom!("a");
let b_atom = atom!("b");
- wam.machine_st
- .heap
- .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
+ let mut functor_writer = Heap::functor_writer(functor!(
+ f_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 mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.extend(functor!(
+ let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(0))
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(0)
]
));
- 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();
for _ in 0..20 {
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 5);
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(f_atom, 4)
);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
-
- assert_eq!(
- unmark_cell_bits!(iter.next().unwrap()),
- atom_as_cell!(a_atom)
- );
-
- assert_eq!(
- unmark_cell_bits!(iter.next().unwrap()),
- atom_as_cell!(b_atom)
- );
-
- assert_eq!(
- unmark_cell_bits!(iter.next().unwrap()),
- atom_as_cell!(a_atom)
- );
-
- assert_eq!(iter.next(), None);
- }
-
- all_cells_unmarked(&wam.machine_st.heap);
-
- wam.machine_st.heap.clear();
-
- wam.machine_st.heap.push(str_loc_as_cell!(1));
-
- wam.machine_st.heap.extend(functor!(
- f_atom,
- [
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(1))
- ]
- ));
-
- for _ in 0..200000 {
- let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
-
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- atom_as_cell!(f_atom, 4)
+ str_loc_as_cell!(0)
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(1));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(a_atom)
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
{
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
// term is: [a, b]
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(a_atom));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(atom_as_cell!(b_atom));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(a_atom));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(atom_as_cell!(b_atom));
+ section.push_cell(empty_list_as_cell!());
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
-
- wam.machine_st.heap.pop();
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
// now make the list cyclic.
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap[4] = heap_loc_as_cell!(0);
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
wam.machine_st.heap.clear();
- // first a 'dangling' partial string, later modified to be a two-part complete string,
- // then a three-part cyclic string involving an uncompacted list of chars.
- let pstr_var_cell =
- 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];
+ // first a 'dangling' partial string, later modified to be a
+ // two-part complete string, then a three-part cyclic string
+ // involving an uncompacted list of chars.
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+ wam.machine_st.allocate_pstr("abc ").unwrap();
+
+ 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 mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(1),
+ pstr_loc_as_cell!(0)
);
-
- assert!(iter.next().is_none());
- }
-
- assert_eq!(wam.machine_st.heap[0], pstr_cell);
- assert_eq!(wam.machine_st.heap[1], heap_loc_as_cell!(1));
-
- wam.machine_st.heap[1] = pstr_loc_as_cell!(3);
-
- let pstr_second_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
-
- let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
-
- {
- let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(4),
+ heap_loc_as_cell!(1),
);
-
assert!(iter.next().is_none());
}
- assert_eq!(wam.machine_st.heap[0], pstr_cell);
- assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(3));
- assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(0));
- assert_eq!(wam.machine_st.heap[3], pstr_second_cell);
- assert_eq!(wam.machine_st.heap[4], heap_loc_as_cell!(4));
+ wam.machine_st.heap[1] = pstr_loc_as_cell!(heap_index!(3));
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(pstr_loc_as_cell!(5));
- wam.machine_st.heap.push(pstr_offset_as_cell!(0));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(2)));
+ wam.machine_st.allocate_pstr("def").unwrap();
- wam.machine_st.heap[2] = heap_loc_as_cell!(4);
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(4)).unwrap();
+ wam.machine_st.heap.push_cell(pstr_loc_as_cell!(0)).unwrap();
{
- let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
-
- let pstr_offset_cell = pstr_offset_as_cell!(0);
+ let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 5);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- fixnum_as_cell!(Fixnum::build_with(2))
+ pstr_loc_as_cell!(0)
);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
-
- assert_eq!(iter.next(), None);
- }
-
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[1]),
- pstr_loc_as_cell!(3)
- );
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- pstr_loc_as_cell!(5)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_offset_as_cell!(0)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- fixnum_as_cell!(Fixnum::build_with(2))
- );
-
- wam.machine_st.heap.truncate(4);
-
- 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)));
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
-
- {
- let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 6);
- let pstr_offset_cell = pstr_offset_as_cell!(0);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- pstr_loc_as_cell!(4)
+ pstr_loc_as_cell!(heap_index!(3))
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- fixnum_as_cell!(Fixnum::build_with(0))
+ heap_loc_as_cell!(4),
);
-
- assert_eq!(iter.next(), None);
+ assert!(iter.next().is_none());
}
- all_cells_unmarked(&wam.machine_st.heap);
-
- wam.machine_st.heap[5] = fixnum_as_cell!(Fixnum::build_with(1i64));
+ wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
{
- let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 6);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
- assert_eq!(
- unmark_cell_bits!(iter.next().unwrap()),
- pstr_loc_as_cell!(4)
- );
+ let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 5);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- pstr_offset_as_cell!(0)
+ pstr_loc_as_cell!(0)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- pstr_offset_as_cell!(0)
+ pstr_loc_as_cell!(heap_index!(3))
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- fixnum_as_cell!(Fixnum::build_with(1))
+ pstr_loc_as_cell!(heap_index!(3) + 2)
);
-
assert_eq!(iter.next(), None);
}
- assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0));
- assert_eq!(
- wam.machine_st.heap[5],
- fixnum_as_cell!(Fixnum::build_with(1i64))
- );
-
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
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));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(list_loc_as_cell!(3));
+ 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 mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
// instance.
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
// instance.
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(2));
+ section.push_cell(heap_loc_as_cell!(3));
+ section.push_cell(heap_loc_as_cell!(3));
+ section.push_cell(heap_loc_as_cell!(0));
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 4);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
wam.machine_st.heap.clear();
// print L = [L|L].
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(1));
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
wam.machine_st.heap.clear();
// term is [X,f(Y),Z].
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(3)); // 2
- wam.machine_st.heap.push(list_loc_as_cell!(4)); // 3
- wam.machine_st.heap.push(str_loc_as_cell!(6)); // 4
- wam.machine_st.heap.push(heap_loc_as_cell!(8));
- wam.machine_st.heap.push(atom_as_cell!(f_atom, 1)); // 6
- wam.machine_st.heap.push(heap_loc_as_cell!(11)); // 7
- wam.machine_st.heap.push(list_loc_as_cell!(9));
- wam.machine_st.heap.push(heap_loc_as_cell!(9));
- wam.machine_st.heap.push(empty_list_as_cell!());
-
- wam.machine_st.heap.push(attr_var_as_cell!(11)); // linked from 7.
- wam.machine_st.heap.push(heap_loc_as_cell!(12));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(3)); // 2
+ section.push_cell(list_loc_as_cell!(4)); // 3
+ section.push_cell(str_loc_as_cell!(6)); // 4
+ section.push_cell(heap_loc_as_cell!(8));
+ section.push_cell(atom_as_cell!(f_atom, 1)); // 6
+ section.push_cell(heap_loc_as_cell!(11)); // 7
+ section.push_cell(list_loc_as_cell!(9));
+ section.push_cell(heap_loc_as_cell!(9));
+ section.push_cell(empty_list_as_cell!());
+
+ section.push_cell(attr_var_as_cell!(11)); // linked from 7.
+ section.push_cell(heap_loc_as_cell!(12));
+ section.push_cell(heap_loc_as_cell!(0));
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 13);
let clpz_atom = atom!("clpz");
let p_atom = atom!("p");
- wam.machine_st.heap.pop();
- wam.machine_st.heap.pop();
-
- wam.machine_st.heap.push(heap_loc_as_cell!(13)); // 12
- wam.machine_st.heap.push(list_loc_as_cell!(14)); // 13
- wam.machine_st.heap.push(str_loc_as_cell!(16)); // 14
- wam.machine_st.heap.push(heap_loc_as_cell!(19)); // 15
- wam.machine_st.heap.push(atom_as_cell!(clpz_atom, 2)); // 16
- wam.machine_st.heap.push(atom_as_cell!(a_atom)); // 17
- wam.machine_st.heap.push(atom_as_cell!(b_atom)); // 18
- wam.machine_st.heap.push(list_loc_as_cell!(20)); // 19
- wam.machine_st.heap.push(str_loc_as_cell!(22)); // 20
- wam.machine_st.heap.push(empty_list_as_cell!()); // 21
- wam.machine_st.heap.push(atom_as_cell!(p_atom, 1)); // 22
- wam.machine_st.heap.push(heap_loc_as_cell!(23)); // 23
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.truncate(12);
+
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(13)); // 12
+ section.push_cell(list_loc_as_cell!(14)); // 13
+ section.push_cell(str_loc_as_cell!(16)); // 14
+ section.push_cell(heap_loc_as_cell!(19)); // 15
+ section.push_cell(atom_as_cell!(clpz_atom, 2)); // 16
+ section.push_cell(atom_as_cell!(a_atom)); // 17
+ section.push_cell(atom_as_cell!(b_atom)); // 18
+ section.push_cell(list_loc_as_cell!(20)); // 19
+ section.push_cell(str_loc_as_cell!(22)); // 20
+ section.push_cell(empty_list_as_cell!()); // 21
+ section.push_cell(atom_as_cell!(p_atom, 1)); // 22
+ section.push_cell(heap_loc_as_cell!(23)); // 23
+ section.push_cell(heap_loc_as_cell!(0));
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 24);
wam.machine_st.heap.clear();
{
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(0)));
+ wam.machine_st.heap.push_cell(fixnum_as_cell!(Fixnum::build_with(0))).unwrap();
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
- wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
+ writer.write_with(|section| {
+ section.push_cell(str_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("g"), 2));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(atom_as_cell!(atom!("y")));
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
assert!(iter.next().is_none());
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
- wam.machine_st.heap.push(str_loc_as_cell!(0));
- wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
- wam.machine_st.heap.push(str_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("g"), 2));
+ section.push_cell(str_loc_as_cell!(0));
+ section.push_cell(atom_as_cell!(atom!("y")));
+ section.push_cell(str_loc_as_cell!(0));
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
assert!(iter.next().is_none());
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
- wam.machine_st.heap.push(atom_as_cell!(atom!("="), 2));
- wam.machine_st.heap.push(atom_as_cell!(atom!("X")));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(list_loc_as_cell!(8));
- wam.machine_st.heap.push(str_loc_as_cell!(4));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(str_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("g"), 2));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(atom_as_cell!(atom!("y")));
+ section.push_cell(atom_as_cell!(atom!("="), 2));
+ section.push_cell(atom_as_cell!(atom!("X")));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(list_loc_as_cell!(8));
+ section.push_cell(str_loc_as_cell!(4));
+ section.push_cell(empty_list_as_cell!());
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 7);
assert!(iter.next().is_none());
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(wam.machine_st.heap[0], str_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(atom!("g"), 2));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cell!(atom!("f"), 2));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(str_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("f"), 2));
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(str_loc_as_cell!(0));
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
wam.machine_st.heap.clear();
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
// representation of one of the heap terms as in issue #1384.
- wam.machine_st.heap.push(list_loc_as_cell!(7)); // 0
- wam.machine_st.heap.push(heap_loc_as_cell!(0)); // 1
- wam.machine_st.heap.push(list_loc_as_cell!(3)); // 2
- wam.machine_st.heap.push(list_loc_as_cell!(5)); // 3
- wam.machine_st.heap.push(empty_list_as_cell!()); // 4
- wam.machine_st.heap.push(heap_loc_as_cell!(2)); // 5
- wam.machine_st.heap.push(heap_loc_as_cell!(2)); // 6
- wam.machine_st.heap.push(empty_list_as_cell!()); // 7
- wam.machine_st.heap.push(heap_loc_as_cell!(3)); // 8
-
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(7)); // 0
+ section.push_cell(heap_loc_as_cell!(0)); // 1
+ section.push_cell(list_loc_as_cell!(3)); // 2
+ section.push_cell(list_loc_as_cell!(5)); // 3
+ section.push_cell(empty_list_as_cell!()); // 4
+ section.push_cell(heap_loc_as_cell!(2)); // 5
+ section.push_cell(heap_loc_as_cell!(2)); // 6
+ section.push_cell(empty_list_as_cell!()); // 7
+ section.push_cell(heap_loc_as_cell!(3)); // 8
+ section.push_cell(heap_loc_as_cell!(0)); // 9
+ });
{
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 9);
fn heap_stackful_iter_tests() {
let mut wam = MockWAM::new();
+ // clear the heap of resource error data etc
+ wam.machine_st.heap.clear();
+
let f_atom = atom!("f");
let a_atom = atom!("a");
let b_atom = atom!("b");
- wam.machine_st
- .heap
- .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
+ let mut functor_writer = Heap::functor_writer(functor!(
+ f_atom,
+ [atom_as_cell(a_atom),
+ atom_as_cell(b_atom)]),
+ );
+
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+ let h = wam.machine_st.heap.cell_len();
- wam.machine_st.heap.push(str_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(cell).unwrap();
{
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- 3,
+ h,
);
assert_eq!(
wam.machine_st.heap.clear();
- wam.machine_st.heap.extend(functor!(
+ let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(0))
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(0)
]
));
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+ let h = wam.machine_st.heap.cell_len();
+
+ wam.machine_st.heap.push_cell(cell).unwrap();
+
for _ in 0..20 {
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- 4,
+ h,
);
assert_eq!(
wam.machine_st.heap.clear();
{
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
&mut wam.machine_st.heap,
{
// mutually referencing variables.
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(1)).unwrap();
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
&mut wam.machine_st.heap,
wam.machine_st.heap.clear();
// term is: [a, b]
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(a_atom));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(atom_as_cell!(b_atom));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(a_atom));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(atom_as_cell!(b_atom));
+ section.push_cell(empty_list_as_cell!());
+ });
{
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
assert_eq!(iter.next(), None);
}
- wam.machine_st.heap.pop();
-
// now make the list cyclic.
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap[4] = heap_loc_as_cell!(0);
{
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
- let pstr_var_cell =
- 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.allocate_pstr("abc ").unwrap();
+
+ 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 mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- 0,
+ 2,
);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(1),
+ pstr_loc_as_cell!(0)
);
-
- assert_eq!(iter.next(), None);
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ heap_loc_as_cell!(1)
+ );
+ assert!(iter.next().is_none());
}
- // here
-
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
+ wam.machine_st.heap[1] = pstr_loc_as_cell!(heap_index!(3));
+ wam.machine_st.allocate_pstr("def").unwrap();
- let pstr_second_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
- let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(4)).unwrap();
+ wam.machine_st.heap.push_cell(pstr_loc_as_cell!(0)).unwrap();
{
let mut iter = stackful_preorder_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- 0,
+ 5,
);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(3),
+ pstr_loc_as_cell!(0)
);
-
- assert_eq!(iter.next(), None);
- }
-
- 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 h = wam.machine_st.heap.len();
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
-
- {
- let mut iter = stackful_preorder_iter::<NonListElider>(
- &mut wam.machine_st.heap,
- &mut wam.machine_st.stack,
- h,
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(heap_index!(3))
);
-
- let pstr_offset_cell = pstr_offset_as_cell!(0);
-
- // pstr_offset_cell.set_forwarding_bit(true);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(
- iter.next().unwrap(),
- fixnum_as_cell!(Fixnum::build_with(0i64))
+ unmark_cell_bits!(iter.next().unwrap()),
+ heap_loc_as_cell!(4),
);
-
assert_eq!(iter.next(), None);
}
- /*
- {
- let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
- let string: String = iter.chars().collect();
- assert_eq!(string, "abc def");
- }
- */
-
- wam.machine_st.heap.pop();
- wam.machine_st.heap.pop();
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(1i64)));
-
- let h = wam.machine_st.heap.len();
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
{
let mut iter = stackful_preorder_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 5,
);
- let pstr_offset_cell = pstr_offset_as_cell!(0);
-
- // pstr_offset_cell.set_forwarding_bit(true);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
assert_eq!(
- iter.next().unwrap(),
- fixnum_as_cell!(Fixnum::build_with(1i64))
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(0)
);
-
- let h = iter.focus();
-
- assert_eq!(h.value(), 5);
- assert_eq!(unmark_cell_bits!(iter.heap[4]), pstr_offset_as_cell!(0));
assert_eq!(
- unmark_cell_bits!(iter.heap[5]),
- fixnum_as_cell!(Fixnum::build_with(1i64))
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(heap_index!(3))
+ );
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(heap_index!(3) + 2)
+ );
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(heap_index!(3) + 2)
);
-
assert_eq!(iter.next(), None);
}
wam.machine_st.heap.clear();
- let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
+ let functor = functor!(
+ f_atom,
+ [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
+ );
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
- wam.machine_st.heap.extend(functor);
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(empty_list_as_cell!());
+ });
- let h = wam.machine_st.heap.len();
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ let mut functor_writer = Heap::functor_writer(functor);
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+
+ wam.machine_st.heap.push_cell(cell).unwrap();
{
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 0,
);
assert_eq!(
assert_eq!(iter.next(), None);
}
- 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);
let mut iter = stackful_preorder_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 0,
);
assert_eq!(
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(1));
+ });
{
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(pstr_as_cell!(atom!("a string")));
- wam.machine_st.heap.push(empty_list_as_cell!());
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_pstr("a string");
+ section.push_cell(empty_list_as_cell!());
+ section.push_cell(pstr_loc_as_cell!(0));
+ });
{
let mut iter = stackful_preorder_iter::<NonListElider>(
);
assert_eq!(
- unmark_cell_bits!(iter.next().unwrap()),
- pstr_as_cell!(atom!("a string"))
+ iter.heap.slice_to_str(0, "a string".len()),
+ "a string"
+ );
+ assert_eq!(
+ iter.next().unwrap(),
+ empty_list_as_cell!()
);
-
- assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
-
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
- wam.machine_st.heap.push(atom_as_cell!(atom!("="), 2));
- wam.machine_st.heap.push(atom_as_cell!(atom!("X")));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(list_loc_as_cell!(8));
- wam.machine_st.heap.push(str_loc_as_cell!(4));
- wam.machine_st.heap.push(empty_list_as_cell!());
-
- let h = wam.machine_st.heap.len();
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(str_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("g"), 2));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(atom_as_cell!(atom!("y")));
+ section.push_cell(atom_as_cell!(atom!("="), 2));
+ section.push_cell(atom_as_cell!(atom!("X")));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(list_loc_as_cell!(8));
+ section.push_cell(str_loc_as_cell!(4));
+ section.push_cell(empty_list_as_cell!());
+ section.push_cell(heap_loc_as_cell!(0));
+ });
{
let mut iter = stackful_preorder_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 10,
);
assert_eq!(
fn heap_stackful_post_order_iter() {
let mut wam = MockWAM::new();
+ // clear the heap of resource error data etc
+ wam.machine_st.heap.clear();
+
let f_atom = atom!("f");
let a_atom = atom!("a");
let b_atom = atom!("b");
- wam.machine_st.heap.push(str_loc_as_cell!(1));
+ let mut functor_writer = Heap::functor_writer(functor!(
+ f_atom,
+ [atom_as_cell(a_atom),
+ atom_as_cell(b_atom)]),
+ );
+
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+ let h = wam.machine_st.heap.cell_len();
- wam.machine_st
- .heap
- .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
+ wam.machine_st.heap.push_cell(cell).unwrap();
{
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- 0,
+ h,
);
assert_eq!(
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
- wam.machine_st.heap.extend(functor!(
+
+ let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(1))
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(0)
]
));
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+ let h = wam.machine_st.heap.cell_len();
+
+ wam.machine_st.heap.push_cell(cell).unwrap();
+
for _ in 0..20 {
// 0000 {
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- 0,
+ h,
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(a_atom)
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(1));
-
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ str_loc_as_cell!(0)
+ );
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
atom_as_cell!(f_atom, 4)
wam.machine_st.heap.clear();
{
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
{
// mutually referencing variables.
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(1)).unwrap();
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
wam.machine_st.heap.clear();
// term is: [a, b]
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(a_atom));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(atom_as_cell!(b_atom));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
- let h = wam.machine_st.heap.len();
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(a_atom));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(atom_as_cell!(b_atom));
+ section.push_cell(empty_list_as_cell!());
+ });
{
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 0,
);
assert_eq!(
assert_eq!(iter.next(), None);
}
- wam.machine_st.heap.pop();
- wam.machine_st.heap.pop();
-
// now make the list cyclic.
- let h = wam.machine_st.heap.len();
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap[4] = heap_loc_as_cell!(0);
{
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 4,
);
// the cycle will be iterated twice before being detected.
);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
- let pstr_var_cell =
- 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.allocate_pstr("abc ").unwrap();
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
-
- let h = wam.machine_st.heap.len() - 1;
+ 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 mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 2,
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
heap_loc_as_cell!(1),
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-
- assert_eq!(iter.next(), None);
- }
-
- wam.machine_st.heap.pop();
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(pstr_loc_as_cell!(2));
-
- let pstr_second_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
- let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
-
- let h = wam.machine_st.heap.len() - 1;
-
- {
- let mut iter = stackful_post_order_iter::<NonListElider>(
- &mut wam.machine_st.heap,
- &mut wam.machine_st.stack,
- h,
- );
-
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(3),
+ pstr_loc_as_cell!(0)
);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-
assert_eq!(iter.next(), None);
}
- wam.machine_st.heap.pop();
- 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)));
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+ wam.machine_st.heap[1] = pstr_loc_as_cell!(heap_index!(3));
+ wam.machine_st.allocate_pstr("def").unwrap();
- let h = wam.machine_st.heap.len() - 1;
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(4)).unwrap();
+ wam.machine_st.heap.push_cell(pstr_loc_as_cell!(0)).unwrap();
{
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 5,
);
assert_eq!(
- iter.next().unwrap(),
- fixnum_as_cell!(Fixnum::build_with(0i64))
+ unmark_cell_bits!(iter.next().unwrap()),
+ heap_loc_as_cell!(4),
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- pstr_offset_as_cell!(0)
+ pstr_loc_as_cell!(heap_index!(3))
+ );
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(0)
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-
assert_eq!(iter.next(), None);
}
- wam.machine_st.heap.pop();
- wam.machine_st.heap.pop();
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(1i64)));
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
-
- let h = wam.machine_st.heap.len() - 1;
+ wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
{
let mut iter = stackful_post_order_iter::<NonListElider>(
&mut wam.machine_st.heap,
&mut wam.machine_st.stack,
- h,
+ 5,
);
assert_eq!(
- iter.next().unwrap(),
- fixnum_as_cell!(Fixnum::build_with(1i64))
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(heap_index!(3) + 2)
);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- pstr_offset_as_cell!(0)
+ pstr_loc_as_cell!(heap_index!(3) + 2)
+ );
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(heap_index!(3))
+ );
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(0)
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-
assert_eq!(iter.next(), None);
}
wam.machine_st.heap.clear();
- let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
+ let functor = functor!(
+ f_atom,
+ [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]
+ );
+
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(empty_list_as_cell!());
+ });
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut functor_writer = Heap::functor_writer(functor);
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
- wam.machine_st.heap.extend(functor);
+ wam.machine_st.heap.push_cell(cell).unwrap();
{
let mut iter = stackful_post_order_iter::<NonListElider>(
assert_eq!(iter.next(), None);
}
- 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);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
}
fn heap_stackless_post_order_iter() {
let mut wam = MockWAM::new();
+ // clear the heap of resource error data etc
+ wam.machine_st.heap.clear();
+
let f_atom = atom!("f");
let a_atom = atom!("a");
let b_atom = atom!("b");
- wam.machine_st
- .heap
- .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
+ let mut functor_writer = Heap::functor_writer(functor!(
+ f_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 mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 3);
wam.machine_st.heap.clear();
- wam.machine_st.heap.extend(functor!(
+ let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(0))
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(0)
]
));
- 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();
for _ in 0..20 {
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 5);
wam.machine_st.heap.clear();
{
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
{
// mutually referencing variables.
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(1)).unwrap();
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
wam.machine_st.heap.clear();
// term is: [a, b]
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(a_atom));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(atom_as_cell!(b_atom));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(a_atom));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(atom_as_cell!(b_atom));
+ section.push_cell(empty_list_as_cell!());
+ });
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
assert_eq!(iter.next(), None);
}
- wam.machine_st.heap.pop();
-
// now make the list cyclic.
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap[4] = heap_loc_as_cell!(0);
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
- let pstr_var_cell =
- 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.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 mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 2);
unmark_cell_bits!(iter.next().unwrap()),
heap_loc_as_cell!(1),
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
+ assert_eq!(
+ unmark_cell_bits!(iter.next().unwrap()),
+ pstr_loc_as_cell!(0)
+ );
assert_eq!(iter.next(), None);
}
- wam.machine_st.heap.pop();
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(pstr_loc_as_cell!(2));
-
- let pstr_second_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
-
- let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
+ wam.machine_st.heap[2] = heap_loc_as_cell!(2);
+ wam.machine_st.allocate_pstr("def").unwrap();
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(pstr_loc_as_cell!(0)).unwrap();
{
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 4);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(3),
+ heap_loc_as_cell!(1),
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-
- assert_eq!(iter.next(), None);
- }
-
- all_cells_unmarked(&wam.machine_st.heap);
-
- 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(0)));
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
-
- {
- let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 7);
- let mut pstr_loc_cell = pstr_loc_as_cell!(0);
-
- pstr_loc_cell.set_forwarding_bit(true);
-
- // assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64)));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(3)
+ pstr_loc_as_cell!(0)
);
-
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
- wam.machine_st.heap.pop();
- wam.machine_st.heap.pop();
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(1)));
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+ wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(3) + 2);
{
- let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 7);
+ let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 4);
- //assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1)));
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
- heap_loc_as_cell!(3)
+ pstr_loc_as_cell!(heap_index!(3) + 2)
);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
- assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
assert_eq!(iter.next(), None);
}
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
+
wam.machine_st.heap.clear();
- let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
+ let functor = functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom), atom_as_cell(b_atom)]);
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
- wam.machine_st.heap.extend(functor);
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(empty_list_as_cell!());
+ });
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ let mut functor_writer = Heap::functor_writer(functor);
+ functor_writer(&mut wam.machine_st.heap).unwrap();
{
- let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 9);
+ let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
assert_eq!(
unmark_cell_bits!(iter.next().unwrap()),
assert_eq!(iter.next(), None);
}
- 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);
assert_eq!(iter.next(), None);
}
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
}
}
use crate::heap_iter::*;
use crate::machine::heap::*;
use crate::machine::machine_indices::*;
-use crate::machine::machine_state::pstr_loc_and_offset;
use crate::machine::partial_string::*;
use crate::machine::stack::*;
use crate::machine::streams::*;
use std::iter::once;
use std::net::{IpAddr, TcpListener};
use std::rc::Rc;
-use std::sync::Arc;
/* contains the location, name, precision and Specifier of the parent op. */
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Clone, Copy)]
struct CommaSeparatedCharList {
- pstr: PartialString,
- offset: usize,
+ // pstr: PartialString,
+ // offset: usize,
+ pstr_loc: usize,
max_depth: usize,
- end_cell: HeapCellValue,
- end_h: Option<usize>,
+ // end_cell: HeapCellValue,
+ // end_h: Option<usize>,
}
#[derive(Debug, Clone)]
pub struct HCPrinter<'a, Outputter> {
outputter: Outputter,
iter: StackfulPreOrderHeapIter<'a, ListElider>,
- atom_tbl: Arc<AtomTable>,
op_dir: &'a OpDir,
state_stack: Vec<TokenOrRedirect>,
toplevel_spec: Option<DirectedOp>,
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 {
($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(' ');
$action;
} else {
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
pub fn new(
heap: &'a mut Heap,
- atom_tbl: Arc<AtomTable>,
stack: &'a mut Stack,
op_dir: &'a OpDir,
output: Outputter,
HCPrinter {
outputter: output,
iter: stackful_preorder_iter(heap, stack, root_loc),
- atom_tbl,
op_dir,
state_stack: vec![],
toplevel_spec: None,
}
}
- #[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>) {
if let Some(op) = parent_op {
if op.is_left() && op.is_prefix() {
// 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 {
- 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 char_count > 0 {
self.state_stack.push(TokenOrRedirect::Close);
return true;
}
- append_str!(self, "'.'");
- push_char!(self, '(');
+ macro_rules! emit_char {
+ ($c:expr) => ({
+ append_str!(self, "'.'");
+ push_char!(self, '(');
- print_char!(self, self.quoted, c);
- push_char!(self, ',');
+ print_char!(self, self.quoted, $c);
+ 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
fn print_proper_string(&mut self, focus: usize, max_depth: usize) {
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| {
// refrain from quoting characters other than '"' and '\'
// unless self.quoted is true.
};
if max_depth == 0 {
- for c in iter.chars() {
- for c in char_to_string(c).chars() {
- push_char!(self, c);
+ while let Some(iteratee) = iter.next() {
+ 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 iter {
+ for c in char_to_string(c).chars() {
+ push_char!(self, c);
+ }
}
}
} else {
let mut char_count = 0;
- for c in iter.chars().take(max_depth) {
- char_count += 1;
+ while let Some(iteratee) = iter.next() {
+ 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() {
- push_char!(self, c);
+ for c in iter.take(max_depth - char_count) {
+ char_count += 1;
+
+ for c in char_to_string(c).chars() {
+ push_char!(self, c);
+ }
}
}
self.iter.pop_stack();
self.iter.pop_stack();
}
- HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset => {
+ HeapCellValueTag::PStrLoc => {
self.iter.pop_stack();
}
- HeapCellValueTag::CStr => {}
+ // HeapCellValueTag::CStr => {}
_ => {
unreachable!();
}
let focus = self.iter.focus();
let mut heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus.value() as usize);
- let next_h;
- let next_hare;
-
- if heap_pstr_iter.next().is_some() {
- next_h = heap_pstr_iter.focus;
- next_hare = heap_pstr_iter.focus();
+ let is_cyclic = if heap_pstr_iter.next().is_some() {
for _ in heap_pstr_iter.by_ref() {}
+ heap_pstr_iter.is_cyclic()
} else {
return self.push_list(max_depth);
- }
+ };
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) {
self.remove_list_children(focus.value() as usize);
let at_cdr = self.outputter.ends_with("|");
- if self.double_quotes && !self.ignore_ops && end_cell.is_string_terminator(self.iter.heap) {
- self.remove_list_children(focus.value() as usize);
- return self.print_proper_string(focus.value() as usize, max_depth);
+ if self.double_quotes && !self.ignore_ops && !is_cyclic {
+ if end_cell.is_string_terminator(self.iter.heap) {
+ self.remove_list_children(focus.value() as usize);
+ return self.print_proper_string(focus.value() as usize, max_depth);
+ }
}
if self.ignore_ops {
(HeapCellValueTag::Lis) => {
self.push_list(max_depth)
}
- _ => {
+ (HeapCellValueTag::PStrLoc, h) => {
let switch = Rc::new(Cell::new((!at_cdr, 0)));
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) {
- let pstr = cell_as_string!(self.iter.heap[h]);
- self.state_stack.push(TokenOrRedirect::CommaSeparatedCharList(CommaSeparatedCharList {
- pstr, offset, max_depth, end_cell: next_h, end_h,
- }));
+ self.state_stack.push(
+ TokenOrRedirect::CommaSeparatedCharList(
+ CommaSeparatedCharList {
+ pstr_loc: h, max_depth,
+ }
+ ),
+ );
} else {
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
}
self.open_list(switch);
}
+ _ => {
+ unreachable!()
+ }
);
}
}
fn print_comma_separated_char_list(&mut self, char_list: CommaSeparatedCharList) {
let CommaSeparatedCharList {
- pstr,
- offset,
+ pstr_loc,
max_depth,
- end_cell,
- end_h,
} = char_list;
- let pstr_str = pstr.as_str_from(offset);
- if let Some(c) = pstr_str.chars().next() {
- let offset = offset + c.len_utf8();
+ let c = self.iter.heap.char_at(pstr_loc);
+
+ 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) {
self.state_stack
.push(TokenOrRedirect::CommaSeparatedCharList(
CommaSeparatedCharList {
- pstr,
- offset,
+ pstr_loc: pstr_loc + c.len_utf8(),
max_depth: max_depth.saturating_sub(1),
- end_cell,
- end_h,
},
));
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);
}
} else if self.max_depth_exhausted(max_depth) {
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
- } else if end_cell != empty_list_as_cell!() {
- if let Some(end_h) = end_h {
- self.iter
- .push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap));
+ } else {
+ /*
+ let end_cell_h = Heap::neighboring_cell_offset(pstr_loc);
+ 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),
+ );
+
+ if end_cell != empty_list_as_cell!() {
+ 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::FunctorRedirect(max_depth + 1));
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
}
}
(HeapCellValueTag::Atom, (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) => {
let (name, arity) = cell_as_atom_cell!(self.iter.heap[s])
.get_name_and_arity();
(HeapCellValueTag::F64, f) => {
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);
}
(HeapCellValueTag::Lis) => {
mod tests {
use super::*;
+ use crate::functor_macro::*;
use crate::machine::mock_wam::*;
#[test]
fn term_printing_tests() {
let mut wam = MockWAM::new();
+ // clear the heap of resource error data etc
+ wam.machine_st.heap.clear();
+
let f_atom = atom!("f");
let a_atom = atom!("a");
let b_atom = atom!("b");
let c_atom = atom!("c");
- wam.machine_st
- .heap
- .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
+ let mut functor_writer = Heap::functor_writer(functor!(
+ f_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(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
- 0,
+ 3,
);
let output = printer.print();
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.extend(functor!(
+ let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(0))
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(0)
]
));
- let h = wam.machine_st.heap.len();
- 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(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
- h,
+ 5,
);
let output = printer.print();
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();
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
// print L = [L|L].
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
+ writer.write_with(|section| {
+ section.push_cell(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(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
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();
- let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(str_loc_as_cell!(5));
+ section.push_cell(empty_list_as_cell!());
+ });
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(str_loc_as_cell!(5));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ 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)]
+ ));
- wam.machine_st.heap.extend(functor);
+ functor_writer(&mut wam.machine_st.heap).unwrap();
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
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);
{
let printer = HCPrinter::new(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
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(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
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
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- for idx in 0..3000 {
- 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));
- }
+ let mut writer = wam.machine_st.heap.reserve(6002).unwrap();
- 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(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
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();
- put_partial_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+ wam.machine_st.allocate_pstr("abc").unwrap();
- let h = wam.machine_st.heap.len() - 1;
+ 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 printer = HCPrinter::new(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
- h,
+ 2,
);
let output = printer.print();
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();
- wam.machine_st.heap.pop();
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
- 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.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!());
+ wam.machine_st.heap[1] = list_loc_as_cell!(3);
{
let mut printer = HCPrinter::new(
&mut wam.machine_st.heap,
- Arc::clone(&wam.machine_st.atom_tbl),
&mut wam.machine_st.stack,
&wam.op_dir,
PrinterOutputter::new(),
- 0,
+ 2,
);
printer.double_quotes = true;
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();
"=(X,[a,b,c|X])"
);
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(
&wam.parse_and_print_term("[a,b,\"a\",[a,b,c]].").unwrap(),
"[a,b,[a],[a,b,c]]"
);
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(
&wam.parse_and_print_term("[\"abc\",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))");
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.op_dir
.insert((atom!("+"), Fixity::In), OpDesc::build_with(500, YFX));
"[a|[]+b]"
);
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
assert_eq!(
&wam.parse_and_print_term("[a|[b|c]*d].").unwrap(),
"[a|[b|c]*d]"
);
- all_cells_unmarked(&wam.machine_st.heap);
+ all_cells_unmarked(wam.machine_st.heap.splice(..));
wam.op_dir
.insert((atom!("fy"), Fixity::Pre), OpDesc::build_with(9, FY));
use crate::atom_table::*;
use crate::forms::*;
use crate::instructions::*;
-use crate::parser::ast::*;
+use crate::machine::heap::*;
+use crate::parser::ast::Fixnum;
use crate::types::*;
use fxhash::FxBuildHasher;
fn add_static_indexed_choice_for_constant(
&mut self,
external: usize,
- constant: Literal,
+ constant: HeapCellValue,
index: usize,
) {
let third_level_index = if self.append_or_prepend.is_append() {
fn add_dynamic_indexed_choice_for_constant(
&mut self,
external: usize,
- constant: Literal,
+ constant: HeapCellValue,
index: usize,
) {
let third_level_index = if self.append_or_prepend.is_append() {
fn index_overlapping_constant(
&mut self,
- orig_constant: Literal,
- overlapping_constant: Literal,
+ orig_constant: HeapCellValue,
+ overlapping_constant: HeapCellValue,
index: usize,
) {
loop {
}
}
- fn index_constant(&mut self, constant: Literal, index: usize) {
+ fn index_constant(&mut self, constant: HeapCellValue, index: usize) {
loop {
let indexing_code_len = self.indexing_code.len();
}
pub(crate) fn remove_constant_indices(
- constant: Literal,
- overlapping_constants: &[Literal],
+ constant: HeapCellValue,
+ overlapping_constants: &[HeapCellValue],
indexing_code: &mut [IndexingLine],
offset: usize,
) {
}
pub(crate) fn constant_key_alternatives(
- constant: Literal,
- atom_tbl: &AtomTable,
+ constant: HeapCellValue,
+ // atom_tbl: &AtomTable,
// arena: &mut Arena,
-) -> Vec<Literal> {
+) -> Vec<HeapCellValue> {
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 {
Literal::Atom(ref name) => {
if let Some(c) = name.as_char() {
}
_ => {}
}
+ */
constants
}
#[derive(Debug)]
pub(crate) struct StaticCodeIndices {
- constants: IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher>,
+ constants: IndexMap<HeapCellValue, VecDeque<IndexedChoiceInstruction>, FxBuildHasher>,
lists: VecDeque<IndexedChoiceInstruction>,
structures: IndexMap<(Atom, usize), VecDeque<IndexedChoiceInstruction>, FxBuildHasher>,
}
#[derive(Debug)]
pub(crate) struct DynamicCodeIndices {
- constants: IndexMap<Literal, VecDeque<usize>, FxBuildHasher>,
+ constants: IndexMap<HeapCellValue, VecDeque<usize>, FxBuildHasher>,
lists: VecDeque<usize>,
structures: IndexMap<(Atom, usize), VecDeque<usize>, FxBuildHasher>,
}
fn constants(
&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 structures(
&mut self,
#[inline]
fn constants(
&mut self,
- ) -> &mut IndexMap<Literal, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
+ ) -> &mut IndexMap<HeapCellValue, VecDeque<IndexedChoiceInstruction>, FxBuildHasher> {
&mut self.constants
}
}
#[inline]
- fn constants(&mut self) -> &mut IndexMap<Literal, VecDeque<usize>, FxBuildHasher> {
+ fn constants(&mut self) -> &mut IndexMap<HeapCellValue, VecDeque<usize>, FxBuildHasher> {
&mut self.constants
}
fn index_constant(
&mut self,
- atom_tbl: &AtomTable,
- constant: Literal,
+ constant: HeapCellValue,
index: usize,
- ) -> Vec<Literal> {
- let overlapping_constants = constant_key_alternatives(constant, atom_tbl);
+ ) -> Vec<HeapCellValue> {
+ let overlapping_constants = constant_key_alternatives(constant);
let code = self.indices.constants().entry(constant).or_default();
let is_initial_index = code.is_empty();
pub(crate) fn index_term(
&mut self,
- heap: &[HeapCellValue],
+ heap: &Heap,
optimal_arg: HeapCellValue,
index: usize,
clause_index_info: &mut ClauseIndexInfo,
- atom_tbl: &AtomTable,
) {
read_heap_cell!(optimal_arg,
(HeapCellValueTag::Str, s) => {
(HeapCellValueTag::Atom, (name, arity)) => {
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(
self.optimal_index,
0,
- Literal::Atom(name),
+ atom_as_cell!(name),
overlapping_constants,
);
}
(HeapCellValueTag::Lis
- | HeapCellValueTag::CStr
+ // | HeapCellValueTag::CStr
| HeapCellValueTag::PStrLoc) => {
clause_index_info.opt_arg_index_key = OptArgIndexKey::List(self.optimal_index, 0);
self.index_list(index);
}
- _ => {
- match Literal::try_from(optimal_arg) {
- Ok(lit) => {
- let overlapping_constants = self.index_constant(atom_tbl, lit, index);
-
- clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal(
- self.optimal_index,
- 0,
- lit,
- overlapping_constants,
- );
- }
- _ => {}
- }
+ _ if optimal_arg.is_constant() => {
+ let overlapping_constants = self.index_constant(optimal_arg, index);
+
+ clause_index_info.opt_arg_index_key = OptArgIndexKey::Literal(
+ self.optimal_index,
+ 0,
+ optimal_arg,
+ overlapping_constants,
+ );
}
+ _ => {}
);
}
use std::ops::Deref;
use std::vec::Vec;
-pub(crate) trait TermIterator:
- Deref<Target = [HeapCellValue]> + Iterator<Item = HeapCellValue>
-{
+pub(crate) trait TermIterator: Deref<Target = Heap> + Iterator<Item = HeapCellValue> {
fn focus(&self) -> IterStackLoc;
fn level(&mut self) -> Level;
}
}
fn record_path(
- heap: &[HeapCellValue],
+ heap: &impl SizedHeap,
root_terms: &mut BitSet<usize>,
mut root_loc: usize,
) -> usize {
}
}
(HeapCellValueTag::Lis) => {
- root_terms.insert(root_loc);
- break;
- }
+ root_terms.insert(root_loc);
+ break;
+ }
_ => {
if cell.is_ref() {
root_terms.insert(cell.get_value() as usize);
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 root_loc = record_path(heap, &mut root_terms, root_loc);
(root_loc, root_terms)
}
fn find_shallow_terms(
- heap: &[HeapCellValue],
+ heap: &impl SizedHeap,
root_loc: usize,
) -> IndexMap<usize, BitSet<usize>, FxBuildHasher> {
let mut shallow_terms_map = IndexMap::with_hasher(FxBuildHasher::default());
impl<I: FocusedHeapIter, const SKIP_ROOT: bool> TargetIterator<I, SKIP_ROOT> {
fn new(iter: I, root_loc: usize, arg_c: usize) -> Self {
- let (derefed_root_loc, root_terms) = find_root_terms(&iter, root_loc);
- let shallow_terms = find_shallow_terms(&iter, derefed_root_loc);
+ let (derefed_root_loc, root_terms) = find_root_terms(iter.deref(), root_loc);
+ let shallow_terms = find_shallow_terms(iter.deref(), derefed_root_loc);
Self {
shallow_terms,
}
impl<I: FocusedHeapIter, const SKIP_ROOT: bool> Deref for TargetIterator<I, SKIP_ROOT> {
- type Target = [HeapCellValue];
+ type Target = Heap;
fn deref(&self) -> &Self::Target {
self.iter.deref()
stack: &'a mut Stack,
root_loc: usize,
) -> FactIterator<'a, SKIP_ROOT> {
- // let cell = heap[root_loc];
TargetIterator::new(stackful_preorder_iter(heap, stack, root_loc), root_loc, 0)
}
stack: &'a mut Stack,
root_loc: usize,
) -> QueryIterator<'a, SKIP_ROOT> {
- // let cell = heap[root_loc];
TargetIterator::new(stackful_post_order_iter(heap, stack, root_loc), root_loc, 1)
}
#![recursion_limit = "4112"]
#![deny(missing_docs)]
+
#[macro_use]
extern crate static_assertions;
pub(crate) mod arena;
#[macro_use]
pub(crate) mod parser;
+#[macro_use]
+pub(crate) mod functor_macro;
mod allocator;
mod arithmetic;
pub(crate) mod codegen;
%
% 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
% to `false` since it supports unbounded integer arithmethic. Read only.
% * `integer_rounding_function`: Describes the rounding donde by `//` and `rem` functions. On Scryer is
% `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.
%
-current_prolog_flag(Flag, Value) :- Flag == max_arity, !, Value = 1023.
-current_prolog_flag(max_arity, 1023).
+current_prolog_flag(Flag, Value) :- Flag == max_arity, !, Value = 255.
+current_prolog_flag(max_arity, 255).
current_prolog_flag(Flag, Value) :- Flag == bounded, !, Value = false.
current_prolog_flag(bounded, false).
current_prolog_flag(Flag, Value) :- Flag == integer_rounding_function, !, Value == toward_zero.
read_term(Stream, Term, [singletons(Singletons)])
; Term = end_of_file
),
- % write('Term: '), writeq(Term), nl,
( Term == end_of_file ->
close(Stream),
'$conclude_load'(Evacuable)
compile_term(Term, Evacuable) :-
expand_terms_and_goals(Term, Terms),
- % write('Terms: '), writeq(Terms),nl,
!,
( var(Terms) ->
instantiation_error(load/1)
( atom(Module) ->
prolog_load_context(module, Target),
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), _),
( loader:print_goal_expansion_warning(Pred),
builtins:(Body1 = Body0)
)
; module_expanded_head_variables(Head1, HeadVars),
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), _),
( loader:print_goal_expansion_warning(Pred),
builtins:(Body1 = Body0)
};
}
-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| {
let eval_error = machine_st.evaluation_error(EvalError::ZeroDivisor);
let stub = stub_gen();
})
}
-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| {
let eval_error = machine_st.evaluation_error(EvalError::Undefined);
let stub = stub_gen();
fn numerical_type_error(
valid_type: ValidType,
n: Number,
- stub_gen: impl Fn() -> FunctorStub + 'static,
+ stub_gen: impl Fn() -> MachineStub + 'static,
) -> MachineStubGen {
Box::new(move |machine_st| {
let type_error = machine_st.type_error(valid_type, n);
pub fn rational_from_number(
n: Number,
- stub_gen: impl Fn() -> FunctorStub + 'static,
+ stub_gen: impl Fn() -> MachineStub + 'static,
arena: &mut Arena,
) -> Result<TypedArenaPtr<Rational>, MachineStubGen> {
match n {
pub fn get_rational(
&mut self,
at: &ArithmeticTerm,
- caller: impl Fn() -> FunctorStub + 'static,
+ caller: impl Fn() -> MachineStub + 'static,
) -> Result<TypedArenaPtr<Rational>, MachineStub> {
let n = self.get_number(at)?;
&mut self,
value: HeapCellValue,
) -> Result<Number, MachineStub> {
+ debug_assert!(value.is_ref());
+
let stub_gen = || functor_stub(atom!("is"), 2);
let root_loc = if value.is_ref() && !value.is_stack_var() {
(HeapCellValueTag::Str, s) => {
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) => {
(atom!("."), 2)
}
parse_and_write_parsed_term_to_heap(&mut wam, "3 + 4 - 1 + 2.", &op_dir).unwrap();
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))),
);
parse_and_write_parsed_term_to_heap(&mut wam, "5 * 4 - 1.", &op_dir).unwrap();
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))),
);
parse_and_write_parsed_term_to_heap(&mut wam, "sign(-1).", &op_dir).unwrap();
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)))
);
}
call_goals([ListOfGoalLists | ListsCubed]) :-
+ '$debug_hook',
call_goals_0(ListOfGoalLists),
call_goals(ListsCubed).
call_goals([]).
use indexmap::IndexSet;
use std::cmp::Ordering;
-use std::vec::IntoIter;
pub(super) type Bindings = Vec<(usize, HeapCellValue)>;
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
.attr_var_init
.bindings
.iter()
.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 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 {
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!(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() {
vec![]
} else {
});
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);
let e = self.e;
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));
- self.verify_attributes();
+ self.verify_attributes()?;
self.num_of_args = 3;
self.b0 = self.b;
self.p = p;
+
+ Ok(())
}
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_vars = vec![];
let root_loc = if cell.is_ref() {
fn compile_standalone_clause(
&mut self,
- term: FocusedHeap,
+ term: TermWriteResult,
settings: CodeGenSettings,
) -> Result<StandaloneCompileResult, SessionError> {
let mut preprocessor = Preprocessor::new(settings);
- let clause = self.try_term_to_tl(term, &mut preprocessor)?;
- let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings);
+ let clause = preprocessor.try_term_to_tl(self, term)?;
+ 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 {
clause_code,
let mut preprocessor = Preprocessor::new(settings);
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 mut code = cg.compile_predicate(clauses)?;
+ let machine_st = LS::machine_st(&mut self.payload);
+
+ let mut cg = CodeGenerator::new(settings);
+ let mut code = cg.compile_predicate(&mut machine_st.heap, clauses)?;
if settings.is_extensible {
let mut clause_clause_locs = VecDeque::new();
pub(super) fn incremental_compile_clause(
&mut self,
key: PredicateKey,
- clause: FocusedHeap,
+ clause: TermWriteResult,
compilation_target: CompilationTarget,
non_counted_bt: bool,
append_or_prepend: AppendOrPrepend,
&mut self,
key: PredicateKey,
compilation_target: CompilationTarget,
- clause_clauses: Vec<FocusedHeap>,
+ clause_clauses: Vec<TermWriteResult>,
append_or_prepend: AppendOrPrepend,
) -> Result<(), SessionError> {
let clause_clause_compilation_target = match compilation_target {
}
pub(super) fn compile_and_submit(&mut self) -> Result<(), SessionError> {
- let key = self
+ let key = match self
.payload
.predicates
.first()
- .and_then(|cl| {
- let arity = ClauseInfo::arity(cl);
- ClauseInfo::name(cl).map(|name| (name, arity))
- })
- .ok_or(SessionError::NamelessEntry)?;
+ .map(|term| term.focus) {
+ Some(focus) => {
+ clause_predicate_key(self.machine_heap(), focus)
+ .ok_or(SessionError::NamelessEntry)?
+ }
+ None => {
+ return Err(SessionError::NamelessEntry);
+ }
+ };
let listing_src_file_name = self.listing_src_file_name();
) -> Result<(), SessionError> {
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 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 {
- self.machine_st.heap.push(var);
- }
+ writer.write_with(move |section| {
+ section.push_cell(atom_as_cell!(atom!(""), arity));
- let head_loc = if arity > 0 {
- str_loc_as_cell!(new_header_loc)
- } else {
- heap_loc_as_cell!(new_header_loc)
- };
+ for var in vars {
+ section.push_cell(var);
+ }
- 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));
- self.machine_st.heap.push(head_loc);
- self.machine_st.heap.push(body_cell);
+ section.push_cell(atom_as_cell!(atom!(":-"), 2));
+ section.push_cell(head_loc);
+ section.push_cell(body_cell);
+ });
let mut compile = || {
- use crate::heap_iter::eager_stackful_preorder_iter;
-
let mut loader: Loader<'_, InlineLoadState<'_>> =
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 {
global_clock_tick: None,
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)
};
use crate::atom_table::*;
use crate::machine::get_structure_index;
+use crate::machine::heap::*;
use crate::machine::stack::*;
use crate::types::*;
use std::mem;
-use std::ops::IndexMut;
+use std::ops::{IndexMut, Range};
type Trail = Vec<(Ref, HeapCellValue)>;
pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
fn store(&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 stack(&mut self) -> &mut Stack;
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>(
target: T,
addr: HeapCellValue,
attr_var_policy: AttrVarPolicy,
-) {
+) -> Result<(), usize> {
let mut copy_term_state = CopyTermState::new(target, attr_var_policy);
- copy_term_state.copy_term_impl(addr);
- copy_term_state.copy_attr_var_lists();
+ copy_term_state.copy_term_impl(addr)?;
+ copy_term_state.copy_attr_var_lists()?;
copy_term_state.unwind_trail();
+
+ Ok(())
}
#[derive(Debug)]
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 {
read_heap_cell!(self.target[addr + offset],
(HeapCellValueTag::Lis, h) => {
if h >= self.old_h {
*self.value_at_scan() = list_loc_as_cell!(h);
self.scan += 1;
- return;
+ return Ok(());
}
}
_ => {
}
let threshold = self.target.threshold();
+ self.target.copy_slice_to_end(addr .. addr + 2)?;
*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
.target
.store(self.target.deref(heap_loc_as_cell!(addr + 1)));
}
self.scan += 1;
+ Ok(())
}
- fn copy_partial_string(&mut self, scan_tag: HeapCellValueTag, pstr_loc: usize) {
- read_heap_cell!(self.target[pstr_loc],
- (HeapCellValueTag::PStrLoc, h) => {
- debug_assert!(h >= self.old_h);
+ /*
+ * write a null byte to the first word of a partial string to
+ * flag that it has been copied followed by the copied
+ * 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 {
- HeapCellValueTag::PStrLoc => {
- pstr_loc_as_cell!(h)
- }
- tag => {
- debug_assert_eq!(tag, HeapCellValueTag::PStrOffset);
- pstr_offset_as_cell!(h)
- }
- };
+ fn copy_partial_string(&mut self, pstr_loc: usize) -> Result<(), usize> {
+ let head_cell_idx = self.target.pstr_head_cell_index(pstr_loc);
+ let head_byte_idx = heap_index!(head_cell_idx);
+ let pstr_offset = pstr_loc - head_byte_idx;
- self.scan += 1;
- return;
- }
- (HeapCellValueTag::Var, h) => {
- debug_assert!(h >= self.old_h);
- debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
+ // if a partial string has been copied previously, we
+ // 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
+ // comment.
- *self.value_at_scan() = pstr_offset_as_cell!(h);
- self.scan += 1;
+ if self.target[head_cell_idx].into_bytes()[0] == 0u8 {
+ 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 tail_loc = self.target.copy_pstr_to_threshold(head_byte_idx)?;
- let replacement = read_heap_cell!(self.target[pstr_loc],
- (HeapCellValueTag::CStr) => {
- debug_assert_eq!(scan_tag, HeapCellValueTag::PStrOffset);
+ *self.value_at_scan() = pstr_loc_as_cell!(heap_index!(threshold) + pstr_offset);
- *self.value_at_scan() = pstr_offset_as_cell!(threshold);
- self.target.push(self.target[pstr_loc]);
+ self.trail.push((Ref::heap_cell(head_cell_idx), self.target[head_cell_idx]));
+ self.write_pstr_index(head_cell_idx, threshold);
- heap_loc_as_cell!(threshold)
- }
- _ => {
- *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)
- };
+ let tail_cell = self.target[tail_loc];
+ let mut writer = self.target.reserve(1)?;
- self.target.push(self.target[pstr_loc]);
- self.target.push(self.target[pstr_loc + 1]);
-
- pstr_loc_as_cell!(threshold)
- }
- );
+ writer.write_with(|section| {
+ section.push_cell(tail_cell);
+ });
self.scan += 1;
- let trail_item = mem::replace(&mut self.target[pstr_loc], replacement);
- self.trail.push((Ref::heap_cell(pstr_loc), trail_item));
+ Ok(())
}
- fn copy_attr_var_lists(&mut self) {
+ fn copy_attr_var_lists(&mut self) -> Result<(), usize> {
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.push_attr_var_queue(threshold - 1);
- self.copy_attr_var_list(list_loc);
+ self.copy_attr_var_list(list_loc)?;
}
}
+
+ Ok(())
}
/*
* structure which is ensured by this function and not at all by
* 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() {
let threshold = self.target.threshold();
let heap_loc = list_addr.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));
- self.target.push(heap_loc_as_cell!(threshold + 1));
+ writer.write_with(|section| {
+ 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],
- (HeapCellValueTag::Atom) => {
- self.target.push(self.target[str_loc]);
- }
- (HeapCellValueTag::Str) => {
- self.copy_term_impl(self.target[str_loc]);
- }
- _ => {
- unreachable!();
+ if str_cell.to_atom().is_some() {
+ section.push_cell(str_cell);
}
- );
+ });
+ debug_assert_eq!(str_cell.get_tag(), HeapCellValueTag::Str);
+ self.copy_term_impl(str_cell)?;
list_addr = self.target[heap_loc + 1];
if HeapCellValueTag::Lis == list_addr.get_tag() {
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,
(HeapCellValueTag::Var, h) => {
self.target[frontier] = heap_loc_as_cell!(frontier);
self.trail.push((Ref::attr_var(h), attr_var_as_cell!(h)));
if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
- self.target.push(attr_var_as_cell!(threshold));
- self.target.push(heap_loc_as_cell!(threshold + 1));
+ let mut writer = self.target.reserve(2).unwrap();
+
+ 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];
self.trail.push((Ref::heap_cell(h + 1), old_list_link));
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 rd = self.target.deref(addr);
let ra = self.target.store(rd);
if h >= self.old_h {
*self.value_at_scan() = ra;
self.scan += 1;
- return;
+ return Ok(());
}
}
(HeapCellValueTag::Lis, h) => {
);
self.scan += 1;
- return;
+ return Ok(());
}
}
_ => {}
);
if rd == ra {
- self.reinstantiate_var(ra, self.scan);
+ self.reinstantiate_var(ra, self.scan)?;
self.scan += 1;
} else {
*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],
- (HeapCellValueTag::Atom, (name, arity)) => {
+ (HeapCellValueTag::Atom, (_name, arity)) => {
let threshold = self.target.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(
&mut self.target[addr],
str_loc_as_cell!(threshold),
);
self.trail.push((Ref::heap_cell(addr), trail_item));
+/*
self.target.push(atom_as_cell!(name, arity));
for i in 0..arity {
let hcv = self.target[addr + 1 + i];
self.target.push(hcv);
}
-
- 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.
- self.target.push(index_cell);
+*/
+ if !self.target.pstr_at(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();
+
+ writer.write_with(|section| {
+ section.push_cell(index_cell);
+ });
+ }
}
}
(HeapCellValueTag::Str, h) => {
);
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.target.push(addr);
+ let mut writer = self.target.reserve(1)?;
+
+ writer.write_with(|section| {
+ section.push_cell(addr);
+ });
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();
read_heap_cell!(addr,
(HeapCellValueTag::Lis, h) => {
if h >= self.old_h {
self.scan += 1;
+ continue;
} else {
- self.copy_list(h);
+ self.copy_list(h)
}
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var) => {
- self.copy_var(addr);
+ self.copy_var(addr)
}
(HeapCellValueTag::Str, h) => {
- self.copy_structure(h);
+ self.copy_structure(h)
}
- (HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrOffset, pstr_loc) => {
- self.copy_partial_string(addr.get_tag(), pstr_loc);
+ (HeapCellValueTag::PStrLoc, pstr_loc) => {
+ self.copy_partial_string(pstr_loc)
}
_ => {
self.scan += 1;
+ continue;
}
- );
+ )?;
}
+
+ Ok(())
}
fn unwind_trail(mut self) {
#[cfg(test)]
mod tests {
use super::*;
+ use crate::functor_macro::*;
use crate::machine::mock_wam::*;
#[test]
fn copier_tests() {
let mut wam = MockWAM::new();
+ // clear the heap of resource error data etc
+ wam.machine_st.heap.clear();
+
let f_atom = atom!("f");
let a_atom = atom!("a");
let b_atom = atom!("b");
- wam.machine_st
- .heap
- .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
+ let mut functor_writer = Heap::functor_writer(
+ functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(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[1], atom_as_cell!(a_atom));
{
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.
wam.machine_st.heap.clear();
- let pstr_var_cell =
- 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];
+ let mut writer = wam.machine_st.heap.reserve(4).unwrap();
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(pstr_loc_as_cell!(2));
+ writer.write_with(|section| {
+ section.push_pstr("abc ");
+ section.push_cell(pstr_loc_as_cell!(heap_index!(2)));
- let pstr_second_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
- 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)));
+ section.push_pstr("def");
+ section.push_cell(pstr_loc_as_cell!(0));
+ });
{
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!(
- wam.machine_st.heap[5],
- fixnum_as_cell!(Fixnum::build_with(0i64))
+ wam.machine_st.heap.slice_to_str(0, "abc ".len()),
+ "abc "
);
+ assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(heap_index!(2)));
+ assert_eq!(
+ wam.machine_st.heap.slice_to_str(heap_index!(2), "def".len()),
+ "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[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!(
- wam.machine_st.heap[12],
- fixnum_as_cell!(Fixnum::build_with(0i64))
+ 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.extend(functor!(
+ let mut functor_writer = Heap::functor_writer(functor!(
f_atom,
[
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(0))
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(0)
]
));
+ functor_writer(&mut wam.machine_st.heap).unwrap();
+
{
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));
use crate::atom_table::*;
+use crate::machine::heap::*;
use crate::types::*;
/* Use the pointer reversal technique of the Deutsch-Schorr-Waite
* - Cells are only marked during 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
- * 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
* phase
*
#[derive(Debug)]
pub(crate) struct CycleDetectingIter<'a, const STOP_AT_CYCLES: bool> {
- pub(crate) heap: &'a mut [HeapCellValue],
+ pub(crate) heap: &'a mut Heap,
start: usize,
current: usize,
next: u64,
}
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);
let next = heap[start].get_value();
self.current = next;
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));
}
}
}
HeapCellValueTag::PStrLoc => {
let h = self.next as usize;
- let cell = self.heap[h];
- let last_cell_loc = h + 1;
+ let (_, last_cell_loc) = self.heap.scan_slice_to_str(h);
if self.heap[last_cell_loc].get_forwarding_bit() {
if self.cycle_detection_active() {
self.heap[last_cell_loc].set_value(self.current as u64);
self.current = last_cell_loc;
- return Some(cell);
- }
- 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);
+ return Some(pstr_loc_as_cell!(h));
}
tag @ HeapCellValueTag::Atom => {
let cell = HeapCellValue::build_with(tag, self.next);
return None;
}
}
- HeapCellValueTag::PStr => {
- if self.backward() {
- return None;
- }
- }
_ => {
return Some(self.backward_and_return());
}
use crate::instructions::*;
use crate::iterators::fact_iterator;
use crate::machine::Stack;
+use crate::machine::heap::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::CompilationError;
use crate::machine::preprocessor::*;
}
}
- pub fn classify_fact(
+ pub fn classify_fact<'a, LS: LoadState<'a>>(
mut self,
- term: &mut FocusedHeap,
+ loader: &mut Loader<'a, LS>,
+ term: &TermWriteResult,
) -> Result<ClassifyFactResult, CompilationError> {
- let focus = term.focus;
- self.classify_head_variables(term, focus)?;
-
+ self.classify_head_variables(loader, &term, term.focus)?;
Ok(self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
pub fn classify_rule<'a, LS: LoadState<'a>>(
mut self,
loader: &mut Loader<'a, LS>,
- term: &mut FocusedHeap,
+ term: &TermWriteResult,
) -> Result<ClassifyRuleResult, CompilationError> {
- let head_loc = term.nth_arg(term.focus, 1).unwrap();
- let body_loc = term.nth_arg(term.focus, 2).unwrap();
+ let heap = &mut LS::machine_st(&mut loader.payload).heap;
+
+ 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(term, head_loc)?;
+ self.classify_head_variables(loader, &term, head_loc)?;
self.root_set.insert(self.current_branch_num.clone());
let mut query_terms = self.classify_body_variables(loader, term, body_loc)?;
&mut self,
arg_c: usize,
arity: usize,
- term: &mut FocusedHeap,
- term_loc: usize,
+ term: &mut FocusedHeapRefMut,
+ inverse_var_locs: &InverseVarLocs,
context: GenContext,
) {
let classify_info = ClassifyInfo { arg_c, arity };
let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>(
- &mut term.heap,
+ term.heap,
&mut stack,
- term_loc,
+ term.focus,
);
// second arg is true to iterate the root, which may be a variable
}
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(
context,
self.probe_body_var(context, var_info);
}
- fn classify_head_variables(
+ fn classify_head_variables<'a, LS: LoadState<'a>>(
&mut self,
- term: &mut FocusedHeap,
+ loader: &mut Loader<'a, LS>,
+ term: &TermWriteResult,
head_loc: usize,
) -> Result<(), CompilationError> {
- let arity = read_heap_cell!(term.deref_loc(head_loc),
- (HeapCellValueTag::Str, s) => {
- cell_as_atom_cell!(term.heap[s]).get_arity()
- }
- (HeapCellValueTag::Atom) => {
- return Ok(());
- }
- _ => {
- return Err(CompilationError::InvalidRuleHead);
- }
- );
+ let heap = &mut LS::machine_st(&mut loader.payload).heap;
+ let arity = term_predicate_key(heap, head_loc)
+ .and_then(|(_, arity)| Some(arity))
+ .ok_or(CompilationError::InvalidRuleHead)?;
let mut classify_info = ClassifyInfo { arg_c: 1, arity };
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;
debug_assert_eq!(value.get_tag(), HeapCellValueTag::Str);
let mut lvl = Level::Shallow;
let mut stack = Stack::uninitialized();
let mut iter = fact_iterator::<false>(
- &mut term.heap,
+ heap,
&mut stack,
idx,
);
fn classify_body_variables<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
- terms: &mut FocusedHeap,
+ terms: &TermWriteResult,
term_loc: usize,
) -> Result<ChunkedTermVec, CompilationError> {
let mut state_stack = vec![TraversalState::Term {
- subterm: terms.heap[term_loc],
+ subterm: loader.machine_heap()[term_loc],
term_loc,
}];
let mut build_stack = ChunkedTermVec::new();
for (arg_c, term_loc) in
($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(
loader,
$key,
- terms.as_ref_mut($term_loc),
+ &terms,
HeapCellValue::build_with($tag, $term_loc as u64),
self.call_policy,
)));
let context = build_stack.current_gen_context();
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(
loader,
$key,
$module_name,
- terms.as_ref_mut($term_loc),
+ &terms,
HeapCellValue::build_with($tag, $term_loc as u64),
self.call_policy,
),
}
loop {
+ let heap = loader.machine_heap();
+
read_heap_cell!(subterm,
(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();
match (name, arity) {
(atom!("->") | atom!(";") | atom!(","), 3) => {
- if blunt_index_ptr(&mut terms.heap, (name, 2), subterm_loc) {
- subterm = terms.heap[subterm_loc];
+ if blunt_index_ptr(heap, (name, 2), subterm_loc) {
+ subterm = heap[subterm_loc];
continue;
}
add_chunk!((name, 2), HeapCellValueTag::Str, subterm_loc);
}
(atom!(","), 2) => {
- let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
- let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap();
- let head = terms.heap[head_loc];
+ let head_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
+ let tail_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
+ 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()
.rev()
.chain(std::iter::once((head, head_loc)))
state_stack.extend(iter);
}
(atom!(";"), 2) => {
- let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
- let tail_loc = terms.nth_arg(subterm_loc, 2).unwrap();
+ let head_loc = term_nth_arg(heap, subterm_loc, 1).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 branches: Vec<_> = std::iter::once((head, head_loc))
.chain(
- unfold_by_str_locs(&mut terms.heap, tail_loc, atom!(";"))
+ unfold_by_str_locs(heap, tail_loc, atom!(";"))
.into_iter(),
)
.collect();
build_stack.current_chunk_num += 1;
}
(atom!("->"), 2) => {
- let if_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
- let then_term_loc = terms.nth_arg(subterm_loc, 2).unwrap();
+ let if_term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
+ let then_term_loc = term_nth_arg(heap, subterm_loc, 2).unwrap();
- let if_term = terms.heap[if_term_loc];
- let then_term = terms.heap[then_term_loc];
+ let if_term = heap[if_term_loc];
+ let then_term = heap[then_term_loc];
let prev_b = if matches!(
state_stack.last(),
self.var_num += 1;
}
(atom!("\\+"), 1) => {
- let not_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
- let not_term = terms.heap[not_term_loc];
+ let not_term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
+ let not_term = heap[not_term_loc];
let build_stack_len = build_stack.len();
build_stack.reserve_branch(2);
self.var_num += 1;
}
(atom!(":"), 2) => {
- let module_name_loc = terms.nth_arg(subterm_loc, 1).unwrap();
- let predicate_term_loc = terms.nth_arg(subterm_loc, 2).unwrap();
+ let module_name_loc = term_nth_arg(heap, subterm_loc, 1).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 predicate_term = terms.deref_loc(predicate_term_loc);
+ let module_name = focused.deref_loc(module_name_loc);
+ let predicate_term = focused.deref_loc(predicate_term_loc);
read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
read_heap_cell!(predicate_term,
(HeapCellValueTag::Str, s) => {
- let key = cell_as_atom_cell!(terms.heap[s])
+ let key = cell_as_atom_cell!(heap[s])
.get_name_and_arity();
add_qualified_chunk!(
let context = build_stack.current_gen_context();
- self.probe_body_term(1, 0, terms, module_name_loc, context);
- self.probe_body_term(2, 0, terms, predicate_term_loc, context);
+ focused.focus = module_name_loc;
- let h = terms.heap.len();
+ self.probe_body_term(
+ 1, 0, &mut focused, &terms.inverse_var_locs, context,
+ );
+
+ focused.focus = predicate_term_loc;
+
+ self.probe_body_term(
+ 2, 0, &mut focused, &terms.inverse_var_locs, context,
+ );
+
+ let h = heap.cell_len();
- terms.heap.push(atom_as_cell!(atom!("call"), 1));
- terms.heap.push(str_loc_as_cell!(subterm_loc));
+ 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(
loader,
(atom!("call"), 1),
- terms.as_ref_mut(h),
+ terms,
str_loc_as_cell!(h),
self.call_policy,
)));
}
(atom!("$call_with_inference_counting"), 1) => {
- let term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
- let subterm = terms.deref_loc(term_loc);
+ let term_loc = term_nth_arg(heap, subterm_loc, 1).unwrap();
+ 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::Term { subterm, 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) => {
if h != term_loc {
- subterm = terms.heap[h];
+ subterm = heap[h];
term_loc = h;
continue;
}
use crate::arena::*;
use crate::atom_table::*;
+use crate::functor_macro::*;
use crate::instructions::*;
use crate::machine::arithmetic_ops::*;
use crate::machine::machine_errors::*;
match $e {
Ok(val) => val,
Err(msg) => {
- $s.throw_exception(msg);
+ if !msg.is_empty() {
+ $s.throw_exception(msg);
+ }
+
$s.backtrack();
continue;
}
}};
}
+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 {
($s:expr) => {{
if !$s.increment_call_count() {
}};
}
+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;
impl MachineState {
}
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 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);
}
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];
-
unify_fn!(*self, target_addr, heap_addr);
Ok(())
}
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 = heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, key_pairs));
+ let heap_addr = resource_error_call_result!(
+ 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];
v
}
(HeapCellValueTag::PStrLoc |
- HeapCellValueTag::Lis |
- HeapCellValueTag::CStr) => {
+ HeapCellValueTag::Lis) => {
+ // HeapCellValueTag::CStr) => {
l
}
(HeapCellValueTag::Fixnum |
HeapCellValueTag::CutPoint |
- HeapCellValueTag::Char |
+ // HeapCellValueTag::Char |
HeapCellValueTag::F64) => {
c
}
)
}
+ /*
#[inline(always)]
pub(crate) fn constant_to_literal(&self, addr: HeapCellValue) -> Literal {
read_heap_cell!(addr,
}
)
}
+ */
#[inline(always)]
pub(crate) fn select_switch_on_structure_index(
}
}
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,
_ => IndexingCodePtr::Fail,
};
self.machine_st.allocate(num_cells);
}
&Instruction::DefaultCallAcyclicTerm => {
- let addr = self.machine_st.registers[1];
+ let addr = self.deref_register(1);
- if self.machine_st.is_cyclic_term(addr) {
- self.machine_st.backtrack();
- } else {
- self.machine_st.p += 1;
+ if addr.is_ref() {
+ self.machine_st.heap[0] = addr;
+
+ if self.machine_st.is_cyclic_term(0) {
+ self.machine_st.backtrack();
+ continue;
+ }
}
+
+ self.machine_st.p += 1;
}
&Instruction::DefaultExecuteAcyclicTerm => {
- let addr = self.machine_st.registers[1];
+ let addr = self.deref_register(1);
- if self.machine_st.is_cyclic_term(addr) {
- self.machine_st.backtrack();
- } else {
- self.machine_st.p = self.machine_st.cp;
+ if addr.is_ref() {
+ self.machine_st.heap[0] = addr;
+
+ if self.machine_st.is_cyclic_term(0) {
+ self.machine_st.backtrack();
+ continue;
+ }
}
+
+ self.machine_st.p = self.machine_st.cp;
}
&Instruction::DefaultCallArg => {
try_or_throw!(self.machine_st, self.machine_st.try_arg());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallAcyclicTerm => {
- let addr = self.machine_st.registers[1];
+ let addr = self.deref_register(1);
- if self.machine_st.is_cyclic_term(addr) {
- self.machine_st.backtrack();
- } else {
- increment_call_count!(self.machine_st);
- self.machine_st.p += 1;
+ if addr.is_ref() {
+ self.machine_st.heap[0] = addr;
+
+ if self.machine_st.is_cyclic_term(0) {
+ self.machine_st.backtrack();
+ continue;
+ }
}
+
+ increment_call_count!(self.machine_st);
+ self.machine_st.p += 1;
}
&Instruction::ExecuteAcyclicTerm => {
- let addr = self.machine_st.registers[1];
+ let addr = self.deref_register(1);
- if self.machine_st.is_cyclic_term(addr) {
- self.machine_st.backtrack();
- } else {
- increment_call_count!(self.machine_st);
- self.machine_st.p = self.machine_st.cp;
+ if addr.is_ref() {
+ self.machine_st.heap[0] = addr;
+
+ if self.machine_st.is_cyclic_term(0) {
+ self.machine_st.backtrack();
+ continue;
+ }
}
+
+ increment_call_count!(self.machine_st);
+ self.machine_st.p = self.machine_st.cp;
}
&Instruction::CallArg => {
try_or_throw!(self.machine_st, self.machine_st.try_arg());
self.machine_st.backtrack();
}
}
- (HeapCellValueTag::Char) => {
- self.machine_st.p += 1;
- }
_ => {
self.machine_st.backtrack();
}
self.machine_st.backtrack();
}
}
- (HeapCellValueTag::Char) => {
- self.machine_st.p = self.machine_st.cp;
- }
_ => {
self.machine_st.backtrack();
}
.store(self.machine_st.deref(self.machine_st[r]));
read_heap_cell!(d,
- (HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
+ (HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
HeapCellValueTag::Cons) => {
self.machine_st.p += 1;
}
.store(self.machine_st.deref(self.machine_st[r]));
read_heap_cell!(d,
- (HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
+ (HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
HeapCellValueTag::Cons) => {
self.machine_st.p = self.machine_st.cp;
}
read_heap_cell!(d,
(HeapCellValueTag::Lis |
- HeapCellValueTag::PStrLoc |
- HeapCellValueTag::CStr) => {
+ HeapCellValueTag::PStrLoc) => {
+ // HeapCellValueTag::CStr) => {
self.machine_st.p += 1;
}
(HeapCellValueTag::Str, s) => {
read_heap_cell!(d,
(HeapCellValueTag::Lis |
- HeapCellValueTag::PStrLoc |
- HeapCellValueTag::CStr) => {
+ HeapCellValueTag::PStrLoc) => {
+ // HeapCellValueTag::CStr) => {
self.machine_st.p = self.machine_st.cp;
}
(HeapCellValueTag::Str, s) => {
&Instruction::CallNamed(arity, name, ref idx) => {
let idx = idx.get();
- // println!("calling {}/{}", name.as_str(), arity);
-
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
if self.machine_st.fail {
&Instruction::ExecuteNamed(arity, name, ref idx) => {
let idx = idx.get();
- // println!("executing {}/{}", name.as_str(), arity);
-
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
if self.machine_st.fail {
&Instruction::DefaultCallNamed(arity, name, ref idx) => {
let idx = idx.get();
- // println!("calling {}/{}", name.as_str(), arity);
-
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
if self.machine_st.fail {
&Instruction::DefaultExecuteNamed(arity, name, ref idx) => {
let idx = idx.get();
- // println!("executing {}/{}", name.as_str(), arity);
-
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
if self.machine_st.fail {
self.machine_st.p = self.machine_st.cp;
}
&Instruction::GetConstant(_, c, reg) => {
- let value = self.machine_st.deref(self.machine_st[reg]);
- self.machine_st.write_literal_to_var(value, c);
+ unify!(self.machine_st, self.machine_st[reg], c);
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::GetList(_, reg) => {
read_heap_cell!(store_v,
(HeapCellValueTag::PStrLoc, h) => {
- let (h, n) = pstr_loc_and_offset(&self.machine_st.heap, 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 = HeapPtr::PStr(h);
self.machine_st.s_offset = 0;
self.machine_st.mode = MachineMode::Read;
}
self.machine_st.mode = MachineMode::Read;
}
(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.mode = MachineMode::Write;
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 store_v = self.machine_st.store(deref_v);
read_heap_cell!(store_v,
(HeapCellValueTag::Str |
HeapCellValueTag::Lis |
- HeapCellValueTag::PStrLoc |
- HeapCellValueTag::CStr) => {
- self.machine_st.match_partial_string(store_v, string, has_tail);
+ HeapCellValueTag::PStrLoc) => {
+ debug_assert!(store_v.is_ref());
+
+ 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::StackVar |
HeapCellValueTag::Var) => {
- let target_cell = self.machine_st.push_str_to_heap(
- &string.as_str(),
- has_tail,
+ let target_cell = backtrack_on_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_pstr(string)
);
self.machine_st.bind(
store_v.as_var().unwrap(),
target_cell,
);
+
+ self.machine_st.mode = MachineMode::Write;
}
_ => {
self.machine_st.backtrack();
);
}
(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));
- self.machine_st.heap.push(atom_as_cell!(name, arity));
+ push_cell!(self.machine_st, str_loc_as_cell!(h+1));
+ 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.mode = MachineMode::Write;
match self.machine_st.mode {
MachineMode::Read => {
let addr = self.machine_st.read_s();
-
- self.machine_st.write_literal_to_var(addr, v);
+ unify!(&mut self.machine_st, addr, v);
if self.machine_st.fail {
self.machine_st.backtrack();
}
}
MachineMode::Write => {
- self.machine_st.heap.push(v);
+ push_cell!(self.machine_st, v);
}
}
let value = self
.machine_st
.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,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, 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.heap.push(heap_loc_as_cell!(h));
+ push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)(
&mut self.machine_st,
Ref::heap_cell(h),
&Instruction::UnifyVariable(reg) => {
match self.machine_st.mode {
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;
}
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);
}
}
}
}
MachineMode::Write => {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(heap_loc_as_cell!(h));
+ let h = self.machine_st.heap.cell_len();
+ push_cell!(self.machine_st, heap_loc_as_cell!(h));
let addr = self.machine_st.store(self.machine_st[reg]);
(self.machine_st.bind_fn)(
// the former code of this match arm was:
// 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
// check when enabled and so it was changed to
self.machine_st.s_offset += n;
}
MachineMode::Write => {
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
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));
}
}
}
}
}
}
- &Instruction::PutConstant(_, c, reg) => {
- self.machine_st[reg] = c;
+ &Instruction::PutConstant(_, cell, reg) => {
+ self.machine_st[reg] = cell;
self.machine_st.p += 1;
}
&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;
}
- &Instruction::PutPartialString(_, string, reg, has_tail) => {
- let pstr_addr = if has_tail {
- if string != atom!("") {
- let h = self.machine_st.heap.len();
- 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)
- };
+ &Instruction::PutPartialString(_, ref string, reg) => {
+ self.machine_st[reg] = backtrack_on_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_pstr(&string)
+ );
- self.machine_st[reg] = pstr_addr;
self.machine_st.p += 1;
}
&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.p += 1;
if addr.is_protected(self.machine_st.e) {
self.machine_st.registers[arg] = addr;
} 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)(
&mut self.machine_st,
Ref::heap_cell(h),
self.machine_st.registers[arg] = self.machine_st[norm];
}
RegType::Temp(_) => {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(heap_loc_as_cell!(h));
+ let h = self.machine_st.heap.cell_len();
+ push_cell!(self.machine_st, 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.p += 1;
}
&Instruction::SetConstant(c) => {
- self.machine_st.heap.push(c);
+ push_cell!(self.machine_st, c);
self.machine_st.p += 1;
}
&Instruction::SetLocalValue(reg) => {
let stored_v = self.machine_st.store(addr);
if stored_v.is_stack_var() {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(heap_loc_as_cell!(h));
+ let h = self.machine_st.heap.cell_len();
+ push_cell!(self.machine_st, heap_loc_as_cell!(h));
(self.machine_st.bind_fn)(
&mut self.machine_st,
Ref::heap_cell(h),
stored_v,
);
} else {
- self.machine_st.heap.push(stored_v);
+ push_cell!(self.machine_st, stored_v);
}
self.machine_st.p += 1;
}
&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.p += 1;
}
&Instruction::SetValue(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;
}
&Instruction::SetVoid(n) => {
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
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;
}
&Instruction::CallCopyToLiftedHeap => {
self.copy_to_lifted_heap();
- self.machine_st.p += 1;
+ step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteCopyToLiftedHeap => {
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 => {
self.create_partial_string();
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));
if self.machine_st.fail {
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));
if self.machine_st.fail {
}
&Instruction::CallSetBall => {
self.set_ball();
- self.machine_st.p += 1;
+ step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteSetBall => {
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 => {
self.push_ball_stack();
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallLoadHTML => {
- self.load_html();
+ backtrack_on_resource_error!(self.machine_st, self.load_html());
step_or_fail!(self, self.machine_st.p += 1);
}
&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);
}
&Instruction::CallLoadXML => {
- self.load_xml();
+ backtrack_on_resource_error!(self.machine_st, self.load_xml());
step_or_fail!(self, self.machine_st.p += 1);
}
&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);
}
&Instruction::CallGetEnv => {
let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r));
- let h = self.machine_st.heap.len();
- self.machine_st
- .heap
- .extend(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
+ let mut writer = Heap::functor_writer(
+ 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();
- 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);
}
let r = self.machine_st.registers[2];
let r = self.machine_st.store(self.machine_st.deref(r));
- let h = self.machine_st.heap.len();
- self.machine_st
- .heap
- .extend(functor!(atom!("-"), [fixnum(n), fixnum(p)]));
+ let mut writer = Heap::functor_writer(
+ 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();
- 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);
}
-#![allow(dead_code)]
-
+#[cfg(test)]
use crate::atom_table::*;
+#[cfg(test)]
use crate::machine::heap::*;
+#[cfg(test)]
use crate::types::*;
+#[cfg(test)]
+use fxhash::FxBuildHasher;
+#[cfg(test)]
+use indexmap::IndexMap;
+
#[cfg(test)]
use crate::heap_iter::{FocusedHeapIter, HeapOrStackTag, IterStackLoc};
#[cfg(test)]
use std::ops::Deref;
+#[cfg(test)]
pub(crate) trait UnmarkPolicy {
fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue>
where
fn record_focus(_iter: &mut StacklessPreOrderHeapIter<Self>)
where
Self: Sized,
- {
- }
+ {}
}
#[cfg(test)]
}
}
+#[cfg(test)]
struct MarkerUMP {}
+#[cfg(test)]
impl UnmarkPolicy for MarkerUMP {
#[inline(always)]
fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue> {
}
}
+#[cfg(test)]
+type PStrLocValuesMap = IndexMap<usize, usize, FxBuildHasher>;
+
+#[cfg(test)]
#[derive(Debug)]
pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> {
- pub(crate) heap: &'a mut [HeapCellValue],
+ pub(crate) heap: &'a mut Heap,
start: usize,
current: usize,
next: u64,
iter_state: UMP,
+ pstr_loc_values: PStrLocValuesMap,
}
#[cfg(test)]
impl<'a> Deref for StacklessPreOrderHeapIter<'a, IteratorUMP> {
- type Target = [HeapCellValue];
+ type Target = Heap;
fn deref(&self) -> &Self::Target {
self.heap
}
}
+#[cfg(test)]
impl<'a, UMP: UnmarkPolicy> Drop for StacklessPreOrderHeapIter<'a, UMP> {
fn drop(&mut self) {
UMP::invert_marker(self);
}
}
+#[cfg(test)]
impl<'a> StacklessPreOrderHeapIter<'a, MarkerUMP> {
- 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);
let next = heap[start].get_value();
current: start,
next,
iter_state: MarkerUMP {},
+ pstr_loc_values: PStrLocValuesMap::with_hasher(FxBuildHasher::default()),
}
}
}
#[cfg(test)]
impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> {
- pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
+ #[cfg(test)]
+ pub(crate) fn new(heap: &'a mut Heap, start: usize) -> Self {
heap[start].set_forwarding_bit(true);
let next = heap[start].get_value();
current: start,
next,
iter_state: IteratorUMP { mark_phase: true },
+ pstr_loc_values: PStrLocValuesMap::with_hasher(FxBuildHasher::default()),
}
}
}
+#[cfg(test)]
impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
fn backward_and_return(&mut self) -> HeapCellValue {
let mut current = self.heap[self.current];
return Some(cell);
}
- if self.next < self.heap.len() as u64 && UMP::report_var_link(self) {
+ if self.next < self.heap.cell_len() as u64 && UMP::report_var_link(self) {
let tag = HeapCellValueTag::AttrVar;
return Some(HeapCellValue::build_with(tag, next as u64));
}
return Some(cell);
}
- if self.next < self.heap.len() as u64 && UMP::report_var_link(self) {
+ if self.next < self.heap.cell_len() as u64 && UMP::report_var_link(self) {
let tag = HeapCellValueTag::Var;
return Some(HeapCellValue::build_with(tag, next as u64));
}
let arity = cell_as_atom_cell!(self.heap[h]).get_arity();
- for cell in &mut self.heap[h + 1..h + arity + 1] {
+ for cell in &mut self.heap.splice_mut(h + 1..h + arity + 1) {
cell.set_forwarding_bit(true);
}
}
HeapCellValueTag::PStrLoc => {
let h = self.next as usize;
+ let (_, last_cell_loc) = self.heap.scan_slice_to_str(h);
+
+ self.pstr_loc_values.insert(self.current, h);
- if self.heap[h + 1].get_forwarding_bit() {
+ if self.heap[last_cell_loc].get_forwarding_bit() {
return Some(self.backward_and_return());
}
- let cell = self.heap[h];
-
- let last_cell_loc = h + 1;
-
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;
self.heap[last_cell_loc].set_forwarding_bit(true);
- return Some(cell);
- }
- HeapCellValueTag::PStrOffset => {
- let h = self.next as usize;
- let cell = self.heap[h];
-
- let last_cell_loc = h + 1;
-
- if self.heap[last_cell_loc].get_forwarding_bit() {
- return Some(self.backward_and_return());
- }
-
- if self.heap[h].get_tag() == HeapCellValueTag::PStr {
- 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);
+ return Some(pstr_loc_as_cell!(h));
}
tag @ HeapCellValueTag::Atom => {
let cell = HeapCellValue::build_with(tag, self.next);
return None;
}
}
- HeapCellValueTag::PStr => {
+ HeapCellValueTag::Cons if self.heap.pstr_at(self.current) => {
+ let pstr_loc_loc = self.heap[self.current].get_value() as usize;
+ let pstr_loc_val = self.pstr_loc_values.get(&pstr_loc_loc).unwrap();
+
+ self.heap[self.current].set_value(self.next);
+
+ self.next = *pstr_loc_val as u64;
+ self.current = pstr_loc_loc;
+
if self.backward() {
return None;
}
}
}
+#[cfg(test)]
impl<'a, UMP: UnmarkPolicy> Iterator for StacklessPreOrderHeapIter<'a, UMP> {
type Item = HeapCellValue;
}
}
-pub fn mark_cells(heap: &mut Heap, start: usize) {
- let mut iter = StacklessPreOrderHeapIter::<MarkerUMP>::new(heap, start);
- while iter.forward().is_some() {}
-}
-
#[cfg(test)]
mod tests {
use super::*;
+ use crate::functor_macro::*;
use crate::machine::mock_wam::*;
+ fn mark_cells(heap: &mut Heap, start: usize) {
+ let mut iter = StacklessPreOrderHeapIter::<MarkerUMP>::new(heap, start);
+ while iter.forward().is_some() {}
+ }
+
#[test]
fn heap_marking_tests() {
let mut wam = MockWAM::new();
+ // clear the heap of resource error data etc
+ wam.machine_st.heap.clear();
+
let f_atom = atom!("f");
let a_atom = atom!("a");
let b_atom = atom!("b");
- wam.machine_st.heap.push(str_loc_as_cell!(1));
+ let mut functor_writer = Heap::functor_writer(
+ functor!(f_atom, [atom_as_cell(a_atom), atom_as_cell(b_atom)]),
+ );
- wam.machine_st
- .heap
- .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+ let h = wam.machine_st.heap.cell_len();
- mark_cells(&mut wam.machine_st.heap, 0);
+ wam.machine_st.heap.push_cell(cell).unwrap();
+
+ mark_cells(&mut wam.machine_st.heap, h);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
- str_loc_as_cell!(1)
+ unmark_cell_bits!(wam.machine_st.heap[3]),
+ str_loc_as_cell!(0)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[1]),
+ unmark_cell_bits!(wam.machine_st.heap[0]),
atom_as_cell!(f_atom, 2)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
+ unmark_cell_bits!(wam.machine_st.heap[1]),
atom_as_cell!(a_atom)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
+ unmark_cell_bits!(wam.machine_st.heap[2]),
atom_as_cell!(b_atom)
);
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
+ let mut functor_writer = Heap::functor_writer(
+ functor!(
+ f_atom,
+ [
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(1)
+ ]
+ ),
+ );
- wam.machine_st.heap.extend(functor!(
- f_atom,
- [
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(1))
- ]
- ));
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+ let h = wam.machine_st.heap.cell_len();
- mark_cells(&mut wam.machine_st.heap, 0);
+ wam.machine_st.heap.push_cell(cell).unwrap();
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ mark_cells(&mut wam.machine_st.heap, h);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
- str_loc_as_cell!(1)
+ unmark_cell_bits!(wam.machine_st.heap[5]),
+ str_loc_as_cell!(0)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[1]),
+ unmark_cell_bits!(wam.machine_st.heap[0]),
atom_as_cell!(f_atom, 4)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
+ unmark_cell_bits!(wam.machine_st.heap[1]),
atom_as_cell!(a_atom)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
+ unmark_cell_bits!(wam.machine_st.heap[2]),
atom_as_cell!(b_atom)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
+ unmark_cell_bits!(wam.machine_st.heap[3]),
atom_as_cell!(a_atom)
);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- str_loc_as_cell!(1)
- );
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
// make the structure doubly cyclic.
- wam.machine_st.heap[2] = str_loc_as_cell!(1);
+ wam.machine_st.heap[1] = str_loc_as_cell!(0);
- mark_cells(&mut wam.machine_st.heap, 0);
+ mark_cells(&mut wam.machine_st.heap, h);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
+ let mut functor_writer = Heap::functor_writer(
+ functor!(
+ f_atom,
+ [
+ atom_as_cell(a_atom),
+ atom_as_cell(b_atom),
+ atom_as_cell(a_atom),
+ str_loc_as_cell(0)
+ ]
+ ),
+ );
- wam.machine_st.heap.extend(functor!(
- f_atom,
- [
- atom(a_atom),
- atom(b_atom),
- atom(a_atom),
- cell(str_loc_as_cell!(1))
- ]
- ));
+ let cell = functor_writer(&mut wam.machine_st.heap).unwrap();
+ let h = wam.machine_st.heap.cell_len();
- mark_cells(&mut wam.machine_st.heap, 0);
+ wam.machine_st.heap.push_cell(cell).unwrap();
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ mark_cells(&mut wam.machine_st.heap, h);
+
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
- str_loc_as_cell!(1)
+ unmark_cell_bits!(wam.machine_st.heap[5]),
+ str_loc_as_cell!(0)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[1]),
+ unmark_cell_bits!(wam.machine_st.heap[0]),
atom_as_cell!(f_atom, 4)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
+ unmark_cell_bits!(wam.machine_st.heap[1]),
atom_as_cell!(a_atom)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
+ unmark_cell_bits!(wam.machine_st.heap[2]),
atom_as_cell!(b_atom)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
+ unmark_cell_bits!(wam.machine_st.heap[3]),
atom_as_cell!(a_atom)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- str_loc_as_cell!(1)
+ unmark_cell_bits!(wam.machine_st.heap[4]),
+ str_loc_as_cell!(0)
);
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(0)).unwrap();
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
wam.machine_st.heap.clear();
- // term is: [a, b]
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(a_atom));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(atom_as_cell!(b_atom));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+
+ writer.write_with(|section| {
+ // term is: [a, b]
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(a_atom));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(atom_as_cell!(b_atom));
+ section.push_cell(empty_list_as_cell!());
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
empty_list_as_cell!()
);
- wam.machine_st.heap.pop();
-
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
// now make the list cyclic.
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ wam.machine_st.heap[4] = heap_loc_as_cell!(0);
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
heap_loc_as_cell!(0)
);
- for cell in &mut wam.machine_st.heap {
+ for cell in &mut wam.machine_st.heap.splice_mut(..) {
cell.set_mark_bit(false);
}
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
// term is: [a, <stream ptr>]
let stream = Stream::from_static_string("test", &mut wam.machine_st.arena);
- let stream_cell =
- HeapCellValue::from(ConsPtr::build_with(stream.as_ptr(), ConsPtrMaskTag::Cons));
+ let stream_cell = HeapCellValue::from(
+ ConsPtr::build_with(stream.as_ptr(), ConsPtrMaskTag::Cons),
+ );
+
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(a_atom));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(stream_cell);
- wam.machine_st.heap.push(empty_list_as_cell!());
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(a_atom));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(stream_cell);
+ section.push_cell(empty_list_as_cell!());
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
// now a cycle of variables.
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(2));
+ section.push_cell(heap_loc_as_cell!(3));
+ section.push_cell(heap_loc_as_cell!(0));
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
// two-part complete string, then a three-part cyclic string
// involving an uncompacted list of chars.
- wam.machine_st.heap.push(pstr_loc_as_cell!(1));
-
- let pstr_var_cell =
- 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];
-
- mark_cells(&mut wam.machine_st.heap, 0);
-
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
-
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
- pstr_loc_as_cell!(1)
- );
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- heap_loc_as_cell!(2)
- );
+ let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap();
- wam.machine_st.heap.pop();
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(1)).unwrap();
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ let pstr_cell_loc = wam.machine_st.heap.cell_len();
- wam.machine_st.heap.push(pstr_loc_as_cell!(3));
+ wam.machine_st.heap.push_cell(pstr_loc_as_cell!(heap_index!(0))).unwrap();
- let pstr_second_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
- let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
+ mark_cells(&mut wam.machine_st.heap, pstr_cell_loc);
- mark_cells(&mut wam.machine_st.heap, 0);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(3)
+ wam.machine_st.heap.slice_to_str(heap_index!(0), "abc ".len()),
+ "abc "
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
+ assert_eq!(unmark_cell_bits!(wam.machine_st.heap[pstr_cell_loc]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- heap_loc_as_cell!(4)
+ unmark_cell_bits!(wam.machine_st.heap[1]),
+ heap_loc_as_cell!(1)
);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ wam.machine_st.heap[1] = pstr_loc_as_cell!(heap_index!(3));
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(pstr_loc_as_cell!(5));
- wam.machine_st.heap.push(pstr_offset_as_cell!(1));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(2)));
- wam.machine_st.heap.push(pstr_loc_as_cell!(5));
+ wam.machine_st.allocate_pstr("abc ").unwrap();
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(4)).unwrap();
- mark_cells(&mut wam.machine_st.heap, 7);
+ mark_cells(&mut wam.machine_st.heap, 2);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
+
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(3)
+ wam.machine_st.heap.slice_to_str(heap_index!(0), "abc ".len()),
+ "abc "
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- pstr_loc_as_cell!(5)
+ wam.machine_st.heap[1],
+ pstr_loc_as_cell!(heap_index!(3))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(0))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_loc_as_cell!(5)
+ wam.machine_st.heap[4],
+ heap_loc_as_cell!(4)
);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ // create a cycle offset two characters into the partial string at 0
+ wam.machine_st.heap[4] = pstr_loc_as_cell!(heap_index!(0) + 2);
- wam.machine_st.heap[7] = heap_loc_as_cell!(2);
+ mark_cells(&mut wam.machine_st.heap, 2);
- mark_cells(&mut wam.machine_st.heap, 7);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
- all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]);
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(3)
+ wam.machine_st.heap.slice_to_str(0, "abc ".len()),
+ "abc "
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- pstr_loc_as_cell!(5)
+ wam.machine_st.heap[1],
+ pstr_loc_as_cell!(heap_index!(3))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(0))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- heap_loc_as_cell!(2)
+ wam.machine_st.heap[4],
+ pstr_loc_as_cell!(heap_index!(0) + 2)
);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ wam.machine_st.heap[4] = heap_loc_as_cell!(2);
- wam.machine_st.heap[7] = pstr_loc_as_cell!(1);
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(2)).unwrap();
- mark_cells(&mut wam.machine_st.heap, 7);
+ mark_cells(&mut wam.machine_st.heap, 5);
+
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
- all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]);
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(3)
+ wam.machine_st.heap.slice_to_str(0, "abc ".len()),
+ "abc "
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- pstr_loc_as_cell!(5)
+ wam.machine_st.heap[1],
+ pstr_loc_as_cell!(heap_index!(3))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(0))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_loc_as_cell!(1)
+ wam.machine_st.heap[4],
+ heap_loc_as_cell!(2)
+ );
+ assert_eq!(
+ wam.machine_st.heap[5],
+ heap_loc_as_cell!(2)
);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ wam.machine_st.heap[4] = pstr_loc_as_cell!(0);
- wam.machine_st.heap[7] = heap_loc_as_cell!(0);
+ mark_cells(&mut wam.machine_st.heap, 2);
- mark_cells(&mut wam.machine_st.heap, 7);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(.. 5));
- all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]);
+ unmark_all_cells(wam.machine_st.heap.splice_mut(.. 5));
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(3)
+ wam.machine_st.heap.slice_to_str(0, "abc ".len()),
+ "abc "
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- pstr_loc_as_cell!(5)
+ wam.machine_st.heap[1],
+ pstr_loc_as_cell!(heap_index!(3))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(0))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- heap_loc_as_cell!(0)
+ wam.machine_st.heap[4],
+ pstr_loc_as_cell!(heap_index!(0))
+ );
+ assert_eq!(
+ wam.machine_st.heap[5],
+ heap_loc_as_cell!(2)
);
wam.machine_st.heap.truncate(4);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ let mut writer = wam.machine_st.heap.reserve(2).unwrap();
- wam.machine_st
- .heap
- .push(atom_as_cell!(atom!("irrelevant stuff")));
- wam.machine_st.heap.push(pstr_offset_as_cell!(1));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(2)));
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("irrelevant stuff")));
+ section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 2)); // offset two chars into pstr at 0
+ });
- // this is at index 7
- wam.machine_st.heap.push(pstr_loc_as_cell!(5));
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(5)).unwrap();
- mark_cells(&mut wam.machine_st.heap, 7);
+ mark_cells(&mut wam.machine_st.heap, 6);
- assert!(!wam.machine_st.heap[0].get_mark_bit());
+ // indices 0 and 3 are the beginning of one-cell partial
+ // strings, and they should be marked! despite the HeapCellValue casts
+ // otherwise not being sensible.
+ assert!(wam.machine_st.heap[0].get_mark_bit());
assert!(wam.machine_st.heap[1].get_mark_bit());
- assert!(wam.machine_st.heap[2].get_mark_bit());
+ assert!(!wam.machine_st.heap[2].get_mark_bit());
assert!(wam.machine_st.heap[3].get_mark_bit());
assert!(wam.machine_st.heap[4].get_mark_bit());
assert!(wam.machine_st.heap[5].get_mark_bit());
assert!(wam.machine_st.heap[6].get_mark_bit());
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(3)
- );
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- atom_as_cell!(atom!("irrelevant stuff"))
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_offset_as_cell!(1)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- fixnum_as_cell!(Fixnum::build_with(2))
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_loc_as_cell!(5)
- );
-
- wam.machine_st.heap.clear();
-
- wam.machine_st
- .heap
- .push(atom_as_cell!(atom!("irrelevant stuff")));
- wam.machine_st.heap.push(pstr_cell);
- wam.machine_st.heap.push(pstr_loc_as_cell!(4));
- wam.machine_st
- .heap
- .push(atom_as_cell!(atom!("irrelevant stuff")));
- wam.machine_st.heap.push(pstr_second_cell);
- wam.machine_st.heap.push(pstr_loc_as_cell!(7));
- wam.machine_st
- .heap
- .push(atom_as_cell!(atom!("irrelevant stuff")));
- wam.machine_st.heap.push(pstr_offset_as_cell!(1));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(2)));
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(7));
-
- mark_cells(&mut wam.machine_st.heap, 9);
-
- assert!(!wam.machine_st.heap[0].get_mark_bit());
- assert!(wam.machine_st.heap[1].get_mark_bit());
- assert!(wam.machine_st.heap[2].get_mark_bit());
- assert!(!wam.machine_st.heap[3].get_mark_bit());
- assert!(wam.machine_st.heap[4].get_mark_bit());
- assert!(wam.machine_st.heap[5].get_mark_bit());
- assert!(!wam.machine_st.heap[6].get_mark_bit());
- assert!(wam.machine_st.heap[7].get_mark_bit());
- assert!(wam.machine_st.heap[8].get_mark_bit());
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
- atom_as_cell!(atom!("irrelevant stuff"))
+ wam.machine_st.heap.slice_to_str(0, "abc ".len()),
+ "abc "
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(4)
+ wam.machine_st.heap[1],
+ pstr_loc_as_cell!(heap_index!(3))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
- atom_as_cell!(atom!("irrelevant stuff"))
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(0))
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_loc_as_cell!(7)
+ wam.machine_st.heap.slice_to_str(heap_index!(3), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
+ wam.machine_st.heap[4],
atom_as_cell!(atom!("irrelevant stuff"))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap[5],
+ pstr_loc_as_cell!(heap_index!(0) + 2)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[8]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap[6],
+ heap_loc_as_cell!(5)
);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ wam.machine_st.heap.clear();
- wam.machine_st.heap[9] = heap_loc_as_cell!(5);
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
- mark_cells(&mut wam.machine_st.heap, 9);
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("irrelevant stuff")));
+ section.push_pstr("abc ");
+ section.push_cell(pstr_loc_as_cell!(heap_index!(4)));
+ section.push_cell(atom_as_cell!(atom!("irrelevant stuff")));
+ section.push_pstr("def");
+ section.push_cell(pstr_loc_as_cell!(heap_index!(1) + 2));
+ section.push_cell(atom_as_cell!(atom!("irrelevant stuff")));
+ section.push_cell(pstr_loc_as_cell!(heap_index!(1) + 2));
+ });
+
+ mark_cells(&mut wam.machine_st.heap, 7);
assert!(!wam.machine_st.heap[0].get_mark_bit());
assert!(wam.machine_st.heap[1].get_mark_bit());
assert!(wam.machine_st.heap[4].get_mark_bit());
assert!(wam.machine_st.heap[5].get_mark_bit());
assert!(!wam.machine_st.heap[6].get_mark_bit());
- assert!(wam.machine_st.heap[7].get_mark_bit());
- assert!(wam.machine_st.heap[8].get_mark_bit());
- for cell in &wam.machine_st.heap {
- assert!(!cell.get_forwarding_bit());
- }
+ assert!(!wam.machine_st.heap[0].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[1].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[2].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[3].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[4].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[5].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[6].get_forwarding_bit());
+
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
- atom_as_cell!(atom!("irrelevant stuff"))
- );
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(4)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
- atom_as_cell!(atom!("irrelevant stuff"))
- );
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_loc_as_cell!(7)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
+ wam.machine_st.heap[0],
atom_as_cell!(atom!("irrelevant stuff"))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap.slice_to_str(heap_index!(1), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[8]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(4))
);
-
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
-
- wam.machine_st.heap[9] = pstr_loc_as_cell!(4);
-
- mark_cells(&mut wam.machine_st.heap, 9);
-
- assert!(!wam.machine_st.heap[0].get_mark_bit());
- assert!(wam.machine_st.heap[1].get_mark_bit());
- assert!(wam.machine_st.heap[2].get_mark_bit());
- assert!(!wam.machine_st.heap[3].get_mark_bit());
- assert!(wam.machine_st.heap[4].get_mark_bit());
- assert!(wam.machine_st.heap[5].get_mark_bit());
- assert!(!wam.machine_st.heap[6].get_mark_bit());
- assert!(wam.machine_st.heap[7].get_mark_bit());
- assert!(wam.machine_st.heap[8].get_mark_bit());
-
- for cell in &wam.machine_st.heap {
- assert!(!cell.get_forwarding_bit());
- }
-
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
+ wam.machine_st.heap[3],
atom_as_cell!(atom!("irrelevant stuff"))
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(4)
+ wam.machine_st.heap.slice_to_str(heap_index!(4), "def".len()),
+ "def"
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
- atom_as_cell!(atom!("irrelevant stuff"))
+ wam.machine_st.heap[5],
+ pstr_loc_as_cell!(heap_index!(1) + 2)
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_loc_as_cell!(7)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
+ wam.machine_st.heap[6],
atom_as_cell!(atom!("irrelevant stuff"))
);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_offset_as_cell!(1)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[8]),
- fixnum_as_cell!(Fixnum::build_with(2))
- );
-
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
- mark_cells(&mut wam.machine_st.heap, 9);
+ wam.machine_st.heap[7] = heap_loc_as_cell!(2);
- wam.machine_st.heap[9] = heap_loc_as_cell!(2);
+ mark_cells(&mut wam.machine_st.heap, 7);
assert!(!wam.machine_st.heap[0].get_mark_bit());
assert!(wam.machine_st.heap[1].get_mark_bit());
assert!(wam.machine_st.heap[5].get_mark_bit());
assert!(!wam.machine_st.heap[6].get_mark_bit());
assert!(wam.machine_st.heap[7].get_mark_bit());
- assert!(wam.machine_st.heap[8].get_mark_bit());
- for cell in &wam.machine_st.heap {
- assert!(!cell.get_forwarding_bit());
- }
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
+
+ assert!(!wam.machine_st.heap[0].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[1].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[2].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[3].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[4].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[5].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[6].get_forwarding_bit());
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
+ wam.machine_st.heap[0],
atom_as_cell!(atom!("irrelevant stuff"))
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(4)
+ wam.machine_st.heap.slice_to_str(heap_index!(1), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
- atom_as_cell!(atom!("irrelevant stuff"))
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(4))
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_loc_as_cell!(7)
+ wam.machine_st.heap[3],
+ atom_as_cell!(atom!("irrelevant stuff"))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- atom_as_cell!(atom!("irrelevant stuff"))
+ wam.machine_st.heap.slice_to_str(heap_index!(4), "def".len()),
+ "def"
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap[5],
+ pstr_loc_as_cell!(heap_index!(1) + 2)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[8]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap[6],
+ atom_as_cell!(atom!("irrelevant stuff"))
);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
-
- wam.machine_st.heap[9] = pstr_loc_as_cell!(1);
+ wam.machine_st.heap[7] = pstr_loc_as_cell!(heap_index!(4));
- mark_cells(&mut wam.machine_st.heap, 9);
+ mark_cells(&mut wam.machine_st.heap, 7);
assert!(!wam.machine_st.heap[0].get_mark_bit());
assert!(wam.machine_st.heap[1].get_mark_bit());
assert!(wam.machine_st.heap[5].get_mark_bit());
assert!(!wam.machine_st.heap[6].get_mark_bit());
assert!(wam.machine_st.heap[7].get_mark_bit());
- assert!(wam.machine_st.heap[8].get_mark_bit());
- for cell in &wam.machine_st.heap {
- assert!(!cell.get_forwarding_bit());
- }
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
+
+ assert!(!wam.machine_st.heap[0].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[1].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[2].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[3].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[4].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[5].get_forwarding_bit());
+ assert!(!wam.machine_st.heap[6].get_forwarding_bit());
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
+ wam.machine_st.heap[0],
atom_as_cell!(atom!("irrelevant stuff"))
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_loc_as_cell!(4)
+ wam.machine_st.heap.slice_to_str(heap_index!(1), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
- atom_as_cell!(atom!("irrelevant stuff"))
+ wam.machine_st.heap[2],
+ pstr_loc_as_cell!(heap_index!(4))
);
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_loc_as_cell!(7)
+ wam.machine_st.heap[3],
+ atom_as_cell!(atom!("irrelevant stuff"))
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- atom_as_cell!(atom!("irrelevant stuff"))
+ wam.machine_st.heap.slice_to_str(heap_index!(4), "def".len()),
+ "def"
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[7]),
- pstr_offset_as_cell!(1)
+ wam.machine_st.heap[5],
+ pstr_loc_as_cell!(heap_index!(1) + 2)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[8]),
- fixnum_as_cell!(Fixnum::build_with(2))
+ wam.machine_st.heap[6],
+ atom_as_cell!(atom!("irrelevant stuff"))
);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
-
wam.machine_st.heap.clear();
- // embedded cyclic partial string.
+ // embedded cyclic partial string
- wam.machine_st.heap.push(pstr_cell);
- wam.machine_st.heap.push(pstr_loc_as_cell!(2));
- wam.machine_st.heap.push(pstr_offset_as_cell!(0));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(3)));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(8).unwrap();
- mark_cells(&mut wam.machine_st.heap, 4);
+ writer.write_with(|section| {
+ section.push_pstr("abc ");
+ section.push_cell(pstr_loc_as_cell!(heap_index!(0) + 3)); // 3 character offset into pstr_cell
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(pstr_loc_as_cell!(0));
+ section.push_cell(empty_list_as_cell!());
+ section.push_cell(heap_loc_as_cell!(2));
+ });
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ mark_cells(&mut wam.machine_st.heap, 5);
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
+
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[1]),
- pstr_loc_as_cell!(2)
- );
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_offset_as_cell!(0)
+ wam.machine_st.heap.slice_to_str(heap_index!(0), "abc ".len()),
+ "abc "
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
- fixnum_as_cell!(Fixnum::build_with(3))
+ wam.machine_st.heap[1],
+ pstr_loc_as_cell!(heap_index!(0) + 3)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- list_loc_as_cell!(5)
+ wam.machine_st.heap[2],
+ list_loc_as_cell!(3)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
+ wam.machine_st.heap[3],
pstr_loc_as_cell!(0)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
+ wam.machine_st.heap[4],
empty_list_as_cell!()
);
-
- wam.machine_st.heap.clear();
-
- wam.machine_st.heap.push(pstr_cell);
- wam.machine_st.heap.push(pstr_loc_as_cell!(2));
- wam.machine_st.heap.push(pstr_offset_as_cell!(0));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(3)));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
- wam.machine_st.heap.push(pstr_loc_as_cell!(0));
- wam.machine_st.heap.push(heap_loc_as_cell!(4));
-
- mark_cells(&mut wam.machine_st.heap, 4);
-
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
-
- for cell in &mut wam.machine_st.heap {
- cell.set_mark_bit(false);
- }
-
- assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[1]),
- pstr_loc_as_cell!(2)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
- pstr_offset_as_cell!(0)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
- fixnum_as_cell!(Fixnum::build_with(3))
- );
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[4]),
- list_loc_as_cell!(5)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[5]),
- pstr_loc_as_cell!(0)
- );
- assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[6]),
- heap_loc_as_cell!(4)
+ wam.machine_st.heap[5],
+ heap_loc_as_cell!(2)
);
wam.machine_st.heap.clear();
// a chain of variables, ending in a self-referential variable.
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(2));
+ section.push_cell(heap_loc_as_cell!(3));
+ section.push_cell(heap_loc_as_cell!(3));
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
+
+ unmark_all_cells(wam.machine_st.heap.splice_mut(..));
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[0]),
+ wam.machine_st.heap[0],
heap_loc_as_cell!(1)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[1]),
+ wam.machine_st.heap[1],
heap_loc_as_cell!(2)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[2]),
+ wam.machine_st.heap[2],
heap_loc_as_cell!(3)
);
assert_eq!(
- unmark_cell_bits!(wam.machine_st.heap[3]),
+ wam.machine_st.heap[3],
heap_loc_as_cell!(3)
);
wam.machine_st.heap.clear();
// print L = [L|L].
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(1));
+
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(1));
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
// term is [X,f(Y),Z].
// Z is an attributed variable, but has a variable attributes list.
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(3)); // 2
- wam.machine_st.heap.push(list_loc_as_cell!(4)); // 3
- wam.machine_st.heap.push(str_loc_as_cell!(6)); // 4
- wam.machine_st.heap.push(heap_loc_as_cell!(8));
- wam.machine_st.heap.push(atom_as_cell!(f_atom, 1)); // 6
- wam.machine_st.heap.push(heap_loc_as_cell!(11)); // 7
- wam.machine_st.heap.push(list_loc_as_cell!(9));
- wam.machine_st.heap.push(heap_loc_as_cell!(9));
- wam.machine_st.heap.push(empty_list_as_cell!());
- wam.machine_st.heap.push(attr_var_as_cell!(11)); // linked from 7.
- wam.machine_st.heap.push(heap_loc_as_cell!(12));
+
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(3)); // 2
+ section.push_cell(list_loc_as_cell!(4)); // 3
+ section.push_cell(str_loc_as_cell!(6)); // 4
+ section.push_cell(heap_loc_as_cell!(8));
+ section.push_cell(atom_as_cell!(f_atom, 1)); // 6
+ section.push_cell(heap_loc_as_cell!(11)); // 7
+ section.push_cell(list_loc_as_cell!(9));
+ section.push_cell(heap_loc_as_cell!(9));
+ section.push_cell(empty_list_as_cell!());
+ section.push_cell(attr_var_as_cell!(11)); // linked from 7.
+ section.push_cell(heap_loc_as_cell!(12));
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
let clpz_atom = atom!("clpz");
let p_atom = atom!("p");
- for cell in &mut wam.machine_st.heap {
+ for cell in &mut wam.machine_st.heap.splice_mut(..) {
cell.set_mark_bit(false);
cell.set_forwarding_bit(false);
}
- wam.machine_st.heap.pop();
-
- wam.machine_st.heap.push(heap_loc_as_cell!(13)); // 12
- wam.machine_st.heap.push(list_loc_as_cell!(14)); // 13
- wam.machine_st.heap.push(str_loc_as_cell!(16)); // 14
- wam.machine_st.heap.push(heap_loc_as_cell!(19)); // 15
- wam.machine_st.heap.push(atom_as_cell!(clpz_atom, 2)); // 16
- wam.machine_st.heap.push(atom_as_cell!(a_atom)); // 17
- wam.machine_st.heap.push(atom_as_cell!(b_atom)); // 18
- wam.machine_st.heap.push(list_loc_as_cell!(20)); // 19
- wam.machine_st.heap.push(str_loc_as_cell!(22)); // 20
- wam.machine_st.heap.push(empty_list_as_cell!()); // 21
- wam.machine_st.heap.push(atom_as_cell!(p_atom, 1)); // 22
- wam.machine_st.heap.push(heap_loc_as_cell!(23)); // 23
+ wam.machine_st.heap[12] = heap_loc_as_cell!(13);
+
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(14)); // 13
+ section.push_cell(str_loc_as_cell!(16)); // 14
+ section.push_cell(heap_loc_as_cell!(19)); // 15
+ section.push_cell(atom_as_cell!(clpz_atom, 2)); // 16
+ section.push_cell(atom_as_cell!(a_atom)); // 17
+ section.push_cell(atom_as_cell!(b_atom)); // 18
+ section.push_cell(list_loc_as_cell!(20)); // 19
+ section.push_cell(str_loc_as_cell!(22)); // 20
+ section.push_cell(empty_list_as_cell!()); // 21
+ section.push_cell(atom_as_cell!(p_atom, 1)); // 22
+ section.push_cell(heap_loc_as_cell!(23)); // 23
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
heap_loc_as_cell!(23)
);
- for cell in &mut wam.machine_st.heap {
+ for cell in &mut wam.machine_st.heap.splice_mut(..) {
cell.set_mark_bit(false);
cell.set_forwarding_bit(false);
}
// push some unrelated nonsense cells to the heap and check that they
// are unmarked after the marker has finished at 0.
- wam.machine_st.heap.push(heap_loc_as_cell!(5));
- wam.machine_st.heap.push(heap_loc_as_cell!(5));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(5));
+ section.push_cell(heap_loc_as_cell!(5));
+ section.push_cell(list_loc_as_cell!(5));
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap[0..24]);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(0..24));
- for cell in &wam.machine_st.heap[24..] {
+ for cell in wam.machine_st.heap.splice(24..) {
assert!(!cell.get_mark_bit());
}
wam.machine_st.heap.clear();
wam.machine_st
.heap
- .push(fixnum_as_cell!(Fixnum::build_with(0)));
+ .push_cell(fixnum_as_cell!(Fixnum::build_with(0)))
+ .unwrap();
mark_cells(&mut wam.machine_st.heap, 0);
- assert_eq!(wam.machine_st.heap.len(), 1);
+ assert_eq!(wam.machine_st.heap.cell_len(), 1);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
- wam.machine_st.heap.push(atom_as_cell!(atom!("="), 2));
- wam.machine_st.heap.push(atom_as_cell!(atom!("X")));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(list_loc_as_cell!(8));
- wam.machine_st.heap.push(str_loc_as_cell!(4));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(str_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("g"), 2));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(atom_as_cell!(atom!("y")));
+ section.push_cell(atom_as_cell!(atom!("="), 2));
+ section.push_cell(atom_as_cell!(atom!("X")));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(list_loc_as_cell!(8));
+ section.push_cell(str_loc_as_cell!(4));
+ section.push_cell(empty_list_as_cell!());
+ });
mark_cells(&mut wam.machine_st.heap, 7);
- assert_eq!(wam.machine_st.heap.len(), 10);
+ assert_eq!(wam.machine_st.heap.cell_len(), 10);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cell!(atom!("f"), 2));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(str_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("f"), 2));
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(heap_loc_as_cell!(1));
+ section.push_cell(str_loc_as_cell!(0));
+ });
mark_cells(&mut wam.machine_st.heap, 3);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
// representation of one of the heap terms as in issue #1384.
- wam.machine_st.heap.push(list_loc_as_cell!(1));
- wam.machine_st.heap.push(empty_list_as_cell!());
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(empty_list_as_cell!());
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
- wam.machine_st.heap.push(list_loc_as_cell!(5));
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(empty_list_as_cell!());
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(empty_list_as_cell!());
+ section.push_cell(heap_loc_as_cell!(2));
+ section.push_cell(list_loc_as_cell!(5));
+ });
mark_cells(&mut wam.machine_st.heap, 7);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
// representation of one of the heap terms as in issue #1384.
- wam.machine_st.heap.push(list_loc_as_cell!(7));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
- wam.machine_st.heap.push(list_loc_as_cell!(3)); // A = [B|[]].
- wam.machine_st.heap.push(list_loc_as_cell!(5)); // B = [A|A].
- wam.machine_st.heap.push(empty_list_as_cell!());
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
- wam.machine_st.heap.push(empty_list_as_cell!()); // C = [[]|B].
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(7));
+ section.push_cell(heap_loc_as_cell!(0));
+ section.push_cell(list_loc_as_cell!(3)); // A = [B|[]].
+ section.push_cell(list_loc_as_cell!(5)); // B = [A|A].
+ section.push_cell(empty_list_as_cell!());
+ section.push_cell(heap_loc_as_cell!(2));
+ section.push_cell(heap_loc_as_cell!(2));
+ section.push_cell(empty_list_as_cell!()); // C = [[]|B].
+ section.push_cell(heap_loc_as_cell!(3));
+ section.push_cell(heap_loc_as_cell!(0));
+ });
mark_cells(&mut wam.machine_st.heap, 9);
assert!(wam.machine_st.heap[0].get_mark_bit());
assert!(!wam.machine_st.heap[1].get_mark_bit());
- all_cells_marked_and_unforwarded(&wam.machine_st.heap[2..]);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(2..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
unmark_cell_bits!(wam.machine_st.heap[8]),
heap_loc_as_cell!(3)
);
+ assert_eq!(
+ unmark_cell_bits!(wam.machine_st.heap[9]),
+ heap_loc_as_cell!(0)
+ );
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(str_loc_as_cell!(1));
- wam.machine_st.heap.push(atom_as_cell!(atom!("+"), 2));
- wam.machine_st.heap.push(str_loc_as_cell!(4));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(2)));
- wam.machine_st.heap.push(atom_as_cell!(atom!("-"), 2));
- wam.machine_st.heap.push(str_loc_as_cell!(7));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(1)));
- wam.machine_st.heap.push(atom_as_cell!(atom!("+"), 2));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(3)));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(4)));
+ let mut writer = wam.machine_st.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(str_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("+"), 2));
+ section.push_cell(str_loc_as_cell!(4));
+ section.push_cell(fixnum_as_cell!(Fixnum::build_with(2)));
+ section.push_cell(atom_as_cell!(atom!("-"), 2));
+ section.push_cell(str_loc_as_cell!(7));
+ section.push_cell(fixnum_as_cell!(Fixnum::build_with(1)));
+ section.push_cell(atom_as_cell!(atom!("+"), 2));
+ section.push_cell(fixnum_as_cell!(Fixnum::build_with(3)));
+ section.push_cell(fixnum_as_cell!(Fixnum::build_with(4)));
+ });
mark_cells(&mut wam.machine_st.heap, 0);
- all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+ all_cells_marked_and_unforwarded(wam.machine_st.heap.splice(..));
assert_eq!(
unmark_cell_bits!(wam.machine_st.heap[0]),
-use crate::arena::*;
use crate::atom_table::*;
use crate::forms::*;
-use crate::machine::machine_indices::*;
-use crate::machine::partial_string::*;
-use crate::parser::ast::*;
+use crate::functor_macro::*;
use crate::types::*;
-use crate::parser::dashu::{Integer, Rational};
-
+use std::alloc;
use std::convert::TryFrom;
+use std::mem;
+use std::ops::{Bound, Index, IndexMut, Range, RangeBounds};
+use std::ptr;
+use std::sync::Once;
-pub(crate) type Heap = Vec<HeapCellValue>;
+use super::MachineState;
-impl From<Literal> for HeapCellValue {
- #[inline]
- fn from(literal: Literal) -> Self {
- match literal {
- Literal::Atom(name) => atom_as_cell!(name),
- Literal::Char(c) => char_as_cell!(c),
- Literal::CodeIndex(ptr) => {
- untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(ptr))
+use bitvec::prelude::*;
+use bitvec::slice::BitSlice;
+
+#[derive(Debug)]
+pub struct Heap {
+ inner: InnerHeap,
+ pstr_vec: BitVec,
+ resource_err_loc: usize,
+}
+
+impl Drop for Heap {
+ fn drop(&mut self) {
+ unsafe {
+ let layout = alloc::Layout::array::<u8>(self.inner.byte_cap).unwrap();
+ alloc::dealloc(self.inner.ptr, layout);
+ }
+ }
+}
+
+#[derive(Debug)]
+struct InnerHeap {
+ ptr: *mut u8,
+ byte_len: usize,
+ byte_cap: usize,
+}
+
+impl InnerHeap {
+ unsafe fn grow(&mut self) -> bool {
+ let new_cap = if self.byte_cap == 0 {
+ 256 * 256 * 8
+ } else {
+ 2 * self.byte_cap
+ };
+
+ let new_layout = alloc::Layout::array::<u8>(new_cap).unwrap();
+
+ assert!(
+ new_layout.size() <= isize::MAX as usize,
+ "Allocation too large. We should probably GC (TODO)"
+ );
+
+ let new_ptr = if self.byte_cap == 0 {
+ alloc::alloc(new_layout)
+ } else {
+ let old_layout = alloc::Layout::array::<u8>(self.byte_cap).unwrap();
+ alloc::realloc(self.ptr, old_layout, new_layout.size())
+ };
+
+ if !new_ptr.is_null() {
+ self.ptr = new_ptr;
+ self.byte_cap = new_cap;
+
+ true
+ } else {
+ false
+ }
+ }
+}
+
+unsafe impl Send for Heap {}
+unsafe impl Sync for Heap {}
+
+static RESOURCE_ERROR_OFFSET_INIT: Once = Once::new();
+
+// return the string at ptr and the tail location relative to ptr.
+// pstr_vec records the location of each string cell starting at index
+// 0.
+fn scan_slice_to_str(orig_ptr: *const u8, pstr_vec: &BitSlice) -> (&str, usize) {
+ unsafe {
+ debug_assert_eq!(pstr_vec[0], true);
+ const ALIGN_CELL: usize = Heap::heap_cell_alignment();
+
+ let tail_cell_offset = pstr_vec[0..].first_zero().unwrap();
+ let offset = (ALIGN_CELL - orig_ptr.align_offset(ALIGN_CELL)) % 8;
+ let buf_len = heap_index!(tail_cell_offset) - offset;
+ let slice = std::slice::from_raw_parts(orig_ptr, buf_len);
+
+ // skip the final buffer byte which may not be 0 depending on
+ // the context, i.e. marking by an iterator. it is counted by
+ // the initial 1 as part of the padding but for this reason
+ // mustn't be allowed to stop the count.
+
+ let padding_len = 1 + slice.iter()
+ .rev()
+ .skip(1)
+ .position(|b| *b != 0u8)
+ .unwrap();
+
+ let s_len = slice.len() - padding_len;
+ (std::str::from_utf8_unchecked(&slice[0 .. s_len]), tail_cell_offset)
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub(crate) enum PStrSegmentCmpResult {
+ Mismatch { c1: char, c2: char },
+ FirstMatch { pstr_loc1: usize, pstr_loc2: usize, l1_offset: usize },
+ SecondMatch { pstr_loc1: usize, pstr_loc2: usize, l2_offset: usize },
+ BothMatch { pstr_loc1: usize, pstr_loc2: usize, null_offset: usize },
+}
+
+impl PStrSegmentCmpResult {
+ pub(crate) fn continue_pstr_compare(
+ self,
+ pdl: &mut Vec<HeapCellValue>,
+ ) -> Option<std::cmp::Ordering> {
+ match self {
+ PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset } => {
+ let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + l1_offset);
+ let rest_of_l2 = pstr_loc_as_cell!(pstr_loc2 + l1_offset);
+
+ pdl.push(heap_loc_as_cell!(tail1));
+ pdl.push(rest_of_l2);
+ }
+ PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset } => {
+ let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + l2_offset);
+ let rest_of_l1 = pstr_loc_as_cell!(pstr_loc1 + l2_offset);
+
+ pdl.push(rest_of_l1);
+ pdl.push(heap_loc_as_cell!(tail2));
}
- Literal::Fixnum(n) => fixnum_as_cell!(n),
- Literal::Integer(bigint_ptr) => {
- typed_arena_ptr_as_cell!(bigint_ptr)
+ PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset } => {
+ // exhaustive match
+ let tail1 = Heap::neighboring_cell_offset(pstr_loc1 + null_offset);
+ let tail2 = Heap::neighboring_cell_offset(pstr_loc2 + null_offset);
+
+ pdl.push(heap_loc_as_cell!(tail1));
+ pdl.push(heap_loc_as_cell!(tail2));
}
- Literal::Rational(bigint_ptr) => {
- typed_arena_ptr_as_cell!(bigint_ptr)
+ PStrSegmentCmpResult::Mismatch { c1, c2 } => {
+ return Some(c1.cmp(&c2));
}
- Literal::Float(f) => HeapCellValue::from(f.as_ptr()),
- Literal::String(s) => {
- if s == atom!("") {
- empty_list_as_cell!()
- } else {
- string_as_cstr_cell!(s)
+ }
+
+ None
+ }
+}
+
+#[derive(Debug)]
+pub(crate) struct HeapView<'a> {
+ slice: *const u8,
+ cell_offset: usize,
+ slice_cell_len: usize,
+ pstr_slice: &'a BitSlice,
+}
+
+impl<'a> HeapView<'a> {
+ /*
+ pub fn get(&self, idx: usize) -> Option<HeapCellValue> {
+ if idx < self.slice_cell_len {
+ Some(*self.index(idx))
+ } else {
+ None
+ }
+ }
+ */
+
+ fn iter_follow(&mut self) -> Option<HeapCellValue> {
+ if self.slice_cell_len == 0 {
+ None
+ } else {
+ let cell;
+
+ if self.pstr_slice[0] {
+ cell = pstr_loc_as_cell!(heap_index!(self.cell_offset));
+ let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
+
+ unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
+ self.slice_cell_len -= next_cell_idx;
+ self.cell_offset += next_cell_idx;
+ self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
+ } else {
+ unsafe {
+ cell = ptr::read(self.slice as *mut HeapCellValue);
+ self.slice = self.slice.add(heap_index!(1));
}
+
+ self.cell_offset += 1;
+ self.slice_cell_len -= 1;
+ self.pstr_slice = &self.pstr_slice[1 ..];
}
+
+ Some(cell)
}
}
}
-impl TryFrom<HeapCellValue> for Literal {
- type Error = ();
+impl<'a> Iterator for HeapView<'a> {
+ type Item = HeapCellValue;
- fn try_from(value: HeapCellValue) -> Result<Literal, ()> {
- read_heap_cell!(value,
- (HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- Ok(Literal::Atom(name))
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter_follow()
+ }
+}
+
+impl<'a> Index<usize> for HeapView<'a> {
+ type Output = HeapCellValue;
+
+ fn index(&self, idx: usize) -> &Self::Output {
+ debug_assert!(idx < self.slice_cell_len);
+ unsafe {
+ &*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
+ }
+ }
+}
+
+#[derive(Debug)]
+pub(crate) struct HeapViewMut<'a> {
+ slice: *mut u8,
+ cell_offset: usize,
+ slice_cell_len: usize,
+ pstr_slice: &'a BitSlice,
+}
+
+impl<'a> HeapViewMut<'a> {
+ fn iter_follow(&mut self) -> Option<&'a mut HeapCellValue> {
+ if self.slice_cell_len == 0 {
+ None
+ } else {
+ let cell;
+
+ loop {
+ if self.pstr_slice[0] {
+ let next_cell_idx = self.pstr_slice[0 ..].first_zero().unwrap();
+
+ unsafe { self.slice = self.slice.add(heap_index!(next_cell_idx)); }
+
+ self.slice_cell_len -= next_cell_idx;
+ self.cell_offset += next_cell_idx;
+ self.pstr_slice = &self.pstr_slice[next_cell_idx ..];
} else {
- Err(())
+ unsafe {
+ cell = &mut *(self.slice as *mut HeapCellValue);
+ self.slice = self.slice.add(heap_index!(1));
+ }
+
+ self.cell_offset += 1;
+ self.slice_cell_len -= 1;
+ self.pstr_slice = &self.pstr_slice[1 ..];
+
+ break;
}
}
- (HeapCellValueTag::Char, c) => {
- Ok(Literal::Char(c))
+
+ Some(cell)
+ }
+ }
+}
+
+
+
+impl<'a> Index<usize> for HeapViewMut<'a> {
+ type Output = HeapCellValue;
+
+ fn index(&self, idx: usize) -> &Self::Output {
+ debug_assert!(idx < self.slice_cell_len);
+ unsafe {
+ &*(self.slice.add(heap_index!(idx)) as *const HeapCellValue)
+ }
+ }
+}
+
+impl<'a> IndexMut<usize> for HeapViewMut<'a> {
+ fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
+ debug_assert!(idx < self.slice_cell_len);
+ unsafe {
+ &mut *(self.slice.add(heap_index!(idx)) as *mut HeapCellValue)
+ }
+ }
+}
+
+impl<'a> Iterator for &'a mut HeapViewMut<'a> {
+ type Item = &'a mut HeapCellValue;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter_follow()
+ }
+}
+
+#[derive(Debug)]
+pub struct PStrWriteInfo {
+ pstr_loc: usize,
+}
+
+#[derive(Debug)]
+pub(crate) struct ReservedHeapSection<'a> {
+ heap_ptr: *mut u8,
+ heap_cell_len: usize,
+ pstr_vec: &'a mut BitVec,
+}
+
+impl<'a> ReservedHeapSection<'a> {
+ #[inline]
+ pub(crate) fn cell_len(&self) -> usize {
+ self.heap_cell_len
+ }
+
+ pub(crate) fn push_cell(&mut self, cell: HeapCellValue) {
+ unsafe {
+ ptr::write(self.heap_ptr.add(heap_index!(self.heap_cell_len)) as *mut _, cell);
+ }
+ self.pstr_vec.push(false);
+ self.heap_cell_len += 1;
+ }
+
+ fn push_pstr_segment(
+ &mut self,
+ src: &str,
+ ) -> usize {
+ if src.is_empty() {
+ return 0;
+ }
+
+ let cells_written;
+ let str_byte_len = src.len();
+
+ const ALIGN_CELL: usize = Heap::heap_cell_alignment();
+
+ unsafe {
+ ptr::copy_nonoverlapping(
+ src.as_ptr(),
+ self.heap_ptr.add(heap_index!(self.heap_cell_len)),
+ str_byte_len,
+ );
+
+ let zero_region_idx = heap_index!(self.heap_cell_len) + str_byte_len;
+
+ let align_offset = self.heap_ptr
+ .add(zero_region_idx)
+ .align_offset(ALIGN_CELL);
+
+ let align_offset = if align_offset == 0 {
+ ALIGN_CELL
+ } else {
+ align_offset
+ };
+
+ ptr::write_bytes(
+ self.heap_ptr.add(zero_region_idx),
+ 0u8,
+ align_offset,
+ );
+
+ cells_written = cell_index!(src.len() + align_offset);
+ self.heap_cell_len += cells_written;
+ }
+
+ cells_written
+ }
+
+ pub(crate) fn push_pstr(
+ &mut self,
+ mut src: &str,
+ ) -> Option<HeapCellValue> {
+ let orig_h = self.cell_len();
+
+ if src.is_empty() {
+ return if orig_h == self.heap_cell_len {
+ // src is empty and always was. nothing allocated
+ // in this case, so nothing to point to in heap.
+ None
+ } else {
+ self.push_cell(heap_loc_as_cell!(orig_h));
+ Some(heap_loc_as_cell!(orig_h))
+ };
+ }
+
+ loop {
+ let null_char_idx = src.find('\u{0}').unwrap_or_else(|| src.len());
+
+ let cell_len = self.cell_len();
+ let cells_written = self.push_pstr_segment(&src[0..null_char_idx]);
+ let tail_idx = self.cell_len();
+
+ self.pstr_vec.resize(cell_len + cells_written, true);
+
+ if cells_written == 0 {
+ return None;
+ } else if null_char_idx + 1 < src.len() {
+ self.push_cell(pstr_loc_as_cell!(heap_index!(tail_idx + 1)));
+ src = &src[null_char_idx + 1 ..];
+ } else {
+ return Some(pstr_loc_as_cell!(heap_index!(orig_h)));
}
- (HeapCellValueTag::Fixnum, n) => {
- Ok(Literal::Fixnum(n))
+ }
+ }
+
+ pub(crate) fn functor_writer(
+ functor: Vec<FunctorElement>,
+ ) -> impl FnMut(&mut ReservedHeapSection) {
+ struct FunctorData<'a> {
+ functor: &'a Vec<FunctorElement>,
+ cell_offset: usize,
+ cursor: usize,
+ }
+
+ move |section| {
+ let mut functor_stack = vec![FunctorData {
+ functor: &functor,
+ cell_offset: section.heap_cell_len,
+ cursor: 0,
+ }];
+
+ while let Some(FunctorData { functor, cell_offset, mut cursor }) = functor_stack.pop() {
+ while cursor < functor.len() {
+ match &functor[cursor] {
+ &FunctorElement::AbsoluteCell(cell) => {
+ section.push_cell(cell);
+ }
+ &FunctorElement::Cell(cell) => {
+ section.push_cell(cell + cell_offset);
+ }
+ &FunctorElement::String(_cell_len, ref string) => {
+ if section.push_pstr(&string).is_some() {
+ section.push_cell(empty_list_as_cell!());
+ }
+ }
+ FunctorElement::InnerFunctor(_inner_size, succ_functor) => {
+ if cursor + 1 < functor.len() {
+ functor_stack.push(FunctorData {
+ functor: &functor,
+ cell_offset,
+ cursor: cursor + 1,
+ });
+ }
+
+ functor_stack.push(FunctorData {
+ functor: succ_functor,
+ cell_offset: section.heap_cell_len,
+ cursor: 0,
+ });
+
+ break;
+ }
+ }
+
+ cursor += 1;
+ }
}
- (HeapCellValueTag::F64, f) => {
- Ok(Literal::Float(f.as_offset()))
+ }
+ }
+}
+
+impl<'a> Index<usize> for ReservedHeapSection<'a> {
+ type Output = HeapCellValue;
+
+ #[inline]
+ fn index(&self, idx: usize) -> &Self::Output {
+ debug_assert!(idx < self.heap_cell_len);
+ unsafe {
+ &*(self.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
+ }
+ }
+}
+
+#[must_use]
+#[derive(Debug)]
+pub struct HeapWriter<'a> {
+ section: ReservedHeapSection<'a>,
+ heap_byte_len: &'a mut usize,
+}
+
+impl<'a> HeapWriter<'a> {
+ #[allow(dead_code)]
+ pub(crate) fn write_with_error_handling<E>(
+ &mut self,
+ writer: impl FnOnce(&mut ReservedHeapSection) -> Result<(), E>,
+ ) -> Result<usize, E> {
+ let old_section_cell_len = self.section.heap_cell_len;
+ writer(&mut self.section)?;
+ *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
+
+ // return the number of bytes written
+ Ok(heap_index!(self.section.heap_cell_len - old_section_cell_len))
+ }
+
+ pub(crate) fn write_with(
+ &mut self,
+ writer: impl FnOnce(&mut ReservedHeapSection),
+ ) -> usize {
+ let old_section_cell_len = self.section.heap_cell_len;
+ writer(&mut self.section);
+ *self.heap_byte_len = heap_index!(self.section.heap_cell_len);
+
+ // return the number of bytes written
+ heap_index!(self.section.heap_cell_len - old_section_cell_len)
+ }
+
+ #[inline]
+ pub(crate) fn truncate(&mut self, cell_offset: usize) {
+ self.section.heap_cell_len = cell_offset;
+ self.section.pstr_vec.truncate(cell_offset);
+ *self.heap_byte_len = heap_index!(cell_offset);
+ }
+
+ #[inline]
+ pub(crate) fn is_empty(&self) -> bool {
+ self.section.heap_cell_len == 0
+ }
+
+ #[inline]
+ pub(crate) fn cell_len(&self) -> usize {
+ self.section.heap_cell_len
+ }
+}
+
+impl<'a> Index<usize> for HeapWriter<'a> {
+ type Output = HeapCellValue;
+
+ #[inline]
+ fn index(&self, idx: usize) -> &Self::Output {
+ debug_assert!(heap_index!(idx) < *self.heap_byte_len);
+ unsafe {
+ &*(self.section.heap_ptr.add(heap_index!(idx)) as *const HeapCellValue)
+ }
+ }
+}
+
+impl<'a> IndexMut<usize> for HeapWriter<'a> {
+ #[inline]
+ fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
+ debug_assert!(heap_index!(idx) < *self.heap_byte_len);
+ unsafe {
+ &mut *(self.section.heap_ptr.add(heap_index!(idx)) as *mut HeapCellValue)
+ }
+ }
+}
+
+impl<'a> SizedHeap for HeapWriter<'a> {
+ fn cell_len(&self) -> usize {
+ self.section.cell_len()
+ }
+
+ fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
+ let (s, tail_cell_offset) = scan_slice_to_str(
+ unsafe { self.section.heap_ptr.add(slice_loc) },
+ &self.section.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..],
+ );
+
+ (s, cell_index!(slice_loc) + tail_cell_offset)
+ }
+
+ fn pstr_at(&self, cell_offset: usize) -> bool {
+ self.section.pstr_vec[cell_offset]
+ }
+}
+
+impl<'a> SizedHeapMut for HeapWriter<'a> {}
+
+impl Heap {
+ pub(crate) fn new() -> Self {
+ Self {
+ inner: InnerHeap {
+ ptr: ptr::null_mut(),
+ byte_len: 0,
+ byte_cap: 0,
+ },
+ pstr_vec: bitvec![],
+ resource_err_loc: 0,
+ }
+ }
+
+ #[inline(always)]
+ unsafe fn grow(&mut self) -> bool {
+ let result = self.inner.grow();
+
+ if result {
+ self.pstr_vec.reserve(cell_index!(self.inner.byte_cap));
+ }
+
+ result
+ }
+
+ #[inline]
+ fn resource_error_offset(&self) -> usize {
+ self.resource_err_loc
+ }
+
+ pub(crate) fn with_cell_capacity(cap: usize) -> Result<Self, usize> {
+ let ptr = unsafe {
+ let layout = alloc::Layout::array::<HeapCellValue>(cap).unwrap();
+ alloc::alloc(layout)
+ };
+
+ if ptr.is_null() {
+ panic!("could not allocate {} bytes for heap!", heap_index!(cap))
+ } else {
+ Ok(Self {
+ inner: InnerHeap {
+ ptr,
+ byte_len: 0,
+ byte_cap: heap_index!(cap),
+ },
+ pstr_vec: bitvec![],
+ resource_err_loc: 0,
+ })
+ }
+ }
+
+ #[must_use]
+ pub fn reserve(&mut self, num_cells: usize) -> Result<HeapWriter, usize> {
+ let section;
+ let len = heap_index!(num_cells);
+
+ loop {
+ unsafe {
+ if self.free_space() >= len {
+ section = ReservedHeapSection {
+ heap_ptr: self.inner.ptr,
+ heap_cell_len: cell_index!(self.inner.byte_len),
+ pstr_vec: &mut self.pstr_vec,
+ };
+ break;
+ } else if !self.grow() {
+ return Err(self.resource_error_offset());
+ }
}
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::Integer, n) => {
- Ok(Literal::Integer(n))
- }
- (ArenaHeaderTag::Rational, n) => {
- Ok(Literal::Rational(n))
- }
- (ArenaHeaderTag::IndexPtr, ip) => {
- Ok(Literal::CodeIndex(CodeIndex::from(ip)))
- }
- _ => {
- Err(())
- }
- )
+ }
+
+ Ok(HeapWriter {
+ section,
+ heap_byte_len: &mut self.inner.byte_len,
+ })
+ }
+
+ pub(crate) fn last_cell_mut(&mut self) -> Option<&mut HeapCellValue> {
+ if self.inner.byte_len == 0 {
+ None
+ } else {
+ unsafe {
+ Some(&mut *(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
+ as *mut HeapCellValue))
}
- (HeapCellValueTag::CStr, cstr_atom) => {
- Ok(Literal::String(cstr_atom))
+ }
+ }
+
+ pub(crate) fn last_cell(&mut self) -> Option<HeapCellValue> {
+ if self.inner.byte_len == 0 {
+ None
+ } else {
+ unsafe {
+ Some(ptr::read(self.inner.ptr.add(self.inner.byte_len - heap_index!(1))
+ as *const HeapCellValue))
}
- _ => {
- Err(())
+ }
+ }
+
+ #[inline]
+ pub(crate) fn is_empty(&self) -> bool {
+ self.inner.byte_len == 0
+ }
+
+ pub(crate) fn index_of(&mut self, cell: HeapCellValue) -> Result<usize, usize> {
+ Ok(if cell.is_var() {
+ cell.get_value() as usize
+ } else {
+ let focus = self.cell_len();
+ self.push_cell(cell)?;
+ focus
+ })
+ }
+
+ pub(crate) fn clear(&mut self) {
+ unsafe {
+ let layout = alloc::Layout::array::<u8>(self.inner.byte_cap).unwrap();
+ alloc::dealloc(self.inner.ptr, layout);
+ }
+
+ self.inner.ptr = ptr::null_mut();
+ self.inner.byte_len = 0;
+ self.inner.byte_cap = 0;
+
+ self.pstr_vec.clear();
+ }
+
+ pub(crate) fn append(&mut self, heap_slice: HeapView) -> Result<(), usize> {
+ unsafe {
+ loop {
+ if self.free_space() >= heap_index!(heap_slice.slice_cell_len) {
+ ptr::copy_nonoverlapping(
+ heap_slice.slice,
+ self.inner.ptr.add(self.inner.byte_len),
+ heap_index!(heap_slice.slice_cell_len),
+ );
+
+ self.inner.byte_len += heap_index!(heap_slice.slice_cell_len);
+ self.pstr_vec.extend(heap_slice.pstr_slice.iter());
+
+ break;
+ } else if !self.grow() {
+ return Err(self.resource_error_offset());
+ }
}
- )
+ }
+
+ Ok(())
}
-}
-// sometimes we need to dereference variables that are found only in
-// the heap without access to the full WAM (e.g., while detecting
-// cycles in terms), and which therefore may only point other cells in
-// the heap (thanks to the design of the WAM).
-pub fn heap_bound_deref(heap: &[HeapCellValue], mut value: HeapCellValue) -> HeapCellValue {
- loop {
- let new_value = read_heap_cell!(value,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- heap[h]
+ pub(crate) fn store_resource_error(&mut self) {
+ RESOURCE_ERROR_OFFSET_INIT.call_once(move || {
+ let stub = functor!(atom!("resource_error"), [atom_as_cell((atom!("memory")))]);
+ self.resource_err_loc = cell_index!(self.inner.byte_len);
+
+ let mut writer = Heap::functor_writer(stub);
+ writer(self).unwrap();
+ });
+ }
+
+ pub(crate) fn compare_pstr_segments(
+ &self,
+ pstr_loc1: usize,
+ pstr_loc2: usize,
+ ) -> PStrSegmentCmpResult {
+ unsafe {
+ let slice1 = std::slice::from_raw_parts(
+ self.inner.ptr.add(pstr_loc1),
+ self.inner.byte_len - pstr_loc1,
+ );
+
+ let slice2 = std::slice::from_raw_parts(
+ self.inner.ptr.add(pstr_loc2),
+ self.inner.byte_len - pstr_loc2,
+ );
+
+ let str1 = std::str::from_utf8_unchecked(&slice1);
+ let str2 = std::str::from_utf8_unchecked(&slice2);
+
+ debug_assert!(!str1.is_empty());
+ debug_assert!(!str2.is_empty());
+
+ for ((idx, c1), c2) in str1.char_indices().zip(str2.chars()) {
+ if c1 == '\u{0}' && c2 == '\u{0}' {
+ return PStrSegmentCmpResult::BothMatch { pstr_loc1, pstr_loc2, null_offset: idx };
+ } else if c1 == '\u{0}' {
+ return PStrSegmentCmpResult::FirstMatch { pstr_loc1, pstr_loc2, l1_offset: idx };
+ } else if c2 == '\u{0}' {
+ return PStrSegmentCmpResult::SecondMatch { pstr_loc1, pstr_loc2, l2_offset: idx };
+ } else if c1 != c2 {
+ return PStrSegmentCmpResult::Mismatch { c1, c2 };
+ }
}
- _ => {
- value
+
+ unreachable!() // PStrSegmentCmpResult::Match(std::cmp::min(str1.len(), str2.len()))
+ }
+ }
+
+ #[inline]
+ pub(crate) fn slice_to_str(&self, slice_loc: usize, slice_len: usize) -> &str {
+ unsafe {
+ let slice = std::slice::from_raw_parts(self.inner.ptr.add(slice_loc), slice_len);
+ std::str::from_utf8_unchecked(&slice)
+ }
+ }
+
+ #[inline]
+ pub(crate) fn byte_len(&self) -> usize {
+ self.inner.byte_len
+ }
+
+ #[inline]
+ pub(crate) fn cell_len(&self) -> usize {
+ cell_index!(self.inner.byte_len)
+ }
+
+ // free space in bytes.
+ #[inline]
+ fn free_space(&self) -> usize {
+ self.inner.byte_cap - self.inner.byte_len
+ }
+
+ pub(crate) fn char_iter<'a>(&'a self, pstr_loc: usize) -> PStrSegmentIter<'a> {
+ PStrSegmentIter::from(self, pstr_loc)
+ }
+
+ // either succeed & return nothing or fail & return an offset into
+ // the heap to a pre-allocated resource error
+ pub(crate) fn push_cell(&mut self, cell: HeapCellValue) -> Result<(), usize> {
+ unsafe {
+ if self.inner.byte_len == self.inner.byte_cap {
+ if !self.grow() {
+ return Err(self.resource_error_offset());
+ }
}
- );
- if new_value != value && new_value.is_var() {
- value = new_value;
- continue;
+ let cell_ptr = (self.inner.ptr as *mut HeapCellValue).add(self.cell_len());
+ cell_ptr.write(cell);
+ self.pstr_vec.push(false);
+ self.inner.byte_len += heap_index!(1);
}
- return value;
+ Ok(())
}
-}
-pub fn heap_bound_store(heap: &[HeapCellValue], value: HeapCellValue) -> HeapCellValue {
- read_heap_cell!(value,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- heap[h]
+ /*
+ pub(crate) fn pop_cell(&mut self) -> Option<HeapCellValue> {
+ unsafe {
+ if self.inner.byte_len > 0 {
+ let cell_ptr = (self.inner.ptr as *const HeapCellValue)
+ .add(self.cell_len())
+ .sub(1);
+ let cell = ptr::read(cell_ptr);
+
+ self.inner.byte_len -= heap_index!(1);
+ self.pstr_vec.pop();
+
+ Some(cell)
+ } else {
+ None
+ }
}
- _ => {
- value
+ }
+ */
+
+ fn slice_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
+ let start = match range.start_bound() {
+ Bound::Included(lower_bound) => *lower_bound,
+ Bound::Excluded(lower_bound) => *lower_bound + 1,
+ Bound::Unbounded => 0,
+ };
+
+ let end = match range.end_bound() {
+ Bound::Included(upper_bound) => *upper_bound + 1,
+ Bound::Excluded(0) => 0,
+ Bound::Excluded(upper_bound) => *upper_bound,
+ Bound::Unbounded => self.cell_len(),
+ };
+
+ Range { start, end }
+ }
+
+ pub(crate) fn splice<R: RangeBounds<usize>>(
+ &self,
+ range: R,
+ ) -> HeapView {
+ let range = self.slice_range(range);
+
+ HeapView {
+ slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
+ cell_offset: range.start,
+ slice_cell_len: range.end - range.start,
+ pstr_slice: &self.pstr_vec.as_bitslice()[range],
}
- )
-}
+ }
-#[allow(dead_code)]
-pub fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: usize) {
- for (index, term) in heap.enumerate() {
- println!("{} : {:?}", h + index, term);
+ pub(crate) fn splice_mut<R: RangeBounds<usize>>(
+ &self,
+ range: R,
+ ) -> HeapViewMut {
+ let range = self.slice_range(range);
+
+ HeapViewMut {
+ slice: unsafe { self.inner.ptr.add(heap_index!(range.start)) },
+ cell_offset: range.start,
+ slice_cell_len: range.end - range.start,
+ pstr_slice: &self.pstr_vec.as_bitslice()[range],
+ }
}
-}
-#[inline]
-pub(crate) fn put_complete_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
- match allocate_pstr(heap, s, atom_tbl) {
- Some(h) => {
- heap.pop(); // pop the trailing variable cell from the heap planted by allocate_pstr.
+ pub fn allocate_pstr(&mut self, src: &str) -> Result<Option<PStrWriteInfo>, usize> {
+ let size_in_heap = Self::compute_pstr_size(src);
+ let pstr_loc = heap_index!(self.cell_len());
+
+ Ok(if size_in_heap > 0 {
+ let mut writer = self.reserve(size_in_heap)?;
+
+ writer.write_with(|section| {
+ section.push_pstr(src);
+ });
+
+ Some(PStrWriteInfo { pstr_loc })
+ } else {
+ None
+ })
+ }
+
+ const fn heap_cell_alignment() -> usize {
+ // yes, size_of, not align_of. the alignment of HeapCellValue
+ // is 1 byte. In the heap, though, its alignment must be its
+ // size.
+ mem::size_of::<HeapCellValue>()
+ }
+
+ // takes a byte offset into the Heap ptr.
+ #[inline(always)]
+ pub(crate) const fn neighboring_cell_offset(offset: usize) -> usize {
+ const ALIGN_CELL: usize = Heap::heap_cell_alignment();
+ cell_index!((offset & !(ALIGN_CELL - 1)) + ALIGN_CELL)
+ }
+
+ #[inline]
+ pub(crate) fn iter(&self) -> HeapView {
+ HeapView {
+ slice: self.inner.ptr,
+ cell_offset: 0,
+ slice_cell_len: cell_index!(self.inner.byte_len),
+ pstr_slice: &self.pstr_vec.as_bitslice(),
+ }
+ }
+
+ #[inline]
+ pub(crate) fn pstr_vec(&self) -> &BitSlice<usize> {
+ self.pstr_vec.as_bitslice()
+ }
+
+ #[inline]
+ pub(crate) fn char_at(&self, byte_idx: usize) -> char {
+ let s = unsafe {
+ let char_ptr = self.inner.ptr.add(byte_idx);
+ let slice = std::slice::from_raw_parts(char_ptr, mem::size_of::<char>());
+ std::str::from_utf8_unchecked(&slice)
+ };
+
+ s.chars().next().unwrap()
+ }
+
+ pub(crate) fn last_str_char_and_tail(&self, loc: usize) -> (char, HeapCellValue) {
+ unsafe {
+ let char_ptr = self.inner.ptr.add(loc);
+ let slice = std::slice::from_raw_parts(char_ptr, self.inner.byte_len - loc);
- if heap.len() == h + 1 {
- let pstr_atom = cell_as_atom!(heap[h]);
- heap[h] = atom_as_cstr_cell!(pstr_atom);
- heap_loc_as_cell!(h)
+ let s = std::str::from_utf8_unchecked(&slice);
+ let mut chars_iter = s.chars();
+ let c = chars_iter.next().unwrap();
+ let succ_len = loc + c.len_utf8();
+
+ if chars_iter.next() == Some('\u{0}') {
+ (c, heap_loc_as_cell!(Self::neighboring_cell_offset(succ_len)))
} else {
- heap.push(empty_list_as_cell!());
- pstr_loc_as_cell!(h)
+ (c, pstr_loc_as_cell!(succ_len))
}
}
- None => {
- let h = heap.len();
- heap.push(empty_list_as_cell!());
- heap_loc_as_cell!(h)
- }
}
-}
-#[inline]
-pub(crate) fn put_partial_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
- match allocate_pstr(heap, s, atom_tbl) {
- Some(h) => {
- pstr_loc_as_cell!(h)
+ // copies only the string, not its tail. returns the cell index of
+ // the tail location
+ pub(crate) fn copy_pstr_within(&mut self, pstr_loc: usize) -> Result<usize, usize> {
+ let (s, tail_loc) = self.scan_slice_to_str(pstr_loc);
+ let s_len = s.len();
+
+ const ALIGN_CELL: usize = Heap::heap_cell_alignment();
+
+ let align_offset = unsafe {
+ self.inner.ptr
+ .add(self.inner.byte_len + s_len)
+ .align_offset(ALIGN_CELL)
+ };
+
+ let align_offset = if align_offset == 0 {
+ ALIGN_CELL
+ } else {
+ align_offset
+ };
+
+ let copy_size = s_len + align_offset;
+
+ unsafe {
+ loop {
+ if self.free_space() >= copy_size {
+ let slice = std::slice::from_raw_parts_mut(
+ self.inner.ptr,
+ self.inner.byte_len + s_len,
+ );
+
+ slice.copy_within(
+ pstr_loc .. pstr_loc + s_len,
+ self.inner.byte_len,
+ );
+
+ ptr::write_bytes(
+ self.inner.ptr.add(self.inner.byte_len + s_len),
+ 0u8,
+ align_offset,
+ );
+
+ self.inner.byte_len += copy_size;
+ self.pstr_vec.resize(self.cell_len(), true);
+
+ break;
+ } else if !self.grow() {
+ return Err(self.resource_error_offset());
+ }
+ }
}
- None => {
- empty_list_as_cell!()
+
+ Ok(tail_loc)
+ }
+
+ // src is a cell-indexed range.
+ pub(crate) fn copy_slice_to_end<R: RangeBounds<usize>>(&mut self, src: R) -> Result<(), usize> {
+ let range = self.slice_range(src);
+ let len = range.end - range.start;
+
+ unsafe {
+ loop {
+ if self.free_space() >= len {
+ ptr::copy_nonoverlapping(
+ self.inner.ptr.add(heap_index!(range.start)),
+ self.inner.ptr.add(self.inner.byte_len),
+ heap_index!(len),
+ );
+
+ self.pstr_vec.resize(self.cell_len() + len, false);
+ self.inner.byte_len += heap_index!(len);
+
+ break;
+ } else if !self.grow() {
+ return Err(self.resource_error_offset());
+ }
+ }
}
+
+ Ok(())
}
-}
-#[inline]
-pub(crate) fn allocate_pstr(heap: &mut Heap, mut src: &str, atom_tbl: &AtomTable) -> Option<usize> {
- let orig_h = heap.len();
+ // assumes the string will be allocated on a ALIGN_CELL-byte boundary
+ pub(crate) const fn compute_pstr_size(src: &str) -> usize {
+ const ALIGN_CELL: usize = Heap::heap_cell_alignment();
- loop {
if src.is_empty() {
- return if orig_h == heap.len() {
- None
+ return 0;
+ }
+
+ let mut byte_size = 0;
+ let mut null_idx = 0;
+
+ loop {
+ let src_bytes = src.as_bytes();
+
+ while null_idx < src_bytes.len() {
+ if src_bytes[null_idx] == 0u8 {
+ break;
+ }
+
+ null_idx += 1;
+ }
+
+ byte_size += (null_idx & !(ALIGN_CELL - 1)) + ALIGN_CELL;
+
+ if (null_idx + 1) % ALIGN_CELL == 0 {
+ byte_size += 2 * mem::size_of::<HeapCellValue>();
} else {
- let tail_h = heap.len() - 1;
- heap[tail_h] = heap_loc_as_cell!(tail_h);
+ byte_size += mem::size_of::<HeapCellValue>();
+ }
- Some(orig_h)
- };
+ if null_idx + 1 >= src.len() {
+ break;
+ } else {
+ null_idx += 1;
+ }
}
- let h = heap.len();
+ byte_size
+ }
+
+ pub(crate) const fn compute_functor_byte_size(functor: &[FunctorElement]) -> usize {
+ let mut byte_size = 0;
+ let mut idx = 0;
- let (pstr, rest_src) = match PartialString::new(src, atom_tbl) {
- Some(tuple) => tuple,
- None => {
- if src.len() > '\u{0}'.len_utf8() {
- src = &src['\u{0}'.len_utf8()..];
- continue;
- } else if orig_h == h {
- return None;
- } else {
- heap[h - 1] = heap_loc_as_cell!(h - 1);
- return Some(orig_h);
+ while idx < functor.len() {
+ match &functor[idx] {
+ &FunctorElement::InnerFunctor(inner_cell_size, ref _inner_functor) => {
+ byte_size += inner_cell_size as usize * mem::size_of::<HeapCellValue>();
+ }
+ FunctorElement::AbsoluteCell(_cell) | FunctorElement::Cell(_cell) => {
+ byte_size += mem::size_of::<HeapCellValue>();
+ }
+ &FunctorElement::String(cell_len, _) => {
+ byte_size += cell_len as usize * mem::size_of::<HeapCellValue>();
}
}
+
+ idx += 1;
+ }
+
+ byte_size
+ }
+
+ pub(crate) fn functor_writer(
+ functor: Vec<FunctorElement>,
+ ) -> impl FnMut(&mut Heap) -> Result<HeapCellValue, usize> {
+ let size = Heap::compute_functor_byte_size(&functor);
+ let mut functor_writer = ReservedHeapSection::functor_writer(functor);
+
+ move |heap| {
+ let mut writer = heap.reserve(size)?;
+ let heap_byte_len = *writer.heap_byte_len;
+ let bytes_written = writer.write_with(&mut functor_writer);
+
+ Ok(if cell_index!(bytes_written) > 1 {
+ str_loc_as_cell!(cell_index!(heap_byte_len))
+ } else {
+ heap_loc_as_cell!(cell_index!(heap_byte_len))
+ })
+ }
+ }
+
+ #[inline]
+ pub(crate) fn truncate(&mut self, cell_offset: usize) {
+ self.inner.byte_len = heap_index!(cell_offset);
+ self.pstr_vec.truncate(cell_offset);
+ }
+}
+
+
+
+pub(crate) struct PStrSegmentIter<'a> {
+ string_buf: &'a str,
+}
+
+impl<'a> PStrSegmentIter<'a> {
+ fn from(heap: &'a Heap, pstr_loc: usize) -> Self {
+ debug_assert!(pstr_loc <= heap.inner.byte_len);
+
+ let string_buf = unsafe {
+ let char_ptr = heap.inner.ptr.add(pstr_loc);
+ let slice = std::slice::from_raw_parts(char_ptr, heap.inner.byte_len - pstr_loc);
+ std::str::from_utf8_unchecked(&slice)
};
- heap.push(string_as_pstr_cell!(pstr));
+ PStrSegmentIter { string_buf }
+ }
+}
- if !rest_src.is_empty() {
- heap.push(pstr_loc_as_cell!(h + 2));
- src = rest_src;
- } else {
- heap.push(heap_loc_as_cell!(h + 1));
- return Some(orig_h);
+impl<'a> Iterator for PStrSegmentIter<'a> {
+ type Item = char;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.string_buf.chars().next().and_then(|c| {
+ if c == '\u{0}' {
+ None
+ } else {
+ self.string_buf = &self.string_buf[c.len_utf8() ..];
+ Some(c)
+ }
+ })
+ }
+}
+
+impl MachineState {
+ pub(crate) fn allocate_pstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
+ match self.heap.allocate_pstr(src)? {
+ None => Ok(empty_list_as_cell!()),
+ Some(PStrWriteInfo { pstr_loc, .. }) => Ok(pstr_loc_as_cell!(pstr_loc)),
+ }
+ }
+
+ // note that allocate_cstr does emit a tail cell to the string
+ // (completing it with the empty list), allocate_pstr does not, in
+ // any incarnation.
+ pub(crate) fn allocate_cstr(&mut self, src: &str) -> Result<HeapCellValue, usize> {
+ match self.heap.allocate_pstr(src)? {
+ None => Ok(empty_list_as_cell!()),
+ Some(PStrWriteInfo { pstr_loc, .. }) => {
+ self.heap.push_cell(empty_list_as_cell!())?;
+ Ok(pstr_loc_as_cell!(pstr_loc))
+ }
}
}
}
-pub fn filtered_iter_to_heap_list<SrcT: Into<HeapCellValue>>(
- heap: &mut Heap,
- values: impl Iterator<Item = SrcT>,
- filter_fn: impl Fn(&Heap, HeapCellValue) -> bool,
-) -> usize {
- let head_addr = heap.len();
- let mut h = head_addr;
+pub trait SizedHeap: Index<usize, Output = HeapCellValue> {
+ // return the size of the instance in cells
+ fn cell_len(&self) -> usize;
+
+ // return a pointer to the heap string and the cell index of its tail
+ fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize);
+
+ // return true iff a partial string is stored at cell_offset.
+ fn pstr_at(&self, cell_offset: usize) -> bool;
+}
+
+pub trait SizedHeapMut: IndexMut<usize, Output = HeapCellValue> + SizedHeap {
+}
+
+impl Index<usize> for Heap {
+ type Output = HeapCellValue;
+
+ fn index(&self, idx: usize) -> &Self::Output {
+ unsafe { &*(self.inner.ptr as *const HeapCellValue).add(idx) }
+ }
+}
+
+impl IndexMut<usize> for Heap {
+ fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
+ unsafe { &mut *(self.inner.ptr as *mut HeapCellValue).add(idx) }
+ }
+}
+
+impl SizedHeap for Heap {
+ fn cell_len(&self) -> usize {
+ self.cell_len()
+ }
+
+ fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
+ let (s, tail_cell_offset) = scan_slice_to_str(
+ unsafe { self.inner.ptr.add(slice_loc) },
+ &self.pstr_vec.as_bitslice()[cell_index!(slice_loc) ..],
+ );
- for value in values {
- let value = value.into();
+ (s, cell_index!(slice_loc) + tail_cell_offset)
+ }
+
+ fn pstr_at(&self, cell_offset: usize) -> bool {
+ self.pstr_vec[cell_offset]
+ }
+}
+
+impl SizedHeapMut for Heap {}
+
+impl<'a> SizedHeap for HeapView<'a> {
+ fn cell_len(&self) -> usize {
+ self.slice_cell_len
+ }
+
+ fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
+ let (s, tail_cell_offset) = scan_slice_to_str(
+ unsafe { self.slice.add(slice_loc) },
+ &self.pstr_slice[cell_index!(slice_loc) ..],
+ );
+
+ (s, cell_index!(slice_loc) + tail_cell_offset)
+ }
+
+ fn pstr_at(&self, cell_offset: usize) -> bool {
+ self.pstr_slice[cell_offset]
+ }
+}
+
+impl<'a> SizedHeap for HeapViewMut<'a> {
+ fn cell_len(&self) -> usize {
+ self.slice_cell_len
+ }
- if filter_fn(heap, value) {
- heap.push(list_loc_as_cell!(h + 1));
- heap.push(value);
+ fn scan_slice_to_str(&self, slice_loc: usize) -> (&str, usize) {
+ let (s, tail_cell_offset) = scan_slice_to_str(
+ unsafe { self.slice.add(slice_loc) },
+ &self.pstr_slice[cell_index!(slice_loc) ..],
+ );
+
+ (s, cell_index!(slice_loc) + tail_cell_offset)
+ }
+
+ fn pstr_at(&self, cell_offset: usize) -> bool {
+ self.pstr_slice[cell_offset]
+ }
+}
- h += 2;
+impl<'a> SizedHeapMut for HeapViewMut<'a> {}
+
+// sometimes we need to dereference variables that are found only in
+// the heap without access to the full WAM (e.g., while detecting
+// cycles in terms), and which therefore may only point other cells in
+// the heap (thanks to the design of the WAM).
+pub fn heap_bound_deref(heap: &impl SizedHeap, mut value: HeapCellValue) -> HeapCellValue {
+ loop {
+ let new_value = read_heap_cell!(value,
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+ heap[h]
+ }
+ _ => {
+ value
+ }
+ );
+
+ if new_value != value && new_value.is_var() {
+ value = new_value;
+ continue;
}
+
+ return value;
}
+}
- heap.push(empty_list_as_cell!());
+pub fn heap_bound_store(heap: &impl SizedHeap, value: HeapCellValue) -> HeapCellValue {
+ read_heap_cell!(value,
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+ heap[h]
+ }
+ _ => {
+ value
+ }
+ )
+}
- head_addr
+#[allow(dead_code)]
+pub fn print_heap_terms<'a, I: Iterator<Item = HeapCellValue>>(heap: I, h: usize) {
+ for (index, term) in heap.enumerate() {
+ println!("{} : {:?}", h + index, term);
+ }
}
-#[inline(always)]
-pub fn iter_to_heap_list<Iter, SrcT>(heap: &mut Heap, values: Iter) -> usize
-where
- Iter: Iterator<Item = SrcT>,
- SrcT: Into<HeapCellValue>,
-{
- filtered_iter_to_heap_list(heap, values, |_, _| true)
+pub fn sized_iter_to_heap_list<SrcT: Into<HeapCellValue>>(
+ heap: &mut Heap,
+ size: usize,
+ values: impl Iterator<Item = SrcT>,
+) -> Result<HeapCellValue, usize> {
+ if size > 0 {
+ let h = heap.cell_len();
+ let mut writer = heap.reserve(1 + 2 * size)?;
+
+ writer.write_with(|section| {
+ for (idx, value) in values.enumerate() {
+ section.push_cell(list_loc_as_cell!(h + 1 + 2 * idx));
+ section.push_cell(value.into());
+ }
+
+ section.push_cell(empty_list_as_cell!());
+ });
+
+ Ok(heap_loc_as_cell!(h))
+ } else {
+ Ok(empty_list_as_cell!())
+ }
}
pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<usize> {
use crate::atom_table;
use crate::heap_iter::{stackful_post_order_iter, NonListElider};
-use crate::machine::machine_indices::VarKey;
use crate::machine::mock_wam::CompositeOpDir;
use crate::machine::{
ArenaHeaderTag, F64Offset, F64Ptr, Fixnum, Number, BREAK_FROM_DISPATCH_LOOP_LOC,
LIB_QUERY_SUCCESS,
};
-use crate::parser::ast::{Var, VarPtr};
-use crate::parser::parser::{Parser, Tokens};
-use crate::read::{write_term_to_heap, TermWriteResult};
+use crate::parser::ast::{TermWriteResult, Var};
+use crate::parser::lexer::LexerParser;
+use crate::parser::parser::Tokens;
use crate::types::UntypedArenaPtr;
use dashu::{Integer, Rational};
pub(crate) fn from_heapcell(
machine: &mut Machine,
heap_cell: HeapCellValue,
- var_names: &mut IndexMap<HeapCellValue, VarPtr>,
+ var_names: &mut IndexMap<HeapCellValue, Var>,
) -> Self {
// Adapted from MachineState::read_term_from_heap
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.stack,
- heap_cell,
+ 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);
read_heap_cell!(addr,
term_stack.push(list);
}
(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 {
- Some(Var::Named(name)) => term_stack.push(Term::Var(name)),
+ Some(name) => term_stack.push(Term::Var(name.to_string())),
_ => {
let anon_name = loop {
// Generate a name for the anonymous variable
let anon_name = count_to_letter_code(anon_count);
// Find if this name is already being used
- var_names.sort_by(|_, a, _, b| {
- var_ptr_cmp(a.borrow().clone(), b.borrow().clone())
- });
+ var_names.sort_by(|_, a, _, b| a.cmp(b));
+
let binary_result = var_names.binary_search_by(|_,a| {
- let var_ptr = Var::Named(anon_name.clone());
- var_ptr_cmp(a.borrow().clone(), var_ptr.clone())
+ let a: &String = a.as_ref();
+ a.cmp(&anon_name)
});
match binary_result {
Ok(_) => anon_count += 1, // Name already used
Err(_) => {
// Name not used, assign it to this variable
- let var_ptr = VarPtr::from(Var::Named(anon_name.clone()));
- var_names.insert(addr, var_ptr);
+ let var = anon_name.clone();
+ var_names.insert(addr, Var::from(var));
break anon_name;
},
}
(HeapCellValueTag::F64, f) => {
term_stack.push(Term::Float((*f).into()));
}
- (HeapCellValueTag::Char, c) => {
- term_stack.push(Term::Atom(c.into()));
- }
(HeapCellValueTag::Fixnum, n) => {
term_stack.push(Term::Integer(n.into()));
}
);
}
}
- (HeapCellValueTag::CStr, s) => {
- term_stack.push(Term::String(s.as_str().to_string()));
- }
(HeapCellValueTag::Atom, (name, arity)) => {
//let h = iter.focus().value() as usize;
//let mut arity = arity;
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 char_iter = iter.base_iter.heap.char_iter(pstr_loc);
match tail {
Term::Atom(atom) => {
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) => {
- let mut list: Vec<Term> = atom
- .as_str()
- .to_string()
- .chars()
+ let mut list: Vec<Term> = char_iter
.map(|x| Term::Atom(x.to_string()))
.collect();
list.extend(l.into_iter());
term_stack.push(Term::List(list));
},
_ => {
- let mut list: Vec<Term> = atom
- .as_str()
- .to_string()
- .chars()
+ let mut list: Vec<Term> = char_iter
.map(|x| Term::Atom(x.to_string()))
.collect();
}
}
}
- // 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!();
}
machine: &'a mut Machine,
term: TermWriteResult,
stub_b: usize,
- var_names: IndexMap<HeapCellValue, VarPtr>,
+ var_names: IndexMap<HeapCellValue, Var>,
called: bool,
}
if let Err(resource_err_loc) = machine
.machine_st
.heap
- .append(&machine.machine_st.ball.stub)
+ .append(machine.machine_st.ball.stub.splice(..))
{
return Some(Err(Term::from_heapcell(
machine,
or_frame.prelude.attr_var_queue_len = 0;
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;
}
/// Runs a query.
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),
&mut self.machine_st,
);
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
-use crate::machine::preprocessor::*;
use crate::machine::term_stream::*;
use crate::machine::*;
use crate::parser::ast::*;
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]
pub(super) fn remove_module_op_exports(&mut self) {
for (mut op_decl, record) in self.payload.module_op_exports.drain(0..) {
use std::fmt;
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,
* which may be incremental or monolithic. The monolithic term stream
}
pub struct PredicateQueue {
- pub(super) predicates: Vec<FocusedHeap>,
- pub(super) compilation_target: CompilationTarget,
+ pub predicates: Vec<TermWriteResult>,
+ pub compilation_target: CompilationTarget,
}
impl PredicateQueue {
#[inline]
- pub(super) fn push(&mut self, clause: FocusedHeap) {
- self.predicates.push(clause);
+ pub(super) fn push(&mut self, term_write_result: TermWriteResult) {
+ self.predicates.push(term_write_result);
}
#[inline]
- pub(crate) fn first(&self) -> Option<&FocusedHeap> {
+ pub(crate) fn first(&self) -> Option<&TermWriteResult> {
self.predicates.first()
}
let repo_len = loader.wam_prelude.code.len();
loader.payload.retraction_info.reset(repo_len);
-
loader.remove_module_op_exports();
Ok(loader.payload.compilation_target)
#[inline(always)]
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)]
}
}
- pub(crate) fn copy_term_from_heap(&mut self, cell: HeapCellValue) -> FocusedHeap {
- use crate::iterators::fact_iterator;
-
- 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
+ #[inline]
+ pub(super) fn machine_heap(&mut self) -> &mut Heap {
+ &mut LS::machine_st(&mut self.payload).heap
}
pub(crate) fn load(mut self) -> Result<LS::Evacuable, SessionError> {
let composite_op_dir = self.wam_prelude.composite_op_dir(compilation_target);
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) {
- self.compile_and_submit()?;
+ let machine_st = LS::machine_st(&mut self.payload);
+ 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 {
- let new_focus = term.nth_arg(term.focus, 1).unwrap();
- let term = term.as_ref_mut(new_focus);
+ if Some((atom!(":-"), 1)) == term_key_opt {
+ let machine_st = LS::machine_st(&mut self.payload);
+ term.focus = term_nth_arg(&machine_st.heap, term.focus, 1).unwrap();
return Ok(Some(setup_declaration(self, term)?));
}
let machine_st = LS::machine_st(&mut self.payload);
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)?;
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 mut term = FocusedHeap::empty();
+ let focus = machine_st.heap.cell_len();
read_heap_cell!(cell,
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
.get_name_and_arity();
- term.copy_term_from_machine_heap(machine_st, cell);
- let focus = term.heap.len();
+ let mut writer = machine_st.heap.reserve(4)
+ .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
- term.heap.push(str_loc_as_cell!(focus+1));
- term.heap.push(atom_as_cell!(atom!("clause"), 2));
+ writer.write_with(|section| {
+ section.push_cell(str_loc_as_cell!(focus+1));
+ section.push_cell(atom_as_cell!(atom!("clause"), 2));
- match (name, arity) {
- (atom!(":-"), 2) => {
- term.heap.push(heap_loc_as_cell!(2));
- term.heap.push(heap_loc_as_cell!(3));
- }
- _ => {
- term.heap.push(heap_loc_as_cell!(0));
- term.heap.push(atom_as_cell!(atom!("true")));
+ match (name, arity) {
+ (atom!(":-"), 2) => {
+ section.push_cell(heap_loc_as_cell!(s+1));
+ 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.focus = focus;
+ });
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
- term.heap.push(str_loc_as_cell!(1));
- term.heap.push(atom_as_cell!(atom!("clause"), 2));
- term.heap.push(atom_as_cell!(name));
- term.heap.push(atom_as_cell!(atom!("true")));
-
- term.focus = 0;
+ let mut writer = machine_st.heap.reserve(4)
+ .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?;
+
+ 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 {
return Err(CompilationError::InadmissibleFact);
}
}
);
- let value = term.heap[term.focus];
- term.inverse_var_locs = inverse_var_locs_from_iter(
- eager_stackful_preorder_iter(&mut term.heap, value),
- );
- Ok(term)
+ Ok(TermWriteResult::from(&mut machine_st.heap, heap_loc_as_cell!(focus))
+ .map_err(|_err_loc| ParserError::ResourceError(ParserErrorSrc::default()))?)
}
fn add_extensible_predicate_declaration(
fn add_clause_clause_if_dynamic(&mut self, value: HeapCellValue) -> Result<(), SessionError> {
let machine_st = LS::machine_st(&mut self.payload);
- let term = FocusedHeapRefMut::from_cell(&mut machine_st.heap, value);
-
- let name_opt = ClauseInfo::name(&term);
+ let key_opt = clause_predicate_key_from_heap(&machine_st.heap, value);
- if let Some(predicate_name) = name_opt {
- let arity = ClauseInfo::arity(&term);
+ if let Some((predicate_name, predicate_arity)) = key_opt {
let predicates_compilation_target = self.payload.predicates.compilation_target;
let is_dynamic = self
.wam_prelude
.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)
.unwrap_or(false);
pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult {
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 add_clause = || {
- let term = loader.copy_term_from_heap(value);
-
loader.incremental_compile_clause(
(atom!("term_expansion"), 2),
term,
.machine_st
.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 {
atom!("user") => CompilationTarget::User,
_ => CompilationTarget::Module(target_module_name),
};
- let add_clause = || {
- let term = loader.copy_term_from_heap(value);
+ let value = self.machine_st.registers[2];
+ 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) {
- Some(atom!(":-")) => term.nth_arg(term.focus, 1).and_then(|h| term.nth_arg(h, 1)),
- Some(_) => term.nth_arg(term.focus, 1),
+ let add_clause = || {
+ let indexing_arg_opt = match term_predicate_key(&self.machine_st.heap, term.focus) {
+ 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,
};
- if let Some(indexing_term_loc) = indexing_arg {
- if let Some(indexing_name) = term.name(indexing_term_loc) {
- loader
- .wam_prelude
- .indices
- .goal_expansion_indices
- .insert((indexing_name, term.arity(indexing_term_loc)));
- }
+ let key_opt = indexing_arg_opt.and_then(|indexing_term_loc| {
+ term_predicate_key(&self.machine_st.heap, indexing_term_loc)
+ });
+
+ let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
+
+ if let Some((name, arity)) = key_opt {
+ loader
+ .wam_prelude
+ .indices
+ .goal_expansion_indices
+ .insert((name, arity));
}
loader.incremental_compile_clause(
let stub_gen = || functor_stub(key.0, key.1);
let assert_clause = self.machine_st.registers[2];
- let (name, arity) = {
- let term = FocusedHeapRefMut::from_cell(&mut self.machine_st.heap, assert_clause);
- (ClauseInfo::name(&term), ClauseInfo::arity(&term))
- };
+ let key_opt = clause_predicate_key_from_heap(&self.machine_st.heap, assert_clause);
- let mut compile_assert = |assert_clause, name, arity| {
+ let mut compile_assert = |assert_clause, key_opt| {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
Loader::new(self, LiveTermStream::new(ListingSource::User));
loader.payload.compilation_target = compilation_target;
- let name = if let Some(name) = name {
- name
+ let (name, arity) = if let Some(key) = key_opt {
+ key
} else {
return Err(SessionError::from(CompilationError::InvalidRuleHead));
};
// if a new predicate was just created, make it dynamic.
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(
(name, arity),
- asserted_clause,
+ term,
compilation_target,
false,
append_or_prepend,
LiveLoadAndMachineState::evacuate(loader)
};
- match compile_assert(assert_clause, name, arity) {
+ match compile_assert(assert_clause, key_opt) {
Ok(_) => Ok(()),
Err(SessionError::CompilationError(
CompilationError::InvalidRuleHead | CompilationError::InadmissibleFact,
};
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 =
(!loader.payload.predicates.is_empty()
- && loader.payload.predicates.compilation_target != compilation_target)
- || !key.is_consistent(&loader.payload.predicates);
+ && loader.payload.predicates.compilation_target != compilation_target)
+ || !is_consistent;
let result = LiveLoadAndMachineState::evacuate(loader);
self.restore_load_state_payload(result)
.get_meta_predicate_spec(predicate_name, arity, &compilation_target)
{
Some(meta_specs) => {
- let term_loc = self.machine_st.heap.len();
+ let term_loc = self.machine_st.heap.cell_len();
- self.machine_st
- .heap
- .push(atom_as_cell!(predicate_name, arity));
- self.machine_st
- .heap
- .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 mut writer = match self.machine_st.heap.reserve(3 + meta_specs.len()) {
+ Ok(writer) => writer,
+ Err(err_loc) => {
+ self.machine_st.throw_resource_error(err_loc);
+ return;
+ }
+ };
- let heap_loc = self.machine_st.heap.len();
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(predicate_name, arity));
+
+ for meta_spec in meta_specs.iter() {
+ section.push_cell(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))
+ }
+ });
+ }
- self.machine_st
- .heap
- .push(atom_as_cell!(atom!("meta_predicate"), 1));
- self.machine_st.heap.push(str_loc_as_cell!(term_loc));
+ 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!(
self.machine_st,
}
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)?;
- let term = self.copy_term_from_heap(value);
- self.payload.term_stream.term_queue.push_back(term);
+ let machine_st = LiveLoadAndMachineState::machine_st(&mut self.payload);
+ 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()
}
}
#[cfg(feature = "ffi")]
use crate::ffi::FFIError;
use crate::forms::*;
+use crate::functor_macro::*;
use crate::machine::heap::*;
use crate::machine::loader::CompilationTarget;
use crate::machine::machine_state::*;
use crate::machine::system_calls::BrentAlgState;
use crate::types::*;
-pub type MachineStub = Vec<HeapCellValue>;
+pub type MachineStub = Vec<FunctorElement>;
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)]
pub(crate) struct MachineError {
stub: MachineStub,
location: Option<ParserErrorSrc>,
- from: ErrorProvenance,
}
// from 7.12.2 b) of 13211-1:1995
fn type_error(self, _machine_st: &mut MachineState, valid_type: ValidType) -> MachineError {
let stub = functor!(
atom!("type_error"),
- [atom(valid_type.as_atom()), cell(self)]
+ [atom_as_cell((valid_type.as_atom())), cell(self)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
}
impl TypeError for MachineStub {
- 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,
- }
- }
-}
-
-impl TypeError for FunctorStub {
- 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!(
atom!("type_error"),
- [atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)],
- [self]
+ [atom_as_cell((valid_type.as_atom())), functor(self)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
}
}
}
let stub = functor!(
atom!("type_error"),
[
- atom(valid_type.as_atom()),
- number(&mut machine_st.arena, self)
+ atom_as_cell((valid_type.as_atom())),
+ number(self, (&mut machine_st.arena))
]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
}
let stub = functor!(
atom!("permission_error"),
[
- atom(perm.as_atom()),
- atom(index_atom),
- cell(atom_as_cell!(self))
+ atom_as_cell((perm.as_atom())),
+ atom_as_cell(index_atom),
+ atom_as_cell(self)
]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
}
let stub = functor!(
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 {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
}
impl PermissionError for MachineStub {
fn permission_error(
self,
- machine_st: &mut MachineState,
+ _machine_st: &mut MachineState,
index_atom: Atom,
perm: Permission,
) -> MachineError {
let stub = functor!(
atom!("permission_error"),
[
- atom(perm.as_atom()),
- atom(index_atom),
- str(machine_st.heap.len(), 0)
- ],
- [self]
+ atom_as_cell((perm.as_atom())),
+ atom_as_cell(index_atom),
+ functor(self)
+ ]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
}
}
}
impl DomainError for HeapCellValue {
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 {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
}
-impl DomainError for FunctorStub {
- fn domain_error(
- self,
- machine_st: &mut MachineState,
- valid_type: DomainErrorType,
- ) -> MachineError {
+impl DomainError for Number {
+ fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(
atom!("domain_error"),
- [atom(valid_type.as_atom()), str(machine_st.heap.len(), 0)],
- [self]
+ [atom_as_cell((error.as_atom())), number(self, (&mut machine_st.arena))]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
}
}
}
-impl DomainError for Number {
- fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
+impl DomainError for MachineStub {
+ fn domain_error(self, _machine_st: &mut MachineState, error: DomainErrorType) -> MachineError {
let stub = functor!(
atom!("domain_error"),
- [atom(error.as_atom()), number(&mut machine_st.arena, self)]
+ [atom_as_cell((error.as_atom())), functor(self)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
}
-pub(super) type FunctorStub = [HeapCellValue; 3];
-
#[inline(always)]
-pub(super) fn functor_stub(name: Atom, arity: usize) -> FunctorStub {
- [
- atom_as_cell!(atom!("/"), 2),
- atom_as_cell!(name),
- fixnum_as_cell!(Fixnum::build_with(arity as i64)),
- ]
+pub(super) fn functor_stub(name: Atom, arity: usize) -> MachineStub {
+ functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)])
}
impl MachineState {
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
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 {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
ResourceError::FiniteMemory(size_requested) => {
functor!(
atom!("resource_error"),
- [atom(atom!("finite_memory")), cell(size_requested)]
+ [atom_as_cell((atom!("finite_memory"))), cell(size_requested)]
)
}
ResourceError::OutOfFiles => {
- functor!(atom!("resource_error"), [atom(atom!("file_descriptors"))])
+ functor!(atom!("resource_error"), [atom_as_cell((atom!("file_descriptors")))])
}
};
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
ExistenceError::Module(name) => {
let stub = functor!(
atom!("existence_error"),
- [atom(atom!("source_sink")), atom(name)]
+ [atom_as_cell((atom!("source_sink"))), atom_as_cell(name)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
ExistenceError::QualifiedProcedure {
name,
arity,
} => {
- let h = self.heap.len();
-
- let ind_stub = functor!(atom!("/"), [atom(name), fixnum(arity)]);
- let res_stub = functor!(atom!(":"), [atom(module_name), str(h + 3, 0)], [ind_stub]);
+ 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 stub = functor!(
atom!("existence_error"),
- [atom(atom!("procedure")), str(h, 0)],
- [res_stub]
+ [atom_as_cell((atom!("procedure"))), functor(res_stub)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
}
}
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!(
atom!("existence_error"),
- [atom(atom!("procedure")), str(self.heap.len(), 0)],
- [culprit]
+ [atom_as_cell((atom!("procedure"))), functor(culprit)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
}
}
ExistenceError::ModuleSource(source) => {
let stub = functor!(
atom!("existence_error"),
- [atom(atom!("source_sink")), str(self.heap.len(), 0)],
- [source_stub]
+ [atom_as_cell((atom!("source_sink"))), functor(source_stub)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Constructed,
}
}
ExistenceError::SourceSink(culprit) => {
let stub = functor!(
atom!("existence_error"),
- [atom(atom!("source_sink")), cell(culprit)]
+ [atom_as_cell((atom!("source_sink"))), cell(culprit)]
);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
ExistenceError::Stream(culprit) => {
let stub = functor!(
atom!("existence_error"),
- [atom(atom!("stream")), cell(culprit)]
+ [atom_as_cell((atom!("stream"))), cell(culprit)]
);
MachineError {
stub,
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>(
&mut self,
err: Permission,
fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError {
match err {
- ArithmeticError::UninstantiatedVar => self.instantiation_error(),
ArithmeticError::NonEvaluableFunctor(cell, arity) => {
let culprit = functor!(atom!("/"), [cell(cell), fixnum(arity)]);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
Permission::Modify,
atom!("static_procedure"),
functor_stub(key.0, key.1)
- .into_iter()
- .collect::<MachineStub>(),
),
SessionError::CannotOverwriteStaticProcedure(key) => self.permission_error(
Permission::Modify,
atom!("static_procedure"),
functor_stub(key.0, key.1)
- .into_iter()
- .collect::<MachineStub>(),
),
SessionError::CannotOverwriteBuiltInModule(module) => {
self.permission_error(Permission::Modify, atom!("static_module"), module)
let stub = functor!(
atom!("module_does_not_contain_claimed_export"),
- [atom(module_name), str(self.heap.len() + 4, 0)],
- [functor_stub]
+ [atom_as_cell(module_name), functor(functor_stub)]
);
self.permission_error(Permission::Access, atom!("private_procedure"), stub)
self.permission_error(
Permission::Modify,
atom!("module"),
- functor!(error_atom, [atom(module_name)]),
+ functor!(error_atom, [atom_as_cell(module_name)]),
)
}
SessionError::NamelessEntry => {
}
SessionError::CompilationError(err) => self.syntax_error(err),
SessionError::PredicateNotMultifileOrDiscontiguous(compilation_target, key) => {
- let functor_stub = functor_stub(key.0, key.1);
-
let stub = functor!(
atom!(":"),
[
- atom(compilation_target.module_name()),
- str(self.heap.len() + 4, 0)
- ],
- [functor_stub]
+ atom_as_cell((compilation_target.module_name())),
+ functor((key.0), [fixnum((key.1))])
+ ]
);
self.permission_error(
}
let location = err.line_and_col_num();
- let len = self.heap.len();
let stub = err.as_functor();
- let stub = functor!(atom!("syntax_error"), [str(len, 0)], [stub]);
+ let stub = functor!(atom!("syntax_error"), [functor(stub)]);
MachineError {
stub,
location,
- from: ErrorProvenance::Constructed,
}
}
- pub(super) fn representation_error(&mut self, flag: RepFlag) -> MachineError {
- let stub = functor!(atom!("representation_error"), [atom(flag.as_atom())]);
+ pub(super) fn representation_error(&self, flag: RepFlag) -> MachineError {
+ let stub = functor!(atom!("representation_error"), [atom_as_cell((flag.as_atom()))]);
MachineError {
stub,
location: None,
- from: ErrorProvenance::Received,
}
}
#[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 {
FFIError::ValueCast => atom!("value_cast"),
FFIError::ValueDontFit => atom!("value_dont_fit"),
FFIError::FunctionNotFound => atom!("function_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 {
stub,
location: None,
- from: ErrorProvenance::Constructed,
}
}
- pub(super) fn error_form(&mut self, err: MachineError, src: FunctorStub) -> MachineStub {
- let h = self.heap.len();
- let location = err.location;
- let stub_addition_len = if err.len() == 1 {
- 0 // if err contains 1 cell, it can be inlined at stub[1].
- } else {
- err.len()
- };
-
- 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));
+ pub(super) fn error_form(&mut self, err: MachineError, src: MachineStub) -> MachineStub {
+ if let Some(ParserErrorSrc { line_num, .. }) = err.location {
+ functor!(atom!("error"), [functor((err.stub)),
+ functor((atom!(":")), [functor(src),
+ number(line_num, (&mut self.arena))])])
} else {
- stub[1] = err.stub[0];
- }
-
- if let Some(ParserErrorSrc { line_num, .. }) = location {
- stub.push(atom_as_cell!(atom!(":"), 2));
- stub.push(str_loc_as_cell!(h + 6 + stub_addition_len));
- stub.push(integer_as_cell!(Number::arena_from(
- line_num,
- &mut self.arena
- )));
+ functor!(atom!("error"), [functor((err.stub)),
+ functor(src)])
}
+ }
- stub.extend(src.iter());
- stub
+ // throw an error pre-allocated in the heap
+ pub(super) fn throw_resource_error(&mut self, err_loc: usize) {
+ self.registers[1] = str_loc_as_cell!(err_loc);
+ self.set_ball();
+ self.unwind_stack();
}
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.stub.truncate(0);
- self.heap.extend(err);
+ let mut writer = Heap::functor_writer(err);
- self.registers[1] = if err_len == 1 {
- heap_loc_as_cell!(h)
- } else {
- str_loc_as_cell!(h)
+ self.registers[1] = match writer(&mut self.heap) {
+ Ok(loc) => loc,
+ Err(resource_err_loc) => {
+ self.throw_resource_error(resource_err_loc);
+ return;
+ }
};
self.set_ball();
}
}
-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)]
pub enum CompilationError {
Arithmetic(ArithmeticError),
#[derive(Debug)]
pub enum DirectiveError {
- ExpectedDirective(Term),
+ ExpectedDirective(HeapCellValue),
InvalidDirective(Atom, usize /* arity */),
- InvalidOpDeclNameType(Term),
- InvalidOpDeclSpecDomain(Term),
+ InvalidOpDeclNameType(HeapCellValue),
+ InvalidOpDeclSpecDomain(HeapCellValue),
InvalidOpDeclSpecValue(Atom),
- InvalidOpDeclPrecType(Term),
+ InvalidOpDeclPrecType(HeapCellValue),
InvalidOpDeclPrecDomain(Fixnum),
ShallNotCreate(Atom),
ShallNotModify(Atom),
functor!(atom!("exceeded_max_arity"))
}
CompilationError::InadmissibleFact => {
- // TODO: type_error(callable, _).
functor!(atom!("inadmissible_fact"))
}
CompilationError::InadmissibleQueryTerm => {
- // TODO: type_error(callable, _).
functor!(atom!("inadmissible_query_term"))
}
CompilationError::InvalidDirective(_) => {
CompilationError::InvalidModuleExport => {
functor!(atom!("invalid_module_export"))
}
- CompilationError::InvalidModuleResolution(ref module_name) => {
- functor!(atom!("no_such_module"), [atom(module_name)])
+ &CompilationError::InvalidModuleResolution(module_name) => {
+ functor!(atom!("no_such_module"), [atom_as_cell(module_name)])
}
CompilationError::InvalidRuleHead => {
functor!(atom!("invalid_head_of_rule")) // TODO: type_error(callable, _).
// used by '$skip_max_list'.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CycleSearchResult {
- Cyclic(usize),
+ Cyclic { lambda: usize }, // number of steps
EmptyList,
- NotList(usize, HeapCellValue), // the list length until the second argument in the heap
- PartialList(usize, Ref), // the list length (up to max), and an offset into the heap.
- ProperList(usize), // the list length.
- PStrLocation(usize, usize, usize), // list length (up to max), the heap address of the PStr, the offset
- UntouchedList(usize, usize), // list length (up to max), the address of an uniterated Addr::Lis(address).
- UntouchedCStr(Atom, usize),
+ NotList { num_steps: usize, heap_loc: HeapCellValue },
+ PartialList { num_steps: usize, heap_loc: HeapCellValue },
+ ProperList { num_steps: usize },
+ PStrLocation { num_steps: usize, pstr_loc: HeapCellValue },
+ UntouchedList { num_steps: usize, list_loc: usize },
}
impl MachineState {
let sorted = self.store(self.deref(self.registers[2]));
match BrentAlgState::detect_cycles(&self.heap, list) {
- CycleSearchResult::PartialList(..) => {
+ CycleSearchResult::PartialList { .. } => {
let err = self.instantiation_error();
return Err(self.error_form(err, stub_gen()));
}
- CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => {
+ CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } => {
let err = self.type_error(ValidType::List, list);
return Err(self.error_form(err, stub_gen()));
}
};
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);
Err(self.error_form(err, stub_gen()))
}
let stub_gen = || functor_stub(atom!("keysort"), 2);
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);
Err(self.error_form(err, stub_gen()))
}
let sorted = self.store(self.deref(self[temp_v!(2)]));
match BrentAlgState::detect_cycles(&self.heap, pairs) {
- CycleSearchResult::PartialList(..) => {
+ CycleSearchResult::PartialList { .. } => {
let err = self.instantiation_error();
Err(self.error_form(err, stub_gen()))
}
- CycleSearchResult::NotList(..) | CycleSearchResult::Cyclic(_) => {
+ CycleSearchResult::NotList { .. } | CycleSearchResult::Cyclic { .. } => {
let err = self.type_error(ValidType::List, pairs);
Err(self.error_form(err, stub_gen()))
}
}
}
+impl From<CodeIndex> for HeapCellValue {
+ #[inline(always)]
+ fn from(idx: CodeIndex) -> HeapCellValue {
+ untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx))
+ }
+}
+
impl CodeIndex {
#[inline]
pub(crate) fn new(ptr: IndexPtr, arena: &mut Arena) -> Self {
std::mem::replace(self.0.deref_mut(), value)
}
+ /*
#[inline(always)]
pub(crate) fn as_ptr(&self) -> *const IndexPtr {
self.0.as_ptr()
}
+ */
}
pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;
use crate::arena::*;
use crate::atom_table::*;
use crate::forms::*;
+use crate::functor_macro::*;
use crate::heap_iter::*;
use crate::heap_print::*;
use crate::machine::attributed_variables::*;
use crate::machine::streams::*;
use crate::machine::Machine;
use crate::parser::ast::*;
-use crate::read::TermWriteResult;
use crate::types::*;
use crate::parser::dashu::Integer;
use std::convert::TryFrom;
use std::fmt;
-use std::ops::{Index, IndexMut};
+use std::ops::{Index, IndexMut, Range};
use std::rc::Rc;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub(super) enum HeapPtr {
HeapCell(usize),
- PStrChar(usize, usize),
- PStrLocation(usize, usize),
+ PStr(usize), // Char(usize),
+ // PStrLocation(usize),
}
impl Default for HeapPtr {
}
}
-pub type CallResult = Result<(), Vec<HeapCellValue>>;
+pub type CallResult = Result<(), Vec<FunctorElement>>;
+/*
#[inline(always)]
pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixnum) {
read_heap_cell!(heap[index],
}
)
}
+*/
fn push_var_eq_functors(
heap: &mut Heap,
+ size: usize,
iter: impl Iterator<Item = (usize, Var)>,
atom_tbl: &AtomTable,
-) -> Vec<HeapCellValue> {
- let mut list_of_var_eqs = vec![];
+) -> Result<HeapCellValue, usize> {
+ let src_h = heap.cell_len();
- for (var_loc, var) in iter { // (var, binding) in iter {
- let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
- let h = heap.len();
- let binding = heap[var_loc];
+ if size > 0 {
+ let mut writer = heap.reserve(1 + 5 * size)?;
- heap.push(atom_as_cell!(atom!("="), 2));
- heap.push(atom_as_cell!(var_atom));
- heap.push(binding);
+ writer.write_with(|section| {
+ for (var_loc, var) in iter { // (var, binding) in iter {
+ 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);
+ }
- list_of_var_eqs
-}
+ 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!())
+ }
+}
+/*
pub(crate) fn copy_and_align_iter<Iter: Iterator<Item = HeapCellValue>>(
iter: Iter,
boundary: i64,
let diff = boundary - h;
iter.map(move |heap_value| heap_value - diff)
}
+*/
#[derive(Debug)]
pub struct Ball {
self.stub.clear();
}
- pub(super) fn copy_and_align(&self, h: usize) -> Heap {
- copy_and_align_iter(self.stub.iter().cloned(), self.boundary as i64, h as i64).collect()
+ pub(super) fn copy_and_align_to(&self, dest: &mut Heap) -> Result<usize, usize> {
+ 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)
}
}
impl<'a> CopierTarget for CopyTerm<'a> {
#[inline(always)]
- fn threshold(&self) -> usize {
- self.state.heap.len()
+ fn store(&self, value: HeapCellValue) -> HeapCellValue {
+ self.state.store(value)
}
#[inline(always)]
- fn push(&mut self, hcv: HeapCellValue) {
- self.state.heap.push(hcv);
+ fn deref(&self, value: HeapCellValue) -> HeapCellValue {
+ self.state.deref(value)
}
#[inline(always)]
}
#[inline(always)]
- fn store(&self, value: HeapCellValue) -> HeapCellValue {
- self.state.store(value)
+ fn stack(&mut self) -> &mut Stack {
+ &mut self.state.stack
}
#[inline(always)]
- fn deref(&self, value: HeapCellValue) -> HeapCellValue {
- self.state.deref(value)
+ fn threshold(&self) -> usize {
+ self.state.heap.cell_len()
}
#[inline(always)]
- fn stack(&mut self) -> &mut Stack {
- &mut self.state.stack
+ 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)
}
}
attr_var_queue: &'a mut Vec<usize>,
stack: &'a mut Stack,
heap: &'a mut Heap,
- heap_boundary: usize,
stub: &'a mut Heap,
}
heap: &'a mut Heap,
stub: &'a mut Heap,
) -> Self {
- let hb = heap.len();
-
CopyBallTerm {
attr_var_queue,
stack,
heap,
- heap_boundary: hb,
stub,
}
}
type Output = HeapCellValue;
fn index(&self, index: usize) -> &Self::Output {
- if index < self.heap_boundary {
+ if index < self.heap.cell_len() {
&self.heap[index]
} else {
- let index = index - self.heap_boundary;
+ let index = index - self.heap.cell_len();
&self.stub[index]
}
}
impl<'a> IndexMut<usize> for CopyBallTerm<'a> {
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]
} else {
- let index = index - self.heap_boundary;
+ let index = index - self.heap.cell_len();
&mut self.stub[index]
}
}
impl<'a> CopierTarget for CopyBallTerm<'a> {
fn threshold(&self) -> usize {
- self.heap_boundary + self.stub.len()
- }
-
- fn push(&mut self, value: HeapCellValue) {
- self.stub.push(value);
+ self.heap.cell_len() + self.stub.cell_len()
}
#[inline(always)]
fn store(&self, value: HeapCellValue) -> HeapCellValue {
read_heap_cell!(value,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => {
- if h < self.heap_boundary {
+ if h < self.heap.cell_len() {
self.heap[h]
} else {
- let index = h - self.heap_boundary;
+ let index = h - self.heap.cell_len();
self.stub[index]
}
}
fn stack(&mut self) -> &mut 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 {
let addr = self.store(self.deref(addr));
read_heap_cell!(addr,
- (HeapCellValueTag::Char, c) => {
- chars.push(c);
- continue;
- }
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
if let Some(c) = name.as_char() {
pub fn write_read_term_options(
&mut self,
mut var_list: Vec<(Var, HeapCellValue, usize)>,
- singleton_var_list: Vec<HeapCellValue>,
+ singletons_heap_list: HeapCellValue,
) -> CallResult {
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
+ /*
let list_of_var_eqs = push_var_eq_functors(
&mut self.heap,
var_list.iter().map(|(var_name, var, _)| {
(var.get_value() as usize, var_name.clone())
}),
+ num_vars,
&self.atom_tbl,
);
+ */
let singleton_addr = self.registers[3];
- let singletons_offset = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.heap,
- singleton_var_list.into_iter()
- ));
-
- unify_fn!(*self, singletons_offset, singleton_addr);
+ unify_fn!(*self, singletons_heap_list, singleton_addr);
if self.fail {
return Ok(());
}
let vars_addr = self.registers[4];
- let vars_offset = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.heap,
- var_list.into_iter().map(|(_, cell, _)| cell)
- ));
+ let vars_offset = resource_error_call_result!(
+ self,
+ sized_iter_to_heap_list(
+ &mut self.heap,
+ var_list.len(),
+ var_list.iter().map(|(_, cell, _)| *cell),
+ )
+ );
unify_fn!(*self, vars_offset, vars_addr);
}
let var_names_addr = self.registers[5];
+ /*
let var_names_offset = heap_loc_as_cell!(iter_to_heap_list(
&mut self.heap,
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))
}
pub fn read_term_body(&mut self, term: TermWriteResult) -> CallResult {
- let heap_loc = read_heap_cell!(self.heap[term.heap_loc],
- (HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
+ let heap_loc = self.heap[term.focus];
+
+ /*
+ read_heap_cell!(self.heap[term.heap_loc],
+ (HeapCellValueTag::PStr) => { // | HeapCellValueTag::PStrOffset) => {
pstr_loc_as_cell!(term.heap_loc)
}
_ => {
heap_loc_as_cell!(term.heap_loc)
}
);
+ */
unify_fn!(*self, heap_loc, self.registers[2]);
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);
if let Some(var) = cell.as_var() {
}
}
- let singleton_var_list = push_var_eq_functors(
- &mut self.heap,
- term.inverse_var_locs
- .iter()
- .filter_map(|(var_loc, var_name)| {
- // add h to offset the term variable into its heap location.
- let r = Ref::heap_cell(*var_loc);
-
- if singleton_var_set.get(&r).cloned().unwrap_or(false) {
- Some((*var_loc, var_name.clone()))
- } else {
- None
- }
- }),
- &self.atom_tbl,
+ let singleton_var_list = resource_error_call_result!(
+ self,
+ push_var_eq_functors(
+ &mut self.heap,
+ singleton_var_set
+ .iter()
+ .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) {
+ Some((*var_loc, var_name.clone()))
+ } else {
+ None
+ }
+ }),
+ &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());
for (var_loc, var_name) in term.inverse_var_locs {
CompilationError::ParserError(e) if e.is_unexpected_eof() => {
match eof_handler(self, stream)? {
OnEOF::Return => {
- return self.write_read_term_options(vec![], vec![])
+ return self.write_read_term_options(vec![], empty_list_as_cell!());
}
OnEOF::Continue => continue,
}
}
read_heap_cell!(atom,
- (HeapCellValueTag::Char, c) => {
- var_names.insert(var, Rc::new(c.to_string()));
- }
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
var_names.insert(var, Rc::new(name.as_str().to_owned()));
}
);
- let h = self.heap.len();
- self.heap.push(term_to_be_printed);
+ let term_loc = self.heap.cell_len();
+
+ step_or_resource_error!(
+ self,
+ self.heap.push_cell(term_to_be_printed),
+ { return Ok(None); }
+ );
let mut printer = HCPrinter::new(
&mut self.heap,
- Arc::clone(&self.atom_tbl),
&mut self.stack,
op_dir,
PrinterOutputter::new(),
- h,
+ term_loc,
);
printer.ignore_ops = ignore_ops;
}
);
}
-
- 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)]
impl MachineState {
pub(crate) fn new() -> Self {
+ let mut heap = Heap::with_cell_capacity(256 * 256).unwrap();
+
+ // this is an interstitial cell reserved for use by the runtime.
+ heap.push_cell(empty_list_as_cell!()).unwrap();
+ heap.store_resource_error();
+
MachineState {
arena: Arena::new(),
atom_tbl: AtomTable::new(),
cp: 0,
attr_var_init: AttrVarInitializer::new(0),
fail: false,
- heap: Heap::with_capacity(256 * 256),
+ heap,
mode: MachineMode::Write,
stack: Stack::new(),
registers: [heap_loc_as_cell!(0); MAX_ARITY + 1], // self.registers[0] is never used.
unifier.unify_atom(atom, value);
}
- pub fn unify_complete_string(&mut self, atom: Atom, value: HeapCellValue) {
+ pub fn unify_list(&mut self, l1: usize, value: HeapCellValue) {
let mut unifier = DefaultUnifier::from(self);
- unifier.unify_complete_string(atom, value);
+ unifier.unify_list(l1, value);
+ }
+
+ pub fn unify_partial_string(&mut self, pstr_loc: usize, value: HeapCellValue) {
+ let mut unifier = DefaultUnifier::from(self);
+ unifier.unify_partial_string(pstr_loc, value);
}
pub fn unify_char(&mut self, c: char, value: HeapCellValue) {
self.ball.reset();
let addr = self.registers[1];
- self.ball.boundary = self.heap.len();
-
- copy_term(
- CopyBallTerm::new(
- &mut self.attr_var_init.attr_var_queue,
- &mut self.stack,
- &mut self.heap,
- &mut self.ball.stub,
- ),
- addr,
- AttrVarPolicy::DeepCopy,
+ let ball_boundary = self.heap.cell_len();
+
+ step_or_resource_error!(
+ self,
+ copy_term(
+ CopyBallTerm::new(
+ &mut self.attr_var_init.attr_var_queue,
+ &mut self.stack,
+ &mut self.heap,
+ &mut self.ball.stub,
+ ),
+ addr,
+ AttrVarPolicy::DeepCopy,
+ )
);
+
+ self.ball.boundary = ball_boundary;
}
#[inline(always)]
self.fail = true;
}
+ // return the read value and the succeeding HeapPtr
pub(crate) fn read_s(&mut self) -> HeapCellValue {
- match &mut self.s {
- &mut HeapPtr::HeapCell(h) => self.deref(self.heap[h + self.s_offset]),
- &mut HeapPtr::PStrChar(h, n) if self.s_offset == 0 => {
- read_heap_cell!(self.heap[h],
- (HeapCellValueTag::PStr, pstr_atom) => {
- let pstr = PartialString::from(pstr_atom);
-
- if let Some(c) = pstr.as_str_from(n).chars().next() {
- char_as_cell!(c)
- } else {
- self.deref(self.heap[h+1])
- }
- }
- (HeapCellValueTag::CStr, cstr_atom) => {
- let pstr = PartialString::from(cstr_atom);
-
- if let Some(c) = pstr.as_str_from(n).chars().next() {
- char_as_cell!(c)
- } else {
- empty_list_as_cell!()
- }
- }
- _ => {
- unreachable!()
- }
- )
- }
- &mut HeapPtr::PStrChar(h, ref mut n) | &mut HeapPtr::PStrLocation(h, ref mut n) => {
- read_heap_cell!(self.heap[h],
- (HeapCellValueTag::PStr, pstr_atom) => {
- let pstr = PartialString::from(pstr_atom);
- let n_offset: usize = pstr.as_str_from(*n)
- .chars()
- .take(self.s_offset)
- .map(|c| c.len_utf8())
- .sum();
-
- self.s_offset = 0;
- *n += n_offset;
-
- if *n < pstr_atom.len() {
- let h_len = self.heap.len();
-
- self.heap.push(pstr_offset_as_cell!(h));
- self.heap.push(fixnum_as_cell!(Fixnum::build_with(*n as i64)));
-
- pstr_loc_as_cell!(h_len)
- } else {
- self.deref(self.heap[h+1])
- }
- }
- (HeapCellValueTag::CStr, cstr_atom) => {
- let pstr = PartialString::from(cstr_atom);
- let n_offset: usize = pstr.as_str_from(*n)
- .chars()
- .take(self.s_offset)
- .map(|c| c.len_utf8())
- .sum();
-
- self.s_offset = 0;
- *n += n_offset;
-
- if *n < cstr_atom.len() {
- let h_len = self.heap.len();
-
- self.heap.push(pstr_offset_as_cell!(h));
- self.heap.push(fixnum_as_cell!(Fixnum::build_with(*n as i64)));
-
- pstr_loc_as_cell!(h_len)
- } else {
- empty_list_as_cell!()
- }
- }
- _ => {
- unreachable!()
+ match self.s {
+ HeapPtr::HeapCell(h) => self.deref(self.heap[h + self.s_offset]),
+ HeapPtr::PStr(h) => {
+ let mut char_iter = self.heap.char_iter(h);
+
+ if self.s_offset == 0 { // read the car of the list
+ let c = char_iter.next().unwrap();
+ char_as_cell!(c)
+ } else { // read the (self.s_offset)^{th} cdr of the list
+ let byte_offset: usize = char_iter
+ .take(self.s_offset)
+ .map(|c| c.len_utf8())
+ .sum();
+ let new_h = h + byte_offset;
+
+ self.s_offset = 0;
+
+ if self.heap.char_iter(new_h).next().is_some() {
+ self.s = HeapPtr::PStr(new_h);
+ pstr_loc_as_cell!(new_h)
+ } else {
+ let h = Heap::neighboring_cell_offset(new_h);
+ self.s = HeapPtr::HeapCell(h);
+ self.deref(heap_loc_as_cell!(h))
}
- )
+ }
}
}
}
return Some(n1.cmp(&n2));
}
}
+ /*
(HeapCellValueTag::Char, c2) => {
if let Some(c1) = n1.as_char() {
if c1 != c2 {
);
}
}
+ */
(HeapCellValueTag::Str, s) => {
let n2 = cell_as_atom_cell!(self.heap[s])
.get_name();
}
)
}
+ /*
(HeapCellValueTag::Char, c1) => {
read_heap_cell!(v2,
(HeapCellValueTag::Atom, (n2, _a2)) => {
}
)
}
+ */
(HeapCellValueTag::Str, s) => {
let n1 = cell_as_atom_cell!(self.heap[s])
.get_name();
return Some(n1.cmp(&n2));
}
}
+ /*
(HeapCellValueTag::Char, c2) => {
if let Some(c1) = n1.as_char() {
if c1 != c2 {
);
}
}
+ */
(HeapCellValueTag::Str, s) => {
let n2 = cell_as_atom_cell!(self.heap[s])
.get_name();
)
}
Some(TermOrderCategory::Compound) => {
- fn stalled_pstr_iter_comparator(
- iteratee: PStrIteratee,
- iter2: HeapPStrIter,
- pdl: &mut Vec<HeapCellValue>,
- ) -> Option<Ordering> {
- let compound = Some(TermOrderCategory::Compound);
-
- if iter2.focus.order_category(iter2.heap) != compound {
- Some(compound.cmp(&iter2.focus.order_category(iter2.heap)))
- } else {
- let c1 = match iteratee {
- PStrIteratee::Char(_, c) => c,
- PStrIteratee::PStrSegment(focus, pstr_atom, n) => {
- let pstr = PartialString::from(pstr_atom);
-
- match pstr.as_str_from(n).chars().next() {
- Some(c) => c,
- None => {
- pdl.push(iter2.focus);
- // iter2 is continuable, so it
- // has a tail in the heap at
- // focus+1.
- pdl.push(iter2.heap[focus + 1]);
-
- return None;
- }
- }
- }
- };
-
- read_heap_cell!(iter2.focus,
- (HeapCellValueTag::Lis, l) => {
- pdl.push(iter2.heap[l]);
- pdl.push(char_as_cell!(c1));
-
- None
- }
- (HeapCellValueTag::Str, s) => {
- let (name, arity) = cell_as_atom_cell!(iter2.heap[s])
- .get_name_and_arity();
-
- if name == atom!(".") && arity == 2 {
- pdl.push(iter2.heap[s+1]);
- pdl.push(char_as_cell!(c1));
-
- None
- } else {
- Some((2, atom!(".")).cmp(&(arity, name)))
- }
- }
- _ => {
- unreachable!()
- }
- )
- }
- }
-
- fn pstr_comparator(
- heap: &[HeapCellValue],
- pdl: &mut Vec<HeapCellValue>,
- s1: usize,
- s2: usize,
- ) -> Option<Ordering> {
- let mut iter1 = HeapPStrIter::new(heap, s1);
- let mut iter2 = HeapPStrIter::new(heap, s2);
-
- match compare_pstr_prefixes(&mut iter1, &mut iter2) {
- PStrCmpResult::Ordered(ordering) => Some(ordering),
- PStrCmpResult::FirstIterContinuable(iteratee) => {
- stalled_pstr_iter_comparator(iteratee, iter2, pdl)
- }
- PStrCmpResult::SecondIterContinuable(iteratee) => {
- let result = stalled_pstr_iter_comparator(iteratee, iter1, pdl);
-
- if let Some(ordering) = result {
- Some(ordering.reverse())
- } else {
- let pdl_len = pdl.len();
- pdl.swap(pdl_len - 2, pdl_len - 1);
- result
- }
- }
- PStrCmpResult::Unordered => {
- pdl.push(iter2.focus);
- pdl.push(iter1.focus);
-
- None
- }
- }
- }
-
read_heap_cell!(v1,
(HeapCellValueTag::Lis, l1) => {
read_heap_cell!(v2,
- (HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
- let h = self.heap.len();
-
- self.heap.push(v1);
- self.heap.push(v2);
-
- if let Some(ordering) = pstr_comparator(
- &self.heap, &mut self.pdl, h, h+1
- ) {
- if ordering != Ordering::Equal {
- self.heap.pop();
- self.heap.pop();
-
- self.pdl.clear();
-
- return Some(ordering);
- }
- }
-
- self.heap.pop();
- self.heap.pop();
+ (HeapCellValueTag::PStrLoc, l2) => {
+ // like the action of
+ // partial_string_to_pdl here but
+ // the ordering of PDL pushes is
+ // (crucially for comparison
+ // correctness) different.
+ let (c, succ_cell) = self.heap.last_str_char_and_tail(l2);
+
+ self.pdl.push(succ_cell);
+ self.pdl.push(heap_loc_as_cell!(l1 + 1));
+
+ self.pdl.push(char_as_cell!(c));
+ self.pdl.push(heap_loc_as_cell!(l1));
}
(HeapCellValueTag::Lis, l2) => {
if tabu_list.contains(&(l1, l2)) {
}
)
}
- (HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
- let h = self.heap.len();
-
- self.heap.push(v1);
- self.heap.push(v2);
+ (HeapCellValueTag::PStrLoc, l1) => {
+ read_heap_cell!(v2,
+ (HeapCellValueTag::PStrLoc, l2) => {
+ let cmp_result = self.heap.compare_pstr_segments(l1, l2);
- if let Some(ordering) = pstr_comparator(
- &self.heap, &mut self.pdl, h, h+1,
- ) {
- if ordering != Ordering::Equal {
- self.heap.pop();
- self.heap.pop();
+ if let Some(ordering) = cmp_result.continue_pstr_compare(&mut self.pdl) {
+ return Some(ordering);
+ }
+ }
+ (HeapCellValueTag::Lis, l2) => {
+ let (c, succ_cell) = self.heap.last_str_char_and_tail(l1);
- self.pdl.clear();
+ self.pdl.push(succ_cell);
+ self.pdl.push(heap_loc_as_cell!(l2 + 1));
- return Some(ordering);
+ self.pdl.push(char_as_cell!(c));
+ self.pdl.push(heap_loc_as_cell!(l2));
}
- }
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.heap[s])
+ .get_name_and_arity();
+
+ if name == atom!(".") && arity == 2 {
+ let (c, succ_cell) = self.heap.last_str_char_and_tail(l1);
+
+ self.pdl.push(heap_loc_as_cell!(s+2));
+ self.pdl.push(succ_cell);
- self.heap.pop();
- self.heap.pop();
+ self.pdl.push(heap_loc_as_cell!(s+1));
+ self.pdl.push(char_as_cell!(c));
+ } else {
+ self.fail = true;
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ );
}
(HeapCellValueTag::Str, s1) => {
read_heap_cell!(v2,
}
}
}
- (HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
- let h = self.heap.len();
-
- self.heap.push(v1);
- self.heap.push(v2);
+ (HeapCellValueTag::PStrLoc, l2) => {
+ let (name, arity) = cell_as_atom_cell!(self.heap[s1])
+ .get_name_and_arity();
- if let Some(ordering) = pstr_comparator(
- &self.heap, &mut self.pdl, h, h+1,
- ) {
- if ordering != Ordering::Equal {
- self.heap.pop();
- self.heap.pop();
+ if name == atom!(".") && arity == 2 {
+ let (c, succ_cell) = self.heap.last_str_char_and_tail(l2);
- self.pdl.clear();
+ self.pdl.push(succ_cell);
+ self.pdl.push(heap_loc_as_cell!(s1+2));
- return Some(ordering);
- }
+ self.pdl.push(char_as_cell!(c));
+ self.pdl.push(heap_loc_as_cell!(s1+1));
+ } else {
+ self.fail = true;
}
-
- self.heap.pop();
- self.heap.pop();
}
_ => {
unreachable!()
Some(Ordering::Equal)
}
- pub fn match_partial_string(&mut self, value: HeapCellValue, string: Atom, has_tail: bool) {
- let h = self.heap.len();
- self.heap.push(value);
-
- let prefix_len;
- let mut heap_pstr_iter = HeapPStrIter::new(&self.heap, h);
-
- let s = string.as_str();
-
- match heap_pstr_iter.compare_pstr_to_string(&s) {
- Some(PStrPrefixCmpResult {
- focus,
- offset,
- prefix_len,
- }) if prefix_len == s.len() => {
- let focus_addr = self.heap[focus];
-
- read_heap_cell!(focus_addr,
- (HeapCellValueTag::PStr | HeapCellValueTag::CStr, pstr_atom) => {
- if has_tail {
- self.s = HeapPtr::PStrLocation(focus, offset);
- self.s_offset = 0;
- self.mode = MachineMode::Read;
- } else if offset == pstr_atom.len() {
- let focus = heap_pstr_iter.focus;
- unify!(self, focus, empty_list_as_cell!());
- } else {
- self.fail = true;
- }
- }
- (HeapCellValueTag::PStrLoc | HeapCellValueTag::PStrOffset, h) => {
- let (focus, _) = pstr_loc_and_offset(&self.heap, h);
- let pstr_atom = cell_as_atom!(self.heap[focus]);
-
- if has_tail {
- self.s = HeapPtr::PStrLocation(focus, offset);
- self.s_offset = 0;
- self.mode = MachineMode::Read;
- } else if offset == pstr_atom.len() {
- let focus = heap_pstr_iter.focus;
- unify!(self, focus, empty_list_as_cell!());
- } else {
- self.fail = true;
- }
- }
- _ => {
- let focus = heap_pstr_iter.focus();
-
- if has_tail {
- self.s = HeapPtr::HeapCell(focus);
- self.s_offset = 0;
- self.mode = MachineMode::Read;
- } else {
- let focus = heap_pstr_iter.focus;
- unify!(self, focus, empty_list_as_cell!());
- }
- }
- );
+ /* TODO: new, inlined match_partial_string. now inlined into GetPartialString,
+ * the only place it is called from. Therefore, it has been inlined.
- return;
+ pub fn match_partial_string(
+ &mut self,
+ value: HeapCellValue,
+ string: &str,
+ ) -> Result<(), usize> {
+ debug_assert!(value.is_ref());
+
+ self.heap[0] = value;
+ let mut heap_pstr_iter = HeapPStrIter::new(&self.heap, 0);
+
+ match heap_pstr_iter.compare_pstr_to_string(string) {
+ Some(PStrCmpResult::CompleteMatch { bytes_matched, pstr_loc }) => {
+ self.s_offset = bytes_matched;
+ self.s = HeapPtr::PStr(pstr_loc);
+ self.mode = MachineMode::Read;
}
- Some(PStrPrefixCmpResult {
- prefix_len: inner_prefix_len,
- ..
- }) => {
- prefix_len = inner_prefix_len;
+ Some(PStrCmpResult::PartialMatch { string, var_loc }) => {
+ let cell = self.heap.allocate_pstr(string)?;
+ unify!(self, cell, heap_loc_as_loc!(var_loc));
}
None => {
- read_heap_cell!(value,
- (HeapCellValueTag::Str, s) => {
- let cell = heap_loc_as_cell!(s + 1);
- let is_list = self.heap[s] == atom_as_cell!(atom!("."), 2);
-
- if !(is_list && self.store(self.deref(cell)).is_var()) {
- self.fail = true;
- return;
- }
- }
- (HeapCellValueTag::Lis, l) => {
- let cell = heap_loc_as_cell!(l);
-
- if !self.store(self.deref(cell)).is_var() {
- self.fail = true;
- return;
- }
- }
- (HeapCellValueTag::AttrVar |
- HeapCellValueTag::StackVar |
- HeapCellValueTag::Var) => {
- }
- _ => {
- self.fail = true;
- return;
- }
- );
-
- prefix_len = 0;
+ self.fail = true;
}
}
- let focus = heap_pstr_iter.focus();
- let tail_addr = self.heap[focus];
- let target_cell = self.push_str_to_heap(&string.as_str()[prefix_len..], has_tail);
-
- unify!(self, tail_addr, target_cell);
- }
-
- #[inline(always)]
- pub(super) fn push_str_to_heap(&mut self, pstr: &str, has_tail: bool) -> HeapCellValue {
- let h = self.heap.len();
-
- if has_tail {
- self.s = HeapPtr::HeapCell(h + 1);
- self.s_offset = 0;
- self.mode = MachineMode::Read;
-
- put_partial_string(&mut self.heap, pstr, &self.atom_tbl)
- } else {
- put_complete_string(&mut self.heap, pstr, &self.atom_tbl)
- }
- }
-
- pub(super) fn write_literal_to_var(&mut self, deref_v: HeapCellValue, lit: HeapCellValue) {
- let store_v = self.store(deref_v);
-
- read_heap_cell!(lit,
- (HeapCellValueTag::Atom, (atom, arity)) => {
- if arity == 0 {
- self.unify_atom(atom, store_v);
- } else {
- self.fail = true;
- }
- }
- (HeapCellValueTag::Char, c) => {
- self.unify_char(c, store_v);
- }
- (HeapCellValueTag::Fixnum, n) => {
- self.unify_fixnum(n, store_v);
- }
- (HeapCellValueTag::F64, f64_ptr) => {
- self.unify_f64(f64_ptr, store_v);
- }
- (HeapCellValueTag::Cons, ptr) => {
- match_untyped_arena_ptr!(ptr,
- (ArenaHeaderTag::Integer, n) => {
- self.unify_big_int(n, store_v);
- }
- (ArenaHeaderTag::Rational, r) => {
- self.unify_rational(r, store_v);
- }
- _ => {
- self.fail = true;
- }
- )
- }
- (HeapCellValueTag::CStr, cstr_atom) => {
- read_heap_cell!(store_v,
- (HeapCellValueTag::PStrLoc |
- HeapCellValueTag::Lis |
- HeapCellValueTag::Str) => {
- self.match_partial_string(store_v, cstr_atom, false);
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var) => {
- let r = store_v.as_var().unwrap();
- self.bind(r, lit);
- }
- (HeapCellValueTag::CStr, cstr2_atom) => {
- self.fail = cstr_atom != cstr2_atom;
- }
- _ => {
- self.fail = true;
- }
- );
- }
- _ => {
- unreachable!()
- }
- )
+ Ok(())
}
+ */
pub(crate) fn setup_call_n_init_goal_info(
&mut self,
(name, 0, 0)
}
+ /*
(HeapCellValueTag::Char, c) => {
(AtomTable::build_with(&self.atom_tbl, &c.to_string()), 0, 0)
}
+ */
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.instantiation_error();
}
#[inline]
- pub fn is_cyclic_term(&mut self, value: HeapCellValue) -> bool {
- let value = self.store(self.deref(value));
-
- if value.is_stack_var() || value.is_constant() {
+ pub fn is_cyclic_term(&mut self, term_loc: usize) -> bool {
+ if self.heap[term_loc].is_stack_var() {
return false;
}
- let h = self.heap.len();
- self.heap.push(value);
-
- let cycle_found = {
- let mut iter = cycle_detecting_stackless_preorder_iter(&mut self.heap, h);
- for _ in iter.by_ref() {}
- iter.cycle_found()
- };
-
- self.heap.pop();
- cycle_found
+ let mut iter = cycle_detecting_stackless_preorder_iter(&mut self.heap, term_loc);
+ for _ in iter.by_ref() {}
+ iter.cycle_found()
}
// arg(+N, +Term, ?Arg)
(HeapCellValueTag::PStrLoc, pstr_loc) => {
if n == 1 || n == 2 {
let a3 = self.registers[3];
- let (h, offset) = pstr_loc_and_offset(&self.heap, pstr_loc);
+ // let (h, offset) = pstr_loc_and_offset(&self.heap, pstr_loc);
+ let mut char_iter = self.heap.char_iter(pstr_loc);
- let pstr = cell_as_string!(self.heap[h]);
- let offset = offset.get_num() as usize;
+ // let pstr = cell_as_string!(self.heap[h]);
+ // let offset = offset.get_num() as usize;
- if let Some(c) = pstr.as_str_from(offset).chars().next() {
+ if let Some(c) = char_iter.next() { // pstr.as_str_from(offset).chars().next() {
if n == 1 {
self.unify_char(c, a3);
} else {
- let offset = (offset + c.len_utf8()) as i64;
- let h_len = self.heap.len();
- let pstr_atom: Atom = pstr.into();
+ // let offset = (offset + c.len_utf8()) as i64;
+ // let h_len = self.heap.len();
+ // let pstr_atom: Atom = pstr.into();
+ if char_iter.next().is_some() {
+ unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3);
+ } else {
+ let tail_idx = Heap::neighboring_cell_offset(pstr_loc);
+ unify_fn!(*self, self.heap[tail_idx]);
+ }
+ /*
if pstr_atom.len() > offset as usize {
self.heap.push(pstr_offset_as_cell!(h));
self.heap.push(fixnum_as_cell!(Fixnum::build_with(offset)));
}
}
}
+ */
}
} else {
unreachable!()
self.fail = true;
}
}
+ /*
(HeapCellValueTag::CStr, cstr_atom) => {
let cstr = PartialString::from(cstr_atom);
unreachable!()
}
}
+ */
_ => {
// 8.5.2.3 d)
let err = self.type_error(ValidType::Compound, term);
fn try_functor_unify_components(&mut self, name: HeapCellValue, arity: usize) {
let a2 = self.deref(self.registers[2]);
- self.write_literal_to_var(a2, name);
+ unify!(self, a2, name);
if !self.fail {
let a3 = self.store(self.deref(self.registers[3]));
}
}
- fn try_functor_fabricate_struct(&mut self, name: Atom, arity: usize, r: Ref) {
- let h = self.heap.len();
+ fn try_functor_fabricate_struct(&mut self, name: Atom, arity: usize, r: Ref) -> Result<(), usize> {
+ let h = self.heap.cell_len();
+ let mut writer = self.heap.reserve(arity + 1)?;
let f_a = if name == atom!(".") && arity == 2 {
- self.heap.push(heap_loc_as_cell!(h));
- self.heap.push(heap_loc_as_cell!(h + 1));
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(h));
+ section.push_cell(heap_loc_as_cell!(h + 1));
+ });
list_loc_as_cell!(h)
} else {
- self.heap.push(atom_as_cell!(name, arity));
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(name, arity));
- for i in 0..arity {
- self.heap.push(heap_loc_as_cell!(h + i + 1));
- }
+ for i in 0..arity {
+ section.push_cell(heap_loc_as_cell!(h + i + 1));
+ }
+ });
if arity == 0 {
heap_loc_as_cell!(h)
};
(self.bind_fn)(self, r, f_a);
+ Ok(())
}
pub fn try_functor(&mut self) -> CallResult {
let a1 = self.store(self.deref(self.registers[1]));
read_heap_cell!(a1,
- (HeapCellValueTag::Cons | HeapCellValueTag::Char | HeapCellValueTag::Fixnum |
+ (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // | HeapCellValueTag::Char
HeapCellValueTag::F64) => {
self.try_functor_unify_components(a1, 0);
}
let (name, arity) = cell_as_atom_cell!(self.heap[s]).get_name_and_arity();
self.try_functor_compound_case(name, arity);
}
- (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
+ (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => { // | HeapCellValueTag::CStr) => {
self.try_functor_compound_case(atom!("."), 2);
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
};
read_heap_cell!(store_name,
- (HeapCellValueTag::Cons | HeapCellValueTag::Char | HeapCellValueTag::Fixnum |
+ (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char |
HeapCellValueTag::F64) if arity == 0 => {
self.bind(a1.as_var().unwrap(), deref_name);
}
(HeapCellValueTag::Atom, (name, atom_arity)) => {
debug_assert_eq!(atom_arity, 0);
- self.try_functor_fabricate_struct(
- name,
- arity as usize,
- a1.as_var().unwrap(),
+ resource_error_call_result!(
+ self,
+ self.try_functor_fabricate_struct(
+ name,
+ arity as usize,
+ a1.as_var().unwrap(),
+ )
);
}
(HeapCellValueTag::Str, s) => {
.get_name_and_arity();
if atom_arity == 0 {
- self.try_functor_fabricate_struct(
- name,
- arity as usize,
- a1.as_var().unwrap(),
+ resource_error_call_result!(
+ self,
+ self.try_functor_fabricate_struct(
+ name,
+ arity as usize,
+ a1.as_var().unwrap(),
+ )
);
} else {
let err = self.type_error(ValidType::Atomic, store_name);
return Err(self.error_form(err, stub_gen()));
}
}
+ /*
(HeapCellValueTag::Char, c) => {
let c = AtomTable::build_with(&self.atom_tbl, &c.to_string());
- self.try_functor_fabricate_struct(
- c,
- arity as usize,
- a1.as_var().unwrap(),
+ resource_error_call_result!(
+ self,
+ self.try_functor_fabricate_struct(
+ c,
+ arity as usize,
+ a1.as_var().unwrap(),
+ )
);
}
+ */
(HeapCellValueTag::Cons | HeapCellValueTag::Fixnum |
HeapCellValueTag::F64) if arity != 0 => {
let err = self.type_error(ValidType::Atom, store_name);
pub fn try_from_list(
&mut self,
value: HeapCellValue,
- stub_gen: impl Fn() -> FunctorStub,
+ stub_gen: impl Fn() -> MachineStub,
) -> Result<Vec<HeapCellValue>, MachineStub> {
let value = self.store(self.deref(value));
(HeapCellValueTag::Lis, l) => {
self.try_from_inner_list(vec![], l, stub_gen, value)
}
- (HeapCellValueTag::PStrLoc, h) => {
- self.try_from_partial_string(vec![], h, stub_gen, value)
+ (HeapCellValueTag::PStrLoc, pstr_loc) => {
+ self.try_from_partial_string(vec![], pstr_loc, stub_gen, value)
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar | HeapCellValueTag::Var) => {
let err = self.instantiation_error();
Err(self.error_form(err, stub_gen()))
}
}
+ /*
(HeapCellValueTag::CStr, cstr_atom) => {
let cstr = cstr_atom.as_str();
Ok(cstr.chars().map(|c| char_as_cell!(c)).collect())
}
+ */
_ => {
let err = self.type_error(ValidType::List, value);
Err(self.error_form(err, stub_gen()))
&mut self,
mut result: Vec<HeapCellValue>,
mut l: usize,
- stub_gen: impl Fn() -> FunctorStub,
+ stub_gen: impl Fn() -> MachineStub,
a1: HeapCellValue,
) -> Result<Vec<HeapCellValue>, MachineStub> {
result.push(self.heap[l]);
result.push(self.heap[hcp]);
l = hcp + 1;
}
- (HeapCellValueTag::PStrLoc, l) => {
- return self.try_from_partial_string(result, l, stub_gen, a1);
+ (HeapCellValueTag::PStrLoc, pstr_loc) => {
+ return self.try_from_partial_string(result, pstr_loc, stub_gen, a1);
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
fn try_from_partial_string(
&mut self,
mut chars: Vec<HeapCellValue>,
- h: usize,
- stub_gen: impl Fn() -> FunctorStub,
+ pstr_loc: usize,
+ stub_gen: impl Fn() -> MachineStub,
a1: HeapCellValue,
) -> Result<Vec<HeapCellValue>, MachineStub> {
- let mut heap_pstr_iter = HeapPStrIter::new(&self.heap, h);
+ self.heap[0] = pstr_loc_as_cell!(pstr_loc);
+ let mut heap_pstr_iter = HeapPStrIter::new(&self.heap, 0);
- for iteratee in heap_pstr_iter.by_ref() {
+ while let Some(iteratee) = heap_pstr_iter.next() {
match iteratee {
- PStrIteratee::Char(_, c) => chars.push(char_as_cell!(c)),
- PStrIteratee::PStrSegment(_, pstr_atom, n) => {
- let pstr = PartialString::from(pstr_atom);
- chars.extend(pstr.as_str_from(n).chars().map(|c| char_as_cell!(c)));
+ PStrIteratee::Char { value: c, .. } => chars.push(char_as_cell!(c)),
+ PStrIteratee::PStrSlice {
+ slice_loc,
+ slice_len,
+ } => {
+ let pstr = heap_pstr_iter.heap.slice_to_str(slice_loc, slice_len);
+ chars.extend(pstr.chars().map(|c| char_as_cell!(c)));
}
}
}
- match self.heap[h].get_tag() {
- HeapCellValueTag::PStr => {
- if heap_pstr_iter.at_string_terminator() {
- Ok(chars)
- } else {
- read_heap_cell!(self.heap[heap_pstr_iter.focus()],
- (HeapCellValueTag::Lis, l) => {
- self.try_from_inner_list(chars, l, stub_gen, a1)
- }
- (HeapCellValueTag::Atom, (name, arity)) => {
- if name == atom!(".") && arity == 2 {
- let l = heap_pstr_iter.focus() + 1;
- self.try_from_inner_list(chars, l, stub_gen, a1)
- } else {
- let err = self.type_error(ValidType::List, a1);
- Err(self.error_form(err, stub_gen()))
- }
- }
- _ => {
- let err = self.type_error(ValidType::List, a1);
- Err(self.error_form(err, stub_gen()))
- }
- )
- }
- }
- HeapCellValueTag::CStr => Ok(chars),
- _ => {
- unreachable!()
- }
+ let end_cell = heap_pstr_iter.heap[heap_pstr_iter.focus()];
+
+ if heap_pstr_iter.is_cyclic() || end_cell == empty_list_as_cell!() {
+ let err = self.type_error(ValidType::List, a1);
+ return Err(self.error_form(err, stub_gen()));
}
+
+ Ok(chars)
}
// returns true on failure.
pub fn integers_to_bytevec(
&mut self,
value: HeapCellValue,
- stub_gen: impl Fn() -> FunctorStub,
+ stub_gen: impl Fn() -> MachineStub,
) -> Vec<u8> {
let mut bytes: Vec<u8> = Vec::new();
pub use crate::machine::streams::*;
pub use crate::machine::*;
pub use crate::parser::ast::*;
-use crate::read::*;
-pub use crate::types::*;
-
-use std::sync::Arc;
#[cfg(test)]
use crate::machine::copier::CopierTarget;
#[cfg(test)]
-use std::ops::{Deref, DerefMut, Index, IndexMut};
+use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
// a mini-WAM for test purposes.
Self {
machine_st: MachineState::new(),
op_dir,
- //flags: MachineFlags::default(),
}
}
) -> Result<String, CompilationError> {
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
.inverse_var_locs
let mut printer = HCPrinter::new(
&mut self.machine_st.heap,
- Arc::clone(&self.machine_st.atom_tbl),
&mut self.machine_st.stack,
&self.op_dir,
PrinterOutputter::new(),
- term_write_result.heap_loc,
+ term_write_result.focus,
);
printer.var_names = var_names;
}
}
- fn push(&mut self, val: HeapCellValue) {
- self.wam.machine_st.heap.push(val);
- }
-
fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
self.wam
.machine_st
}
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)]
-pub fn all_cells_marked_and_unforwarded(heap: &[HeapCellValue]) {
- for (idx, cell) in heap.iter().enumerate() {
+pub fn all_cells_marked_and_unforwarded(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!(
cell.get_mark_bit(),
"cell {:?} at index {} is not marked",
cell,
- idx
+ curr_idx
);
assert!(
!cell.get_forwarding_bit(),
"cell {:?} at index {} is forwarded",
cell,
- idx
+ curr_idx
);
}
}
#[cfg(test)]
-pub fn all_cells_unmarked(heap: &Heap) {
- for (idx, cell) in heap.iter().enumerate() {
+pub fn unmark_all_cells(mut iter: impl SizedHeapMut) {
+ 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!(
!cell.get_mark_bit(),
"cell {:?} at index {} is still marked",
cell,
- idx
- );
-
- assert!(
- !cell.get_forwarding_bit(),
- "cell {:?} at index {} is still forwarded",
- cell,
- idx
+ curr_idx
);
}
}
mod tests {
use super::*;
+ use crate::functor_macro::FunctorElement;
+
#[test]
fn unify_tests() {
let mut wam = MachineState::new();
unify!(
wam,
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);
}
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
unify!(
wam,
- heap_loc_as_cell!(term_write_result_1.heap_loc),
- heap_loc_as_cell!(term_write_result_2.heap_loc)
+ heap_loc_as_cell!(term_write_result_1.focus),
+ heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
unify!(
wam,
- heap_loc_as_cell!(term_write_result_1.heap_loc),
- heap_loc_as_cell!(term_write_result_2.heap_loc)
+ heap_loc_as_cell!(term_write_result_1.focus),
+ heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
unify!(
wam,
- heap_loc_as_cell!(term_write_result_1.heap_loc),
- heap_loc_as_cell!(term_write_result_2.heap_loc)
+ heap_loc_as_cell!(term_write_result_1.focus),
+ heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
unify!(
wam,
- heap_loc_as_cell!(term_write_result_1.heap_loc),
- heap_loc_as_cell!(term_write_result_2.heap_loc)
+ heap_loc_as_cell!(term_write_result_1.focus),
+ heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.fail = false;
wam.heap.clear();
let term_write_result_2 =
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!(
wam,
- heap_loc_as_cell!(term_write_result_1.heap_loc),
- heap_loc_as_cell!(term_write_result_2.heap_loc)
+ heap_loc_as_cell!(term_write_result_1.focus),
+ heap_loc_as_cell!(term_write_result_2.focus)
);
assert!(!wam.fail);
}
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear();
- wam.heap.push(pstr_as_cell!(atom!("this is a string")));
- wam.heap.push(heap_loc_as_cell!(1));
+ let mut writer = wam.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_pstr("this is a string"); // 0
+
+ let h = section.cell_len();
+ assert_eq!(h, 3);
- wam.heap.push(pstr_as_cell!(atom!("this is a string")));
- wam.heap.push(pstr_loc_as_cell!(4));
+ section.push_cell(heap_loc_as_cell!(h)); // 3
+ section.push_pstr("this is a string"); // 4
- wam.heap.push(pstr_offset_as_cell!(0));
- wam.heap.push(fixnum_as_cell!(Fixnum::build_with(6)));
+ let h = section.cell_len();
+ assert_eq!(h + 1, 8);
- unify!(wam, pstr_loc_as_cell!(0), pstr_loc_as_cell!(2));
+ 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_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.push(list_loc_as_cell!(1));
- 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));
+ let mut writer = wam.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("a")));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(atom_as_cell!(atom!("b")));
+ section.push_cell(heap_loc_as_cell!(0));
- wam.heap.push(list_loc_as_cell!(6));
- wam.heap.push(atom_as_cell!(atom!("a")));
- wam.heap.push(list_loc_as_cell!(8));
- wam.heap.push(atom_as_cell!(atom!("b")));
- wam.heap.push(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!(5));
+ });
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
assert!(!wam.fail);
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear();
- wam.heap.push(list_loc_as_cell!(1));
- 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));
+ let mut writer = wam.heap.reserve(96).unwrap();
- wam.heap.push(list_loc_as_cell!(6));
- wam.heap.push(atom_as_cell!(atom!("a")));
- wam.heap.push(list_loc_as_cell!(8));
- wam.heap.push(atom_as_cell!(atom!("c")));
- wam.heap.push(heap_loc_as_cell!(5));
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("a")));
+ section.push_cell(list_loc_as_cell!(3));
+ 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));
assert!(wam.fail);
wam.fail = false;
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
+
wam.heap.clear();
- wam.heap.push(list_loc_as_cell!(1));
- 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));
+ let mut writer = wam.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(atom_as_cell!(atom!("a")));
+ section.push_cell(list_loc_as_cell!(3));
+ section.push_cell(atom_as_cell!(atom!("b")));
+ section.push_cell(heap_loc_as_cell!(5));
- wam.heap.push(list_loc_as_cell!(6));
- wam.heap.push(atom_as_cell!(atom!("a")));
- wam.heap.push(list_loc_as_cell!(8));
- wam.heap.push(atom_as_cell!(atom!("b")));
- wam.heap.push(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!(0));
+ });
unify!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(5));
assert!(!wam.fail);
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
}
#[test]
let term_write_result_2 =
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!(
wam,
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);
let mut wam = MachineState::new();
- wam.heap.push(heap_loc_as_cell!(0));
- wam.heap.push(heap_loc_as_cell!(1));
+ // clear the heap of resource error data etc
+ 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!(
compare_term_test!(wam, wam.heap[0], wam.heap[1]),
Some(Ordering::Equal)
);
+ let cstr_cell = wam.allocate_cstr("string").unwrap();
+
assert_eq!(
compare_term_test!(
wam,
atom_as_cell!(atom!("atom")),
- atom_as_cstr_cell!(atom!("string"))
+ cstr_cell
),
Some(Ordering::Less)
);
wam.heap.clear();
- wam.heap.push(atom_as_cell!(atom!("f"), 1));
- wam.heap.push(heap_loc_as_cell!(1));
+ let mut writer = wam.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("f"), 1));
+ section.push_cell(heap_loc_as_cell!(1));
+ });
assert_eq!(
compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)),
wam.heap.clear();
- // [1,2,3]
- 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]
- wam.heap.push(list_loc_as_cell!(8));
- wam.heap.push(fixnum_as_cell!(Fixnum::build_with(1)));
- wam.heap.push(list_loc_as_cell!(10));
- wam.heap.push(fixnum_as_cell!(Fixnum::build_with(2)));
- wam.heap.push(empty_list_as_cell!());
+ let mut writer = wam.heap.reserve(96).unwrap();
+
+ writer.write_with(|section| {
+ // [1,2,3]
+ section.push_cell(list_loc_as_cell!(1));
+ section.push_cell(fixnum_as_cell!(Fixnum::build_with(1)));
+ section.push_cell(list_loc_as_cell!(3));
+ 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!(
compare_term_test!(wam, heap_loc_as_cell!(7), heap_loc_as_cell!(7)),
Some(Ordering::Greater)
);
+ let cstr_cell = wam.allocate_cstr("string").unwrap();
+
assert_eq!(
compare_term_test!(
wam,
empty_list_as_cell!(),
- atom_as_cstr_cell!(atom!("string"))
+ cstr_cell
),
Some(Ordering::Less)
);
fn is_cyclic_term_tests() {
let mut wam = MachineState::new();
- assert!(!wam.is_cyclic_term(atom_as_cell!(atom!("f"))));
- assert!(!wam.is_cyclic_term(fixnum_as_cell!(Fixnum::build_with(555))));
+ let mut writer = wam.heap.reserve(96).unwrap();
- 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
- .extend(functor!(atom!("f"), [atom(atom!("a")), atom(atom!("b"))]));
+ let mut functor_writer = Heap::functor_writer(
+ functor!(
+ atom!("f"),
+ [atom_as_cell((atom!("a"))),
+ atom_as_cell((atom!("b")))]
+ ),
+ );
+
+ functor_writer(&mut wam.heap).unwrap();
- assert!(!wam.is_cyclic_term(str_loc_as_cell!(0)));
+ let h = wam.heap.cell_len();
+ wam.heap.push_cell(str_loc_as_cell!(0)).unwrap();
- all_cells_unmarked(&wam.heap);
+ assert!(!wam.is_cyclic_term(h));
- assert!(!wam.is_cyclic_term(heap_loc_as_cell!(1)));
+ all_cells_unmarked(wam.heap.splice(..));
- all_cells_unmarked(&wam.heap);
+ assert!(!wam.is_cyclic_term(1));
- assert!(!wam.is_cyclic_term(heap_loc_as_cell!(2)));
+ all_cells_unmarked(wam.heap.splice(..));
- all_cells_unmarked(&wam.heap);
+ assert!(!wam.is_cyclic_term(2));
+
+ all_cells_unmarked(wam.heap.splice(..));
wam.heap[2] = str_loc_as_cell!(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[1] = str_loc_as_cell!(0);
- assert!(wam.is_cyclic_term(str_loc_as_cell!(0)));
-
- all_cells_unmarked(&wam.heap);
-
- assert!(wam.is_cyclic_term(heap_loc_as_cell!(1)));
+ assert!(wam.is_cyclic_term(1));
- all_cells_unmarked(&wam.heap);
+ all_cells_unmarked(wam.heap.splice(..));
wam.heap.clear();
- wam.heap.push(pstr_as_cell!(atom!("a string")));
- wam.heap.push(empty_list_as_cell!());
+ let h = wam.heap.cell_len();
+ wam.allocate_cstr("a string").unwrap();
- assert!(!wam.is_cyclic_term(pstr_loc_as_cell!(0)));
+ assert!(!wam.is_cyclic_term(h));
}
}
#[inline(always)]
pub(crate) fn run_verify_attr_interrupt(&mut self, arity: usize) {
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 {
s,
)) => {
cell = self.deref_register(arg);
- self.machine_st
- .select_switch_on_term_index(cell, v, c, l, s)
+ self.machine_st.select_switch_on_term_index(cell, v, c, l, s)
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
- let lit = self.machine_st.constant_to_literal(cell);
- hm.get(&lit).cloned().unwrap_or(IndexingCodePtr::Fail)
+ // let lit = self.machine_st.constant_to_literal(cell);
+ hm.get(&cell).cloned().unwrap_or(IndexingCodePtr::Fail)
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(hm)) => {
self.machine_st.select_switch_on_structure_index(cell, hm)
if cell.is_var() {
offset += 1;
+ /*
} else if lit.get_tag() == HeapCellValueTag::CStr {
read_heap_cell!(cell,
(HeapCellValueTag::CStr) => {
return false;
}
);
+ */
} 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 {
self.machine_st.fail = false;
let cell = self.deref_register(t);
read_heap_cell!(cell,
- (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
+ (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {// | HeapCellValueTag::CStr) => {
offset += 1;
}
(HeapCellValueTag::Str, s) => {
}
&Instruction::GetPartialString(
Level::Shallow,
- string,
+ ref string,
RegType::Temp(t),
- has_tail,
+ // has_tail,
) => {
+ use crate::machine::partial_string::HeapPStrIter;
+
let cell = self.deref_register(t);
read_heap_cell!(cell,
- (HeapCellValueTag::CStr, cstr) => {
- if !has_tail && string != cstr {
+ (HeapCellValueTag::PStrLoc) => {
+ 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;
}
offset += 1;
+
}
- (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
+ (HeapCellValueTag::Lis) => {
offset += 1;
}
(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 {
offset += 1;
or_frame.prelude.boip = 0;
or_frame.prelude.biip = 0;
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.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
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;
or_frame.prelude.boip = self.machine_st.oip;
or_frame.prelude.biip = self.machine_st.iip + iip_offset; // 1
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.attr_var_queue_len =
self.machine_st.attr_var_init.attr_var_queue.len();
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.iip = 0;
use crate::atom_table::*;
-use crate::parser::ast::*;
use crate::machine::heap::*;
use crate::machine::machine_errors::CycleSearchResult;
use crate::machine::system_calls::BrentAlgState;
use crate::types::*;
-use std::cmp::Ordering;
use std::ops::Deref;
use std::str;
-#[derive(Copy, Clone, Debug)]
-pub struct PartialString(Atom);
-
-fn scan_for_terminator<Iter: Iterator<Item = char>>(iter: Iter) -> usize {
- let mut terminator_idx = 0;
-
- for c in iter {
- if c == '\u{0}' && terminator_idx != 0 {
- return terminator_idx;
- }
-
- terminator_idx += c.len_utf8();
- }
-
- terminator_idx
-}
-
-impl From<Atom> for PartialString {
- #[inline]
- fn from(buf: Atom) -> PartialString {
- PartialString(buf)
- }
-}
-
-impl From<PartialString> for Atom {
- #[inline]
- fn from(val: PartialString) -> Self {
- val.0
- }
-}
-
-impl PartialString {
- #[inline]
- pub(super) fn new<'a>(src: &'a str, atom_tbl: &AtomTable) -> Option<(Self, &'a str)> {
- let terminator_idx = scan_for_terminator(src.chars());
- let pstr = PartialString(AtomTable::build_with(atom_tbl, &src[..terminator_idx]));
- Some(if terminator_idx < src.as_bytes().len() {
- (pstr, &src[terminator_idx + 1..])
- } else {
- (pstr, "")
- })
- }
-
- #[inline(always)]
- pub(crate) fn as_str_from(&self, n: usize) -> AtomString {
- self.0.as_str().map(|str| &str[n..])
- }
-}
-
#[derive(Clone, Copy)]
pub struct HeapPStrIter<'a> {
- pub heap: &'a [HeapCellValue],
- pub focus: HeapCellValue,
+ pub heap: &'a Heap,
+ // pub focus: HeapCellValue,
orig_focus: usize,
brent_st: BrentAlgState,
stepper: fn(&mut HeapPStrIter<'a>) -> Option<PStrIteratee>,
}
#[derive(Debug, Clone, Copy)]
-pub struct PStrPrefixCmpResult {
- pub focus: usize,
- pub offset: usize,
- pub prefix_len: usize,
+pub enum PStrCmpResult<'a> {
+ ListMatch { list_loc: usize },
+ CompletePStrMatch { chars_matched: usize, pstr_loc: usize },
+ PartialPStrMatch { string: &'a str, var_loc: usize },
}
struct PStrIterStep {
next_hare: usize,
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum PStrIteratee {
+ Char { heap_loc: usize, value: char },
+ PStrSlice { slice_loc: usize, slice_len: usize },
+}
+
impl<'a> HeapPStrIter<'a> {
- pub fn new(heap: &'a [HeapCellValue], h: usize) -> Self {
- let value = heap[h];
+ pub fn new(heap: &'a Heap, orig_focus: usize) -> Self {
+ debug_assert!(heap[orig_focus].is_ref());
Self {
heap,
- focus: value,
- orig_focus: h,
- brent_st: BrentAlgState::new(h),
+ orig_focus,
+ brent_st: BrentAlgState::new(orig_focus),
stepper: HeapPStrIter::pre_cycle_discovery_stepper,
}
}
self.brent_st.hare
}
- #[inline(always)]
- pub fn at_string_terminator(&self) -> bool {
- self.focus.is_string_terminator(self.heap)
- }
+ pub fn compare_pstr_to_string<'b>(self, mut s: &'b str) -> Option<PStrCmpResult<'b>> {
+ let mut curr_hare = self.brent_st.hare;
- #[inline(always)]
- pub fn chars(mut self) -> PStrCharsIter<'a> {
- let item = self.next();
- PStrCharsIter { iter: self, item }
- }
+ while !s.is_empty() {
+ read_heap_cell!(self.heap[curr_hare],
+ (HeapCellValueTag::PStrLoc, h) => {
+ let t = self.heap.slice_to_str(h, self.heap.byte_len() - h);
- pub fn compare_pstr_to_string(&mut self, s: &str) -> Option<PStrPrefixCmpResult> {
- let mut result = PStrPrefixCmpResult {
- focus: self.brent_st.hare,
- offset: 0,
- prefix_len: 0,
- };
+ let mut bytes_matched = 0;
+ let mut chars_matched = 0;
- let mut final_result = None;
+ for (sc, tc) in s.chars().zip(t.chars()) {
+ if sc != tc {
+ if tc != '\u{0}' {
+ return None;
+ } else {
+ break;
+ }
+ }
- while let Some(PStrIterStep {
- iteratee,
- next_hare,
- }) = self.step(self.brent_st.hare)
- {
- self.brent_st.hare = next_hare;
- self.focus = self.heap[iteratee.focus()];
+ bytes_matched += sc.len_utf8();
+ chars_matched += 1;
+ }
- result.focus = iteratee.focus();
- result.offset = iteratee.offset();
+ s = &s[bytes_matched ..];
- match iteratee {
- PStrIteratee::Char(_, c1) => {
- if let Some(c2) = s[result.prefix_len..].chars().next() {
- if c1 != c2 {
- return None;
- } else {
- result.prefix_len += c1.len_utf8();
- result.offset += c1.len_utf8();
- }
+ if s.is_empty() {
+ return Some(PStrCmpResult::CompletePStrMatch { chars_matched, pstr_loc: h });
} else {
- final_result = Some(result);
- break;
+ let next_hare = Heap::neighboring_cell_offset(h + bytes_matched);
+ curr_hare = next_hare;
}
}
- PStrIteratee::PStrSegment(_, pstr_atom, n) => {
- let pstr = PartialString::from(pstr_atom);
- let t = pstr.as_str_from(n);
- let s = &s[result.prefix_len..];
-
- if s.len() >= t.len() {
- if s.starts_with(&*t) {
- result.prefix_len += t.len();
- result.offset += t.len();
- } else {
- return None;
- }
- } else if t.starts_with(s) {
- result.prefix_len += s.len();
- result.offset += s.len();
-
- final_result = Some(result);
- break;
- } else {
- return None;
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+ if h == curr_hare {
+ return Some(PStrCmpResult::PartialPStrMatch { string: s, var_loc: h });
}
+
+ curr_hare = h;
+ continue;
}
- }
+ _ => {
+ match self.step(curr_hare).ok() {
+ Some(PStrIterStep { iteratee, next_hare }) => {
+ let value = if let PStrIteratee::Char { value, .. } = iteratee {
+ value
+ } else {
+ unreachable!()
+ };
- if s.len() == result.prefix_len {
- final_result = Some(result);
- break;
- }
- }
+ let c = s.chars().next().unwrap();
- if let Some(result) = &final_result {
- if self.at_string_terminator() {
- self.focus = empty_list_as_cell!();
- self.brent_st.hare = result.focus;
- } else {
- read_heap_cell!(self.heap[result.focus],
- (HeapCellValueTag::Lis | HeapCellValueTag::Str | HeapCellValueTag::PStr) => {
- self.focus = self.heap[self.brent_st.hare];
- }
- _ => {
+ if c == value {
+ s = &s[c.len_utf8() ..];
+
+ if s.is_empty() {
+ return Some(
+ PStrCmpResult::ListMatch {
+ list_loc: next_hare,
+ }
+ );
+ }
+
+ curr_hare = next_hare;
+ } else {
+ return None;
+ }
+ }
+ None => {
+ return None;
+ }
}
- );
- }
+ }
+ );
}
- Some(result)
+ None
}
fn walk_hare_to_cycle_end(&mut self) {
self.brent_st.hare = self.step(self.brent_st.hare).unwrap().next_hare;
}
- self.focus = self.heap[orig_hare];
+ // self.focus = self.heap[orig_hare];
self.brent_st.hare = orig_hare;
}
pub fn to_string_mut(&mut self) -> String {
let mut buf = String::with_capacity(32);
- for iteratee in self.by_ref() {
+ while let Some(iteratee) = self.next() {
match iteratee {
- PStrIteratee::Char(_, c) => {
+ PStrIteratee::Char { value: c, .. } => {
buf.push(c);
}
- PStrIteratee::PStrSegment(_, pstr_atom, n) => {
- let pstr = PartialString::from(pstr_atom);
- buf += &*pstr.as_str_from(n);
+ PStrIteratee::PStrSlice {
+ slice_loc,
+ slice_len,
+ } => {
+ buf += self.heap.slice_to_str(slice_loc, slice_len);
}
}
}
buf
}
- #[inline]
- pub fn is_continuable(&self) -> bool {
- let mut focus = self.focus;
-
- loop {
- read_heap_cell!(focus,
- (HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
- return true;
- }
- (HeapCellValueTag::Atom, (name, arity)) => { // TODO: use Str here?
- return name == atom!(".") && arity == 2;
- }
- (HeapCellValueTag::Lis, h) => {
- let value = self.heap[h];
- let value = heap_bound_store(
- self.heap,
- heap_bound_deref(self.heap, value),
- );
-
- return read_heap_cell!(value,
- (HeapCellValueTag::Atom, (name, arity)) => {
- arity == 0 && name.as_char().is_some()
- }
- (HeapCellValueTag::Char) => {
- true
- }
- _ => {
- false
- }
- );
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- if focus == self.heap[h] {
- return false;
- }
-
- focus = self.heap[h];
- }
- _ => {
- return false;
- }
- );
- }
- }
-
- #[inline(always)]
- pub fn cycle_detected(&self) -> bool {
- self.stepper as usize == HeapPStrIter::post_cycle_discovery_stepper as usize
- }
-
- fn step(&self, mut curr_hare: usize) -> Option<PStrIterStep> {
+ // return the next step in the iteration or the updated curr_hare
+ // for the sake of pointing to the pstr tail
+ fn step(&self, mut curr_hare: usize) -> Result<PStrIterStep, usize> {
loop {
read_heap_cell!(self.heap[curr_hare],
- (HeapCellValueTag::CStr, cstr_atom) => {
- return if self.focus == empty_list_as_cell!() {
- None
- } else {
- Some(PStrIterStep {
- iteratee: PStrIteratee::PStrSegment(curr_hare, cstr_atom, 0),
- next_hare: curr_hare,
- })
- }
- }
(HeapCellValueTag::PStrLoc, h) => {
- curr_hare = h;
- }
- (HeapCellValueTag::PStr, pstr_atom) => {
- return Some(PStrIterStep {
- iteratee: PStrIteratee::PStrSegment(curr_hare, pstr_atom, 0),
- next_hare: curr_hare+1,
- });
- }
- (HeapCellValueTag::PStrOffset, pstr_offset) => {
- if self.focus == empty_list_as_cell!() {
- return None;
- }
-
- let pstr_atom = cell_as_atom!(self.heap[pstr_offset]);
- let n = cell_as_fixnum!(self.heap[curr_hare+1]).get_num() as usize;
+ let (s, tail_loc) = self.heap.scan_slice_to_str(h);
- return if self.heap[pstr_offset].get_tag() == HeapCellValueTag::CStr {
- Some(PStrIterStep {
- iteratee: PStrIteratee::PStrSegment(curr_hare, pstr_atom, n),
- next_hare: pstr_offset,
- })
- } else {
- Some(PStrIterStep {
- iteratee: PStrIteratee::PStrSegment(curr_hare, pstr_atom, n),
- next_hare: pstr_offset+1,
- })
- };
+ return Ok(PStrIterStep {
+ iteratee: PStrIteratee::PStrSlice { slice_loc: h, slice_len: s.len() },
+ next_hare: tail_loc,
+ });
}
(HeapCellValueTag::Lis, h) => {
let value = heap_bound_store(
);
return value.as_char().map(|c| PStrIterStep {
- iteratee: PStrIteratee::Char(curr_hare, c),
+ iteratee: PStrIteratee::Char { heap_loc: curr_hare, value: c },
next_hare: h+1,
- });
+ }).ok_or(curr_hare)
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
);
value.as_char().map(|c| PStrIterStep {
- iteratee: PStrIteratee::Char(curr_hare, c),
+ iteratee: PStrIteratee::Char { heap_loc: curr_hare, value: c },
next_hare: s+2,
- })
+ }).ok_or(curr_hare)
} else {
- None
+ Err(curr_hare)
};
}
(HeapCellValueTag::Atom, (_name, arity)) => {
debug_assert!(arity == 0);
- return None;
+ return Err(curr_hare);
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h == curr_hare {
- return None;
+ return Err(curr_hare);
}
curr_hare = h;
}
_ => {
- return None;
+ return Err(curr_hare);
}
);
}
iteratee,
next_hare,
} = match self.step(self.brent_st.hare) {
- Some(results) => results,
- None => {
+ Ok(results) => results,
+ Err(next_hare) => {
+ self.brent_st.hare = next_hare;
return None;
}
};
- self.focus = self.heap[iteratee.focus()];
-
- if self.at_string_terminator() {
- self.focus = empty_list_as_cell!();
- self.brent_st.hare = iteratee.focus();
-
- return Some(iteratee);
- }
-
match self.brent_st.step(next_hare) {
Some(cycle_result) => {
- debug_assert!(matches!(cycle_result, CycleSearchResult::Cyclic(..)));
+ debug_assert!(matches!(cycle_result, CycleSearchResult::Cyclic { .. }));
self.walk_hare_to_cycle_end();
self.stepper = HeapPStrIter::post_cycle_discovery_stepper;
}
None => {
- self.focus = self.heap[next_hare];
+ // self.focus = self.heap[next_hare];
}
}
iteratee,
next_hare,
} = match self.step(self.brent_st.hare) {
- Some(results) => results,
- None => {
+ Ok(results) => results,
+ Err(next_hare) => {
+ self.brent_st.hare = next_hare;
return None;
}
};
- self.focus = self.heap[next_hare];
+ // self.focus = self.heap[next_hare];
self.brent_st.hare = next_hare;
Some(iteratee)
}
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum PStrIteratee {
- Char(usize, char),
- PStrSegment(usize, Atom, usize),
-}
-
-impl PStrIteratee {
- #[inline]
- fn offset(&self) -> usize {
- match self {
- PStrIteratee::Char(_, _) => 0,
- PStrIteratee::PStrSegment(_, _, n) => *n,
- }
- }
- #[inline]
- fn focus(&self) -> usize {
- match self {
- PStrIteratee::Char(focus, _) => *focus,
- PStrIteratee::PStrSegment(focus, _, _) => *focus,
- }
+ pub(crate) fn is_cyclic(&self) -> bool {
+ self.stepper as usize == Self::post_cycle_discovery_stepper as usize
}
}
pub item: Option<PStrIteratee>,
}
-impl<'a> PStrCharsIter<'a> {
- pub fn peek(&self) -> Option<char> {
- if let Some(iteratee) = self.item {
- match iteratee {
- PStrIteratee::Char(_, c) => {
- return Some(c);
- }
- PStrIteratee::PStrSegment(_, pstr_atom, n) => {
- let pstr = PartialString::from(pstr_atom);
- return pstr.as_str_from(n).chars().next();
- }
- }
- }
-
- None
- }
-}
-
impl<'a> Deref for PStrCharsIter<'a> {
type Target = HeapPStrIter<'a>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(item) = self.item {
match item {
- PStrIteratee::Char(_, c) => {
+ PStrIteratee::Char { value, .. } => {
self.item = self.iter.next();
- return Some(c);
+ return Some(value);
}
- PStrIteratee::PStrSegment(f1, pstr_atom, n) => {
- let pstr = PartialString::from(pstr_atom);
+ PStrIteratee::PStrSlice { slice_loc, slice_len } => {
+ let s = self.iter.heap.slice_to_str(slice_loc, slice_len);
- match pstr.as_str_from(n).chars().next() {
+ match s.chars().next() {
Some(c) => {
- self.item =
- Some(PStrIteratee::PStrSegment(f1, pstr_atom, n + c.len_utf8()));
-
+ self.item = Some(PStrIteratee::PStrSlice {
+ slice_loc: slice_loc + c.len_utf8(),
+ slice_len: slice_len - c.len_utf8(),
+ });
return Some(c);
}
None => {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum PStrCmpResult {
- Ordered(Ordering),
- FirstIterContinuable(PStrIteratee),
- SecondIterContinuable(PStrIteratee),
- Unordered,
-}
-
-impl PStrCmpResult {
- #[inline]
- pub fn is_second_iter(&self) -> bool {
- matches!(self, PStrCmpResult::SecondIterContinuable(_))
- }
-}
-
-#[inline]
-pub fn compare_pstr_prefixes<'a>(
- i1: &mut HeapPStrIter<'a>,
- i2: &mut HeapPStrIter<'a>,
-) -> PStrCmpResult {
- #[inline(always)]
- fn step(iter: &mut HeapPStrIter, hare: usize) -> Option<PStrIterStep> {
- let result = iter.step(hare);
- iter.focus = iter.heap[hare];
-
- if iter.focus.is_string_terminator(iter.heap) {
- iter.focus = empty_list_as_cell!();
- }
-
- result
- }
-
- #[inline(always)]
- fn cycle_detection_step(i1: &mut HeapPStrIter, i2: &HeapPStrIter, step: &PStrIterStep) -> bool {
- if i1.cycle_detected() {
- i1.brent_st.hare = step.next_hare;
- i2.cycle_detected()
- } else if i1.brent_st.step(step.next_hare).is_some() {
- i1.stepper = HeapPStrIter::post_cycle_discovery_stepper;
- i2.cycle_detected()
- } else {
- false
- }
- }
-
- let mut r1 = step(i1, i1.brent_st.hare);
- let mut r2 = step(i2, i2.brent_st.hare);
-
- loop {
- if let Some(step_1) = r1.as_mut() {
- if let Some(step_2) = r2.as_mut() {
- match (step_1.iteratee, step_2.iteratee) {
- (PStrIteratee::Char(_, c1), PStrIteratee::Char(_, c2)) => {
- if c1 != c2 {
- return PStrCmpResult::Ordered(c1.cmp(&c2));
- }
-
- cycle_detection_step(i1, i2, step_1);
- let both_cyclic = cycle_detection_step(i2, i1, step_2);
-
- r1 = step(i1, i1.brent_st.hare);
- r2 = step(i2, i2.brent_st.hare);
-
- if !both_cyclic {
- continue;
- }
- }
- (PStrIteratee::Char(_, c1), PStrIteratee::PStrSegment(f2, pstr_atom, n)) => {
- let pstr = PartialString::from(pstr_atom);
-
- if let Some(c2) = pstr.as_str_from(n).chars().next() {
- if c1 != c2 {
- return PStrCmpResult::Ordered(c1.cmp(&c2));
- }
-
- let n1 = n + c2.len_utf8();
-
- if n1 < pstr_atom.len() {
- step_2.iteratee = PStrIteratee::PStrSegment(f2, pstr_atom, n1);
-
- let c1_result = cycle_detection_step(i1, i2, step_1);
- r1 = step(i1, i1.brent_st.hare);
-
- if !c1_result {
- continue;
- }
- } else {
- cycle_detection_step(i1, i2, step_1);
- let both_cyclic = cycle_detection_step(i2, i1, step_2);
-
- r1 = step(i1, i1.brent_st.hare);
- r2 = step(i2, i2.brent_st.hare);
-
- if !both_cyclic {
- continue;
- }
- }
- } else {
- let c2_result = cycle_detection_step(i2, i1, step_2);
- r2 = step(i2, i2.brent_st.hare);
-
- if !c2_result {
- continue;
- }
- }
- }
- (PStrIteratee::PStrSegment(f1, pstr_atom, n), PStrIteratee::Char(_, c2)) => {
- let pstr = PartialString::from(pstr_atom);
-
- if let Some(c1) = pstr.as_str_from(n).chars().next() {
- if c1 != c2 {
- return PStrCmpResult::Ordered(c1.cmp(&c2));
- }
-
- let n1 = n + c1.len_utf8();
-
- if n1 < pstr_atom.len() {
- step_1.iteratee = PStrIteratee::PStrSegment(f1, pstr_atom, n1);
-
- let c2_result = cycle_detection_step(i2, i1, step_2);
- r2 = step(i2, step_2.next_hare);
-
- if !c2_result {
- continue;
- }
- } else {
- cycle_detection_step(i1, i2, step_1);
- let both_cyclic = cycle_detection_step(i2, i1, step_2);
-
- r1 = step(i1, i1.brent_st.hare);
- r2 = step(i2, i2.brent_st.hare);
-
- if !both_cyclic {
- continue;
- }
- }
- } else {
- let c1_result = cycle_detection_step(i1, i2, step_1);
- r1 = step(i1, i1.brent_st.hare);
-
- if !c1_result {
- continue;
- }
- }
- }
- (
- PStrIteratee::PStrSegment(f1, pstr1_atom, n1),
- PStrIteratee::PStrSegment(f2, pstr2_atom, n2),
- ) => {
- if pstr1_atom == pstr2_atom && n1 == n2 {
- cycle_detection_step(i1, i2, step_1);
- let both_cyclic = cycle_detection_step(i2, i1, step_2);
-
- r1 = step(i1, i1.brent_st.hare);
- r2 = step(i2, i2.brent_st.hare);
-
- if !both_cyclic {
- continue;
- }
-
- break;
- }
-
- let pstr1 = PartialString::from(pstr1_atom);
- let pstr2 = PartialString::from(pstr2_atom);
-
- let str1 = pstr1.as_str_from(n1);
- let str2 = pstr2.as_str_from(n2);
-
- match str1.len().cmp(&str2.len()) {
- Ordering::Equal if *str1 == *str2 => {
- cycle_detection_step(i1, i2, step_1);
- let both_cyclic = cycle_detection_step(i2, i1, step_2);
-
- r1 = step(i1, i1.brent_st.hare);
- r2 = step(i2, i2.brent_st.hare);
-
- if !both_cyclic {
- continue;
- }
- }
- Ordering::Less if str2.starts_with(&*str1) => {
- step_2.iteratee =
- PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len());
- let c1_result = cycle_detection_step(i1, i2, step_1);
- r1 = step(i1, i1.brent_st.hare);
-
- if !c1_result {
- continue;
- }
- }
- Ordering::Greater if str1.starts_with(&*str2) => {
- step_1.iteratee =
- PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len());
- let c2_result = cycle_detection_step(i2, i1, step_2);
- r2 = step(i2, i2.brent_st.hare);
-
- if !c2_result {
- continue;
- }
- }
- _ => {
- return PStrCmpResult::Ordered(str1.cmp(&*str2));
- }
- }
- }
- }
- }
- }
-
- break;
- }
-
- // to have a cyclic term, the cell at i1.focus must be:
- //
- // 1) 'continuable' as a cell in a string traversal, and,
- // 2) matchable by compare_pstr_prefixes to the cell at i2.focus.
- //
- // If both cells are continuable they must have been encountered
- // and thus matched by the compare_pstr_prefixes loop previously,
- // so here it suffices to check if they are both continuable.
-
- let r1_at_end = r1.is_none();
- let r2_at_end = r2.is_none();
-
- if r1_at_end && r2_at_end {
- if i1.focus == i2.focus {
- PStrCmpResult::Ordered(Ordering::Equal)
- } else {
- PStrCmpResult::Unordered
- }
- } else if r1_at_end {
- if i1.focus == empty_list_as_cell!() {
- PStrCmpResult::Ordered(Ordering::Less)
- } else {
- let r2_step = r2.unwrap();
-
- // advance i2 to the next character so the same character
- // isn't repeated
- if matches!(r2_step.iteratee, PStrIteratee::Char(..)) {
- cycle_detection_step(i2, i1, &r2_step);
- }
-
- PStrCmpResult::SecondIterContinuable(r2_step.iteratee)
- }
- } else if r2_at_end {
- if i2.focus == empty_list_as_cell!() {
- PStrCmpResult::Ordered(Ordering::Greater)
- } else {
- let r1_step = r1.unwrap();
-
- // advance i1 to the next character so the same character
- // isn't repeated
- if matches!(r1_step.iteratee, PStrIteratee::Char(..)) {
- cycle_detection_step(i1, i2, &r1_step);
- }
-
- PStrCmpResult::FirstIterContinuable(r1_step.iteratee)
- }
- } else if i1.is_continuable() && i2.is_continuable() {
- PStrCmpResult::Ordered(Ordering::Equal)
- } else {
- PStrCmpResult::Unordered
- }
-}
-
#[cfg(test)]
mod test {
use super::*;
fn pstr_iter_tests() {
let mut wam = MockWAM::new();
- let pstr_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
+ let pstr_cell = wam.machine_st.allocate_pstr("abc ").unwrap();
+ wam.machine_st.heap.push_cell(empty_list_as_cell!()).unwrap();
- let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
+ // not overwriting anything! 0 is an interstitial cell
+ // reserved for use by the runtime
+ wam.machine_st.heap[0] = pstr_cell;
{
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
assert_eq!(
iter.next(),
- Some(PStrIteratee::PStrSegment(0, cell_as_atom!(pstr_cell), 0))
+ Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() }),
);
assert_eq!(iter.next(), None);
-
- assert!(!iter.at_string_terminator());
+ assert!(!iter.is_cyclic());
}
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(pstr_loc_as_cell!(2));
+ assert_eq!(wam.machine_st.heap[2], empty_list_as_cell!());
+
+ wam.machine_st.heap[2] = pstr_loc_as_cell!(heap_index!(3));
- let pstr_second_var_cell =
- put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
+ wam.machine_st.allocate_pstr("def").unwrap();
+ let h = wam.machine_st.heap.cell_len();
- let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
+ wam.machine_st.heap.push_cell(heap_loc_as_cell!(h)).unwrap();
{
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
assert_eq!(
iter.next(),
- Some(PStrIteratee::PStrSegment(0, cell_as_atom!(pstr_cell), 0))
+ Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
);
assert_eq!(
iter.next(),
- Some(PStrIteratee::PStrSegment(
- 2,
- cell_as_atom!(pstr_second_cell),
- 0
- ))
+ Some(PStrIteratee::PStrSlice {
+ slice_loc: heap_index!(3),
+ slice_len: "def".len(),
+ })
);
assert_eq!(iter.next(), None);
- assert!(!iter.at_string_terminator());
+ assert!(!iter.is_cyclic());
}
- wam.machine_st.heap.pop();
- wam.machine_st.heap.push(empty_list_as_cell!());
+ assert_eq!(wam.machine_st.heap[h], heap_loc_as_cell!(h));
+
+ wam.machine_st.heap[h] = empty_list_as_cell!();
{
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
assert_eq!(
iter.next(),
- Some(PStrIteratee::PStrSegment(0, cell_as_atom!(pstr_cell), 0))
+ Some(PStrIteratee::PStrSlice { slice_loc: heap_index!(1), slice_len: "abc ".len() })
);
assert_eq!(
iter.next(),
- Some(PStrIteratee::PStrSegment(
- 2,
- cell_as_atom!(pstr_second_cell),
- 0
- ))
+ Some(PStrIteratee::PStrSlice {
+ slice_loc: heap_index!(3),
+ slice_len: "def".len(),
+ })
);
assert_eq!(iter.next(), None);
- assert!(iter.at_string_terminator());
+ assert!(!iter.is_cyclic());
}
- 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(0)));
+ wam.machine_st.heap[h] = pstr_loc_as_cell!(heap_index!(3));
{
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
-
for _ in iter.by_ref() {}
-
- assert!(!iter.at_string_terminator());
- }
-
- {
- let mut iter1 = HeapPStrIter::new(&wam.machine_st.heap, 0);
- let mut iter2 = HeapPStrIter::new(&wam.machine_st.heap, 0);
-
- assert_eq!(
- compare_pstr_prefixes(&mut iter1, &mut iter2),
- PStrCmpResult::Ordered(Ordering::Equal)
- );
- }
-
- {
- let second_h = wam.machine_st.heap.len();
-
- // construct a structurally similar but different cyclic partial string
- // matching the one beginning at wam.machine_st.heap[0].
-
- put_partial_string(&mut wam.machine_st.heap, "ab", &wam.machine_st.atom_tbl);
-
- wam.machine_st.heap.pop();
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2));
-
- put_partial_string(&mut wam.machine_st.heap, "c ", &wam.machine_st.atom_tbl);
-
- wam.machine_st.heap.pop();
-
- wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 4));
-
- wam.machine_st.heap.push(pstr_second_cell);
- wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 6));
-
- wam.machine_st.heap.push(pstr_offset_as_cell!(second_h));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(0)));
-
- let mut iter1 = HeapPStrIter::new(&wam.machine_st.heap, 0);
- let mut iter2 = HeapPStrIter::new(&wam.machine_st.heap, second_h);
-
- assert_eq!(
- compare_pstr_prefixes(&mut iter1, &mut iter2),
- PStrCmpResult::Ordered(Ordering::Equal)
- );
- }
-
- wam.machine_st.heap.clear();
-
- put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
-
- let pstr_cell = wam.machine_st.heap[0];
-
- wam.machine_st.heap[1] = list_loc_as_cell!(2);
-
- wam.machine_st.heap.push(char_as_cell!('a'));
- wam.machine_st.heap.push(list_loc_as_cell!(4));
- wam.machine_st.heap.push(char_as_cell!('b'));
- wam.machine_st.heap.push(empty_list_as_cell!());
-
- wam.machine_st.heap.push(pstr_cell);
- wam.machine_st.heap.push(heap_loc_as_cell!(7));
-
- {
- let mut iter1 = HeapPStrIter::new(&wam.machine_st.heap, 0);
- let mut iter2 = HeapPStrIter::new(&wam.machine_st.heap, 6);
-
- assert_eq!(
- compare_pstr_prefixes(&mut iter1, &mut iter2),
- PStrCmpResult::FirstIterContinuable(PStrIteratee::Char(1, 'a')),
- );
-
- assert_eq!(iter2.focus, heap_loc_as_cell!(7));
+ assert!(iter.is_cyclic());
}
// test "abc" = [X,Y,Z].
wam.machine_st.heap.clear();
- let cstr_var_cell =
- put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
-
- wam.machine_st.heap.push(list_loc_as_cell!(2));
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
+ let pstr_cell = wam.machine_st.allocate_cstr("abc").unwrap();
+ let start = wam.machine_st.heap.cell_len();
- wam.machine_st.heap.push(list_loc_as_cell!(4));
- wam.machine_st.heap.push(heap_loc_as_cell!(4));
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- wam.machine_st.heap.push(list_loc_as_cell!(6));
- wam.machine_st.heap.push(heap_loc_as_cell!(6));
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1 + start));
+ section.push_cell(heap_loc_as_cell!(1 + start));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ section.push_cell(list_loc_as_cell!(3 + start));
+ section.push_cell(heap_loc_as_cell!(3 + start));
- unify!(wam.machine_st, cstr_var_cell, heap_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(5 + start));
+ section.push_cell(heap_loc_as_cell!(5 + start));
- assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
+ section.push_cell(empty_list_as_cell!());
+ });
- assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
+ unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(2));
- assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
+ assert_eq!(wam.machine_st.heap[1 + start], char_as_cell!('a'));
+ assert_eq!(wam.machine_st.heap[3 + start], char_as_cell!('b'));
+ assert_eq!(wam.machine_st.heap[5 + start], char_as_cell!('c'));
// test "abc" = [X,Y,Z|D].
wam.machine_st.heap.clear();
- let cstr_var_cell =
- put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
-
- wam.machine_st.heap.push(list_loc_as_cell!(2));
- wam.machine_st.heap.push(heap_loc_as_cell!(2)); // X
-
- wam.machine_st.heap.push(list_loc_as_cell!(4));
- wam.machine_st.heap.push(heap_loc_as_cell!(4)); // Y
+ let pstr_cell = wam.machine_st.allocate_cstr("abc").unwrap();
+ let start = wam.machine_st.heap.cell_len();
- wam.machine_st.heap.push(list_loc_as_cell!(6));
- wam.machine_st.heap.push(heap_loc_as_cell!(6)); // Z
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- wam.machine_st.heap.push(heap_loc_as_cell!(7)); // D
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1 + start));
+ section.push_cell(heap_loc_as_cell!(1 + start)); // X
- unify!(wam.machine_st, cstr_var_cell, heap_loc_as_cell!(1));
+ section.push_cell(list_loc_as_cell!(3 + start));
+ section.push_cell(heap_loc_as_cell!(3 + start)); // Y
- assert!(!wam.machine_st.fail);
+ section.push_cell(list_loc_as_cell!(5 + start));
+ section.push_cell(heap_loc_as_cell!(5 + start)); // Z
- assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
+ section.push_cell(heap_loc_as_cell!(6 + start)); // D
+ });
- assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
+ unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(2));
- assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
+ assert!(!wam.machine_st.fail);
- assert_eq!(wam.machine_st.heap[7], empty_list_as_cell!(),);
+ assert_eq!(wam.machine_st.heap[3], char_as_cell!('a'),);
+ assert_eq!(wam.machine_st.heap[5], char_as_cell!('b'),);
+ assert_eq!(wam.machine_st.heap[7], char_as_cell!('c'),);
+ assert_eq!(wam.machine_st.heap[8], empty_list_as_cell!(),);
// test "d" = [d].
wam.machine_st.heap.clear();
- let cstr_var_cell =
- put_complete_string(&mut wam.machine_st.heap, "d", &wam.machine_st.atom_tbl);
+ let pstr_cell = wam.machine_st.allocate_cstr("d").unwrap();
+ let start = wam.machine_st.heap.cell_len();
+
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- wam.machine_st.heap.push(list_loc_as_cell!(2));
- wam.machine_st.heap.push(char_as_cell!('d'));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1 + start));
+ section.push_cell(char_as_cell!('d'));
+ section.push_cell(empty_list_as_cell!());
+ });
- unify!(wam.machine_st, cstr_var_cell, heap_loc_as_cell!(1));
+ unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(start));
assert!(!wam.machine_st.fail);
wam.machine_st.heap.clear();
- let cstr_var_cell =
- put_complete_string(&mut wam.machine_st.heap, "abc", &wam.machine_st.atom_tbl);
+ let pstr_cell = wam.machine_st.allocate_cstr("abc").unwrap();
+ let start = wam.machine_st.heap.cell_len();
- wam.machine_st.heap.push(list_loc_as_cell!(2));
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- wam.machine_st.heap.push(list_loc_as_cell!(4));
- wam.machine_st.heap.push(char_as_cell!('b'));
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(1 + start));
+ section.push_cell(heap_loc_as_cell!(1 + start));
- wam.machine_st.heap.push(list_loc_as_cell!(6));
- wam.machine_st.heap.push(heap_loc_as_cell!(6));
+ section.push_cell(list_loc_as_cell!(3 + start));
+ section.push_cell(char_as_cell!('b'));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ section.push_cell(list_loc_as_cell!(5 + start));
+ section.push_cell(heap_loc_as_cell!(5 + start));
- unify!(wam.machine_st, cstr_var_cell, heap_loc_as_cell!(1));
-
- assert!(!wam.machine_st.fail);
+ section.push_cell(empty_list_as_cell!());
+ });
- assert_eq!(wam.machine_st.heap[2], char_as_cell!('a'),);
+ unify!(wam.machine_st, pstr_cell, heap_loc_as_cell!(start));
- assert_eq!(wam.machine_st.heap[4], char_as_cell!('b'),);
+ assert!(!wam.machine_st.fail);
- assert_eq!(wam.machine_st.heap[6], char_as_cell!('c'),);
+ assert_eq!(wam.machine_st.heap[1 + start], char_as_cell!('a'));
+ assert_eq!(wam.machine_st.heap[3 + start], char_as_cell!('b'));
+ assert_eq!(wam.machine_st.heap[5 + start], char_as_cell!('c'));
// test "abcdef" = [a,b,c|X].
wam.machine_st.heap.clear();
- put_complete_string(&mut wam.machine_st.heap, "abcdef", &wam.machine_st.atom_tbl);
+ let pstr_cell = wam.machine_st.allocate_cstr("abcdef").unwrap();
+ let start = wam.machine_st.heap.cell_len();
- wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
- wam.machine_st.heap.push(heap_loc_as_cell!(2));
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- unify!(wam.machine_st, heap_loc_as_cell!(0), pstr_loc_as_cell!(1));
+ writer.write_with(|section| {
+ section.push_pstr("abc");
+ let h = section.cell_len(); // h == 3
+ section.push_cell(heap_loc_as_cell!(h));
+ });
- print_heap_terms(wam.machine_st.heap.iter(), 0);
+ unify!(wam.machine_st, pstr_cell, pstr_loc_as_cell!(heap_index!(start)));
assert!(!wam.machine_st.fail);
- assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(5));
- assert_eq!(wam.machine_st.heap[3], pstr_loc_as_cell!(1));
- assert_eq!(wam.machine_st.heap[4], atom_as_cstr_cell!(atom!("abcdef")));
- assert_eq!(wam.machine_st.heap[5], pstr_offset_as_cell!(4));
assert_eq!(
- wam.machine_st.heap[6],
- fixnum_as_cell!(Fixnum::build_with("abc".len() as i64))
+ wam.machine_st.heap.slice_to_str(0, "abcdef".len()),
+ "abcdef"
+ );
+ assert_eq!(
+ wam.machine_st.heap.slice_to_str(heap_index!(start), "abc".len()),
+ "abc"
+ );
+ assert_eq!(
+ wam.machine_st.heap[3],
+ pstr_loc_as_cell!(heap_index!(0) + 3)
);
// test iteration on X = [b,c,b,c,b,c,b,c|...] as an offset.
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(pstr_as_cell!(atom!("abc")));
- wam.machine_st.heap.push(pstr_loc_as_cell!(2));
- wam.machine_st.heap.push(pstr_offset_as_cell!(0));
- wam.machine_st
- .heap
- .push(fixnum_as_cell!(Fixnum::build_with(1)));
+ wam.machine_st.allocate_cstr("abc").unwrap();
+ let start = wam.machine_st.heap.cell_len();
+
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(pstr_loc_as_cell!('a'.len_utf8()));
+ });
{
- let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 2);
+ let mut iter = HeapPStrIter::new(&wam.machine_st.heap, start);
assert_eq!(
iter.next(),
- Some(PStrIteratee::PStrSegment(2, atom!("abc"), 1))
+ Some(PStrIteratee::PStrSlice { slice_loc: 'a'.len_utf8(), slice_len: "bc".len() })
);
for _ in iter {}
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("a ")));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(char_as_cell!(' '));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ wam.machine_st.allocate_cstr("a ").unwrap();
+ let start = wam.machine_st.heap.cell_len();
+
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(start));
+ section.push_cell(list_loc_as_cell!(2 + start));
+ section.push_cell(char_as_cell!(' '));
+ section.push_cell(empty_list_as_cell!());
+ });
- unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+ unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
assert!(!wam.machine_st.fail);
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cstr_cell!(atom!(" a")));
- wam.machine_st.heap.push(char_as_cell!(' '));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ wam.machine_st.allocate_cstr(" a").unwrap();
+ let start = wam.machine_st.heap.cell_len();
- unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+ writer.write_with(|section| {
+ section.push_cell(char_as_cell!(' '));
+ section.push_cell(list_loc_as_cell!(2 + start));
+ section.push_cell(heap_loc_as_cell!(2 + start));
+ section.push_cell(empty_list_as_cell!());
+ });
+
+ unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+
+ assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
assert!(!wam.machine_st.fail);
// #2293, test3.
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("a b")));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(char_as_cell!(' '));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
- wam.machine_st.heap.push(heap_loc_as_cell!(5));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ wam.machine_st.allocate_cstr("a b").unwrap();
+ let start = wam.machine_st.heap.cell_len();
+
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(start));
+ section.push_cell(list_loc_as_cell!(2 + start));
+ section.push_cell(char_as_cell!(' '));
+ section.push_cell(list_loc_as_cell!(4 + start));
+ section.push_cell(heap_loc_as_cell!(4 + start));
+ section.push_cell(empty_list_as_cell!());
+ });
- unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+ unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+ assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
+ assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('b'));
assert!(!wam.machine_st.fail);
// #2293, test4.
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cstr_cell!(atom!(" a ")));
- wam.machine_st.heap.push(char_as_cell!(' '));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
- wam.machine_st.heap.push(char_as_cell!(' '));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ wam.machine_st.allocate_cstr(" a ").unwrap();
+ let start = wam.machine_st.heap.cell_len();
- unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+ writer.write_with(|section| {
+ section.push_cell(char_as_cell!(' '));
+ section.push_cell(list_loc_as_cell!(2 + start));
+ section.push_cell(heap_loc_as_cell!(2 + start));
+ section.push_cell(list_loc_as_cell!(4 + start));
+ section.push_cell(char_as_cell!(' '));
+ section.push_cell(empty_list_as_cell!());
+ });
+
+ unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+
+ assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
assert!(!wam.machine_st.fail);
// #2293, test5.
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cstr_cell!(atom!(" a bc")));
- wam.machine_st.heap.push(char_as_cell!(' '));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
- wam.machine_st.heap.push(char_as_cell!(' '));
- wam.machine_st.heap.push(heap_loc_as_cell!(6));
+ wam.machine_st.allocate_cstr(" a bc").unwrap();
+ let start = wam.machine_st.heap.cell_len();
+
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+ writer.write_with(|section| {
+ section.push_cell(char_as_cell!(' '));
+ section.push_cell(list_loc_as_cell!(2 + start));
+ section.push_cell(heap_loc_as_cell!(2 + start));
+ section.push_cell(list_loc_as_cell!(4 + start));
+ section.push_cell(char_as_cell!(' '));
+ section.push_cell(heap_loc_as_cell!(5 + start));
+ });
+ unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+
+ assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('a'));
+ assert_eq!(wam.machine_st.heap[5 + start], pstr_loc_as_cell!(heap_index!(0) + 3));
assert!(!wam.machine_st.fail);
// #2293, test6.
wam.machine_st.heap.clear();
- wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("abc")));
- wam.machine_st.heap.push(heap_loc_as_cell!(1));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(char_as_cell!('b'));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
- wam.machine_st.heap.push(heap_loc_as_cell!(5));
- wam.machine_st.heap.push(empty_list_as_cell!());
+ wam.machine_st.allocate_cstr("abc").unwrap();
+ let start = wam.machine_st.heap.cell_len();
+
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
- unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(start));
+ section.push_cell(list_loc_as_cell!(2 + start));
+ section.push_cell(char_as_cell!('b'));
+ section.push_cell(list_loc_as_cell!(4 + start));
+ section.push_cell(heap_loc_as_cell!(4 + start));
+ section.push_cell(empty_list_as_cell!());
+ });
+ unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+
+ assert_eq!(wam.machine_st.heap[start], char_as_cell!('a'));
+ assert_eq!(wam.machine_st.heap[4 + start], char_as_cell!('c'));
assert!(!wam.machine_st.fail);
// #2293, test7.
wam.machine_st.heap.clear();
-
- wam.machine_st.heap.push(atom_as_cstr_cell!(atom!("abcde")));
- wam.machine_st.heap.push(char_as_cell!('a'));
- wam.machine_st.heap.push(list_loc_as_cell!(3));
- wam.machine_st.heap.push(heap_loc_as_cell!(3));
- wam.machine_st.heap.push(list_loc_as_cell!(5));
- wam.machine_st.heap.push(char_as_cell!('c'));
- wam.machine_st.heap.push(list_loc_as_cell!(7));
- wam.machine_st.heap.push(heap_loc_as_cell!(7));
- wam.machine_st.heap.push(list_loc_as_cell!(9));
- wam.machine_st.heap.push(char_as_cell!('e'));
- wam.machine_st.heap.push(empty_list_as_cell!());
-
- unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
-
+ wam.machine_st.allocate_cstr("abcde").unwrap();
+
+ let start = wam.machine_st.heap.cell_len();
+ let mut writer = wam.machine_st.heap.reserve(16).unwrap();
+
+ writer.write_with(|section| {
+ section.push_cell(char_as_cell!('a'));
+ section.push_cell(list_loc_as_cell!(2 + start));
+ section.push_cell(heap_loc_as_cell!(2 + start));
+ section.push_cell(list_loc_as_cell!(4 + start));
+ section.push_cell(char_as_cell!('c'));
+ section.push_cell(list_loc_as_cell!(6 + start));
+ section.push_cell(heap_loc_as_cell!(6 + start));
+ section.push_cell(list_loc_as_cell!(8 + start));
+ section.push_cell(char_as_cell!('e'));
+ section.push_cell(empty_list_as_cell!());
+ });
+
+ unify!(wam.machine_st, list_loc_as_cell!(start), pstr_loc_as_cell!(0));
+
+ assert_eq!(wam.machine_st.heap[2 + start], char_as_cell!('b'));
+ assert_eq!(wam.machine_st.heap[6 + start], char_as_cell!('d'));
assert!(!wam.machine_st.fail);
}
}
use crate::forms::*;
use crate::instructions::*;
use crate::machine::disjuncts::*;
+use crate::machine::heap::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::CodeIndex;
fn setup_op_decl(term: &FocusedHeapRefMut) -> Result<OpDecl, CompilationError> {
let (focus, _cell) = subterm_index(term.heap, term.focus);
- let name = match term.name(focus+3) {
- Some(name) => name,
- None => return Err(CompilationError::InconsistentEntry),
+ let name = match term_predicate_key(term.heap, focus+3) {
+ Some((name, 0)) => name,
+ _ => {
+ return Err(CompilationError::InvalidDirective(
+ DirectiveError::InvalidOpDeclNameType(term.heap[focus+3]),
+ ));
+ }
};
- let spec = match term.name(focus+2) {
- Some(name) => name,
- None => return Err(CompilationError::InconsistentEntry),
+ let spec = match term_predicate_key(term.heap, focus+2) {
+ Some((name, _)) => name,
+ 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) => {
match u16::try_from(n.get_num()) {
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),
+ ));
}
);
}
fn setup_predicate_indicator(term: &FocusedHeapRefMut) -> Result<PredicateKey, CompilationError> {
- let name_opt = term.name(term.focus);
- let arity = term.arity(term.focus);
+ let key_opt = term_predicate_key(term.heap, 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 = match Number::try_from(term.deref_loc(arity_loc)) {
.ok_or(CompilationError::InvalidModuleExport)?;
let name_loc = term.nth_arg(term.focus, 1).unwrap();
- let name = term
- .name(name_loc)
+ let name = term_predicate_key(term.heap, name_loc)
+ .map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleExport)?;
- if name_opt == Some(atom!("/")) {
+ if matches!(key_opt, Some((atom!("/"), _))) {
Ok((name, arity))
} else {
Ok((name, arity + 2))
setup_predicate_indicator(term)
.map(ModuleExport::PredicateKey)
.or_else(|_| {
- let name_opt = term.name(term.focus);
- let arity = term.arity(term.focus);
+ let key_opt = term_predicate_key(term.heap, 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)?))
} else {
Err(CompilationError::InvalidModuleDecl)
let mut focus = term.focus;
loop {
- read_heap_cell!(term.heap[focus],
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- if h == focus {
- break;
- } else {
- focus = h;
- }
- }
- (HeapCellValueTag::Lis, l) => {
- let term = FocusedHeapRefMut {
- heap: term.heap,
- focus: l,
- };
- exports.push(setup_module_export(&term)?);
-
- focus = l + 1;
- }
- (HeapCellValueTag::Atom, (name, _arity)) => {
- if name == atom!("[]") {
- return Ok(exports);
- } else {
- break;
- }
- }
- _ => {
- break;
- }
- );
+ read_heap_cell!(term.heap[focus],
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+ if h == focus {
+ break;
+ } else {
+ focus = h;
+ }
+ }
+ (HeapCellValueTag::Lis, l) => {
+ let term = FocusedHeapRefMut {
+ heap: term.heap,
+ focus: l,
+ };
+
+ exports.push(setup_module_export(&term)?);
+ focus = l + 1;
+ }
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ if name == atom!("[]") {
+ return Ok(exports);
+ } else {
+ break;
+ }
+ }
+ _ => {
+ break;
+ }
+ );
}
Err(CompilationError::InvalidModuleDecl)
}
-fn setup_module_decl(term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
- let name = term
- .name(term.focus + 1)
+fn setup_module_decl(mut term: FocusedHeapRefMut) -> Result<ModuleDecl, CompilationError> {
+ let name = term_predicate_key(term.heap, term.focus + 1)
+ .map(|(name, _)| name)
.ok_or(CompilationError::InvalidModuleDecl)?;
- let export_list = FocusedHeapRefMut {
- heap: term.heap,
- focus: term.focus + 2,
- };
- let exports = setup_module_export_list(export_list)?;
+
+ term.focus = term.focus + 2;
+ let exports = setup_module_export_list(term)?;
Ok(ModuleDecl { name, exports })
}
heap: term.heap,
focus,
};
- exports.insert(setup_module_export(&term)?);
+ exports.insert(setup_module_export(&term)?);
focus = focus + 1;
}
*/
fn setup_meta_predicate<'a, LS: LoadState<'a>>(
- term: FocusedHeapRefMut,
+ term: TermWriteResult,
loader: &mut Loader<'a, LS>,
) -> Result<(Atom, Atom, Vec<MetaSpec>), CompilationError> {
fn get_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) => {
- 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) {
(atom!(":"), 2) => {
- let module_name = term.heap[s+1];
- let spec = term.heap[s+2];
+ let module_name = heap[s+1];
+ let spec = heap[s+2];
read_heap_cell!(module_name,
(HeapCellValueTag::Atom, (module_name, arity)) => {
if arity == 0 {
read_heap_cell!(spec,
(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();
- let term = FocusedHeapRefMut { heap: term.heap, focus: s };
+ let term = FocusedHeapRefMut { heap, focus: s };
return Ok((module_name, name, get_meta_specs(term, arity)?));
}
_ => {
);
}
_ => {
- 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();
- return Ok((module_name, name, get_meta_specs(term, arity)?));
+
+ return Ok((module_name, name, specs));
}
}
pub(super) fn setup_declaration<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
- term: FocusedHeapRefMut,
+ mut term: TermWriteResult,
) -> Result<Declaration, CompilationError> {
let mut focus = term.focus;
+ let machine_st = LS::machine_st(&mut loader.payload);
loop {
- read_heap_cell!(term.heap[focus],
+ let decl = machine_st.heap[focus];
+
+ read_heap_cell!(decl,
(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) {
(atom!("dynamic"), 1) => {
- let (name, arity) = setup_predicate_indicator(&term)?;
+ let (name, arity) = setup_predicate_indicator(&focused)?;
Ok(Declaration::Dynamic(name, arity))
}
(atom!("module"), 2) => {
- Ok(Declaration::Module(setup_module_decl(term)?))
+ Ok(Declaration::Module(setup_module_decl(focused)?))
}
(atom!("op"), 3) => {
- Ok(Declaration::Op(setup_op_decl(&term)?))
+ Ok(Declaration::Op(setup_op_decl(&focused)?))
}
(atom!("non_counted_backtracking"), 1) => {
- let focus = term.nth_arg(term.focus, 1).unwrap();
- let (name, arity) = setup_predicate_indicator(&FocusedHeapRefMut { heap: term.heap, focus })?;
+ focused.focus = focused.nth_arg(focused.focus, 1).unwrap();
+ let (name, arity) = setup_predicate_indicator(&focused)?;
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) => {
- let (name, exports) = setup_qualified_import(term)?;
-
+ let (name, exports) = setup_qualified_import(focused)?;
Ok(Declaration::UseQualifiedModule(name, exports))
}
(atom!("meta_predicate"), 1) => {
+ term.focus = focus;
let (module_name, name, meta_specs) = setup_meta_predicate(term, loader)?;
Ok(Declaration::MetaPredicate(module_name, name, meta_specs))
}
focus = h;
} else {
return Err(CompilationError::InvalidDirective(
- DirectiveError::ExpectedDirective(heap_loc_as_cell!(h)),
+ DirectiveError::ExpectedDirective(decl),
));
}
}
_ => {
return Err(CompilationError::InvalidDirective(
- DirectiveError::ExpectedDirective(term.heap[focus])
+ DirectiveError::ExpectedDirective(decl),
));
}
);
loader: &mut Loader<'a, LS>,
module_name: Atom,
arity: usize,
- term: &FocusedHeapRefMut,
+ term: &TermWriteResult,
meta_specs: Vec<MetaSpec>,
) -> IndexMap<usize, CodeIndex, FxBuildHasher> {
+ use crate::machine::heap::Heap;
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) {
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") {
continue;
}
- let arity = term.arity(subterm_loc);
-
struct QualifiedNameInfo {
module_name: Atom,
name: Atom,
+ arity: usize,
qualified_term_loc: usize,
}
fn get_qualified_name(
- term: &FocusedHeapRefMut,
+ heap: &Heap,
module_term_loc: usize,
qualified_term_loc: usize,
) -> Option<QualifiedNameInfo> {
- let (module_term_loc, _) = subterm_index(term.heap, module_term_loc);
- let (qualified_term_loc, _) = subterm_index(term.heap, qualified_term_loc);
+ let (module_term_loc, _) = subterm_index(heap, module_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)) => {
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 {
module_name,
name,
+ arity,
qualified_term_loc,
});
}
None
}
- let (subterm_loc, _) = subterm_index(term.heap, subterm_loc);
-
- let subterm_arity = term.arity(subterm_loc);
- let subterm_name_opt = term.name(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 (module_name, key, term_loc) =
- if subterm_name_opt == Some(atom!(":")) && subterm_arity == 2 {
- debug_assert_eq!(term.heap[subterm_loc].get_tag(), HeapCellValueTag::Atom);
-
- match get_qualified_name(term, subterm_loc + 1, subterm_loc + 2) {
+ if subterm_key_opt == Some((atom!(":"), 2)) {
+ match get_qualified_name(loader.machine_heap(), subterm_loc + 1, subterm_loc + 2) {
Some(QualifiedNameInfo {
module_name,
name,
+ arity,
qualified_term_loc,
}) => (
module_name,
- (name, term.arity(qualified_term_loc) + supp_args),
+ (name, arity + supp_args),
qualified_term_loc,
),
None => {
(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);
continue;
}
pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>(
loader: &mut Loader<'a, LS>,
key: PredicateKey,
- terms: FocusedHeapRefMut,
+ terms: &TermWriteResult,
term: HeapCellValue,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// 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);
if let Some(meta_specs) = loader.get_meta_specs(name, arity).cloned() {
let module_name = loader.payload.compilation_target.module_name();
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 {
ct: ClauseType::Named(key.1, key.0, idx),
- arity,
term,
code_indices,
call_policy,
QueryClause {
ct,
- arity: key.1,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
loader: &mut Loader<'a, LS>,
key: PredicateKey,
module_name: Atom,
- terms: FocusedHeapRefMut,
+ terms: &TermWriteResult,
term: HeapCellValue,
call_policy: CallPolicy,
) -> QueryClause {
// supplementary code vector indices are unnecessary for
// 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);
return QueryClause {
ct: ClauseType::Named(key.1, key.0, idx),
- arity,
term,
code_indices,
call_policy,
QueryClause {
ct,
- arity: key.1,
term,
code_indices: IndexMap::with_hasher(FxBuildHasher::default()),
call_policy,
Preprocessor { settings }
}
- pub fn setup_fact(
+ pub fn setup_fact<'a, LS: LoadState<'a>>(
&mut self,
- mut term: FocusedHeap,
+ loader: &mut Loader<'a, LS>,
+ term: TermWriteResult,
) -> Result<(Fact, VarData), CompilationError> {
- if term.name(term.focus).is_some() {
+ let heap = loader.machine_heap();
+
+ if term_predicate_key(heap, term.focus).is_some() {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
- let var_data = classifier.classify_fact(&mut term)?;
+ let var_data = classifier.classify_fact(loader, &term)?;
- Ok((Fact { term }, var_data))
+ Ok((Fact { term_loc: term.focus }, var_data))
} else {
Err(CompilationError::InadmissibleFact)
}
fn setup_rule<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
- mut term: FocusedHeap,
+ term: TermWriteResult,
) -> Result<(Rule, VarData), CompilationError> {
let classifier = VariableClassifier::new(self.settings.default_call_policy());
- let (clauses, var_data) = classifier.classify_rule(loader, &mut term)?;
- let head_loc = term.nth_arg(term.focus, 1).unwrap();
+ let (clauses, var_data) = classifier.classify_rule(loader, &term)?;
+
+ let heap = loader.machine_heap();
+ let head_loc = term_nth_arg(heap, term.focus, 1).unwrap();
- if term.name(head_loc).is_some() {
- Ok((Rule { term, clauses }, var_data))
+ if term_predicate_key(heap, head_loc).is_some() {
+ Ok((Rule { term_loc: term.focus, clauses }, var_data))
} else {
Err(CompilationError::InvalidRuleHead)
}
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
&mut self,
loader: &mut Loader<'a, LS>,
- term: FocusedHeap,
- ) -> Result<TopLevel, CompilationError> {
- let name = term.name(term.focus);
- let arity = term.arity(term.focus);
+ term: TermWriteResult,
+ ) -> Result<PredicateClause, CompilationError> {
+ let heap = &LS::machine_st(&mut loader.payload).heap;
- match (name, arity) {
- (Some(atom!(":-")), 2) => {
+ match term_predicate_key(heap, term.focus) {
+ Some((atom!(":-"), 2)) => {
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)?;
- Ok(TopLevel::Fact(fact, var_data))
+ let (fact, var_data) = self.setup_fact(loader, term)?;
+ Ok(PredicateClause::Fact(fact, var_data))
}
}
}
use crate::arena::*;
use crate::atom_table::*;
+use crate::functor_macro::*;
use crate::parser::ast::*;
use crate::parser::char_reader::*;
use crate::read::*;
#[cfg(feature = "http")]
use crate::http::HttpResponse;
-use crate::machine::heap::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
#[inline]
pub fn get_alias(self) -> Option<Atom> {
if self.has_alias() {
- Some(Atom::from(self.alias() << 3))
+ Some(Atom::from(self.alias()))
} else {
None
}
self.set_has_alias(alias.is_some());
if let Some(alias) = alias {
- self.set_alias(alias.flat_index());
+ self.set_alias(alias.index);
}
}
}
let err = self.permission_error(
Permission::Open,
atom!("source_sink"),
- functor!(atom!("alias"), [atom(alias)]),
+ functor!(atom!("alias"), [atom_as_cell(alias)]),
);
self.error_form(err, stub)
pub(crate) fn reposition_error(&mut self, stub_name: Atom, stub_arity: usize) -> MachineStub {
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);
self.error_form(err, stub)
use crate::parser::ast::*;
+use crate::parser::lexer::LexerParser;
use crate::parser::parser::*;
use base64::Engine;
#[cfg(feature = "ffi")]
use crate::ffi::*;
use crate::forms::*;
+use crate::functor_macro::*;
use crate::heap_iter::*;
use crate::heap_print::*;
#[cfg(feature = "http")]
use fxhash::{FxBuildHasher, FxHasher};
use indexmap::IndexSet;
-use std::cell::Cell;
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::env;
}
impl ModuleQuantification {
- fn to_functor(&self) -> (Vec<HeapCellValue>, HeapCellValueTag) {
+ fn to_functor(&self) -> Vec<FunctorElement> {
match self {
- &ModuleQuantification::Specified(cell) => (
- functor!(atom!("specified"), [cell(cell)]),
- HeapCellValueTag::Str,
- ),
- ModuleQuantification::Unspecified => {
- (functor!(atom!("unspecified")), HeapCellValueTag::Var)
- }
+ &ModuleQuantification::Specified(cell) => functor!(atom!("specified"), [cell(cell)]),
+ ModuleQuantification::Unspecified => functor!(atom!("unspecified")),
}
}
key
}
+fn pstr_segment_char_count_and_tail(heap: &Heap, pstr_loc: usize) -> (usize, usize) {
+ let char_iter = heap.char_iter(pstr_loc);
+
+ let mut char_count = 0;
+ let mut byte_offset = 0;
+
+ for c in char_iter {
+ if c == '\u{0}' {
+ break;
+ }
+
+ char_count += 1;
+ byte_offset += c.len_utf8();
+ }
+
+ (
+ char_count,
+ Heap::neighboring_cell_offset(pstr_loc + byte_offset),
+ )
+}
+
+fn pstr_segment_char_count_up_to(
+ heap: &Heap,
+ pstr_loc: usize,
+ max_chars: usize,
+) -> PStrSegmentCountResult {
+ let mut char_iter = heap.char_iter(pstr_loc);
+ let mut char_count = 0;
+ let mut byte_offset = 0;
+
+ if max_chars > 0 {
+ while let Some(c) = char_iter.next() {
+ if c == '\u{0}' {
+ break;
+ }
+
+ char_count += 1;
+ byte_offset += c.len_utf8();
+
+ if char_count >= max_chars {
+ break;
+ }
+ }
+ }
+
+ if char_iter.next().is_some() {
+ PStrSegmentCountResult::Mid {
+ char_count,
+ pstr_loc: pstr_loc + byte_offset,
+ }
+ } else {
+ let tail_loc = Heap::neighboring_cell_offset(pstr_loc + byte_offset);
+ PStrSegmentCountResult::End {
+ char_count,
+ tail_loc,
+ }
+ }
+}
+
#[derive(Debug, Clone, Copy)]
pub struct BrentAlgState {
pub hare: usize,
self.lam += 1;
if self.tortoise == self.hare {
- return Some(CycleSearchResult::Cyclic(self.lam));
+ return Some(CycleSearchResult::Cyclic { lambda: self.lam });
} else {
self.teleport_tortoise();
}
self.max_steps > -1 && self.num_steps() as i64 >= self.max_steps
}
- pub fn to_result(mut self, heap: &[HeapCellValue]) -> CycleSearchResult {
+ pub fn to_result(mut self, heap: &Heap) -> CycleSearchResult {
loop {
read_heap_cell!(heap[self.hare],
- (HeapCellValueTag::PStrOffset) => {
- let (pstr_loc, offset) = pstr_loc_and_offset(heap, self.hare);
- let offset = offset.get_num() as usize;
-
- let pstr = cell_as_string!(heap[self.hare]);
- self.pstr_chars += pstr.as_str_from(offset).chars().count();
-
- return CycleSearchResult::PStrLocation(self.num_steps(), pstr_loc, offset);
- }
- (HeapCellValueTag::PStrLoc, l) => {
- let (_pstr_loc, offset) = pstr_loc_and_offset(heap, l);
- let offset = offset.get_num() as usize;
- return CycleSearchResult::PStrLocation(self.num_steps(), l, offset);
+ (HeapCellValueTag::PStrLoc) => {
+ // let (_pstr_loc, offset) = pstr_loc_and_offset(heap, l);
+ // let offset = offset.get_num() as usize;
+ let num_steps = self.num_steps();
+ return CycleSearchResult::PStrLocation { num_steps, pstr_loc: heap[self.hare] };
}
(HeapCellValueTag::Atom, (name, arity)) => {
return if name == atom!("[]") && arity == 0 {
- CycleSearchResult::ProperList(self.num_steps())
+ CycleSearchResult::ProperList { num_steps: self.num_steps() }
} else {
- CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
+ let heap_loc = if arity > 0 {
+ str_loc_as_cell!(self.hare)
+ } else {
+ heap_loc_as_cell!(self.hare)
+ };
+
+ CycleSearchResult::NotList { num_steps: self.num_steps(), heap_loc }
};
}
(HeapCellValueTag::Str, s) => {
.get_name_and_arity();
return if name == atom!("[]") && arity == 0 {
- CycleSearchResult::ProperList(self.num_steps())
+ CycleSearchResult::ProperList { num_steps: self.num_steps() }
} else {
- CycleSearchResult::NotList(self.num_steps(), heap[self.hare])
+ CycleSearchResult::NotList {
+ num_steps: self.num_steps(),
+ heap_loc: heap[self.hare],
+ }
};
}
(HeapCellValueTag::Lis, l) => {
- return CycleSearchResult::UntouchedList(self.num_steps(), l);
+ return CycleSearchResult::UntouchedList { num_steps: self.num_steps(), list_loc: l };
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if h == self.hare {
- let var = heap[self.hare].as_var().unwrap();
- return CycleSearchResult::PartialList(self.num_steps(), var);
+ // let var = heap[self.hare].as_var().unwrap();
+ return CycleSearchResult::PartialList {
+ num_steps: self.num_steps(),
+ heap_loc: heap[self.hare],
+ };
} else {
self.hare = h;
}
}
_ => {
- return CycleSearchResult::NotList(self.num_steps(), heap[self.hare]);
+ let heap_loc = heap_loc_as_cell!(self.hare);
+ return CycleSearchResult::NotList { num_steps: self.num_steps(), heap_loc };
}
);
}
}
- fn add_pstr_offset_chars(
- &mut self,
- heap: &[HeapCellValue],
- h: usize,
- offset: usize,
- ) -> Option<CycleSearchResult> {
- read_heap_cell!(heap[h],
- (HeapCellValueTag::CStr, cstr_atom) => {
- let cstr = PartialString::from(cstr_atom);
- let num_chars = cstr.as_str_from(offset).chars().count();
+ fn add_pstr_chars(&mut self, heap: &Heap, pstr_loc: usize) -> Option<CycleSearchResult> {
+ let next_cell_loc;
- if self.max_steps == -1 || self.num_steps() + num_chars <= self.max_steps as usize {
- self.pstr_chars += num_chars;
- Some(CycleSearchResult::ProperList(self.num_steps()))
- } else {
- let char_offset = self.max_steps as usize - self.num_steps();
- self.pstr_chars += char_offset;
- Some(CycleSearchResult::PStrLocation(self.max_steps as usize, h, char_offset + offset))
- }
- }
- (HeapCellValueTag::PStr, pstr_atom) => {
- let pstr = PartialString::from(pstr_atom);
- let num_chars = pstr.as_str_from(offset).chars().count();
+ if self.max_steps == -1 {
+ let num_chars;
+ (num_chars, next_cell_loc) = pstr_segment_char_count_and_tail(heap, pstr_loc);
+ self.pstr_chars += num_chars - 1;
+ } else {
+ let max_chars = self.max_steps as usize - self.num_steps();
- if self.max_steps == -1 || self.num_steps() + num_chars <= self.max_steps as usize {
- self.pstr_chars += num_chars - 1;
- self.step(h+1)
- } else {
- let char_offset = self.max_steps as usize - self.num_steps();
- self.pstr_chars += char_offset;
- Some(CycleSearchResult::PStrLocation(self.max_steps as usize, h, char_offset + offset))
+ match pstr_segment_char_count_up_to(heap, pstr_loc, max_chars) {
+ PStrSegmentCountResult::Mid {
+ char_count,
+ pstr_loc,
+ } => {
+ self.pstr_chars += char_count;
+ return Some(CycleSearchResult::PStrLocation {
+ num_steps: self.num_steps(),
+ pstr_loc: pstr_loc_as_cell!(pstr_loc),
+ });
+ }
+ PStrSegmentCountResult::End {
+ char_count,
+ tail_loc,
+ } => {
+ self.pstr_chars += char_count.saturating_sub(1);
+ next_cell_loc = tail_loc;
}
}
- _ => {
- unreachable!()
- }
- )
- }
+ }
- fn add_pstr_chars_and_step(
- &mut self,
- heap: &[HeapCellValue],
- h: usize,
- ) -> Option<CycleSearchResult> {
- read_heap_cell!(heap[h],
- (HeapCellValueTag::PStrOffset, l) => {
- let (pstr_loc, _) = pstr_loc_and_offset(heap, l);
- let offset = cell_as_fixnum!(heap[h+1]);
- self.add_pstr_offset_chars(heap, pstr_loc, offset.get_num() as usize)
- }
- _ => {
- self.add_pstr_offset_chars(heap, h, 0)
- }
- )
+ self.step(next_cell_loc)
}
#[inline(always)]
- fn cycle_step(&mut self, heap: &[HeapCellValue]) -> Option<CycleSearchResult> {
+ fn cycle_step(&mut self, heap: &Heap) -> Option<CycleSearchResult> {
loop {
let value = heap[self.hare];
read_heap_cell!(value,
(HeapCellValueTag::PStrLoc, h) => {
- return self.add_pstr_chars_and_step(heap, h);
- }
- (HeapCellValueTag::CStr | HeapCellValueTag::PStrOffset) => {
- return self.add_pstr_chars_and_step(heap, self.hare);
+ return self.add_pstr_chars(heap, h);
}
(HeapCellValueTag::Lis, h) => {
return self.step(h+1);
return if name == atom!(".") && arity == 2 {
self.step(s+2)
} else {
- Some(CycleSearchResult::NotList(self.num_steps(), value))
+ Some(CycleSearchResult::NotList { num_steps: self.num_steps(), heap_loc: value })
};
}
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert!(arity == 0);
return if name == atom!("[]") {
- Some(CycleSearchResult::ProperList(self.num_steps()))
+ Some(CycleSearchResult::ProperList { num_steps: self.num_steps() })
} else {
- Some(CycleSearchResult::NotList(self.num_steps(), value))
+ Some(CycleSearchResult::NotList { num_steps: self.num_steps(), heap_loc: value })
};
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if self.hare == h {
- let r = value.as_var().unwrap();
- return Some(CycleSearchResult::PartialList(self.num_steps(), r));
+ return Some(CycleSearchResult::PartialList { num_steps: self.num_steps(), heap_loc: value });
}
self.hare = h;
}
_ => {
- return Some(CycleSearchResult::NotList(self.num_steps(), value));
+ return Some(CycleSearchResult::NotList { num_steps: self.num_steps(), heap_loc: value });
}
);
}
}
- pub fn detect_cycles(heap: &[HeapCellValue], value: HeapCellValue) -> CycleSearchResult {
- let mut pstr_chars = 0;
+ pub fn detect_cycles(heap: &Heap, value: HeapCellValue) -> CycleSearchResult {
+ let mut char_count = 0;
let hare = read_heap_cell!(value,
(HeapCellValueTag::Lis, offset) => {
offset+1
}
(HeapCellValueTag::PStrLoc, h) => {
- let (h_offset, n) = pstr_loc_and_offset(heap, h);
- let n = n.get_num() as usize;
- let pstr = cell_as_string!(heap[h_offset]);
-
- pstr_chars = pstr.as_str_from(n).chars().count() - 1;
-
- if heap[h].get_tag() == HeapCellValueTag::PStrOffset {
- debug_assert!(heap[h].get_tag() == HeapCellValueTag::PStrOffset);
+ let tail_idx;
+ (char_count, tail_idx) = pstr_segment_char_count_and_tail(heap, h);
- if heap[h_offset].get_tag() == HeapCellValueTag::CStr {
- return CycleSearchResult::ProperList(pstr_chars + 1);
- }
+ if heap[tail_idx] == empty_list_as_cell!() {
+ return CycleSearchResult::ProperList { num_steps: char_count };
}
- h_offset+1
- }
- (HeapCellValueTag::PStrOffset) => {
- unreachable!()
- }
- (HeapCellValueTag::CStr, cstr_atom) => {
- let cstr = PartialString::from(cstr_atom);
- return CycleSearchResult::ProperList(cstr.as_str_from(0).chars().count());
+ char_count = char_count.saturating_sub(1);
+ tail_idx
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(heap[s])
} else if name == atom!(".") && arity == 2 {
s + 2
} else {
- return CycleSearchResult::NotList(0, value);
+ return CycleSearchResult::NotList { num_steps: 0, heap_loc: value };
}
}
(HeapCellValueTag::Atom, (name, arity)) => {
return if name == atom!("[]") && arity == 0 {
CycleSearchResult::EmptyList
} else {
- CycleSearchResult::NotList(0, value)
+ debug_assert_eq!(arity, 0);
+ CycleSearchResult::NotList { num_steps: 0, heap_loc: value }
};
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar | HeapCellValueTag::Var) => {
- return CycleSearchResult::PartialList(0, value.as_var().unwrap());
+ return CycleSearchResult::PartialList { num_steps: 0, heap_loc: value };
}
_ => {
- return CycleSearchResult::NotList(0, value);
+ return CycleSearchResult::NotList { num_steps: 0, heap_loc: value };
}
);
let mut brent_st = BrentAlgState::new(hare);
brent_st.power += 1; // advance a step.
- brent_st.pstr_chars = pstr_chars;
+ brent_st.pstr_chars = char_count;
loop {
if let Some(result) = brent_st.cycle_step(heap) {
}
pub fn detect_cycles_with_max(
- heap: &[HeapCellValue],
+ heap: &Heap,
max_steps: usize,
value: HeapCellValue,
) -> CycleSearchResult {
- let mut pstr_chars = 0;
+ let mut char_count = 0;
let hare = read_heap_cell!(value,
(HeapCellValueTag::Lis, offset) => {
if max_steps > 0 {
offset+1
} else {
- return CycleSearchResult::UntouchedList(0, offset);
+ return CycleSearchResult::UntouchedList { num_steps: 0, list_loc: offset };
}
}
(HeapCellValueTag::PStrLoc, h) => {
- let (h_offset, n) = pstr_loc_and_offset(heap, h);
- let n = n.get_num() as usize;
- let pstr = cell_as_string!(heap[h_offset]);
-
- pstr_chars = pstr.as_str_from(n).chars().count() - 1;
-
- if heap[h].get_tag() == HeapCellValueTag::PStrOffset && heap[h_offset].get_tag() == HeapCellValueTag::CStr {
- return if pstr_chars < max_steps {
- CycleSearchResult::ProperList(pstr_chars + 1)
- } else {
- let offset = max_steps + n;
- CycleSearchResult::PStrLocation(max_steps, h_offset, offset)
+ match pstr_segment_char_count_up_to(heap, h, max_steps) {
+ PStrSegmentCountResult::Mid { char_count, pstr_loc } => {
+ let pstr_loc = pstr_loc_as_cell!(pstr_loc);
+ return CycleSearchResult::PStrLocation { num_steps: char_count, pstr_loc };
}
- }
-
- if pstr_chars + 1 > max_steps {
- return CycleSearchResult::PStrLocation(max_steps, h_offset, max_steps);
- }
-
- h_offset+1
- }
- (HeapCellValueTag::PStrOffset) => {
- unreachable!()
- }
- (HeapCellValueTag::CStr, cstr_atom) => {
- return if max_steps > 0 {
- let cstr = PartialString::from(cstr_atom);
- let pstr_chars = cstr.as_str_from(0).chars().count();
-
- if pstr_chars <= max_steps {
- CycleSearchResult::ProperList(pstr_chars)
- } else {
- CycleSearchResult::UntouchedCStr(cstr_atom, max_steps)
+ PStrSegmentCountResult::End { char_count: num_chars, tail_loc } => {
+ char_count = num_chars - 1;
+ tail_loc
}
- } else {
- CycleSearchResult::UntouchedCStr(cstr_atom, 0)
- };
+ }
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
if max_steps > 0 {
s + 2
} else {
- return CycleSearchResult::UntouchedList(0, s + 1);
+ return CycleSearchResult::UntouchedList { num_steps: 0, list_loc: s + 1 };
}
} else {
- return CycleSearchResult::NotList(0, value);
+ return CycleSearchResult::NotList { num_steps: 0, heap_loc: value };
}
}
(HeapCellValueTag::Atom, (name, arity)) => {
return if name == atom!("[]") && arity == 0 {
CycleSearchResult::EmptyList
} else {
- CycleSearchResult::NotList(0, value)
+ debug_assert_eq!(arity, 0);
+ CycleSearchResult::NotList { num_steps: 0, heap_loc: value }
};
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar | HeapCellValueTag::Var) => {
- return CycleSearchResult::PartialList(0, value.as_var().unwrap());
+ return CycleSearchResult::PartialList { num_steps: 0, heap_loc: value };
}
_ => {
- return CycleSearchResult::NotList(0, value);
+ return CycleSearchResult::NotList { num_steps: 0, heap_loc: value };
}
);
let mut brent_st = BrentAlgState::new(hare);
brent_st.power += 1; // advance a step.
- brent_st.pstr_chars = pstr_chars;
+ brent_st.pstr_chars = char_count;
brent_st.max_steps = max_steps as i64;
loop {
Match(usize), // a match
}
+#[derive(Debug)]
+enum PStrSegmentCountResult {
+ Mid { char_count: usize, pstr_loc: usize },
+ End { char_count: usize, tail_loc: usize },
+}
+
#[derive(Debug)]
struct AttrListMatch {
match_site: MatchSite,
);
}
- pub(crate) fn get_attr_var_list(&mut self, attr_var: HeapCellValue) -> Option<usize> {
+ pub(crate) fn get_attr_var_list(
+ &mut self,
+ attr_var: HeapCellValue,
+ ) -> Result<Option<usize>, usize> {
read_heap_cell!(attr_var,
(HeapCellValueTag::AttrVar, h) => {
- Some(h + 1)
+ Ok(Some(h + 1))
}
(HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
// create an AttrVar in the heap.
- let h = self.heap.len();
+ let h = self.heap.cell_len();
+ let mut writer = self.heap.reserve(2)?;
- self.heap.push(attr_var_as_cell!(h));
- self.heap.push(heap_loc_as_cell!(h+1));
+ writer.write_with(|section| {
+ section.push_cell(attr_var_as_cell!(h));
+ section.push_cell(heap_loc_as_cell!(h+1));
+ });
self.bind(Ref::attr_var(h), attr_var);
-
- Some(h + 1)
+ Ok(Some(h + 1))
}
_ => {
- None
+ Ok(None)
}
)
}
}
fn skip_max_list_cycle(&mut self, lam: usize) {
- fn step(heap: &[HeapCellValue], mut value: HeapCellValue) -> usize {
+ fn step(heap: &Heap, mut value: HeapCellValue) -> usize {
loop {
read_heap_cell!(value,
(HeapCellValueTag::PStrLoc, h) => {
- let (h_offset, _) = pstr_loc_and_offset(heap, h);
- return h_offset+1;
+ let (_, tail) = heap.scan_slice_to_str(h);
+ // let (h_offset, _) = pstr_loc_and_offset(heap, h);
+ return tail;
}
(HeapCellValueTag::Lis, h) => {
return h+1;
}
}
- let h = self.heap.len();
- self.heap.push(self.registers[3]);
+ // let h = self.heap.cell_len();
+ // self.heap.push(self.registers[3]);
- let mut hare = h;
+ let orig_hare = step(&self.heap, self.registers[3]);
+ let mut hare = orig_hare;
let mut tortoise = hare;
- for _ in 0..lam {
+ for _ in 1..lam {
hare = step(&self.heap, self.heap[hare]);
}
// reached in the fashion of a C do-while loop since hare
// may point to the beginning of a cycle.
- let mut brent_st = BrentAlgState::new(h);
+ let mut brent_st = BrentAlgState::new(orig_hare);
brent_st.cycle_step(&self.heap);
brent_st.cycle_step(&self.heap);
}
- self.heap.pop();
+ // self.heap.pop_cell();
let target_n = self.store(self.deref(self.registers[1]));
self.unify_fixnum(Fixnum::build_with(brent_st.num_steps() as i64), target_n);
}
fn skip_max_list_result(&mut self, max_steps: i64) {
+ let cell = self.store(self.deref(self.registers[3]));
+
let search_result = if max_steps == -1 {
- BrentAlgState::detect_cycles(&self.heap, self.store(self.deref(self.registers[3])))
+ BrentAlgState::detect_cycles(&self.heap, cell)
} else {
- BrentAlgState::detect_cycles_with_max(
- &self.heap,
- max_steps as usize,
- self.store(self.deref(self.registers[3])),
- )
+ BrentAlgState::detect_cycles_with_max(&self.heap, max_steps as usize, cell)
};
match search_result {
- CycleSearchResult::PStrLocation(steps, pstr_loc, offset) => {
+ CycleSearchResult::PStrLocation {
+ num_steps,
+ pstr_loc,
+ } => {
let steps = if max_steps > -1 {
- std::cmp::min(max_steps, steps as i64)
+ std::cmp::min(max_steps, num_steps as i64)
} else {
- steps as i64
+ max_steps as i64
};
- let cell = if offset > 0 {
- let h = self.heap.len();
- let (pstr_loc, _) = pstr_loc_and_offset(&self.heap, pstr_loc);
-
- self.heap.push(pstr_offset_as_cell!(pstr_loc));
- self.heap
- .push(fixnum_as_cell!(Fixnum::build_with(offset as i64)));
-
- pstr_loc_as_cell!(h)
- } else {
- pstr_loc_as_cell!(pstr_loc)
- };
-
- self.finalize_skip_max_list(steps, cell);
- }
- CycleSearchResult::UntouchedList(n, l) => {
- self.finalize_skip_max_list(n as i64, list_loc_as_cell!(l));
+ self.finalize_skip_max_list(steps, pstr_loc); // cell);
}
- CycleSearchResult::UntouchedCStr(cstr_atom, n) => {
- let cell = if n > 0 {
- let h = self.heap.len();
-
- self.heap.push(string_as_cstr_cell!(cstr_atom));
- self.heap.push(pstr_offset_as_cell!(h));
- self.heap
- .push(fixnum_as_cell!(Fixnum::build_with(n as i64)));
-
- pstr_loc_as_cell!(h + 1)
- } else {
- string_as_cstr_cell!(cstr_atom)
- };
-
- self.finalize_skip_max_list(n as i64, cell);
+ CycleSearchResult::UntouchedList {
+ num_steps,
+ list_loc: l,
+ } => {
+ self.finalize_skip_max_list(num_steps as i64, list_loc_as_cell!(l));
}
CycleSearchResult::EmptyList => {
self.finalize_skip_max_list(0, empty_list_as_cell!());
}
- CycleSearchResult::PartialList(n, r) => {
- self.finalize_skip_max_list(n as i64, r.as_heap_cell_value());
+ CycleSearchResult::PartialList {
+ num_steps,
+ heap_loc,
+ } => self.finalize_skip_max_list(num_steps as i64, heap_loc),
+ CycleSearchResult::ProperList { num_steps } => {
+ self.finalize_skip_max_list(num_steps as i64, empty_list_as_cell!())
}
- CycleSearchResult::ProperList(steps) => {
- self.finalize_skip_max_list(steps as i64, empty_list_as_cell!())
+ CycleSearchResult::NotList {
+ num_steps,
+ heap_loc,
+ } => {
+ self.finalize_skip_max_list(num_steps as i64, heap_loc);
}
- CycleSearchResult::NotList(n, value) => {
- self.finalize_skip_max_list(n as i64, value);
- }
- CycleSearchResult::Cyclic(lam) => {
- self.skip_max_list_cycle(lam);
+ CycleSearchResult::Cyclic { lambda } => {
+ self.skip_max_list_cycle(lambda);
}
};
}
) {
let mut seen_set = IndexSet::new();
- let outcome = if term.is_ref() {
- {
- let mut iter = stackful_post_order_iter::<NonListElider>(
- &mut self.heap, &mut self.stack, term.get_value() as usize,
- );
+ if term.is_ref() {
+ let mut iter = stackful_post_order_iter::<NonListElider>(
+ &mut self.heap,
+ &mut self.stack,
+ term.get_value() as usize,
+ );
- while let Some(value) = iter.next() {
- if iter.parent_stack_len() >= max_depth {
- iter.pop_stack();
- continue;
- }
+ while let Some(value) = iter.next() {
+ if iter.parent_stack_len() >= max_depth {
+ iter.pop_stack();
+ continue;
+ }
- let value = unmark_cell_bits!(value);
+ let value = unmark_cell_bits!(value);
- if value.is_var() {
- seen_set.insert(value);
- }
+ if value.is_var() {
+ seen_set.insert(value);
}
}
+ }
- heap_loc_as_cell!(iter_to_heap_list(&mut self.heap, seen_set.into_iter()))
- } else {
- empty_list_as_cell!()
- };
+ let outcome = step_or_resource_error!(
+ self,
+ sized_iter_to_heap_list(&mut self.heap, seen_set.len(), seen_set.into_iter(),)
+ );
unify_fn!(*self, list_of_vars, outcome);
}
&mut self,
lh_offset: usize,
copy_target: HeapCellValue,
- ) -> usize {
- let threshold = self.lifted_heap.len() - lh_offset;
+ ) -> Result<usize, usize> {
+ let threshold = self.lifted_heap.cell_len() - lh_offset;
let mut copy_ball_term = CopyBallTerm::new(
&mut self.attr_var_init.attr_var_queue,
&mut self.lifted_heap,
);
- copy_ball_term.push(list_loc_as_cell!(threshold + 1));
- copy_ball_term.push(heap_loc_as_cell!(threshold + 3));
- copy_ball_term.push(heap_loc_as_cell!(threshold + 2));
+ let mut writer = copy_ball_term.reserve(3)?;
+
+ writer.write_with(|section| {
+ section.push_cell(list_loc_as_cell!(threshold + 1));
+ section.push_cell(heap_loc_as_cell!(threshold + 3));
+ section.push_cell(heap_loc_as_cell!(threshold + 2));
+ });
- copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy);
+ copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?;
- threshold + lh_offset + 2
+ Ok(threshold + lh_offset + 2)
}
#[inline(always)]
(HeapCellValueTag::Fixnum, n) => {
let lh_offset = n.get_num() as usize;
- if lh_offset >= self.lifted_heap.len() {
+ if lh_offset >= self.lifted_heap.cell_len() {
self.lifted_heap.truncate(lh_offset);
} else {
- let threshold = self.lifted_heap.len() - lh_offset;
- self.lifted_heap.push(addr_constr(threshold));
+ let threshold = self.lifted_heap.cell_len() - lh_offset;
+ step_or_resource_error!(
+ self,
+ self.lifted_heap.push_cell(addr_constr(threshold))
+ );
}
}
_ => {
&mut self,
string: &str,
indices: &IndexStore,
- stub_gen: impl Fn() -> FunctorStub,
+ stub_gen: impl Fn() -> MachineStub,
) -> CallResult {
use crate::parser::lexer::*;
let nx = self.store(self.deref(self.registers[2]));
let iter = std::io::Cursor::new(string);
- let mut lexer = Lexer::new(CharReader::new(iter), self);
+ let mut lexer_parser = LexerParser::new(CharReader::new(iter), self);
let mut tokens = vec![];
match lexer.next_number_token() {
}
loop {
- match lexer.lookahead_char() {
+ match lexer_parser.lookahead_char() {
Err(e) if e.is_unexpected_eof() => {
- let mut parser = Parser::from_lexer(lexer);
let op_dir = CompositeOpDir::new(&indices.op_dir, None);
tokens.reverse();
+ let byte_size = heap_index!(tokens.len());
- match parser.read_term(&op_dir, Tokens::Provided(tokens)) {
+ match lexer_parser.read_term(&op_dir, Tokens::Provided(tokens, byte_size)) {
Ok(term) => {
- let mut error_gen = || {
- let e = ParserError::ParseBigInt(ParserErrorSrc::default());
- let e = self.syntax_error(e);
-
- return Err(self.error_form(e, stub_gen()));
- };
-
- read_heap_cell!(term.heap[term.focus],
+ read_heap_cell!(lexer_parser.machine_st.heap[term.focus],
(HeapCellValueTag::Cons, c) => {
match_untyped_arena_ptr!(c,
(ArenaHeaderTag::Rational, n) => {
self.unify_big_int(n, nx);
}
_ => {
- return error_gen();
+ let e = ParserError::ParseBigInt(lexer_parser.loc_to_err_src());
+ let e = self.syntax_error(e);
+
+ return Err(self.error_form(e, stub_gen()));
}
)
}
self.unify_fixnum(n, nx);
}
_ => {
- return error_gen();
+ let e = ParserError::ParseBigInt(lexer_parser.loc_to_err_src());
+ let e = self.syntax_error(e);
+
+ return Err(self.error_form(e, stub_gen()));
}
);
+
+ return Ok(());
}
Err(e) => {
let e = self.syntax_error(e);
return Err(self.error_form(e, stub_gen()));
}
}
-
- break;
}
Ok(c) => {
- let err_src = lexer.loc_to_err_src();
+ let err_src = lexer_parser.loc_to_err_src();
let err = ParserError::UnexpectedChar(c, err_src);
let err = self.syntax_error(err);
Err(_) => unreachable!(),
}
}
-
- Ok(())
}
pub(crate) fn call_continuation_chunk(
pub fn value_to_str_like(&mut self, value: HeapCellValue) -> Option<AtomOrString> {
read_heap_cell!(value,
+ /*
(HeapCellValueTag::CStr, cstr_atom) => {
// avoid allocating a String if possible:
// We must be careful to preserve the string "[]" as is,
Some(AtomOrString::Atom(cstr_atom))
}
}
+ */
(HeapCellValueTag::Atom, (atom, arity)) => {
if arity == 0 {
// ... likewise.
None
}
}
- (HeapCellValueTag::Char, c) => {
- Some(AtomOrString::String(c.to_string()))
- }
_ => {
if value.is_constant() {
return None;
}
- let h = self.heap.len();
- self.heap.push(value);
+ // 0 is reserved for use by the machine. See
+ // MachineState::new.
+ self.heap[0] = value;
- let mut iter = HeapPStrIter::new(&self.heap, h);
+ let mut iter = HeapPStrIter::new(&self.heap, 0);
let string = iter.to_string_mut();
- let at_terminator = iter.at_string_terminator();
-
- self.heap.pop();
+ let end_cell = iter.heap[iter.focus()];
// if the iteration doesn't terminate like a string
// (i.e. with the [] atom or a CStr), it is not
// "str_like" so return None.
- if at_terminator {
+ if end_cell.is_string_terminator(iter.heap) {
Some(AtomOrString::String(string))
} else {
None
pub(crate) fn codes_to_string(
&mut self,
addrs: impl Iterator<Item = HeapCellValue>,
- stub_gen: impl Fn() -> FunctorStub,
+ stub_gen: impl Fn() -> MachineStub,
) -> Result<String, MachineStub> {
let mut string = String::new();
boip + extract_ptr!(hm.get(&key).cloned().unwrap())
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
- boip + extract_ptr!(hm.get(&Literal::Atom(key.0)).cloned().unwrap())
+ boip + extract_ptr!(hm.get(&atom_as_cell!(key.0)).cloned().unwrap())
}
_ => boip,
};
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
.get_name_and_arity();
- (name, arity, if self.machine_st.heap.len() > s + arity + 1 {
- get_structure_index(self.machine_st.heap[s + arity + 1])
+ (name, arity, if self.machine_st.heap.cell_len() > s + arity + 1 {
+ if !self.machine_st.heap.pstr_at(s + arity + 1) {
+ get_structure_index(self.machine_st.heap[s + arity + 1])
+ } else {
+ None
+ }
} else {
None
})
}
};
- // println!("(fast) calling {}/{}", name.as_str(), arity);
-
if let Some(code_index) = index_cell {
if !code_index.is_undefined() {
+ // println!("(fast) calling {}/{}", name.as_str(), arity);
load_registers(&mut self.machine_st, goal, goal_arity);
self.machine_st.neck_cut();
return call_at_index(self, name, arity, code_index.get());
// disjoint from them. if they are not, the
// expanded goal is not simple.
- let post_supp_args = self.machine_st.heap[s+arity-supp_vars.len()+1 .. s+arity+1]
- .iter()
- .cloned();
+ let post_supp_args = self.machine_st.heap.splice(s+arity-supp_vars.len()+1 .. s+arity+1);
post_supp_args
.zip(supp_vars.iter())
};
let goal = if is_simple_goal {
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
let arity = arity - supp_vars.len();
- for idx in 0 .. arity + 1 {
- let value = self.machine_st.heap[s + idx];
- self.machine_st.heap.push(value);
- }
+ resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.heap.copy_slice_to_end(
+ s .. s + arity + 1
+ )
+ );
self.machine_st.heap[h] = atom_as_cell!(name, arity);
+ // even if arity == 0, goal must be a Str cell,
+ // since an index is about to appended to it.
str_loc_as_cell!(h)
} else {
goal
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(goal);
+ let h = self.machine_st.heap.cell_len();
+ resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.heap.push_cell(goal)
+ );
GoalAnalysisResult {
is_simple_goal: true,
supp_vars,
}
}
+ /*
(HeapCellValueTag::Char, c) => {
let name = AtomTable::build_with(&self.machine_st.atom_tbl,&c.to_string());
+ let h = self.machine_st.heap.cell_len();
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(atom_as_cell!(name));
+ resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.heap.push_cell(atom_as_cell!(name))
+ );
GoalAnalysisResult {
is_simple_goal: true,
supp_vars,
}
}
+ */
_ => {
self.machine_st.fail = true;
return Ok(());
let expanded_term = if result.is_simple_goal {
let idx = self.get_or_insert_qualified_code_index(module_name, result.key);
- self.machine_st
- .heap
- .push(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
+
+ resource_error_call_result!(
+ self.machine_st,
+ self.machine_st
+ .heap
+ .push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)))
+ );
+
result.goal
} else {
let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default());
Err(e) => {
let err = self.machine_st.session_error(e);
let stub = functor_stub(atom!("call"), result.key.1);
-
return Err(self.machine_st.error_form(err, stub));
}
Ok(()) => {
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
+ let mut writer = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.heap.reserve(unexpanded_vars.len() + 2)
+ );
- self.machine_st.heap.push(atom_as_cell!(atom!("$aux"), 0));
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("$aux"), 0));
- for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
- self.machine_st.heap.push(value);
- }
+ for value in unexpanded_vars.difference(&result.supp_vars).cloned() {
+ section.push_cell(value);
+ }
- let anon_str_arity = self.machine_st.heap.len() - h - 1;
+ section.push_cell(atom_as_cell!(atom!("[]")));
+ });
+ let anon_str_arity = self.machine_st.heap.cell_len() - h - 2;
self.machine_st.heap[h] = atom_as_cell!(atom!("$aux"), anon_str_arity);
let idx = CodeIndex::new(
&mut self.machine_st.arena,
);
- self.machine_st
- .heap
- .push(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)));
+ self.machine_st.heap.last_cell_mut().map(|cell| {
+ *cell = untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx));
+ });
str_loc_as_cell!(h)
}
return false;
}
- if self.machine_st.heap.len() > s + 1 + arity {
+ if self.machine_st.heap.cell_len() > s + 1 + arity {
+ if self.machine_st.heap.pstr_at(s + 1 + arity) {
+ return false;
+ }
+
let idx_cell = self.machine_st.heap[s + 1 + arity];
if HeapCellValueTag::Cons == idx_cell.get_tag() {
let target_module_loc = self.machine_st.registers[2];
- let (functor_stub, ref_cell_tag) = module_quantification.to_functor();
-
- let h = self.machine_st.heap.len();
- let ref_cell = HeapCellValue::build_with(ref_cell_tag, h as u64);
+ let functor_stub = module_quantification.to_functor();
+ let mut functor_writer = Heap::functor_writer(functor_stub);
- self.machine_st.heap.extend(functor_stub);
+ let cell = functor_writer(&mut self.machine_st.heap).unwrap();
+ unify_fn!(&mut self.machine_st, cell, target_module_loc);
- unify_fn!(&mut self.machine_st, ref_cell, target_module_loc);
-
- let target_qualified_goal = self.machine_st.registers[3];
-
- unify_fn!(&mut self.machine_st, qualified_goal, target_qualified_goal);
+ if !self.machine_st.fail {
+ let target_qualified_goal = self.machine_st.registers[3];
+ unify_fn!(&mut self.machine_st, qualified_goal, target_qualified_goal);
+ }
}
#[inline(always)]
let target_goal = if arity == 0 {
qualified_goal
} else {
- // if narity + arity > 0 {
- let h = self.machine_st.heap.len();
- self.machine_st
- .heap
- .push(atom_as_cell!(name, narity + arity));
+ let h = self.machine_st.heap.cell_len();
- for idx in 1..narity + 1 {
- self.machine_st.heap.push(self.machine_st.heap[s + idx]);
- }
+ let mut writer = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.heap.reserve(1 + narity + arity)
+ );
- for idx in 1..arity + 1 {
- self.machine_st
- .heap
- .push(self.machine_st.registers[2 + idx]);
- }
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(name, narity + arity));
+
+ for idx in 1..narity + 1 {
+ section.push_cell(section[s + idx]);
+ }
+
+ for idx in 1..arity + 1 {
+ section.push_cell(self.machine_st.registers[2 + idx]);
+ }
+ });
if narity + arity > 0 {
str_loc_as_cell!(h)
};
let target_qualified_goal = self.machine_st.registers[1];
-
unify_fn!(&mut self.machine_st, target_goal, target_qualified_goal);
-
Ok(())
}
module_name
}
_ => {
- let h = self.machine_st.heap.len();
- let call_form = functor!(atom!(":"), [cell(module_name), cell(self.machine_st.registers[2])]);
+ let goal = self.machine_st.registers[2];
+ let mut functor_writer = Heap::functor_writer(
+ functor!(atom!(":"), [cell(module_name), cell(goal)]),
+ );
- self.machine_st.heap.extend(call_form);
+ let goal = resource_error_call_result!(
+ self.machine_st,
+ functor_writer(&mut self.machine_st.heap)
+ );
- let err = self.machine_st.type_error(ValidType::Callable, str_loc_as_cell!(h));
+ let err = self.machine_st.type_error(ValidType::Callable, goal);
let stub = functor_stub(atom!("call"), narity + 1);
return Err(self.machine_st.error_form(err, stub));
for entry in entries {
if let Ok(entry) = entry {
if let Some(name) = entry.file_name().to_str() {
- let name = AtomTable::build_with(&self.machine_st.atom_tbl, name);
- files.push(atom_as_cstr_cell!(name));
+ let file_string_cell = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(name)
+ );
+ files.push(file_string_cell);
continue;
}
}
return Err(err);
}
- let files_list = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- files.into_iter()
- ));
+ let files_list_cell = resource_error_call_result!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ files.len(),
+ files.into_iter()
+ )
+ );
- unify!(self.machine_st, self.machine_st.registers[2], files_list);
+ unify!(
+ self.machine_st,
+ self.machine_st.registers[2],
+ files_list_cell
+ );
return Ok(());
}
}
unreachable!()
}
} {
- let chars_atom = self.systemtime_to_timestamp(time);
+ let chars_string = self.systemtime_to_timestamp(time);
- self.machine_st
- .unify_complete_string(chars_atom, self.machine_st.registers[3]);
+ let cstr_cell = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(&chars_string)
+ );
+ unify!(self.machine_st, cstr_cell, self.machine_st.registers[3]);
return;
}
}
}
};
- let current_atom = AtomTable::build_with(&self.machine_st.atom_tbl, current);
+ let current_string = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(current)
+ );
- let a1 = self.deref_register(1);
- self.machine_st.unify_complete_string(current_atom, a1);
+ unify!(
+ self.machine_st,
+ current_string,
+ self.machine_st.registers[1]
+ );
if self.machine_st.fail {
return Ok(());
}
};
- let canonical_atom = AtomTable::build_with(&self.machine_st.atom_tbl, cs);
-
- let a2 = self.deref_register(2);
- self.machine_st.unify_complete_string(canonical_atom, a2);
+ let canonical_string =
+ resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(cs));
+ unify!(
+ self.machine_st,
+ canonical_string,
+ self.machine_st.registers[2]
+ );
return Ok(());
}
}
#[inline(always)]
pub(crate) fn atom_chars(&mut self) {
let a1 = self.deref_register(1);
- let a2 = self.deref_register(2);
read_heap_cell!(a1,
+ /*
(HeapCellValueTag::Char) => {
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
- self.machine_st.heap.push(a1);
- self.machine_st.heap.push(empty_list_as_cell!());
+ let mut writer = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.heap.reserve(2)
+ );
- unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
- }
- (HeapCellValueTag::Str, s) => {
- let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
- .get_name_and_arity();
+ step_or_resource_error!(
+ self.machine_st,
+ writer.write_with(|section| {
+ section.push_cell(a1);
+ section.push_cell(empty_list_as_cell!());
+ Ok::<(), usize>(())
+ })
+ );
- if arity == 0 {
- self.machine_st.unify_complete_string(
- name,
- a2,
- );
- } else {
- self.machine_st.fail = true;
- }
+ unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
}
+ */
(HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- self.machine_st.unify_complete_string(
- name,
- a2,
- );
- } else {
- self.machine_st.fail = true;
- }
+ debug_assert_eq!(arity, 0);
+
+ let cell = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(&*name.as_str())
+ );
+
+ unify!(self.machine_st, self.machine_st.registers[2], cell);
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let a2 = self.deref_register(2);
self.machine_st.fail = true;
}
_ => {
- unreachable!();
+ self.machine_st.fail = true;
}
);
}
let a1 = self.deref_register(1);
read_heap_cell!(a1,
+ /*
(HeapCellValueTag::Char, c) => {
let h = self.machine_st.heap.len();
unify!(self.machine_st, list_loc_as_cell!(h), self.machine_st.registers[2]);
}
+ */
(HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- let name = name.as_str();
- let iter = name.chars()
- .map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
+ debug_assert_eq!(arity, 0);
- let h = iter_to_heap_list(&mut self.machine_st.heap, iter);
- unify!(self.machine_st, heap_loc_as_cell!(h), self.machine_st.registers[2]);
- } else {
- self.machine_st.fail = true;
- }
+ let name = name.as_str();
+ let iter = name.chars().map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
+
+ let list_cell = resource_error_call_result!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ (&*name).chars().count(),
+ iter,
+ )
+ );
+
+ unify!(self.machine_st, list_cell, self.machine_st.registers[2]);
}
+ /*
(HeapCellValueTag::Str, s) => {
+ /*
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
.get_name_and_arity();
if arity == 0 {
let name = name.as_str();
- let iter = name.chars()
- .map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
+ let iter = name.chars().map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
- let h = iter_to_heap_list(&mut self.machine_st.heap, iter);
- unify!(self.machine_st, heap_loc_as_cell!(h), self.machine_st.registers[2]);
+ let list_cell = resource_error_call_result!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ name.as_str().chars().count(),
+ iter,
+ )
+ );
+
+ unify!(self.machine_st, list_cell, self.machine_st.registers[2]);
} else {
- self.machine_st.fail = true;
- }
+ */
+ self.machine_st.fail = true;
+ // }
}
+ */
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let stub_gen = || functor_stub(atom!("atom_codes"), 2);
return;
}
}
+ /*
(HeapCellValueTag::Char) => {
1
}
+ */
_ => {
unreachable!()
}
return;
}
- let pstr_h = self.machine_st.heap.len();
+ let pstr_h = self.machine_st.heap.cell_len();
+
+ let pstr_loc_cell = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_pstr(&*atom.as_str())
+ );
- self.machine_st.heap.push(pstr_as_cell!(atom));
- self.machine_st.heap.push(heap_loc_as_cell!(pstr_h + 1));
+ let tail_loc = Heap::neighboring_cell_offset(atom.as_str().len() + heap_index!(pstr_h));
- unify!(
+ step_or_resource_error!(
self.machine_st,
- self.machine_st.registers[2],
- pstr_loc_as_cell!(pstr_h)
+ self.machine_st.heap.push_cell(heap_loc_as_cell!(tail_loc))
);
+ unify!(self.machine_st, self.machine_st.registers[2], pstr_loc_cell);
+
if !self.machine_st.fail {
let tail = self.machine_st.registers[3];
- unify!(self.machine_st, tail, heap_loc_as_cell!(pstr_h + 1));
+ unify!(self.machine_st, tail, heap_loc_as_cell!(tail_loc));
}
}
pub(crate) fn is_partial_string(&mut self) {
let value = self.deref_register(1);
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(value);
-
- let mut iter = HeapPStrIter::new(&self.machine_st.heap, h);
+ if value.is_constant() {
+ self.machine_st.fail = empty_list_as_cell!() != value;
+ } else {
+ self.machine_st.heap[0] = value;
+ let mut iter = HeapPStrIter::new(&self.machine_st.heap, 0);
- for _ in iter.by_ref() {}
+ for _ in iter.by_ref() {}
- let at_end_of_pstr = iter.focus.is_var() || iter.at_string_terminator();
- self.machine_st.fail = !at_end_of_pstr;
+ let focus = iter.focus();
+ let end_cell = self.machine_st.heap[focus];
+ let at_end_of_pstr =
+ end_cell.is_var() || end_cell.is_string_terminator(&self.machine_st.heap);
- self.machine_st.heap.pop();
+ self.machine_st.fail = !at_end_of_pstr;
+ }
}
#[inline(always)]
read_heap_cell!(pstr,
(HeapCellValueTag::PStrLoc, h) => {
- let (h, _) = pstr_loc_and_offset(&self.machine_st.heap, h);
-
- if HeapCellValueTag::CStr == self.machine_st.heap[h].get_tag() {
- self.machine_st.unify_atom(
- atom!("[]"),
- a2
- );
- } else {
- unify_fn!(
- self.machine_st,
- heap_loc_as_cell!(h+1),
- a2
- );
- }
- }
- (HeapCellValueTag::CStr) => {
- self.machine_st.unify_atom(
- atom!("[]"),
- a2
- );
+ let (_, tail_loc) = self.machine_st.heap.scan_slice_to_str(h);
+ unify_fn!(self.machine_st, heap_loc_as_cell!(tail_loc), a2);
}
(HeapCellValueTag::Lis, h) => {
unify_fn!(
}
let a2 = read_heap_cell!(a2,
+ /*
(HeapCellValueTag::Char) => {
a2
}
+ */
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
if let Some(c) = name.as_char() {
}
};
- let chars_atom = AtomTable::build_with(&self.machine_st.atom_tbl, string.trim());
- self.machine_st.unify_complete_string(chars_atom, chs);
+ let cstr_cell = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(string.trim())
+ );
+
+ unify!(self.machine_st, cstr_cell, chs);
}
#[inline(always)]
.chars()
.map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
- let h = iter_to_heap_list(&mut self.machine_st.heap, codes);
- unify!(self.machine_st, heap_loc_as_cell!(h), chs);
+ let list_cell = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ string.trim().chars().count(),
+ codes,
+ )
+ );
+
+ unify!(self.machine_st, list_cell, chs);
}
#[inline(always)]
#[inline(always)]
pub(crate) fn lifted_heap_length(&mut self) {
let a1 = self.machine_st.registers[1];
- let lh_len = Fixnum::build_with(self.machine_st.lifted_heap.len() as i64);
+ let lh_len = Fixnum::build_with(self.machine_st.lifted_heap.cell_len() as i64);
self.machine_st.unify_fixnum(lh_len, a1);
}
debug_assert_eq!(arity, 0);
name.as_char().unwrap()
}
+ /*
(HeapCellValueTag::Char, c) => {
c
}
+ */
_ => {
match Number::try_from(a2) {
Ok(Number::Integer(n)) => {
let a2 = self.deref_register(2);
let c = read_heap_cell!(a1,
+ /*
(HeapCellValueTag::Char, c) => {
c
}
+ */
(HeapCellValueTag::Atom, (name, _arity)) => {
name.as_char().unwrap()
}
match (name, arity) {
(atom!("upper"), 1) => {
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
- let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_uppercase().to_string());
- let upper_str = string_as_cstr_cell!(atom);
+ let upper_str = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(&c.to_uppercase().to_string())
+ );
unify!(self.machine_st, reg, upper_str);
}
(atom!("lower"), 1) => {
let reg = self.machine_st.deref(self.machine_st.heap[s+1]);
- let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_lowercase().to_string());
- let lower_str = string_as_cstr_cell!(atom);
+ let lower_str = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(&c.to_uppercase().to_string())
+ );
+
unify!(self.machine_st, reg, lower_str);
}
_ => {
unify_fn!(self.machine_st, addr, *value_loc);
}
None if !ball.stub.is_empty() => {
- let h = self.machine_st.heap.len();
- let stub = ball.copy_and_align(h);
-
- self.machine_st.heap.extend(stub);
+ let h = step_or_resource_error!(
+ self.machine_st,
+ ball.copy_and_align_to(&mut self.machine_st.heap)
+ );
unify_fn!(self.machine_st, addr, heap_loc_as_cell!(h));
return Ok(());
}
}
+ /*
(HeapCellValueTag::Char, c) => {
write!(&mut stream, "{}", c).unwrap();
return Ok(());
}
+ */
_ => {
}
);
(HeapCellValueTag::Atom, (atom, _arity)) => {
char_as_cell!(atom.as_char().unwrap())
}
+ /*
(HeapCellValueTag::Char) => {
addr
}
+ */
_ => {
let err = self.machine_st.type_error(ValidType::InCharacter, addr);
return Err(self.machine_st.error_form(err, stub_gen()));
}
Some(Err(e)) => {
let stub = functor_stub(atom!("$get_n_chars"), 3);
- let err = self.machine_st.session_error(SessionError::from(
- ParserError::IO(e, ParserErrorSrc::default()),
- ));
+ let err =
+ self.machine_st
+ .session_error(SessionError::from(ParserError::IO(
+ e,
+ ParserErrorSrc::default(),
+ )));
return Err(self.machine_st.error_form(err, stub));
}
};
let output = self.deref_register(3);
- let atom = AtomTable::build_with(&self.machine_st.atom_tbl, &string);
+ let cstr_cell =
+ resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(&string));
- self.machine_st.unify_complete_string(atom, output);
+ unify!(self.machine_st, cstr_cell, output);
Ok(())
}
#[inline(always)]
pub(crate) fn copy_to_lifted_heap(&mut self) {
let lh_offset = cell_as_fixnum!(self.deref_register(1)).get_num() as usize;
-
let copy_target = self.machine_st.registers[2];
+ let old_threshold = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st
+ .copy_findall_solution(lh_offset, copy_target)
+ );
- let old_threshold = self
- .machine_st
- .copy_findall_solution(lh_offset, copy_target);
- let new_threshold = self.machine_st.lifted_heap.len() - lh_offset;
+ let new_threshold = self.machine_st.lifted_heap.cell_len() - lh_offset;
self.machine_st.lifted_heap[old_threshold] = heap_loc_as_cell!(new_threshold);
- for addr in self.machine_st.lifted_heap[old_threshold + 1..].iter_mut() {
- *addr -= self.machine_st.heap.len() + lh_offset;
+ for addr in &mut self.machine_st.lifted_heap.splice_mut(old_threshold + 1..) {
+ *addr -= self.machine_st.heap.cell_len() + lh_offset;
}
}
}
};
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
let mut num_functors = 0;
let code_dir = if module_name == atom!("user") {
}
};
- for (name, arity) in code_dir.keys() {
- if self.indices.builtin_property((*name, *arity)) {
+ for (name, arity) in code_dir.keys().cloned() {
+ if self.indices.builtin_property((name, arity)) {
continue;
}
- if name_match(pred_atom, *name) && arity_match(pred_arity, *arity) {
- self.machine_st.heap.extend(functor!(
- atom!("/"),
- [cell(atom_as_cell!(name)), fixnum(*arity)]
- ));
+ if name_match(pred_atom, name) && arity_match(pred_arity, arity) {
+ let functor = functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]); // self.machine_st.heap.extend(
+
+ let mut functor_writer = Heap::functor_writer(functor);
+
+ step_or_resource_error!(self.machine_st, functor_writer(&mut self.machine_st.heap));
num_functors += 1;
}
}
- if num_functors > 0 {
- let h = iter_to_heap_list(
+ let functor_list_cell = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
&mut self.machine_st.heap,
- (0..num_functors).map(|i| str_loc_as_cell!(h + 3 * i)),
- );
+ num_functors,
+ (0..num_functors).map(|i| str_loc_as_cell!(h + 3 * i))
+ )
+ );
- unify!(
- self.machine_st,
- heap_loc_as_cell!(h),
- self.machine_st.registers[4]
- );
- } else {
- unify!(
- self.machine_st,
- empty_list_as_cell!(),
- self.machine_st.registers[4]
- );
- }
+ unify!(
+ self.machine_st,
+ functor_list_cell,
+ self.machine_st.registers[4]
+ );
}
#[inline(always)]
pub(crate) fn get_next_op_db_ref(&mut self) {
let prec = self.deref_register(1);
-
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
fn write_op_functors_to_heap(
heap: &mut Heap,
op_descs: impl Iterator<Item = (Atom, OpDesc)>,
- ) -> usize {
+ ) -> Result<usize, usize> {
let mut num_functors = 0;
for (name, op_desc) in op_descs {
let spec_atom = op_desc.get_spec().get_spec();
- heap.extend(functor!(
+ let functor = functor!(
atom!("op"),
- [
- fixnum(prec),
- cell(atom_as_cell!(spec_atom)),
- cell(atom_as_cell!(name))
- ]
- ));
+ [fixnum(prec), atom_as_cell(spec_atom), atom_as_cell(name)]
+ );
+
+ let mut functor_writer = Heap::functor_writer(functor);
+
+ if let Err(e) = functor_writer(heap) {
+ return Err(e);
+ }
num_functors += 1;
}
- num_functors
+ Ok(num_functors)
}
if prec.is_var() {
(HeapCellValueTag::Str, s) => {
cell_as_atom!(self.machine_st.heap[s])
}
+ /*
(HeapCellValueTag::Char, c) => {
AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_string())
}
+ */
_ => {
unreachable!()
}
if number_of_keys == 0 {
self.machine_st.fail = true;
} else {
- let num_functors =
- write_op_functors_to_heap(&mut self.machine_st.heap, op_descs);
+ let num_functors = step_or_resource_error!(
+ self.machine_st,
+ write_op_functors_to_heap(&mut self.machine_st.heap, op_descs,)
+ );
- let h = iter_to_heap_list(
- &mut self.machine_st.heap,
- (0..num_functors).map(|i| str_loc_as_cell!(h + 4 * i)),
+ let functor_list_cell = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ num_functors,
+ (0..num_functors).map(|i| str_loc_as_cell!(h + 4 * i))
+ )
);
unify!(
self.machine_st,
- heap_loc_as_cell!(h),
+ functor_list_cell,
self.machine_st.registers[4]
);
}
Some((key.0, *op_desc))
});
- write_op_functors_to_heap(&mut self.machine_st.heap, op_descs)
+ step_or_resource_error!(
+ self.machine_st,
+ write_op_functors_to_heap(&mut self.machine_st.heap, op_descs,)
+ )
};
- if num_functors > 0 {
- let h = iter_to_heap_list(
+ let functor_list_cell = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
&mut self.machine_st.heap,
+ num_functors,
(0..num_functors).map(|i| str_loc_as_cell!(h + 4 * i)),
- );
+ )
+ );
- unify!(
- self.machine_st,
- heap_loc_as_cell!(h),
- self.machine_st.registers[4]
- );
- } else {
- self.machine_st.fail = true;
- }
+ unify!(
+ self.machine_st,
+ functor_list_cell,
+ self.machine_st.registers[4]
+ );
} else {
let spec = cell_as_atom!(self.deref_register(2));
let op_atom = cell_as_atom!(self.deref_register(3));
match self.indices.op_dir.get(&(op_atom, fixity)).cloned() {
Some(op_desc) => {
- let num_functors = write_op_functors_to_heap(
- &mut self.machine_st.heap,
- std::iter::once((op_atom, op_desc)),
- );
-
- let h = iter_to_heap_list(
- &mut self.machine_st.heap,
- (0..num_functors).map(|i| str_loc_as_cell!(h + 4 * i)),
+ let num_functors = step_or_resource_error!(
+ self.machine_st,
+ write_op_functors_to_heap(
+ &mut self.machine_st.heap,
+ std::iter::once((op_atom, op_desc))
+ )
);
- unify!(
+ let functor_list = step_or_resource_error!(
self.machine_st,
- heap_loc_as_cell!(h),
- self.machine_st.registers[4]
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ num_functors,
+ (0..num_functors).map(|i| str_loc_as_cell!(h + 4 * i)),
+ )
);
+
+ unify!(self.machine_st, functor_list, self.machine_st.registers[4]);
}
_ => {
self.machine_st.fail = true;
}
};
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
- iter_to_heap_list(
- &mut self.machine_st.heap,
- (0..n).map(|i| heap_loc_as_cell!(h + 2 * i + 1)),
+ let list_cell = resource_error_call_result!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ n,
+ (0..n).map(|i| heap_loc_as_cell!(h + 2 * i + 1)),
+ )
);
- let tail = self.deref_register(1);
- self.machine_st
- .bind(tail.as_var().unwrap(), heap_loc_as_cell!(h));
-
+ unify!(self.machine_st, self.deref_register(1), list_cell);
Ok(())
}
self.machine_st
.unify_fixnum(Fixnum::build_with(status as i64), address_status);
// headers
- let headers: Vec<HeapCellValue> = resp
- .headers()
- .iter()
- .map(|(header_name, header_value)| {
- let h = self.machine_st.heap.len();
-
- let header_term = functor!(
- AtomTable::build_with(
- &self.machine_st.atom_tbl,
- header_name.as_str()
- ),
- [cell(string_as_cstr_cell!(AtomTable::build_with(
- &self.machine_st.atom_tbl,
- header_value.to_str().unwrap()
- )))]
- );
-
- self.machine_st.heap.extend(header_term);
- str_loc_as_cell!(h)
- })
- .collect();
+ let mut headers: Vec<HeapCellValue> = vec![];
+
+ for (header_name, header_value) in resp.headers().iter() {
+ let string_cell = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st
+ .allocate_cstr(header_value.to_str().unwrap())
+ );
+
+ let header_term = functor!(
+ AtomTable::build_with(
+ &self.machine_st.atom_tbl,
+ header_name.as_str()
+ ),
+ [cell(string_cell)]
+ );
+
+ let mut functor_writer = Heap::functor_writer(header_term);
- let headers_list =
- iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
+ let functor_cell = resource_error_call_result!(
+ self.machine_st,
+ functor_writer(&mut self.machine_st.heap)
+ );
+
+ headers.push(functor_cell);
+ }
+
+ let headers_list_cell = resource_error_call_result!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ headers.len(),
+ headers.into_iter(),
+ )
+ );
unify!(
self.machine_st,
- heap_loc_as_cell!(headers_list),
+ headers_list_cell,
self.machine_st.registers[6]
);
self.machine_st.fail = true;
}
}
- });
+
+ Ok(())
+ })?;
} else {
let err = self
.machine_st
(ArenaHeaderTag::HttpListener, http_listener) => {
loop {
match http_listener.incoming.recv_timeout(std::time::Duration::from_millis(200)) {
- Ok(request) => {
- let method_atom = match request.request_data.method {
- Method::GET => atom!("get"),
- Method::POST => atom!("post"),
- Method::PUT => atom!("put"),
- Method::DELETE => atom!("delete"),
- Method::PATCH => atom!("patch"),
- Method::HEAD => atom!("head"),
- Method::OPTIONS => atom!("options"),
- Method::TRACE => atom!("trace"),
- Method::CONNECT => atom!("connect"),
- _ => atom!("unsupported_extension"),
- };
- let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &request.request_data.path);
- let path_cell = atom_as_cstr_cell!(path_atom);
- let headers: Vec<HeapCellValue> = request.request_data.headers.iter().map(|(header_name, header_value)| {
- let h = self.machine_st.heap.len();
- let header_term = functor!(AtomTable::build_with(&self.machine_st.atom_tbl, header_name.as_str()), [cell(string_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, header_value.to_str().unwrap())))]);
+ Ok(request) => {
+ let method_atom = match request.request_data.method {
+ Method::GET => atom!("get"),
+ Method::POST => atom!("post"),
+ Method::PUT => atom!("put"),
+ Method::DELETE => atom!("delete"),
+ Method::PATCH => atom!("patch"),
+ Method::HEAD => atom!("head"),
+ Method::OPTIONS => atom!("options"),
+ Method::TRACE => atom!("trace"),
+ Method::CONNECT => atom!("connect"),
+ _ => atom!("unsupported_extension"),
+ };
- self.machine_st.heap.extend(header_term.into_iter());
- str_loc_as_cell!(h)
- }).collect();
+ let path_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &request.request_data.path);
+ let path_cell = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(&request.request_data.path)
+ );
- let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter());
+ let mut headers = vec![];
- let query_str = request.request_data.query;
- let query_atom = AtomTable::build_with(&self.machine_st.atom_tbl, &query_str);
- let query_cell = string_as_cstr_cell!(query_atom);
+ for (header_name, header_value) in request.request_data.headers {
+ let header_value = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(header_value.to_str().unwrap())
+ );
- let mut stream = Stream::from_http_stream(
- path_atom,
- request.request_data.body,
- &mut self.machine_st.arena
- );
- *stream.options_mut() = StreamOptions::default();
- stream.options_mut().set_stream_type(StreamType::Binary);
+ let header_term = functor!(
+ AtomTable::build_with(&self.machine_st.atom_tbl, header_name.unwrap().as_str()),
+ [cell(header_value)]
+ );
- self.indices.add_stream(stream, atom!("http_accept"), 7)
- .map_err(|stub_gen| stub_gen(&mut self.machine_st))?;
+ let mut functor_writer = Heap::functor_writer(header_term);
- let stream: HeapCellValue = stream.into();
+ let functor_cell = resource_error_call_result!(
+ self.machine_st,
+ functor_writer(&mut self.machine_st.heap)
+ );
- let handle: TypedArenaPtr<HttpResponse> = arena_alloc!(request.response, &mut self.machine_st.arena);
+ headers.push(functor_cell);
+ }
+
+ let headers_list_cell = resource_error_call_result!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ headers.len(),
+ headers.into_iter(),
+ )
+ );
+
+ let query_str = request.request_data.query;
+ let query_cell = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(&query_str)
+ );
+
+ let mut stream = Stream::from_http_stream(
+ path_atom,
+ request.request_data.body,
+ &mut self.machine_st.arena
+ );
+ *stream.options_mut() = StreamOptions::default();
+ stream.options_mut().set_stream_type(StreamType::Binary);
+
+ self.indices.add_stream(stream, atom!("http_accept"), 7)
+ .map_err(|stub_gen| stub_gen(&mut self.machine_st))?;
+
+ let stream = stream_as_cell!(stream);
+
+ let handle = arena_alloc!(request.response, &mut self.machine_st.arena)
+ as TypedArenaPtr<HttpResponse>;
+
+ self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
+ self.machine_st.bind(path.as_var().unwrap(), path_cell);
+ unify!(self.machine_st, headers_list_cell, self.machine_st.registers[4]);
+ self.machine_st.bind(query.as_var().unwrap(), query_cell);
+ self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
+ self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
- self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
- self.machine_st.bind(path.as_var().unwrap(), path_cell);
- unify!(self.machine_st, heap_loc_as_cell!(headers_list), self.machine_st.registers[4]);
- self.machine_st.bind(query.as_var().unwrap(), query_cell);
- self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
- self.machine_st.bind(handle_addr.as_var().unwrap(), typed_arena_ptr_as_cell!(handle));
- break
- }
- Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
- let interrupted = machine::INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
-
- match machine::INTERRUPT.compare_exchange(
- interrupted,
- false,
- std::sync::atomic::Ordering::Relaxed,
- std::sync::atomic::Ordering::Relaxed,
- ) {
- Ok(interruption) => {
- if interruption {
- self.machine_st.throw_interrupt_exception();
- self.machine_st.backtrack();
- // We have extracted controll over the Tokio runtime to the calling context for enabling library use case
- // (see https://github.com/mthom/scryer-prolog/pull/1880)
- // So we only have access to a runtime handle in here and can't shut it down.
- // Since I'm not aware of the consequences of deactivating this new code which came in while PR 1880
- // was not merged, I'm only deactivating it for now.
- //let old_runtime = std::mem::replace(&mut self.runtime, tokio::runtime::Runtime::new().unwrap());
- //old_runtime.shutdown_background();
break
}
+ Err(std::sync::mpsc::RecvTimeoutError::Timeout) => {
+ let interrupted = machine::INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
+
+ match machine::INTERRUPT.compare_exchange(
+ interrupted,
+ false,
+ std::sync::atomic::Ordering::Relaxed,
+ std::sync::atomic::Ordering::Relaxed,
+ ) {
+ Ok(interruption) => {
+ if interruption {
+ self.machine_st.throw_interrupt_exception();
+ self.machine_st.backtrack();
+ // We have extracted controll over the Tokio runtime to the calling context for enabling library use case
+ // (see https://github.com/mthom/scryer-prolog/pull/1880)
+ // So we only have access to a runtime handle in here and can't shut it down.
+ // Since I'm not aware of the consequences of deactivating this new code which came in while PR 1880
+ // was not merged, I'm only deactivating it for now.
+ //let old_runtime = std::mem::replace(&mut self.runtime, tokio::runtime::Runtime::new().unwrap());
+ //old_runtime.shutdown_background();
+ break
+ }
+ }
+ Err(_) => unreachable!(),
+ }
}
- Err(_) => unreachable!(),
- }
-
- }
Err(_) => {
- self.machine_st.fail = true;
- }
- }
- }
+ self.machine_st.fail = true;
+ }
}
- _ => {
+ }
+ }
+ _ => {
unreachable!();
}
);
self.machine_st.unify_f64(n, return_value)
}
Value::Struct(name, args) => {
- let struct_value = self.build_struct(&name, args);
+ let struct_value = resource_error_call_result!(
+ self.machine_st,
+ self.build_struct(&name, args)
+ );
+
unify!(self.machine_st, return_value, struct_value);
}
Value::CString(cstr) => {
- let cstr = AtomTable::build_with(
- &self.machine_st.atom_tbl,
- cstr.to_str().unwrap(),
+ let str_cell = resource_error_call_result!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(cstr.to_str().unwrap())
);
- self.machine_st.unify_complete_string(cstr, return_value);
+
+ unify!(self.machine_st, str_cell, return_value);
}
}
return Ok(());
Err(e) => return Err(e),
}
}
+
self.machine_st.fail = true;
Ok(())
}
#[cfg(feature = "ffi")]
- fn build_struct(&mut self, name: &str, mut args: Vec<Value>) -> HeapCellValue {
+ fn build_struct(&mut self, name: &str, mut args: Vec<Value>) -> Result<HeapCellValue, usize> {
args.insert(0, Value::CString(CString::new(name).unwrap()));
- let cells: Vec<_> = args
- .into_iter()
- .map(|val| match val {
+
+ let mut expanded_args = Vec::with_capacity(args.len());
+
+ for val in args {
+ expanded_args.push(match val {
Value::Int(n) => fixnum_as_cell!(Fixnum::build_with(n)),
Value::Float(n) => HeapCellValue::from(float_alloc!(n, self.machine_st.arena)),
Value::CString(cstr) => atom_as_cell!(AtomTable::build_with(
&self.machine_st.atom_tbl,
&cstr.into_string().unwrap()
)),
- Value::Struct(name, struct_args) => self.build_struct(&name, struct_args),
- })
- .collect();
+ Value::Struct(name, struct_args) => self.build_struct(&name, struct_args)?,
+ });
+ }
- heap_loc_as_cell!(iter_to_heap_list(
+ sized_iter_to_heap_list(
&mut self.machine_st.heap,
- cells.into_iter()
- ))
+ expanded_args.len(),
+ expanded_args.into_iter(),
+ )
}
#[cfg(feature = "ffi")]
#[inline(always)]
pub(crate) fn argv(&mut self) -> CallResult {
let args = self.deref_register(1);
-
let mut args_pstrs = vec![];
+
for arg in env::args() {
- args_pstrs.push(put_complete_string(
- &mut self.machine_st.heap,
- &arg,
- &self.machine_st.atom_tbl,
- ));
+ let pstr_cell =
+ resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(&arg));
+
+ args_pstrs.push(pstr_cell);
}
- let cell = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- args_pstrs.into_iter()
- ));
- unify!(self.machine_st, args, cell);
+ let list_cell = resource_error_call_result!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ args_pstrs.len(),
+ args_pstrs.into_iter(),
+ )
+ );
+
+ unify!(self.machine_st, args, list_cell);
Ok(())
}
#[inline(always)]
pub(crate) fn current_time(&mut self) {
let timestamp = self.systemtime_to_timestamp(SystemTime::now());
- self.machine_st
- .unify_complete_string(timestamp, self.machine_st.registers[1]);
+ let cstr_cell =
+ step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(×tamp));
+
+ unify!(self.machine_st, cstr_cell, self.machine_st.registers[1]);
}
#[inline(always)]
};
let op = read_heap_cell!(self.deref_register(3),
+ /*
(HeapCellValueTag::Char, c) => {
AtomTable::build_with(&self.machine_st.atom_tbl, &c.to_string())
}
+ */
(HeapCellValueTag::Atom, (name, _arity)) => {
name
}
};
if let Some(b) = b {
- let iter = self.machine_st.gather_attr_vars_created_since(b);
+ let attr_vars = self.machine_st.gather_attr_vars_created_since(b);
- let var_list_addr =
- heap_loc_as_cell!(iter_to_heap_list(&mut self.machine_st.heap, iter));
+ let var_list_addr = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ attr_vars.len(),
+ attr_vars.into_iter(),
+ )
+ );
let list_addr = self.machine_st.registers[2];
unify!(self.machine_st, var_list_addr, list_addr);
pub(crate) fn put_to_attributed_variable_list(&mut self) {
let attr_var = self.deref_register(1);
let attr = self.deref_register(3);
- let attr_var_list = match self.machine_st.get_attr_var_list(attr_var) {
+ let attr_var_list_result =
+ step_or_resource_error!(self.machine_st, self.machine_st.get_attr_var_list(attr_var));
+
+ let attr_var_list = match attr_var_list_result {
Some(h) => h,
None => {
self.machine_st.fail = true;
* or str cells (> 0-arity).
*/
- let h = self.machine_st.heap.len();
+ let module_functor = functor!(atom!(":"), [cell(module), cell(attr)]);
+ let h = self.machine_st.heap.cell_len();
- self.machine_st.heap.push(str_loc_as_cell!(h + 1));
- self.machine_st
- .heap
- .extend(functor!(atom!(":"), [cell(module), cell(attr)]));
+ step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.heap.push_cell(str_loc_as_cell!(h + 1))
+ );
+
+ let mut functor_writer = Heap::functor_writer(module_functor);
+ step_or_resource_error!(self.machine_st, functor_writer(&mut self.machine_st.heap));
match self.match_attribute(self.machine_st.heap[attr_var_list], module, attr) {
Some(AttrListMatch { match_site, .. }) => {
// at the end of the (non-empty) list here.
self.machine_st.heap[match_site] = list_loc_as_cell!(h + 4);
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- self.machine_st.heap.push(heap_loc_as_cell!(h + 5));
+
+ let mut writer = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.heap.reserve(2)
+ );
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(h));
+ section.push_cell(heap_loc_as_cell!(h + 5));
+ });
(match_site, l)
}
None => {
// the list is empty.
self.machine_st.heap[attr_var_list] = list_loc_as_cell!(h + 4);
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- self.machine_st.heap.push(heap_loc_as_cell!(h + 5));
+
+ let mut writer =
+ step_or_resource_error!(self.machine_st, self.machine_st.heap.reserve(2));
+
+ writer.write_with(|section| {
+ section.push_cell(heap_loc_as_cell!(h));
+ section.push_cell(heap_loc_as_cell!(h + 5));
+ });
self.machine_st
.attr_var_init
pub(crate) fn get_continuation_chunk(&mut self) {
let e = self.deref_register(1);
let e = cell_as_fixnum!(e).get_num() as usize;
+ let h = self.machine_st.heap.cell_len();
- let p_functor = self.deref_register(2);
-
+ let p_functor_cell = self.deref_register(2);
let num_cells = self.machine_st.stack.index_and_frame(e).prelude.num_cells;
+
+ let mut writer =
+ step_or_resource_error!(self.machine_st, self.machine_st.heap.reserve(2 + num_cells));
+
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("cont_chunk"), 1 + num_cells));
+ section.push_cell(p_functor_cell);
+
+ for idx in 1..=num_cells {
+ let mut stack_offset = stack_loc!(AndFrame, e, idx);
+ let mut addr = self.machine_st.stack[stack_offset];
+
+ while addr.get_tag() == HeapCellValueTag::StackVar {
+ stack_offset = addr.get_value() as usize;
+
+ if self.machine_st.stack[stack_offset] == addr {
+ break;
+ }
+
+ addr = self.machine_st.stack[stack_offset];
+ }
+
+ if addr.get_tag() == HeapCellValueTag::StackVar {
+ section.push_cell(heap_loc_as_cell!(h + 1 + idx));
+
+ self.machine_st.stack[stack_offset] = heap_loc_as_cell!(h + 1 + idx);
+
+ // have to inline the TrailRef::Ref(RefTag::StackCell) case of MachineState::trail
+ // here to get around the borrow checker.
+ if stack_offset < self.machine_st.b {
+ self.machine_st.trail.push(TrailEntry::build_with(
+ TrailEntryTag::TrailedStackVar,
+ stack_offset as u64,
+ ));
+
+ self.machine_st.tr += 1;
+ }
+ } else {
+ section.push_cell(addr);
+ }
+ }
+ });
+
+ /*
let mut addrs = vec![];
for idx in 1..num_cells + 1 {
// avoid pushing stack variables to the heap where they
// must not go.
if addr.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));
self.machine_st.bind(Ref::heap_cell(h), addr);
addrs.push(addr);
}
}
+ */
- let chunk = str_loc_as_cell!(self.machine_st.heap.len());
+ let chunk = str_loc_as_cell!(self.machine_st.heap.cell_len());
+ /*
self.machine_st
.heap
.push(atom_as_cell!(atom!("cont_chunk"), 1 + num_cells));
- self.machine_st.heap.push(p_functor);
+ self.machine_st.heap.push(p_functor_cell);
self.machine_st.heap.extend(addrs);
+ */
unify!(self.machine_st, self.machine_st.registers[3], chunk);
}
let lh_offset = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(lh_offset)))
.get_num() as usize;
- if lh_offset >= self.machine_st.lifted_heap.len() {
+ if lh_offset >= self.machine_st.lifted_heap.cell_len() {
let solutions = self.machine_st.registers[2];
let diff = self.machine_st.registers[3];
unify_fn!(self.machine_st, solutions, diff);
} else {
- let h = self.machine_st.heap.len();
- let mut last_index = h;
+ let h = self.machine_st.heap.cell_len();
- for value in self.machine_st.lifted_heap[lh_offset..].iter().cloned() {
- last_index = self.machine_st.heap.len();
- self.machine_st.heap.push(value + h);
- }
+ step_or_resource_error!(
+ self.machine_st,
+ self.machine_st
+ .heap
+ .append(self.machine_st.lifted_heap.splice(lh_offset..),)
+ );
- if last_index < self.machine_st.heap.len() {
- let diff = self.machine_st.registers[3];
- unify_fn!(self.machine_st, diff, self.machine_st.heap[last_index]);
+ for cell in &mut self.machine_st.heap.splice_mut(h..) {
+ *cell = *cell + h;
}
+ let diff = self.machine_st.registers[3];
+ unify_fn!(
+ self.machine_st,
+ diff,
+ self.machine_st.heap.last_cell().unwrap()
+ );
+
self.machine_st.lifted_heap.truncate(lh_offset);
let solutions = self.machine_st.registers[2];
let lh_offset = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(lh_offset)))
.get_num() as usize;
- if lh_offset >= self.machine_st.lifted_heap.len() {
+ if lh_offset >= self.machine_st.lifted_heap.cell_len() {
let solutions = self.machine_st.registers[2];
unify_fn!(self.machine_st, solutions, empty_list_as_cell!());
} else {
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
+
+ step_or_resource_error!(
+ self.machine_st,
+ self.machine_st
+ .heap
+ .append(self.machine_st.lifted_heap.splice(lh_offset..),)
+ );
- for addr in self.machine_st.lifted_heap[lh_offset..].iter().cloned() {
- self.machine_st.heap.push(addr + h);
+ for cell in &mut self.machine_st.heap.splice_mut(h..) {
+ *cell = *cell + h;
}
self.machine_st.lifted_heap.truncate(lh_offset);
// n has already been confirmed as an integer, and
// internally, Rational is assumed reduced, so its
// denominator must be 1.
- let r = r.numerator().try_into().unwrap();
- r
+ r.numerator().try_into().unwrap()
}
_ => {
unreachable!()
let prev_block = self.machine_st.scc_block;
self.machine_st.run_cleaners_fn = Machine::run_cleaners;
-
self.machine_st.scc_block = b;
self.machine_st.cont_pts.push((addr, b, prev_block));
}
Ok(Number::Integer(n)) => (*n).clone(),
_ => {
let stub = functor_stub(atom!("call_with_inference_limit"), 3);
-
let err = self.machine_st.type_error(ValidType::Integer, a2);
return Err(self.machine_st.error_form(err, stub));
}
#[inline(always)]
pub(crate) fn no_such_predicate(&mut self) -> CallResult {
let module_name = cell_as_atom!(self.deref_register(1));
-
let head = self.deref_register(2);
self.machine_st.fail = read_heap_cell!(head,
#[inline(always)]
pub(crate) fn get_ball(&mut self) {
let addr = self.deref_register(1);
- let h = self.machine_st.heap.len();
-
- if !self.machine_st.ball.stub.is_empty() {
- let stub = self.machine_st.ball.copy_and_align(h);
- self.machine_st.heap.extend(stub);
+ let h = if !self.machine_st.ball.stub.is_empty() {
+ step_or_resource_error!(
+ self.machine_st,
+ self.machine_st
+ .ball
+ .copy_and_align_to(&mut self.machine_st.heap)
+ )
} else {
self.machine_st.fail = true;
return;
- }
+ };
match addr.as_var() {
Some(r) => self.machine_st.bind(r, self.machine_st.heap[h]),
let e = and_frame.prelude.e;
let e = Fixnum::build_with(i64::try_from(e).unwrap());
- let p = str_loc_as_cell!(machine_st.heap.len());
+ let mut writer = Heap::functor_writer(functor!(atom!("dir_entry"), [fixnum(cp)]));
+
+ let p_functor_cell = step_or_resource_error!(machine_st, writer(&mut machine_st.heap));
- machine_st
- .heap
- .extend(functor!(atom!("dir_entry"), [fixnum(cp)]));
machine_st.unify_fixnum(e, machine_st.registers[2]);
if !machine_st.fail {
- unify!(machine_st, p, machine_st.registers[3]);
+ unify!(machine_st, p_functor_cell, machine_st.registers[3]);
}
};
// it later.
let and_frame = self.machine_st.stack.index_and_frame(e);
let cp = and_frame.prelude.cp - 1;
+ let mut writer = Heap::functor_writer(functor!(atom!("dir_entry"), [fixnum(cp)]));
- let p = str_loc_as_cell!(self.machine_st.heap.len());
- self.machine_st.heap.extend(functor!(atom!("dir_entry"), [fixnum(cp)]));
+ let p_functor_cell = step_or_resource_error!(
+ self.machine_st,
+ writer(&mut self.machine_st.heap)
+ );
let e = Fixnum::build_with(i64::try_from(and_frame.prelude.e).unwrap());
self.machine_st.unify_fixnum(e, self.machine_st.registers[2]);
if !self.machine_st.fail {
- unify!(self.machine_st, p, self.machine_st.registers[3]);
+ unify!(self.machine_st, p_functor_cell, self.machine_st.registers[3]);
}
}
_ => {
None => true,
};
}
+ /*
(HeapCellValueTag::Char, c) => {
self.machine_st.fail = non_quoted_token(once(c));
}
+ */
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
self.machine_st.fail = non_quoted_token(name.as_str().chars());
fn read_term_from_atom(
&mut self,
atom_or_string: AtomOrString,
- ) -> Result<Option<FocusedHeap>, MachineStub> {
+ ) -> Result<Option<TermWriteResult>, MachineStub> {
let string = match atom_or_string {
AtomOrString::Atom(atom!("[]")) => "".to_owned(),
_ => atom_or_string.into(),
};
let chars = CharReader::new(ByteStream::from_string(string));
- let mut parser = Parser::new(chars, &mut self.machine_st);
+ let mut parser = LexerParser::new(chars, &mut self.machine_st);
let op_dir = CompositeOpDir::new(&self.indices.op_dir, None);
let term = parser
.value_to_str_like(self.machine_st.registers[1])
.unwrap();
- if let Some(mut term) = self.read_term_from_atom(atom_or_string)? {
- let heap_len = self.machine_st.heap.len();
-
- self.machine_st.heap.extend(
- copy_and_align_iter(term.heap.drain(..), 0, heap_len as i64),
- );
-
- let result = heap_loc_as_cell!(heap_len + term.focus);
+ if let Some(term) = self.read_term_from_atom(atom_or_string)? {
+ let result = self.machine_st.heap[term.focus];
let var = self.deref_register(2).as_var().unwrap();
self.machine_st.bind(var, result);
};
let chars = CharReader::new(ByteStream::from_string(string));
- let term_write_result = self.machine_st.read(chars, &self.indices.op_dir)
- .map(|(term, _)| term.to_machine_heap(&mut self.machine_st))
+ let term = self
+ .machine_st
+ .read(chars, &self.indices.op_dir)
+ .map(|(term, _)| term)
.map_err(|e| {
let e = self.machine_st.session_error(SessionError::from(e));
let stub = functor_stub(atom!("read_term_from_chars"), 3);
self.machine_st.error_form(e, stub)
})?;
- self.machine_st.read_term_body(term_write_result)
+ self.machine_st.read_term_body(term)
}
#[inline(always)]
#[inline(always)]
pub(crate) fn reset_continuation_marker(&mut self) {
- let h = self.machine_st.heap.len();
+ let h = self.machine_st.heap.cell_len();
self.machine_st.registers[3] = atom_as_cell!(atom!("none"));
self.machine_st.registers[4] = heap_loc_as_cell!(h);
- self.machine_st.heap.push(heap_loc_as_cell!(h));
+ step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.heap.push_cell(heap_loc_as_cell!(h))
+ );
}
#[inline(always)]
.add_stream(stream, atom!("tls_client_negotiate"), 3)
.map_err(|stub_gen| stub_gen(&mut self.machine_st))?;
- // FIXME: why are we pushing a random, unreferenced cell on the heap?
- self.machine_st.heap.push(stream.into());
let stream_addr = self.deref_register(3);
self.machine_st
.bind(stream_addr.as_var().unwrap(), stream.into());
}
atom!("position") => {
if let Some((position, lines_read)) = stream.position() {
- let h = self.machine_st.heap.len();
-
let position_term = functor!(
atom!("position_and_lines_read"),
[
- integer(position, &mut self.machine_st.arena),
- integer(lines_read, &mut self.machine_st.arena)
+ number(position, (&mut self.machine_st.arena)),
+ number(lines_read, (&mut self.machine_st.arena))
]
);
- self.machine_st.heap.extend(position_term);
- str_loc_as_cell!(h)
+ let mut functor_writer = Heap::functor_writer(position_term);
+
+ resource_error_call_result!(
+ self.machine_st,
+ functor_writer(&mut self.machine_st.heap)
+ )
} else {
self.machine_st.fail = true;
return Ok(());
let value = self.machine_st.registers[2];
let mut ball = Ball::new();
- ball.boundary = self.machine_st.heap.len();
+ ball.boundary = self.machine_st.heap.cell_len();
- copy_term(
- CopyBallTerm::new(
- &mut self.machine_st.attr_var_init.attr_var_queue,
- &mut self.machine_st.stack,
- &mut self.machine_st.heap,
- &mut ball.stub,
- ),
- value,
- AttrVarPolicy::DeepCopy,
+ step_or_resource_error!(
+ self.machine_st,
+ copy_term(
+ CopyBallTerm::new(
+ &mut self.machine_st.attr_var_init.attr_var_queue,
+ &mut self.machine_st.stack,
+ &mut self.machine_st.heap,
+ &mut ball.stub,
+ ),
+ value,
+ AttrVarPolicy::DeepCopy,
+ )
);
self.indices.global_variables.insert(key, (ball, None));
let seen_vars = self
.machine_st
.attr_vars_of_term(self.machine_st.registers[1]);
- let outcome = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- seen_vars.into_iter()
- ));
+
+ let outcome = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ seen_vars.len(),
+ seen_vars.into_iter(),
+ )
+ );
unify_fn!(self.machine_st, self.machine_st.registers[2], outcome);
}
}
let stored_v = 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));
- self.machine_st.bind(Ref::heap_cell(h), stored_v);
+ step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.heap.push_cell(heap_loc_as_cell!(h))
+ );
+ self.machine_st.bind(Ref::heap_cell(h), stored_v);
heap_loc_as_cell!(h)
} else {
stored_v
};
let mut seen_set = IndexSet::with_hasher(FxBuildHasher::default());
-
self.machine_st.variable_set(&mut seen_set, stored_v);
- let outcome = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- seen_set.into_iter()
- ));
+ let outcome = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ seen_set.len(),
+ seen_set.into_iter(),
+ )
+ );
unify_fn!(self.machine_st, a2, outcome);
}
false
}
- fn walk_code_at_ptr(&mut self, index_ptr: usize) -> HeapCellValue {
- let mut h = self.machine_st.heap.len();
+ fn walk_code_at_ptr(&mut self, index_ptr: usize) -> Result<HeapCellValue, usize> {
+ let orig_h = self.machine_st.heap.cell_len();
+ let mut h = orig_h;
let mut functors = vec![];
let mut functor_list = vec![];
walk_code(&self.code, index_ptr, |instr| {
let old_len = functors.len();
- instr.enqueue_functors(h, &mut self.machine_st.arena, &mut functors);
+ instr.enqueue_functors(&mut self.machine_st.arena, &mut functors);
let new_len = functors.len();
- #[allow(clippy::needless_range_loop)]
for index in old_len..new_len {
let functor_len = functors[index].len();
0 => {}
1 => {
functor_list.push(heap_loc_as_cell!(h));
- h += functor_len;
+ h += cell_index!(Heap::compute_functor_byte_size(&functors[index]));
}
_ => {
functor_list.push(str_loc_as_cell!(h));
- h += functor_len;
+ h += cell_index!(Heap::compute_functor_byte_size(&functors[index]));
}
- }
+ };
}
});
- for functor in functors {
- self.machine_st.heap.extend(functor.into_iter());
- }
+ let mut writer = self.machine_st.heap.reserve(h - orig_h)?;
+
+ writer.write_with(|section| {
+ for functor in functors {
+ let mut functor_writer = ReservedHeapSection::functor_writer(functor);
+ functor_writer(section);
+ }
+ });
- heap_loc_as_cell!(iter_to_heap_list(
+ sized_iter_to_heap_list(
&mut self.machine_st.heap,
- functor_list.into_iter()
- ))
+ functor_list.len(),
+ functor_list.into_iter(),
+ )
}
#[inline(always)]
}
};
- let listing = self.walk_code_at_ptr(first_idx);
+ let listing =
+ resource_error_call_result!(self.machine_st, self.walk_code_at_ptr(first_idx));
+
let listing_var = self.machine_st.registers[4];
unify!(self.machine_st, listing, listing_var);
}
};
- let listing = self.walk_code_at_ptr(index_ptr);
+ let listing = step_or_resource_error!(self.machine_st, self.walk_code_at_ptr(index_ptr));
+
let listing_var = self.machine_st.registers[2];
unify!(self.machine_st, listing, listing_var);
};
let result = printer.print().result();
- let chars = put_complete_string(
- &mut self.machine_st.heap,
- &result,
- &self.machine_st.atom_tbl,
- );
+ let chars =
+ resource_error_call_result!(self.machine_st, self.machine_st.allocate_cstr(&result));
let result_addr = self.deref_register(1);
+ let var = result_addr.as_var().unwrap();
- if let Some(var) = result_addr.as_var() {
- self.machine_st.bind(var, chars);
- } else {
- unreachable!()
- }
+ self.machine_st.bind(var, chars);
Ok(())
}
use git_version::git_version;
let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown");
- let buffer_atom = AtomTable::build_with(&self.machine_st.atom_tbl, buffer);
+ let cstr_cell =
+ step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(&buffer));
- let a1 = self.deref_register(1);
- self.machine_st.unify_complete_string(buffer_atom, a1);
+ unify!(self.machine_st, cstr_cell, self.machine_st.registers[1]);
}
#[inline(always)]
let mut context = Sha3_224::new();
context.update(&bytes);
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .finalize()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ let finalized_context = context.finalize();
+ let context_len = finalized_context.len();
+
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context_len,
+ finalized_context
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ )
}
atom!("sha3_256") => {
let mut context = Sha3_256::new();
context.update(&bytes);
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .finalize()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ let finalized_context = context.finalize();
+ let context_len = finalized_context.len();
+
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context_len,
+ finalized_context
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ )
}
atom!("sha3_384") => {
let mut context = Sha3_384::new();
context.update(&bytes);
+ let finalized_context = context.finalize();
+ let context_len = finalized_context.len();
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .finalize()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context_len,
+ finalized_context
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ )
}
atom!("sha3_512") => {
let mut context = Sha3_512::new();
context.update(&bytes);
+ let finalized_context = context.finalize();
+ let context_len = finalized_context.len();
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .finalize()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context_len,
+ finalized_context
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
}
atom!("blake2s256") => {
let mut context = Blake2s256::new();
context.update(&bytes);
+ let finalized_context = context.finalize();
+ let context_len = finalized_context.len();
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .finalize()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context_len,
+ finalized_context
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
}
atom!("blake2b512") => {
let mut context = Blake2b512::new();
context.update(&bytes);
+ let finalized_context = context.finalize();
+ let context_len = finalized_context.len();
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .finalize()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context_len,
+ finalized_context
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
}
atom!("ripemd160") => {
let mut context = Ripemd160::new();
context.update(&bytes);
+ let finalized_context = context.finalize();
+ let context_len = finalized_context.len();
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .finalize()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context_len,
+ finalized_context
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ )
}
_ => {
let ints = digest::digest(
&bytes,
);
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- ints.as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ ints.as_ref().len(),
+ ints.as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ )
}
};
let rkey = hmac::Key::new(ralg, key.as_ref());
let tag = hmac::sign(&rkey, &data);
- let ints_list = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- tag.as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ));
+ let ints_list = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ tag.as_ref().len(),
+ tag.as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ );
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
}
}
}
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- bytes
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ bytes.len(),
+ bytes
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ )
};
unify!(self.machine_st, self.machine_st.registers[7], ints_list);
&mut bytes,
);
- heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- bytes
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ))
+ step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ bytes.len(),
+ bytes
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ )
};
unify!(self.machine_st, self.machine_st.registers[4], ints_list);
}
};
- let tag_list = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- tag.as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ));
+ let tag_list = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ tag.as_ref().len(),
+ tag.as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ );
- let complete_string = self.u8s_to_string(&in_out);
+ let complete_string = step_or_resource_error!(self.machine_st, self.u8s_to_string(&in_out));
unify!(self.machine_st, self.machine_st.registers[6], tag_list);
unify!(
if buffer.is_empty() {
empty_list_as_cell!()
} else {
- atom_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, &buffer))
+ step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(&buffer))
}
};
let scalar = secp256k1::Scalar::decode_reduce(&scalar_bytes);
point *= scalar;
- let uncompressed = self.u8s_to_string(&point.encode_uncompressed());
+ let uncompressed = step_or_resource_error!(
+ self.machine_st,
+ self.u8s_to_string(&point.encode_uncompressed())
+ );
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
}
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
- let complete_string = self.u8s_to_string(skey.public_key.encoded.as_ref());
+ let complete_string = step_or_resource_error!(
+ self.machine_st,
+ self.u8s_to_string(skey.public_key.encoded.as_ref())
+ );
unify!(
self.machine_st,
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
let sig = skey.sign_raw(&data);
-
- let sig_list = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- sig.as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- ));
+ let sig_list = step_or_resource_error!(
+ self.machine_st,
+ sized_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ sig.as_ref().len(),
+ sig.as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64)))
+ )
+ );
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
}
&<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap(),
);
- let string = self.u8s_to_string(&result[..]);
+ let string = step_or_resource_error!(self.machine_st, self.u8s_to_string(&result[..]));
unify!(self.machine_st, self.machine_st.registers[3], string);
}
}
#[inline(always)]
- pub(crate) fn load_html(&mut self) {
+ pub(crate) fn load_html(&mut self) -> Result<(), usize> {
if let Some(string) = self
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
let document = scraper::Html::parse_document(&string.as_str());
- let result = self.html_node_to_term(document.tree.root().first_child().unwrap());
+ let result = self.html_node_to_term(document.tree.root().first_child().unwrap())?;
unify!(self.machine_st, self.machine_st.registers[2], result);
} else {
self.machine_st.fail = true;
}
+
+ Ok(())
}
#[inline(always)]
- pub(crate) fn load_xml(&mut self) {
+ pub(crate) fn load_xml(&mut self) -> Result<(), usize> {
if let Some(string) = self
.machine_st
.value_to_str_like(self.machine_st.registers[1])
{
match roxmltree::Document::parse(&string.as_str()) {
Ok(doc) => {
- let result = self.xml_node_to_term(doc.root_element());
+ let result = self.xml_node_to_term(doc.root_element())?;
unify!(self.machine_st, self.machine_st.registers[2], result);
}
_ => {
} else {
self.machine_st.fail = true;
}
+
+ Ok(())
}
#[inline(always)]
{
match env::var(&*key.as_str()) {
Ok(value) => {
- let cstr = put_complete_string(
- &mut self.machine_st.heap,
- &value,
- &self.machine_st.atom_tbl,
+ let cstr = step_or_resource_error!(
+ self.machine_st,
+ self.machine_st.allocate_cstr(&value)
);
unify!(self.machine_st, self.machine_st.registers[2], cstr);
match bytes {
Ok(bs) => {
- let string = self.u8s_to_string(&bs);
+ let string =
+ resource_error_call_result!(self.machine_st, self.u8s_to_string(&bs));
unify!(self.machine_st, self.machine_st.registers[1], string);
}
}
let b64 = b64_engine.encode(bytes);
- let string = self.u8s_to_string(b64.as_bytes());
+ let string =
+ resource_error_call_result!(self.machine_st, self.u8s_to_string(b64.as_bytes()));
unify!(self.machine_st, self.machine_st.registers[2], string);
}
1,
)?;
- let mut parser = Parser::new(stream, &mut self.machine_st);
+ let mut lexer_parser = LexerParser::new(stream, &mut self.machine_st);
- match devour_whitespace(&mut parser) {
+ match devour_whitespace(&mut lexer_parser) {
Ok(false) => {
// not at EOF ...
- stream.add_lines_read(parser.lines_read());
+ stream.add_lines_read(lexer_parser.line_num());
// ... unless we are.
if stream.at_end_of_stream() {
}
}
Ok(true) => {
- stream.add_lines_read(parser.lines_read());
+ stream.add_lines_read(lexer_parser.line_num());
self.machine_st.fail = true;
}
Err(err) => {
if path.is_dir() {
if let Some(path) = path.to_str() {
let path_string =
- put_complete_string(&mut self.machine_st.heap, path, &self.machine_st.atom_tbl);
+ step_or_resource_error!(self.machine_st, self.machine_st.allocate_cstr(path));
unify!(self.machine_st, self.machine_st.registers[1], path_string);
return;
unify!(self.machine_st, self.machine_st.registers[2], pop_count);
}
- pub(super) fn systemtime_to_timestamp(&mut self, system_time: SystemTime) -> Atom {
+ pub(super) fn systemtime_to_timestamp(&mut self, system_time: SystemTime) -> String {
let datetime: DateTime<Local> = system_time.into();
let mut fstr = "[".to_string();
}
fstr.push_str("finis].");
- let s = datetime.format(&fstr).to_string();
-
- AtomTable::build_with(&self.machine_st.atom_tbl, &s)
+ datetime.format(&fstr).to_string()
}
pub(super) fn string_encoding_bytes(
}
}
- pub(super) fn xml_node_to_term(&mut self, node: roxmltree::Node) -> HeapCellValue {
+ pub(super) fn xml_node_to_term(
+ &mut self,
+ node: roxmltree::Node,
+ ) -> Result<HeapCellValue, usize> {
if node.is_text() {
- put_complete_string(
- &mut self.machine_st.heap,
- node.text().unwrap(),
- &self.machine_st.atom_tbl,
- )
+ self.machine_st.allocate_cstr(node.text().unwrap())
} else {
let mut avec = Vec::new();
for attr in node.attributes() {
let name = AtomTable::build_with(&self.machine_st.atom_tbl, attr.name());
- let value = put_complete_string(
- &mut self.machine_st.heap,
- attr.value(),
- &self.machine_st.atom_tbl,
- );
+ let value = self.machine_st.allocate_cstr(attr.value())?;
+
+ avec.push(str_loc_as_cell!(self.machine_st.heap.cell_len()));
- avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
+ let mut writer = self.machine_st.heap.reserve(3)?;
- self.machine_st.heap.push(atom_as_cell!(atom!("="), 2));
- self.machine_st.heap.push(atom_as_cell!(name));
- self.machine_st.heap.push(value);
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("="), 2));
+ section.push_cell(atom_as_cell!(name));
+ section.push_cell(value);
+ });
}
- let attrs = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- avec.into_iter()
- ));
+ let attrs =
+ sized_iter_to_heap_list(&mut self.machine_st.heap, avec.len(), avec.into_iter())?;
let mut cvec = Vec::new();
for child in node.children() {
- cvec.push(self.xml_node_to_term(child));
+ cvec.push(self.xml_node_to_term(child)?);
}
- let children = heap_loc_as_cell!(iter_to_heap_list(
- &mut self.machine_st.heap,
- cvec.into_iter()
- ));
+ let children =
+ sized_iter_to_heap_list(&mut self.machine_st.heap, cvec.len(), cvec.into_iter())?;
let tag = AtomTable::build_with(&self.machine_st.atom_tbl, node.tag_name().name());
+ let result = str_loc_as_cell!(self.machine_st.heap.cell_len());
+ let mut writer = self.machine_st.heap.reserve(4)?;
+
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("element"), 3));
+ section.push_cell(atom_as_cell!(tag));
+ section.push_cell(attrs);
+ section.push_cell(children);
+ });
- let result = str_loc_as_cell!(self.machine_st.heap.len());
-
- self.machine_st
- .heap
- .push(atom_as_cell!(atom!("element"), 3));
- self.machine_st.heap.push(atom_as_cell!(tag));
- self.machine_st.heap.push(attrs);
- self.machine_st.heap.push(children);
-
- result
+ Ok(result)
}
}
pub(super) fn html_node_to_term(
&mut self,
node: ego_tree::NodeRef<'_, scraper::Node>,
- ) -> HeapCellValue {
+ ) -> Result<HeapCellValue, usize> {
match node.value().as_element() {
- None => put_complete_string(
- &mut self.machine_st.heap,
- &node.value().as_text().unwrap().text,
- &self.machine_st.atom_tbl,
- ),
+ None => self
+ .machine_st
+ .allocate_cstr(&node.value().as_text().unwrap().text),
Some(element) => {
let mut avec = Vec::new();
for attr in element.attrs() {
let name = AtomTable::build_with(&self.machine_st.atom_tbl, attr.0);
- let value = put_complete_string(
- &mut self.machine_st.heap,
- attr.1,
- &self.machine_st.atom_tbl,
- );
+ let value = self.machine_st.allocate_cstr(attr.1)?;
+
+ avec.push(str_loc_as_cell!(self.machine_st.heap.cell_len()));
- avec.push(str_loc_as_cell!(self.machine_st.heap.len()));
+ let mut writer = self.machine_st.heap.reserve(3)?;
- self.machine_st.heap.push(atom_as_cell!(atom!("="), 2));
- self.machine_st.heap.push(atom_as_cell!(name));
- self.machine_st.heap.push(value);
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("="), 2));
+ section.push_cell(atom_as_cell!(name));
+ section.push_cell(value);
+ });
}
- let attrs = heap_loc_as_cell!(iter_to_heap_list(
+ let attrs = sized_iter_to_heap_list(
&mut self.machine_st.heap,
- avec.into_iter()
- ));
+ avec.len(),
+ avec.into_iter(),
+ )?;
let mut cvec = Vec::new();
for child in node.children() {
- cvec.push(self.html_node_to_term(child));
+ cvec.push(self.html_node_to_term(child)?);
}
- let children = heap_loc_as_cell!(iter_to_heap_list(
+ let children = sized_iter_to_heap_list(
&mut self.machine_st.heap,
- cvec.into_iter()
- ));
+ cvec.len(),
+ cvec.into_iter(),
+ )?;
let tag = AtomTable::build_with(&self.machine_st.atom_tbl, element.name());
- let result = str_loc_as_cell!(self.machine_st.heap.len());
-
- self.machine_st
- .heap
- .push(atom_as_cell!(atom!("element"), 3));
- self.machine_st.heap.push(atom_as_cell!(tag));
- self.machine_st.heap.push(attrs);
- self.machine_st.heap.push(children);
+ let result = str_loc_as_cell!(self.machine_st.heap.cell_len());
+ let mut writer = self.machine_st.heap.reserve(4)?;
+
+ writer.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("element"), 3));
+ section.push_cell(atom_as_cell!(tag));
+ section.push_cell(attrs);
+ section.push_cell(children);
+ });
- result
+ Ok(result)
}
}
}
- pub(super) fn u8s_to_string(&mut self, data: &[u8]) -> HeapCellValue {
+ pub(super) fn u8s_to_string(&mut self, data: &[u8]) -> Result<HeapCellValue, usize> {
let buffer = String::from_iter(data.iter().map(|b| *b as char));
if buffer.is_empty() {
- empty_list_as_cell!()
+ Ok(empty_list_as_cell!())
} else {
- atom_as_cstr_cell!(AtomTable::build_with(&self.machine_st.atom_tbl, &buffer))
+ self.machine_st.allocate_cstr(&buffer)
}
}
}
use crate::machine::machine_errors::*;
use crate::machine::*;
use crate::parser::ast::*;
+use crate::parser::lexer::*;
use crate::parser::parser::*;
use crate::read::devour_whitespace;
pub(super) module_op_exports: ModuleOpExports,
pub(super) non_counted_bt_preds: IndexSet<PredicateKey, FxBuildHasher>,
pub(super) predicates: PredicateQueue,
- pub(super) clause_clauses: Vec<FocusedHeap>,
+ pub(super) clause_clauses: Vec<TermWriteResult>,
}
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 listing_src(&self) -> &ListingSource;
}
#[derive(Debug)]
pub struct BootstrappingTermStream<'a> {
listing_src: ListingSource,
- pub(super) parser: Parser<'a, Stream>,
+ pub(super) lexer_parser: LexerParser<'a, Stream>,
}
impl<'a> BootstrappingTermStream<'a> {
machine_st: &'a mut MachineState,
listing_src: ListingSource,
) -> Self {
- let parser = Parser::new(stream, machine_st);
- Self {
- parser,
- listing_src,
- }
+ let lexer_parser = LexerParser::new(stream, machine_st);
+ Self { lexer_parser, listing_src }
}
}
impl<'a> TermStream for BootstrappingTermStream<'a> {
#[inline]
- fn next(&mut self, op_dir: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
- self.parser.reset();
- self.parser
- .read_term(op_dir, Tokens::Default)
- .map_err(CompilationError::from)
+ fn next(&mut self, op_dir: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
+ let result = self.lexer_parser.read_term(op_dir, Tokens::Default)
+ .map_err(CompilationError::from);
+
+ result
}
#[inline]
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)
}
}
pub struct LiveTermStream {
- pub(super) term_queue: VecDeque<FocusedHeap>,
+ pub(super) term_queue: VecDeque<TermWriteResult>,
pub(super) listing_src: ListingSource,
}
impl TermStream for LiveTermStream {
#[inline]
- fn next(&mut self, _: &CompositeOpDir) -> Result<FocusedHeap, CompilationError> {
+ fn next(&mut self, _: &CompositeOpDir) -> Result<TermWriteResult, CompilationError> {
Ok(self.term_queue.pop_front().unwrap())
}
pub struct 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())))
}
use crate::forms::*;
use crate::heap_iter::{stackful_preorder_iter, NonListElider};
use crate::machine::machine_state::*;
-use crate::machine::partial_string::*;
use crate::machine::*;
use crate::types::*;
-use std::cmp::Ordering;
use std::ops::{Deref, DerefMut};
use derive_more::*;
use indexmap::IndexSet;
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> {
fn unify_structure(&mut self, s1: usize, value: HeapCellValue) {
// s1 is the value of a STR cell.
self.fail = true;
}
}
- (HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr | HeapCellValueTag::PStr) => {
- Self::unify_partial_string(self, list_loc_as_cell!(l1), value)
+ (HeapCellValueTag::PStrLoc, l) => {
+ Self::unify_partial_string(self, l, list_loc_as_cell!(l1))
}
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), list_loc_as_cell!(l1));
);
}
- 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 atom == atom!("") {
- Self::bind(self, r, atom_as_cell!(atom!("[]")));
- } else {
- Self::bind(self, r, atom_as_cstr_cell!(atom));
- }
-
+ Self::bind(self, r, pstr_loc_as_cell!(pstr_loc));
return;
}
+ let machine_st = self.deref_mut();
+
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])
+ let (name, arity) = cell_as_atom_cell!(machine_st.heap[s])
.get_name_and_arity();
- if arity == 0 {
- self.fail = atom == atom!("") && name != atom!("[]");
+ if name == atom!(".") && arity == 2 {
+ machine_st.partial_string_to_pdl(pstr_loc, s+1);
} 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);
- }
+ machine_st.fail = true;
}
}
- (HeapCellValueTag::CStr, cstr_atom) => {
- self.fail = atom != cstr_atom;
+ (HeapCellValueTag::Lis, l) => {
+ machine_st.partial_string_to_pdl(pstr_loc, l);
}
- (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
- Self::unify_partial_string(self, atom_as_cstr_cell!(atom), value);
+ (HeapCellValueTag::PStrLoc, other_pstr_loc) => {
+ let cmp_result = machine_st.heap.compare_pstr_segments(pstr_loc, other_pstr_loc);
- if !self.pdl.is_empty() {
- Self::unify_internal(self);
+ if cmp_result.continue_pstr_compare(&mut machine_st.pdl).is_some() {
+ debug_assert!(matches!(cmp_result, PStrSegmentCmpResult::Mismatch { .. }));
+ machine_st.fail = true;
}
}
_ => {
- self.fail = true;
+ machine_st.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;
- }
-
- let machine_st = self.deref_mut();
-
- let s1 = machine_st.heap.len();
-
- machine_st.heap.push(value_1);
- machine_st.heap.push(value_2);
-
- 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 {
- 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;
- } else {
- machine_st.pdl.push(empty_list_as_cell!());
- machine_st.pdl.push(pstr_iter1.focus);
- }
- }
- continuable @ PStrCmpResult::FirstIterContinuable(iteratee)
- | continuable @ PStrCmpResult::SecondIterContinuable(iteratee) => {
- if continuable.is_second_iter() {
- std::mem::swap(&mut pstr_iter1, &mut pstr_iter2);
- }
-
- let mut chars_iter = PStrCharsIter {
- iter: pstr_iter1,
- item: Some(iteratee),
- };
-
- 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.pdl.push(pstr_iter2.focus);
- }
- }
-
- machine_st.heap.pop();
- machine_st.heap.pop();
- }
-
fn unify_atom(&mut self, atom: Atom, value: HeapCellValue) {
read_heap_cell!(value,
(HeapCellValueTag::Atom, (name, arity)) => {
self.fail = !(arity == 0 && name == atom);
}
+ /*
(HeapCellValueTag::CStr, cstr_atom) if atom == atom!("[]") => {
self.fail = cstr_atom != atom!("");
}
self.fail = true;
}
}
+ */
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), atom_as_cell!(atom));
}
self.fail = true;
}
}
+ /*
(HeapCellValueTag::Char, c2) => {
if c != c2 {
self.fail = true;
}
}
+ */
(HeapCellValueTag::AttrVar, h) => {
Self::bind(self, Ref::attr_var(h), char_as_cell!(c));
}
tabu_list.insert((d1, d2));
}
}
- (HeapCellValueTag::PStrLoc) => {
+ (HeapCellValueTag::PStrLoc, l) => {
read_heap_cell!(d2,
(HeapCellValueTag::PStrLoc |
HeapCellValueTag::Lis |
continue;
}
}
- (HeapCellValueTag::CStr |
- HeapCellValueTag::AttrVar |
+ (HeapCellValueTag::AttrVar |
HeapCellValueTag::Var |
HeapCellValueTag::StackVar) => {
}
}
);
- Self::unify_partial_string(self, d1, d2);
+ Self::unify_partial_string(self, l, d2);
if !self.fail && !d2.is_constant() {
let d2 = self.store(d2);
tabu_list.insert((d1, d2));
}
}
+ /*
(HeapCellValueTag::CStr) => {
read_heap_cell!(d2,
(HeapCellValueTag::AttrVar, h) => {
Self::unify_partial_string(self, d2, d1);
}
+ */
(HeapCellValueTag::F64, f1) => {
Self::unify_f64(self, f1, d2);
}
(HeapCellValueTag::Fixnum, n1) => {
Self::unify_fixnum(self, n1, d2);
}
+ /*
(HeapCellValueTag::Char, c1) => {
Self::unify_char(self, c1, d2);
}
+ */
(HeapCellValueTag::Cons, ptr_1) => {
Self::unify_constant(self, ptr_1, d2);
}
let value = machine_st.store(MachineState::deref(machine_st, value));
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>(
&mut machine_st.heap,
&mut machine_st.stack,
- root_loc, // value,
+ 0,
) {
let cell = unmark_cell_bits!(cell);
/* A simple macro to count the arguments in a variadic list
* 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 {
($c: expr) => {
- HeapCellValue::build_with(HeapCellValueTag::Char, $c as u64)
+ HeapCellValue::from_bytes(AtomCell::new_char_inlined($c).into_bytes())
};
}
macro_rules! atom_as_cell {
($atom:expr) => {
- HeapCellValue::from_bytes(
- AtomCell::build_with($atom.flat_index(), 0, HeapCellValueTag::Atom).into_bytes(),
- )
+ HeapCellValue::from_bytes(AtomCell::build_with($atom.index, 0).into_bytes())
};
($atom:expr, $arity:expr) => {
- HeapCellValue::from_bytes(
- AtomCell::build_with($atom.flat_index(), $arity as u16, HeapCellValueTag::Atom)
- .into_bytes(),
- )
+ HeapCellValue::from_bytes(AtomCell::build_with($atom.index, $arity as u8).into_bytes())
};
}
-macro_rules! cell_as_string {
+macro_rules! cell_as_atom {
($cell:expr) => {
- PartialString::from(cell_as_atom!($cell))
+ AtomCell::from_bytes($cell.into_bytes()).get_name()
};
}
-macro_rules! cell_as_atom {
- ($cell:expr) => {{
- let cell = AtomCell::from_bytes($cell.into_bytes());
- let name = (cell.get_index() as u64) << 3;
-
- Atom::from(name)
- }};
-}
-
macro_rules! cell_as_atom_cell {
($cell:expr) => {
AtomCell::from_bytes($cell.into_bytes())
};
}
-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 {
($h:expr) => {
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 {
($h:expr) => {
HeapCellValue::build_with(HeapCellValueTag::Lis, $h as u64)
};
}
-macro_rules! atom_as_cstr_cell {
- ($atom:expr) => {{
- let offset = $atom.flat_index();
-
- 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! stream_as_cell {
+ ($ptr:expr) => {
+ raw_ptr_as_cell!($ptr.as_ptr())
+ };
}
macro_rules! cell_as_stream {
#[allow(unused_braces)]
$code
}};
+ /*
($cell:ident, PStr, $atom:ident, $code:expr) => {{
let $atom = cell_as_atom!($cell);
#[allow(unused_braces)]
#[allow(unused_braces)]
$code
}};
+ */
($cell:ident, Fixnum, $value:ident, $code:expr) => {{
let $value = Fixnum::from_bytes($cell.into_bytes());
#[allow(unused_braces)]
});
}
-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 {
($cmp: expr, $at_1: expr, $at_2: expr) => {{
$cmp.set_terms($at_1, $at_2);
$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>())
+ };
+}
use crate::arena::*;
use crate::atom_table::*;
use crate::forms::PredicateKey;
-use crate::machine::copier::*;
use crate::machine::heap::*;
use crate::machine::machine_indices::*;
-use crate::machine::machine_state::*;
use crate::types::*;
use std::fmt;
use std::io::{Error as IOError, ErrorKind};
use std::ops::Neg;
use std::rc::Rc;
-use std::sync::Arc;
use std::vec::Vec;
-use crate::parser::dashu::{Integer, Rational};
-
use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use scryer_modular_bitfield::error::OutOfBounds;
pub type Specifier = u32;
-pub const MAX_ARITY: usize = 1023;
+pub const MAX_ARITY: usize = 255;
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub const NEGATIVE_SIGN: u32 = 0x0200;
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)
.map(<$wrapper>::Fixnum)
.unwrap_or_else(|_| <$wrapper>::Integer(arena_alloc!(Integer::from($n), $arena)))
}
}
-#[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 {
($x:expr) => {
$crate::parser::ast::RegType::Temp($x)
};
}
-#[macro_export]
-macro_rules! perm_v {
- ($x:expr) => {
- $crate::parser::ast::RegType::Perm($x)
- };
-}
-
#[bitfield]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct OpDesc {
#[derive(Debug, Clone)]
pub enum ArithmeticError {
NonEvaluableFunctor(HeapCellValue, usize),
- UninstantiatedVar,
}
#[derive(Debug, Copy, Clone, Default)]
MissingQuote(ParserErrorSrc),
NonPrologChar(ParserErrorSrc),
ParseBigInt(ParserErrorSrc),
+ ResourceError(ParserErrorSrc),
UnexpectedChar(char, ParserErrorSrc),
// UnexpectedEOF,
Utf8Error(ParserErrorSrc),
| &ParserError::MissingQuote(err_src)
| &ParserError::NonPrologChar(err_src)
| &ParserError::ParseBigInt(err_src)
+ | &ParserError::ResourceError(err_src)
| &ParserError::UnexpectedChar(_, err_src)
| &ParserError::Utf8Error(err_src) => err_src,
}
ParserError::ParseBigInt(..) => atom!("cannot_parse_big_int"),
ParserError::UnexpectedChar(..) => atom!("unexpected_char"),
ParserError::Utf8Error(..) => atom!("utf8_conversion_error"),
+ ParserError::ResourceError(..) => atom!("resource_error"),
}
}
}
}
}
-/*
-impl From<lexical::Error> for ParserError {
- fn from((e, err_src): (lexical::Error, ParserErrorSrc)) -> ParserError {
- ParserError::LexicalError(e, err_src)
- }
-}
-impl From<IOError> for ParserError {
- fn from(e: IOError) -> ParserError {
- ParserError::IO(e)
+impl From<ParserErrorSrc> for ParserError {
+ fn from(err_src: ParserErrorSrc) -> ParserError {
+ ParserError::LexicalError(err_src)
}
}
-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)]
pub struct CompositeOpDir<'a, 'b> {
pub primary_op_dir: Option<&'b OpDir>,
}
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+/*
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Literal {
Atom(Atom),
- Char(char),
CodeIndex(CodeIndex),
Fixnum(Fixnum),
Integer(TypedArenaPtr<Integer>),
Rational(TypedArenaPtr<Rational>),
Float(F64Offset),
- String(Atom),
+ String(Rc<String>),
}
impl From<F64Ptr> for Literal {
Literal::Atom(ref atom) => {
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::Fixnum(n) => write!(f, "{}", n.get_num()),
Literal::Integer(ref n) => write!(f, "{}", n),
}
}
}
+*/
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];
if subterm.is_ref() {
AnonVar,
Clause(Cell<RegType>, Atom, Vec<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
// other PartialString variants in as_partial_string.
- PartialString(Cell<RegType>, String, Box<Term>),
- CompleteString(Cell<RegType>, Atom),
+ PartialString(Cell<RegType>, Rc<String>, Box<Term>),
+ CompleteString(Cell<RegType>, Rc<String>),
Var(Cell<VarReg>, VarPtr),
}
pub fn name(&self) -> Option<Atom> {
match self {
- &Term::Literal(_, Literal::Atom(ref atom)) | &Term::Clause(_, ref atom, ..) => {
- Some(*atom)
+ Term::Literal(_, cell) => {
+ cell.to_atom()
+ }
+ &Term::Clause(_, atom, ..) => {
+ Some(atom)
}
_ => None,
}
*/
pub(crate) fn fetch_index_ptr(
- heap: &[HeapCellValue],
+ heap: &impl SizedHeap,
arity: usize,
term_loc: usize,
) -> 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;
}
}
pub(crate) fn blunt_index_ptr(
- heap: &mut [HeapCellValue],
+ heap: &mut impl SizedHeapMut,
key: PredicateKey,
term_loc: usize,
) -> bool {
}
pub(crate) fn unfold_by_str_once(
- heap: &mut [HeapCellValue],
+ heap: &mut impl SizedHeapMut,
start_term: HeapCellValue,
atom: Atom,
) -> Option<usize> {
}
pub fn unfold_by_str(
- heap: &mut [HeapCellValue],
+ heap: &mut impl SizedHeapMut,
mut start_term: HeapCellValue,
atom: Atom,
) -> Vec<HeapCellValue> {
*/
pub fn unfold_by_str_locs(
- heap: &mut [HeapCellValue],
+ heap: &mut impl SizedHeapMut,
mut term_loc: usize,
atom: Atom,
) -> Vec<(HeapCellValue, usize)> {
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 {
read_heap_cell!(heap[term_loc],
- (HeapCellValueTag::Atom, (name, _arity)) => {
- return Some(name);
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ return Some((name, arity));
}
(HeapCellValueTag::Str, s) => {
term_loc = s;
}
}
-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 {
let mut occurrence_set: IndexMap<HeapCellValue, usize, FxBuildHasher> =
IndexMap::with_hasher(FxBuildHasher::default());
}
*/
-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 {
read_heap_cell!(heap[term_loc],
(HeapCellValueTag::Str, s) => {
}
}
-pub type VarLocs = IndexMap<Var, HeapCellValue, FxBuildHasher>;
-pub type InverseVarLocs = IndexMap<usize, Var, FxBuildHasher>;
-
#[derive(Debug)]
-pub struct FocusedHeap {
- pub heap: Vec<HeapCellValue>,
+pub struct TermWriteResult {
pub focus: usize,
pub inverse_var_locs: InverseVarLocs,
}
-impl FocusedHeap {
- pub fn empty() -> Self {
- 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)
- }
-}
+pub type VarLocs = IndexMap<Var, HeapCellValue, FxBuildHasher>;
+pub type InverseVarLocs = IndexMap<usize, Var, FxBuildHasher>;
+#[derive(Debug)]
pub struct FocusedHeapRefMut<'a> {
- pub heap: &'a mut Vec<HeapCellValue>,
+ pub heap: &'a mut Heap,
pub focus: usize,
}
impl<'a> FocusedHeapRefMut<'a> {
- pub fn name(&self, term_loc: usize) -> Option<Atom> {
- term_name(&self.heap, term_loc)
+ #[inline]
+ 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 {
- 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 {
- use crate::machine::heap::*;
-
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> {
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,
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
h
}
_ => {
let h = heap.len();
- heap.push(cell);
+ heap.push_cell(cell).unwrap();
h
}
Self { heap, focus }
}
+ */
}
use crate::arena::F64Ptr;
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::machine::heap::*;
pub use crate::machine::machine_state::*;
use crate::parser::ast::*;
use crate::parser::char_reader::*;
use crate::parser::dashu::Integer;
+use crate::types::*;
use std::convert::TryFrom;
use std::fmt;
#[derive(Debug, PartialEq)]
pub enum Token {
- Literal(Literal),
+ Literal(HeapCellValue),
Var(String),
+ String(String),
Open, // '('
OpenCT, // '('
Close, // ')'
}
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]
pub(super) fn is_end(&self) -> bool {
matches!(self, Token::End)
}};
}
-pub struct Lexer<'a, R> {
+pub(crate) struct LexerParser<'a, R> {
pub(crate) reader: R,
pub(crate) machine_st: &'a mut MachineState,
pub(crate) line_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 {
- f.debug_struct("Lexer")
+ f.debug_struct("LexerParser")
.field("reader", &"&'a mut R") // Hacky solution.
.field("line_num", &self.line_num)
.field("col_num", &self.col_num)
}
}
-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 {
- Lexer {
+ LexerParser {
reader: src,
machine_st,
line_num: 0,
}
}
- #[inline]
- pub fn loc_to_err_src(&self) -> ParserErrorSrc {
- ParserErrorSrc { line_num: self.line_num, col_num: self.col_num }
- }
-
#[inline(always)]
fn return_char(&mut self, c: char) {
self.reader.put_back_char(c);
if !token.is_empty() && token.chars().nth(1).is_none() {
if let Some(c) = token.chars().next() {
- return Ok(Token::Literal(Literal::Char(c)));
+ return Ok(Token::Literal(char_as_cell!(c)));
}
}
} else {
- return Err(ParserError::InvalidSingleQuotedCharacter(c, self.loc_to_err_src()));
+ return Err(ParserError::InvalidSingleQuotedCharacter(self.loc_to_err_src()));
}
} else {
match self.get_back_quoted_string() {
}
if token.as_str() == "[]" {
- Ok(Token::Literal(Literal::Atom(atom!("[]"))))
+ Ok(Token::Literal(empty_list_as_cell!()))
} else {
- Ok(Token::Literal(Literal::Atom(AtomTable::build_with(
+ Ok(Token::Literal(atom_as_cell!(AtomTable::build_with(
&self.machine_st.atom_tbl,
&token,
))))
}
}
- fn parse_lossy_wrapper<T: FromLexicalLossy>(&self, token: String) -> Result<T, ParserError> {
- match parse_lossy::<T, _>(token.as_bytes()) {
+ fn parse_lossy_wrapper<T: FromLexical>(&self, token: &str) -> Result<T, ParserError> {
+ match parse::<T, _>(token.as_bytes()) {
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> {
self.return_char(token.pop().unwrap());
- let n = self.parse_lossy_wrapper::<f64>(token)?;
- Ok(Token::Literal(Literal::from(float_alloc!(n, self.machine_st.arena))))
+ let n = self.parse_lossy_wrapper::<f64>(&token)?;
+ Ok(Token::Literal(HeapCellValue::from(float_alloc!(
+ n,
+ self.machine_st.arena
+ ))))
}
fn skip_underscore_in_number(&mut self) -> Result<char, ParserError> {
}
}
- let n = parse_float_lossy(&token)?;
- Ok(NumberToken::Number(Number::Float(float_alloc!(
+ let n = self.parse_lossy_wrapper::<f64>(&token)?;
+ Ok(Token::Literal(HeapCellValue::from(float_alloc!(
n,
self.machine_st.arena
))))
return self.vacate_with_float(token).map(NumberToken::Number);
}
} else {
- let n = parse_float_lossy(&token)?;
- Ok(NumberToken::Number(Number::Float(float_alloc!(
+ let n = self.parse_lossy_wrapper::<f64>(&token)?;
+ Ok(Token::Literal(HeapCellValue::from(float_alloc!(
n,
self.machine_st.arena
))))
if 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 {
- 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 {
- Ok(Token::Literal(Literal::String(atom)))
+ Ok(Token::String(s))
};
}
}
}
}
-
-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)
-}
use crate::arena::*;
use crate::atom_table::*;
-use crate::machine::heap::{heap_bound_deref, heap_bound_store};
-use crate::machine::partial_string::*;
+use crate::forms::Number;
+use crate::machine::heap::*;
use crate::parser::ast::*;
use crate::parser::char_reader::*;
use crate::parser::lexer::*;
use crate::types::*;
-use std::mem;
use std::ops::Neg;
use std::rc::Rc;
#[derive(Debug)]
pub enum Tokens {
Default,
- Provided(Vec<Token>),
+ Provided(Vec<Token>, usize),
}
impl TokenType {
}
#[derive(Debug)]
-pub struct Parser<'a, R> {
- pub lexer: Lexer<'a, R>,
+struct Parser<'a> {
tokens: Vec<Token>,
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,
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 term_size = 0;
loop {
match lexer.next_token() {
Ok(token) => {
let at_end = token.is_end();
+ term_size += token.byte_size(lexer.machine_st.flags);
tokens.push(token);
if at_end {
tokens.reverse();
- Ok(tokens)
-}
-
-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,
- }
+ Ok((tokens, term_size))
}
pub(crate) fn as_partial_string(
- heap: &[HeapCellValue],
+ heap: &impl SizedHeap,
head: HeapCellValue,
tail: HeapCellValue,
) -> Option<(String, Option<HeapCellValue>)> {
return None;
}
}
- (HeapCellValueTag::Char, c) => {
- c.to_string()
- }
_ => {
return None;
}
break;
}
}
- (HeapCellValueTag::Char, c) => {
- string.push(c);
- }
_ => {
return None;
}
tail = heap[l+1];
}
(HeapCellValueTag::PStrLoc, l) => {
- let (index, n) = pstr_loc_and_offset(&heap, l);
- let n = n.get_num() as usize;
-
- 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;
+ let (pstr, tail_loc) = heap.scan_slice_to_str(l);
+ string += pstr;
+ tail = heap[tail_loc];
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
if heap[h] != tail {
)
}
-impl<'a, R: CharRead> Parser<'a, R> {
- 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(),
- }
- }
-
+impl<'a> Parser<'a> {
fn get_term_name(&self, td: TokenDesc) -> Option<Atom> {
match td.tt {
TokenType::HeadTailSeparator => Some(atom!("|")),
TokenType::Comma => Some(atom!(",")),
TokenType::Term { heap_loc } => {
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 {
None
}
}
}
- #[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(
&mut self,
op: TokenDesc,
} = operand_1
{
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.push(arg1);
- self.terms.push(arg2);
+ self.terms.write_with(|section| {
+ section.push_cell(atom_as_cell!(name, 2));
+ 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 {
tt: TokenType::Term {
}
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 {
tt: TokenType::Term { heap_loc: arg1 },
..
} = 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.push(arg1);
- self.terms.push(str_loc_as_cell!(str_loc));
+ self.terms.write_with(|section| {
+ section.push_cell(atom_as_cell!(name, 1));
+ section.push_cell(arg1);
+ section.push_cell(str_loc_as_cell!(str_loc));
+ });
self.stack.push(TokenDesc {
tt: TokenType::Term {
}
fn promote_atom_op(&mut self, atom: Atom, priority: usize, assoc: u32) {
- let h = self.terms.len();
- self.terms.push(atom_as_cell!(atom));
+ let h = self.terms.cell_len();
+ self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom)));
self.stack.push(TokenDesc {
tt: TokenType::Term {
heap_loc: heap_loc_as_cell!(h),
}
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 {
- Token::Literal(Literal::String(s))
- if self.lexer.machine_st.flags.double_quotes.is_codes() =>
- {
+ Token::String(s) if self.flags.double_quotes.is_codes() => {
let mut list = empty_list_as_cell!();
- for c in s.as_str().chars().rev() {
- let h = self.terms.len();
+ self.terms.write_with(|section| {
+ for c in s.as_str().chars().rev() {
+ let h = section.cell_len();
- self.terms
- .push(fixnum_as_cell!(Fixnum::build_with(c as i64)));
- self.terms.push(list);
+ section.push_cell(fixnum_as_cell!(Fixnum::build_with(c as i64)));
+ section.push_cell(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 }
}
- Token::Literal(Literal::String(s))
- if self.lexer.machine_st.flags.double_quotes.is_chars() =>
- {
- if s.is_empty() {
- self.terms.push(empty_list_as_cell!());
- } else {
- self.terms.push(string_as_cstr_cell!(s));
- }
+ Token::String(s) => {
+ debug_assert!(self.flags.double_quotes.is_chars());
+ let mut pstr_cell = heap_loc;
- 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()));
+ if s == "\u{0}" {
+ let h = self.terms.cell_len();
- TokenType::Term { heap_loc }
+ 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 {
+ 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 }
+ }
}
Token::Literal(c) => {
- self.terms.push(HeapCellValue::from(c));
+ self.terms.write_with(|section| section.push_cell(c));
TokenType::Term { heap_loc }
}
Token::Var(var_string) => {
match self.var_locs.get(&var).cloned() {
Some(heap_loc) => {
- self.terms.push(heap_loc);
+ self.terms.write_with(|section| section.push_cell(heap_loc));
TokenType::Term { heap_loc }
}
None => {
- self.terms.push(heap_loc);
+ self.terms.write_with(|section| section.push_cell(heap_loc));
// if var_string == "_", it not being present
// as a key of self.var_locs means it is
return false;
}
- if self.terms.len() < arity {
+ if self.terms.cell_len() < arity {
return false;
}
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 {
- 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) {
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();
- parser.terms.push(str_loc_as_cell!(term_idx));
+ let str_loc_idx = parser.terms.cell_len();
+ parser.terms.write_with(|section| section.push_cell(str_loc_as_cell!(term_idx)));
TokenType::Term {
heap_loc: heap_loc_as_cell!(str_loc_idx),
{
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.
let new_tt = if name == atom!(".") && arity == 2 {
let head = self.term_from_stack(stack_len + 2).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) {
- Some((string_buf, Some(tail))) => {
- let atom =
- AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
+ Some((string_buf, tail_opt)) => {
+ 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));
- self.terms.push(tail);
- self.terms.push(pstr_loc_as_cell!(term_idx));
+ let heap_loc = cell_index!(bytes_written) - 1 + cell_len;
TokenType::Term {
- heap_loc: heap_loc_as_cell!(term_idx + 2),
- }
- }
- 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),
+ heap_loc: heap_loc_as_cell!(heap_loc),
}
}
None => {
- self.terms.push(head);
- self.terms.push(tail);
- self.terms.push(list_loc_as_cell!(term_idx));
+ let bytes_written = self.terms.write_with(|section| {
+ section.push_cell(head);
+ section.push_cell(tail);
+ section.push_cell(list_loc_as_cell!(term_idx));
+ });
TokenType::Term {
- heap_loc: heap_loc_as_cell!(term_idx + 2),
+ heap_loc: heap_loc_as_cell!(
+ cell_len + cell_index!(bytes_written) - 1
+ ),
}
}
}
false
}
- pub fn reset(&mut self) {
- self.stack.clear();
- self.var_locs.clear();
+ fn loc_to_err_src(&self) -> ParserErrorSrc {
+ ParserErrorSrc { line_num: *self.line_num, col_num: *self.col_num }
}
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
);
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
* an operator, so expand the
* terms it compacted out again. */
let focus = term.get_value() as usize;
- let name_opt = term_name(&self.terms, focus);
- let arity = term_arity(&self.terms, focus);
+ let key_opt = term_predicate_key(&self.terms, focus);
- if name_opt == Some(atom!(",")) && arity == 2 {
+ if key_opt == Some((atom!(","), 2)) {
let terms = if op_desc.unfold_bounds == 0 {
unfold_by_str(&mut self.terms, term, atom!(","))
} else {
if let Some(ref mut td) = self.stack.last_mut() {
// parsed an empty list token
if td.tt == TokenType::OpenList {
- let h = self.terms.len();
- self.terms.push(empty_list_as_cell!());
+ let h = self.terms.cell_len();
+ self.terms.write_with(|section| section.push_cell(empty_list_as_cell!()));
td.spec = TERM;
td.tt = TokenType::Term {
Some(term) => term,
None => {
return Err(ParserError::IncompleteReduction(
- self.lexer.loc_to_err_src(),
+ self.loc_to_err_src(),
));
}
};
tail_term
};
- if arity > self.terms.len() {
+ if arity > self.terms.cell_len() {
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() {
let subterm = match token_desc.tt {
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.push(subterm);
- self.terms.push(tail_term);
+ self.terms.write_with(|section| {
+ section.push_cell(link_cell);
+ section.push_cell(subterm);
+ section.push_cell(tail_term);
+ });
tail_term = link_cell;
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 tail_term = self.terms[list_loc + 2];
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);
- let atom = AtomTable::build_with(&self.lexer.machine_st.atom_tbl, &string_buf);
-
- self.terms.push(string_as_pstr_cell!(atom));
- 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));
+ 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);
+ });
- heap_loc_as_cell!(pre_terms_len)
+ heap_loc_as_cell!(pre_terms_len + cell_index!(bytes_written) - 1)
}
None => {
heap_loc_as_cell!(list_loc) // head_term
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)
}
if let Some(ref mut td) = self.stack.last_mut() {
if td.tt == TokenType::OpenCurly {
- let h = self.terms.len();
- self.terms.push(atom_as_cell!(atom!("{}")));
+ let h = self.terms.cell_len();
+
+ self.terms.write_with(|section| section.push_cell(atom_as_cell!(atom!("{}"))));
td.tt = TokenType::Term {
heap_loc: heap_loc_as_cell!(h),
if oc.tt == TokenType::OpenCurly {
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 {
heap_loc: heap_loc_as_cell!(curly_idx + 2),
oc.priority = 0;
oc.spec = TERM;
- self.terms.push(atom_as_cell!(atom!("{}"), 1));
- self.terms.push(heap_loc);
- self.terms.push(str_loc_as_cell!(curly_idx));
+ self.terms.write_with(|section| {
+ section.push_cell(atom_as_cell!(atom!("{}"), 1));
+ section.push_cell(heap_loc);
+ section.push_cell(str_loc_as_cell!(curly_idx));
+ });
/*
let term = match self.terms.pop() {
let term = if self.stack[idx].tt.sep_to_atom().is_some() {
atom_as_cell!(atom!("|"))
- // self.terms
- // .push(Term::Literal(Cell::default(), Literal::Atom(atom)));
} else {
self.term_from_stack(idx).unwrap()
};
match self
.tokens
.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,
// ie. why we don't match on Token::Open.
fn negate_number<N, Negator, ToLiteral>(&mut self, n: N, negator: Negator, constr: ToLiteral)
where
Negator: Fn(N, &mut Arena) -> N,
- ToLiteral: Fn(N, &mut Arena) -> Literal,
+ ToLiteral: Fn(N, &mut Arena) -> HeapCellValue,
{
match self.stack.last().cloned() {
Some(
if name == atom!("-") && (is_prefix!(spec) || is_negate!(spec)) {
self.stack.pop();
- let arena = &mut self.lexer.machine_st.arena;
+ let arena = &mut self.arena;
let literal = constr(negator(n, arena), arena);
self.shift(Token::Literal(literal), 0, TERM);
_ => {}
}
- let literal = constr(n, &mut self.lexer.machine_st.arena);
+ let literal = constr(n, &mut self.arena);
self.shift(Token::Literal(literal), 0, TERM);
}
}
match token {
- Token::Literal(Literal::Fixnum(n)) => {
- self.negate_number(n, |n, _| -n, |n, _| Literal::Fixnum(n))
+ Token::String(string) => {
+ 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) => {
- let atomized = atomize_literal(&self.lexer.machine_st.atom_tbl, c);
-
- if let Some(name) = atomized {
- if !self.shift_op(name, op_dir)? {
- self.shift(Token::Literal(c), 0, TERM);
+ match Number::try_from(c) {
+ Ok(Number::Integer(n)) => {
+ self.negate_number(n, negate_int_rc, |n, _| typed_arena_ptr_as_cell!(n))
+ }
+ 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::Close => {
if !self.reduce_term() && !self.reduce_brackets() {
return Err(ParserError::IncompleteReduction(
- self.lexer.loc_to_err_src(),
+ self.loc_to_err_src(),
));
}
}
Token::CloseList => {
if !self.reduce_list()? {
return Err(ParserError::IncompleteReduction(
- self.lexer.loc_to_err_src(),
+ self.loc_to_err_src(),
));
}
}
Token::CloseCurly => {
if !self.reduce_curly()? {
return Err(ParserError::IncompleteReduction(
- self.lexer.loc_to_err_src(),
+ self.loc_to_err_src(),
));
}
}
| Some(TokenType::HeadTailSeparator)
| Some(TokenType::Comma) => {
return Err(ParserError::IncompleteReduction(
- self.lexer.loc_to_err_src(),
+ self.loc_to_err_src(),
))
}
_ => {}
Ok(())
}
+}
+impl<'a, R: CharRead> LexerParser<'a, R> {
#[inline]
- pub fn lines_read(&self) -> usize {
- self.lexer.line_num
+ pub fn line_num(&self) -> usize {
+ 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.
&mut self,
op_dir: &CompositeOpDir,
tokens: Tokens,
- ) -> Result<FocusedHeap, ParserError> {
- self.tokens = match tokens {
- Tokens::Default => read_tokens(&mut self.lexer)?,
- Tokens::Provided(tokens) => tokens,
+ ) -> Result<TermWriteResult, ParserError> {
+ let (tokens, term_byte_size) = match tokens {
+ Tokens::Default => read_tokens(self)?,
+ Tokens::Provided(tokens, size) => (tokens, size),
+ };
+
+ // the parser uses conditional indirection in many places so
+ // 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()));
+ }
};
- while let Some(token) = self.tokens.pop() {
- self.shift_token(token, op_dir)?;
+ 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);
+
+ let after_len = parser_impl.terms.cell_len();
+
+ debug_assert!(after_len - before_len <= cell_index!(4 * term_byte_size));
- if self.stack.len() > 1 || self.terms.is_empty() {
+ if parser_impl.stack.len() > 1 || parser_impl.terms.is_empty() {
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 {
tt: TokenType::Term { heap_loc },
..
- }) => Ok(FocusedHeap {
- heap: mem::replace(&mut self.terms, vec![]),
+ }) => Ok(TermWriteResult {
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(
- self.lexer.loc_to_err_src(),
+ parser_impl.loc_to_err_src(),
)),
}
}
use crate::atom_table::*;
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::parser::char_reader::*;
+use crate::parser::lexer::LexerParser;
#[cfg(feature = "repl")]
use crate::repl_helper::Helper;
use std::sync::Arc;
pub(crate) fn devour_whitespace<R: CharRead>(
- parser: &mut Parser<'_, R>,
+ lexer: &mut LexerParser<'_, R>,
) -> 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) => Err(e),
Ok(_) => Ok(false),
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 {
pub(crate) fn read<R: CharRead>(
&mut self,
inner: R,
op_dir: &OpDir,
- ) -> Result<(FocusedHeap, usize), ParserError> {
- let mut parser = Parser::new(inner, self);
+ ) -> Result<(TermWriteResult, usize), ParserError> {
+ let mut lexer_parser = LexerParser::new(inner, self);
let op_dir = CompositeOpDir::new(op_dir, None);
- let term_result = parser.read_term(&op_dir, Tokens::Default);
- let lines_read = parser.lines_read();
+ let term_result = lexer_parser.read_term(&op_dir, Tokens::Default);
+ let lines_read = lexer_parser.line_num();
term_result.map(|term| (term, lines_read))
}
}
};
- Ok(term.to_machine_heap(self))
+ Ok(term)
}
}
self.pending_input.put_back_char(c);
}
}
-
-#[derive(Debug)]
-pub struct TermWriteResult {
- pub heap_loc: usize,
- pub inverse_var_locs: InverseVarLocs,
-}
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
pub struct Helper {
let mut matching = index_set
.iter()
- .chain(STATIC_ATOMS_MAP.values())
+ // .chain(STATIC_ATOMS_MAP.values())
.map(|a| a.as_str())
.filter(|a| a.starts_with(sub_str))
.collect::<Vec<_>>();
use crate::instructions::*;
use crate::types::*;
+use std::rc::Rc;
+
pub(crate) struct FactInstruction;
pub(crate) struct QueryInstruction;
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_structure(lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction;
fn to_void(num_subterms: usize) -> Instruction;
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 constant_subterm(literal: Literal) -> Instruction;
+ fn constant_subterm(literal: HeapCellValue) -> Instruction;
fn argument_to_variable(r: RegType, r: usize) -> Instruction;
fn argument_to_value(r: RegType, val: usize) -> Instruction;
}
impl<'a> CompilationTarget<'a> for FactInstruction {
- fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
- Instruction::GetConstant(lvl, HeapCellValue::from(constant), reg)
+ fn to_constant(lvl: Level, cell: HeapCellValue, reg: RegType) -> Instruction {
+ Instruction::GetConstant(lvl, cell, reg)
}
fn to_structure(lvl: Level, name: Atom, arity: usize, reg: RegType) -> Instruction {
matches!(instr, &Instruction::UnifyVoid(_))
}
- fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction {
- Instruction::GetPartialString(lvl, string, r, has_tail)
+ fn to_pstr(lvl: Level, string: Rc<String>, r: RegType) -> Instruction {
+ Instruction::GetPartialString(lvl, string, r)
}
fn incr_void_instr(instr: &mut Instruction) {
}
}
- fn constant_subterm(constant: Literal) -> Instruction {
- Instruction::UnifyConstant(HeapCellValue::from(constant))
+ fn constant_subterm(constant: HeapCellValue) -> Instruction {
+ Instruction::UnifyConstant(constant)
}
fn argument_to_variable(arg: RegType, val: usize) -> Instruction {
}
impl<'a> CompilationTarget<'a> for QueryInstruction {
- fn to_structure(_lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction {
- Instruction::PutStructure(name, arity, r)
+ fn to_constant(lvl: Level, constant: HeapCellValue, reg: RegType) -> Instruction {
+ Instruction::PutConstant(lvl, constant, reg)
}
- fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
- Instruction::PutConstant(lvl, HeapCellValue::from(constant), reg)
+ fn to_structure(_lvl: Level, name: Atom, arity: usize, r: RegType) -> Instruction {
+ Instruction::PutStructure(name, arity, r)
}
fn to_list(lvl: Level, reg: RegType) -> Instruction {
Instruction::PutList(lvl, reg)
}
- fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction {
- Instruction::PutPartialString(lvl, string, r, has_tail)
+ fn to_pstr(lvl: Level, string: Rc<String>, r: RegType) -> Instruction {
+ Instruction::PutPartialString(lvl, string, r)
}
fn to_void(subterms: usize) -> Instruction {
}
}
- fn constant_subterm(constant: Literal) -> Instruction {
- Instruction::SetConstant(HeapCellValue::from(constant))
+ fn constant_subterm(constant: HeapCellValue) -> Instruction {
+ Instruction::SetConstant(constant)
}
fn argument_to_variable(arg: RegType, val: usize) -> Instruction {
error,
true),
\+ 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],
call_with_inference_limit(g(X), 11, R),
[[true, 1],
use crate::arena::*;
use crate::atom_table::*;
use crate::forms::*;
+use crate::machine::heap::*;
use crate::machine::machine_indices::*;
-use crate::machine::partial_string::PartialString;
use crate::machine::streams::*;
use crate::parser::ast::Fixnum;
use std::ops::{Add, Sub, SubAssign};
#[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[repr(u8)]
#[bits = 6]
pub enum HeapCellValueTag {
- Str = 0b000011,
+ Str = 0b000001,
Lis = 0b000101,
- Var = 0b000111,
- StackVar = 0b001001,
- AttrVar = 0b001011,
- PStrLoc = 0b001101,
- PStrOffset = 0b001111,
+ Var = 0b001011,
+ StackVar = 0b001101,
+ AttrVar = 0b010001,
+ PStrLoc = 0b010011,
// constants.
Cons = 0b0,
- F64 = 0b010001,
- Fixnum = 0b010011,
- Char = 0b010101,
- Atom = 0b010111,
- PStr = 0b011001,
- CStr = 0b011011,
- CutPoint = 0b011111,
+ F64 = 0b010101,
+ Fixnum = 0b011001,
+ // Char = 0b011011,
+ Atom = 0b011111,
+ CutPoint = 0b011101,
+ // trail elements.
+ TrailedHeapVar = 0b100001,
+ TrailedStackVar = 0b100011,
+ TrailedAttrVar = 0b100101,
+ TrailedAttrVarListLink = 0b101001,
+ TrailedAttachedValue = 0b101011,
+ TrailedBlackboardEntry = 0b101101,
+ TrailedBlackboardOffset = 0b110001,
}
#[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[repr(u8)]
#[bits = 6]
pub enum HeapCellValueView {
- Str = 0b000011,
+ Str = 0b000001,
Lis = 0b000101,
- Var = 0b000111,
- StackVar = 0b001001,
- AttrVar = 0b001011,
- PStrLoc = 0b001101,
- PStrOffset = 0b001111,
+ Var = 0b001011,
+ StackVar = 0b001101,
+ AttrVar = 0b010001,
+ PStrLoc = 0b010011,
// constants.
Cons = 0b0,
- F64 = 0b010001,
- Fixnum = 0b010011,
- Char = 0b010101,
- Atom = 0b010111,
- PStr = 0b011001,
- CStr = 0b011011,
- CutPoint = 0b011111,
+ F64 = 0b010101,
+ Fixnum = 0b011001,
+ Char = 0b011011,
+ Atom = 0b011111,
+ CutPoint = 0b011101,
// trail elements.
- TrailedHeapVar = 0b101111,
- TrailedStackVar = 0b101011,
- TrailedAttrVar = 0b100001,
- TrailedAttrVarListLink = 0b100011,
- TrailedAttachedValue = 0b100101,
- TrailedBlackboardEntry = 0b100111,
- TrailedBlackboardOffset = 0b110011,
+ TrailedHeapVar = 0b100001,
+ TrailedStackVar = 0b100011,
+ TrailedAttrVar = 0b100101,
+ TrailedAttrVarListLink = 0b101001,
+ TrailedAttachedValue = 0b101011,
+ TrailedBlackboardEntry = 0b101101,
+ TrailedBlackboardOffset = 0b110001,
}
#[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[bits = 1]
pub enum ConsPtrMaskTag {
Cons = 0b0,
+ Atom = 0b1,
}
#[bitfield]
#[derive(BitfieldSpecifier, Copy, Clone, Debug)]
#[bits = 6]
pub(crate) enum RefTag {
- HeapCell = 0b000111,
- StackCell = 0b001001,
- AttrVar = 0b001011,
+ HeapCell = 0b001011,
+ StackCell = 0b001101,
+ AttrVar = 0b010001,
}
#[bitfield]
val: B56,
f: bool,
m: bool,
+ #[allow(dead_code)]
tag: HeapCellValueTag,
}
.field("f", &self.f())
.finish()
}
+ /*
HeapCellValueTag::PStr => {
let (name, _) = cell_as_atom_cell!(self).get_name_and_arity();
.field("f", &self.f())
.finish()
}
+ */
tag => f
.debug_struct("HeapCellValue")
.field("tag", &tag)
}
#[inline]
- pub fn is_string_terminator(mut self, heap: &[HeapCellValue]) -> bool {
- use crate::machine::heap::*;
-
+ pub fn is_string_terminator(mut self, heap: &impl SizedHeap) -> bool {
loop {
return read_heap_cell!(self,
(HeapCellValueTag::Atom, (name, arity)) => {
name == atom!("[]") && arity == 0
}
- (HeapCellValueTag::CStr) => {
- true
- }
(HeapCellValueTag::PStrLoc, h) => {
- self = heap[h];
+ let (_s, tail_loc) = heap.scan_slice_to_str(h);
+ self = heap[tail_loc];
continue;
}
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
self = cell;
continue;
}
- (HeapCellValueTag::PStrOffset, pstr_offset) => {
- heap[pstr_offset].get_tag() == HeapCellValueTag::CStr
- }
_ => {
false
}
| HeapCellValueTag::StackVar
| HeapCellValueTag::AttrVar
| HeapCellValueTag::PStrLoc
- | HeapCellValueTag::PStrOffset
+ // | HeapCellValueTag::PStrOffset
)
}
#[inline]
pub fn as_char(self) -> Option<char> {
read_heap_cell!(self,
- (HeapCellValueTag::Char, c) => {
- Some(c)
- }
(HeapCellValueTag::Atom, (name, arity)) => {
if arity > 0 {
return None;
HeapCellValueTag::Cons
| HeapCellValueTag::F64
| HeapCellValueTag::Fixnum
- | HeapCellValueTag::CutPoint
- | HeapCellValueTag::Char
- | HeapCellValueTag::CStr => true,
+ | HeapCellValueTag::CutPoint => true,
HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0,
_ => false,
}
}
#[inline]
- pub fn is_compound(self, heap: &[HeapCellValue]) -> bool {
+ pub fn is_compound(self, heap: &Heap) -> bool {
match self.get_tag() {
HeapCellValueTag::Str => {
cell_as_atom_cell!(heap[self.get_value() as usize]).get_arity() > 0
}
- HeapCellValueTag::Lis
- | HeapCellValueTag::CStr
- | HeapCellValueTag::PStr
- | HeapCellValueTag::PStrLoc
- | HeapCellValueTag::PStrOffset => true,
+ HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc => true,
HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() > 0,
_ => false,
}
match self.tag_or_err() {
Ok(tag) => tag,
Err(_) => match ConsPtr::from_bytes(self.into_bytes()).tag() {
+ ConsPtrMaskTag::Atom => HeapCellValueTag::Atom,
ConsPtrMaskTag::Cons => HeapCellValueTag::Cons,
},
}
#[inline]
pub fn to_atom(self) -> Option<Atom> {
- match self.tag() {
- HeapCellValueTag::Atom => Some(Atom::from(self.val() << 3)),
- _ => None,
- }
- }
-
- #[inline]
- pub fn to_pstr(self) -> Option<PartialString> {
- match self.tag() {
- HeapCellValueTag::PStr => Some(PartialString::from(Atom::from(self.val() << 3))),
+ match self.get_tag() {
+ HeapCellValueTag::Atom => {
+ Some(AtomCell::from_bytes(self.into_bytes()).get_name())
+ }
_ => None,
}
}
}
}
- pub fn order_category(self, heap: &[HeapCellValue]) -> Option<TermOrderCategory> {
+ pub fn order_category(self, heap: &Heap) -> Option<TermOrderCategory> {
match Number::try_from(self).ok() {
Some(Number::Integer(_)) | Some(Number::Fixnum(_)) | Some(Number::Rational(_)) => {
Some(TermOrderCategory::Integer)
HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar => {
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 {
TermOrderCategory::Compound
} else {
TermOrderCategory::Atom
}),
- HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr => {
+ HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc => {
+ // | HeapCellValueTag::CStr => {
Some(TermOrderCategory::Compound)
}
HeapCellValueTag::Str => {
match self.get_tag() {
tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis
- | tag @ HeapCellValueTag::PStrOffset
- | tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => {
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,
}
}
match self.get_tag() {
tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis
- | tag @ HeapCellValueTag::PStrOffset
- | tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => {
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,
}
}
match self.get_tag() {
tag @ HeapCellValueTag::Str
| tag @ HeapCellValueTag::Lis
- | tag @ HeapCellValueTag::PStrOffset
- | tag @ HeapCellValueTag::PStrLoc
| tag @ HeapCellValueTag::Var
| tag @ HeapCellValueTag::AttrVar => {
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,
}
} else {
-:- op(10, xf, [example, Var]).
\ No newline at end of file
+:- op(10, xf, [example, Var]).
test :- load_html("<html><head><title>Hello!</title></head></html>", Es, []), write(Es).
-:- initialization(test).
\ No newline at end of file
+:- initialization(test).