Merge branch 'master' into library-use-case
This commit is contained in:
@@ -1423,6 +1423,7 @@ mod tests {
|
||||
use crate::machine::mock_wam::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn arith_eval_by_metacall_tests() {
|
||||
let mut wam = MachineState::new();
|
||||
let mut op_dir = default_op_dir();
|
||||
|
||||
@@ -42,42 +42,35 @@ pub(super) fn bootstrapping_compile(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize {
|
||||
fn lower_bound_of_target_clause(skeleton: &mut PredicateSkeleton, target_pos: usize) -> usize {
|
||||
if target_pos == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let arg_num = skeleton.clauses[target_pos - 1].opt_arg_index_key.arg_num();
|
||||
debug_assert!(skeleton.clauses.len() >= 2);
|
||||
|
||||
if arg_num == 0 {
|
||||
return target_pos - 1;
|
||||
}
|
||||
let index = target_pos - 1;
|
||||
|
||||
let mut index_loc_opt = None;
|
||||
let index = if let Some(index_loc) = skeleton.clauses[index]
|
||||
.opt_arg_index_key
|
||||
.switch_on_term_loc()
|
||||
{
|
||||
let search_result = skeleton.clauses.make_contiguous()
|
||||
[0..skeleton.core.clause_assert_margin]
|
||||
.partition_point(|clause_index_info| clause_index_info.clause_start > index_loc);
|
||||
|
||||
for index in (0..target_pos).rev() {
|
||||
let current_arg_num = skeleton.clauses[index].opt_arg_index_key.arg_num();
|
||||
|
||||
if current_arg_num == 0 || current_arg_num != arg_num {
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
if let Some(index_loc) = index_loc_opt {
|
||||
let current_index_loc = skeleton.clauses[index]
|
||||
.opt_arg_index_key
|
||||
.switch_on_term_loc();
|
||||
|
||||
if Some(index_loc) != current_index_loc {
|
||||
return index + 1;
|
||||
}
|
||||
if search_result < skeleton.core.clause_assert_margin {
|
||||
search_result
|
||||
} else {
|
||||
index_loc_opt = skeleton.clauses[index]
|
||||
.opt_arg_index_key
|
||||
.switch_on_term_loc();
|
||||
skeleton.clauses.make_contiguous()[skeleton.core.clause_assert_margin..]
|
||||
.partition_point(|clause_index_info| clause_index_info.clause_start < index_loc)
|
||||
+ skeleton.core.clause_assert_margin
|
||||
}
|
||||
}
|
||||
} else {
|
||||
index
|
||||
};
|
||||
|
||||
0
|
||||
index.clamp(0, skeleton.clauses.len() - 2)
|
||||
}
|
||||
|
||||
fn derelictize_try_me_else(
|
||||
@@ -1215,7 +1208,7 @@ fn print_overwrite_warning(
|
||||
}
|
||||
|
||||
println!(
|
||||
"Warning: overwriting {}/{} because the clauses are discontiguous",
|
||||
"% Warning: overwriting {}/{} because the clauses are discontiguous",
|
||||
key.0.as_str(),
|
||||
key.1
|
||||
);
|
||||
@@ -1327,7 +1320,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
.clause_clause_locs
|
||||
.extend(&clause_clause_locs.make_contiguous()[0..]);
|
||||
|
||||
let skeleton = cg.skeleton;
|
||||
let mut skeleton = cg.skeleton;
|
||||
skeleton.core.is_dynamic = settings.is_dynamic();
|
||||
|
||||
self.add_extensible_predicate(key, skeleton, predicates.compilation_target);
|
||||
}
|
||||
@@ -1527,6 +1521,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
|
||||
let code_len = self.wam_prelude.code.len();
|
||||
|
||||
standalone_skeleton.clauses[0].clause_start += code_len;
|
||||
|
||||
let skeleton = match self
|
||||
.wam_prelude
|
||||
.indices
|
||||
@@ -1539,8 +1535,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
match append_or_prepend {
|
||||
AppendOrPrepend::Append => {
|
||||
let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap();
|
||||
skeleton.clauses.push_back(clause_index_info);
|
||||
|
||||
skeleton.clauses.push_back(clause_index_info);
|
||||
skeleton.core.clause_clause_locs.push_back(code_len);
|
||||
|
||||
self.payload
|
||||
@@ -2148,7 +2144,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
.map(|skeleton| skeleton.predicate_info())
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut predicate_info = self
|
||||
let predicate_info = self
|
||||
.wam_prelude
|
||||
.indices
|
||||
.get_predicate_skeleton(&self.payload.predicates.compilation_target, &key)
|
||||
@@ -2183,7 +2179,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
if is_cross_module_clause && !local_predicate_info.is_extensible {
|
||||
if predicate_info.is_multifile {
|
||||
println!(
|
||||
"Warning: overwriting multifile predicate {}:{}/{} because \
|
||||
"% Warning: overwriting multifile predicate {}:{}/{} because \
|
||||
it was not locally declared multifile.",
|
||||
self.payload.predicates.compilation_target,
|
||||
key.0.as_str(),
|
||||
@@ -2210,8 +2206,6 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
(0..skeleton.clauses.len()).map(Some).collect(),
|
||||
false, // the builtin M:'$clause'/2 is never dynamic.
|
||||
);
|
||||
|
||||
predicate_info.is_dynamic = false;
|
||||
}
|
||||
|
||||
self.payload
|
||||
|
||||
@@ -398,6 +398,7 @@ mod tests {
|
||||
use crate::machine::mock_wam::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on atom_table.rs UB")]
|
||||
fn copier_tests() {
|
||||
let mut wam = MockWAM::new();
|
||||
|
||||
|
||||
@@ -557,20 +557,29 @@ impl Machine {
|
||||
}
|
||||
|
||||
let mut p = self.machine_st.p;
|
||||
let mut arity = 0;
|
||||
|
||||
while self.code[p].is_head_instr() {
|
||||
for r in self.code[p].registers() {
|
||||
if let RegType::Temp(t) = r {
|
||||
arity = std::cmp::max(arity, t);
|
||||
}
|
||||
}
|
||||
|
||||
p += 1;
|
||||
}
|
||||
|
||||
let instr =
|
||||
std::mem::replace(&mut self.code[p], Instruction::VerifyAttrInterrupt);
|
||||
let instr = std::mem::replace(
|
||||
&mut self.code[p],
|
||||
Instruction::VerifyAttrInterrupt(arity),
|
||||
);
|
||||
|
||||
self.code[VERIFY_ATTR_INTERRUPT_LOC] = instr;
|
||||
self.machine_st.attr_var_init.cp = p;
|
||||
}
|
||||
&Instruction::VerifyAttrInterrupt => {
|
||||
let (_, arity) = self.code[VERIFY_ATTR_INTERRUPT_LOC].to_name_and_arity();
|
||||
let arity = std::cmp::max(arity, self.machine_st.num_of_args);
|
||||
&Instruction::VerifyAttrInterrupt(arity) => {
|
||||
// let (_, arity) = self.code[VERIFY_ATTR_INTERRUPT_LOC].to_name_and_arity();
|
||||
// let arity = std::cmp::max(arity, self.machine_st.num_of_args);
|
||||
self.run_verify_attr_interrupt(arity);
|
||||
}
|
||||
&Instruction::Add(ref a1, ref a2, t) => {
|
||||
@@ -4147,6 +4156,14 @@ impl Machine {
|
||||
try_or_throw!(self.machine_st, self.js_eval());
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallArgv => {
|
||||
try_or_throw!(self.machine_st, self.argv());
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
&Instruction::ExecuteArgv => {
|
||||
try_or_throw!(self.machine_st, self.argv());
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallCurrentTime => {
|
||||
self.current_time();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
@@ -4491,44 +4508,28 @@ impl Machine {
|
||||
self.crypto_curve_scalar_mult();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::CallEd25519Sign => {
|
||||
self.ed25519_sign();
|
||||
&Instruction::CallEd25519SignRaw => {
|
||||
self.ed25519_sign_raw();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::ExecuteEd25519Sign => {
|
||||
self.ed25519_sign();
|
||||
&Instruction::ExecuteEd25519SignRaw => {
|
||||
self.ed25519_sign_raw();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::CallEd25519Verify => {
|
||||
self.ed25519_verify();
|
||||
&Instruction::CallEd25519VerifyRaw => {
|
||||
self.ed25519_verify_raw();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::ExecuteEd25519Verify => {
|
||||
self.ed25519_verify();
|
||||
&Instruction::ExecuteEd25519VerifyRaw => {
|
||||
self.ed25519_verify_raw();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::CallEd25519NewKeyPair => {
|
||||
self.ed25519_new_key_pair();
|
||||
&Instruction::CallEd25519SeedToPublicKey => {
|
||||
self.ed25519_seed_to_public_key();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::ExecuteEd25519NewKeyPair => {
|
||||
self.ed25519_new_key_pair();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::CallEd25519KeyPairPublicKey => {
|
||||
self.ed25519_key_pair_public_key();
|
||||
step_or_fail!(self, self.machine_st.p += 1);
|
||||
}
|
||||
#[cfg(feature = "crypto-full")]
|
||||
&Instruction::ExecuteEd25519KeyPairPublicKey => {
|
||||
self.ed25519_key_pair_public_key();
|
||||
&Instruction::ExecuteEd25519SeedToPublicKey => {
|
||||
self.ed25519_seed_to_public_key();
|
||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
||||
}
|
||||
&Instruction::CallCurve25519ScalarMult => {
|
||||
|
||||
@@ -369,6 +369,7 @@ mod tests {
|
||||
use crate::machine::mock_wam::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn heap_marking_tests() {
|
||||
let mut wam = MockWAM::new();
|
||||
|
||||
|
||||
@@ -236,6 +236,7 @@ mod tests {
|
||||
use crate::machine::{QueryMatch, QueryResolution, Value};
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn programatic_query() {
|
||||
let mut machine = Machine::new_lib();
|
||||
|
||||
@@ -275,6 +276,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn failing_query() {
|
||||
let mut machine = Machine::new_lib();
|
||||
let query = String::from(r#"triple("a",P,"b")."#);
|
||||
@@ -288,6 +290,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)]
|
||||
fn complex_results() {
|
||||
let mut machine = Machine::new_lib();
|
||||
machine.load_module_string(
|
||||
@@ -344,6 +347,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn empty_predicate() {
|
||||
let mut machine = Machine::new_lib();
|
||||
machine.load_module_string(
|
||||
@@ -359,6 +363,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn list_results() {
|
||||
let mut machine = Machine::new_lib();
|
||||
machine.load_module_string(
|
||||
@@ -387,6 +392,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn consult() {
|
||||
let mut machine = Machine::new_lib();
|
||||
|
||||
@@ -445,6 +451,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn integration_test() {
|
||||
let mut machine = Machine::new_lib();
|
||||
|
||||
@@ -495,6 +502,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn findall() {
|
||||
let mut machine = Machine::new_lib();
|
||||
|
||||
|
||||
@@ -466,24 +466,48 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
||||
None => return,
|
||||
};
|
||||
|
||||
for (key, code_index) in removed_module.code_dir.iter_mut() {
|
||||
match removed_module
|
||||
.local_extensible_predicates
|
||||
.get(&(CompilationTarget::User, *key))
|
||||
{
|
||||
Some(skeleton) if skeleton.is_multifile => continue,
|
||||
_ => {}
|
||||
let mut skipped_local_predicates = IndexSet::with_hasher(FxBuildHasher::default());
|
||||
|
||||
for ((local_compilation_target, key), skeleton) in
|
||||
removed_module.local_extensible_predicates.iter()
|
||||
{
|
||||
skipped_local_predicates.insert(key);
|
||||
|
||||
if skeleton.is_multifile {
|
||||
continue;
|
||||
}
|
||||
|
||||
let old_index_ptr = code_index.replace(IndexPtr::undefined());
|
||||
if let Some(code_index) = removed_module.code_dir.get_mut(key) {
|
||||
if let Some(global_skeleton) = self
|
||||
.wam_prelude
|
||||
.indices
|
||||
.get_predicate_skeleton(local_compilation_target, key)
|
||||
{
|
||||
let old_index_ptr = code_index.replace(if global_skeleton.core.is_dynamic {
|
||||
IndexPtr::dynamic_undefined()
|
||||
} else {
|
||||
IndexPtr::undefined()
|
||||
});
|
||||
|
||||
self.payload
|
||||
.retraction_info
|
||||
.push_record(RetractionRecord::ReplacedModulePredicate(
|
||||
module_name,
|
||||
*key,
|
||||
old_index_ptr,
|
||||
));
|
||||
self.payload.retraction_info.push_record(
|
||||
RetractionRecord::ReplacedModulePredicate(module_name, *key, old_index_ptr),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (key, code_index) in removed_module.code_dir.iter_mut() {
|
||||
if skipped_local_predicates.contains(key) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !code_index.is_undefined() && !code_index.is_dynamic_undefined() {
|
||||
let old_index_ptr = code_index.replace(IndexPtr::undefined());
|
||||
|
||||
self.payload.retraction_info.push_record(
|
||||
RetractionRecord::ReplacedModulePredicate(module_name, *key, old_index_ptr),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (key, skeleton) in removed_module.extensible_predicates.drain(..) {
|
||||
|
||||
@@ -1833,9 +1833,33 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub(crate) fn scoped_clause_to_evacuable(&mut self) -> CallResult {
|
||||
let module_name = cell_as_atom!(self
|
||||
.machine_st
|
||||
.store(self.machine_st.deref(self.machine_st.registers[1])));
|
||||
let target = self.deref_register(1);
|
||||
|
||||
let mut permission_error = || {
|
||||
let err = self.machine_st.permission_error(
|
||||
Permission::Modify,
|
||||
atom!("static_procedure"),
|
||||
functor_stub(atom!(":"), 2)
|
||||
.into_iter()
|
||||
.collect::<MachineStub>(),
|
||||
);
|
||||
|
||||
self.machine_st
|
||||
.error_form(err, functor_stub(atom!("load"), 1))
|
||||
};
|
||||
|
||||
let module_name = read_heap_cell!(target,
|
||||
(HeapCellValueTag::Atom, (name, arity)) => {
|
||||
if arity == 0 {
|
||||
name
|
||||
} else {
|
||||
return Err(permission_error());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(permission_error());
|
||||
}
|
||||
);
|
||||
|
||||
let loader = self.loader_from_heap_evacuable(temp_v!(3));
|
||||
|
||||
@@ -1948,11 +1972,13 @@ impl Machine {
|
||||
_ => CompilationTarget::Module(module_name),
|
||||
};
|
||||
|
||||
let stub_gen = || match append_or_prepend {
|
||||
AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
|
||||
AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
|
||||
let key = match append_or_prepend {
|
||||
AppendOrPrepend::Append => (atom!("assertz"), 1),
|
||||
AppendOrPrepend::Prepend => (atom!("asserta"), 1),
|
||||
};
|
||||
|
||||
let stub_gen = || functor_stub(key.0, key.1);
|
||||
|
||||
let head = self.deref_register(2);
|
||||
|
||||
if head.is_var() {
|
||||
@@ -1991,7 +2017,11 @@ impl Machine {
|
||||
.map(|code_idx| code_idx.get_tag())
|
||||
.unwrap_or(IndexPtrTag::DynamicUndefined);
|
||||
|
||||
idx_tag == IndexPtrTag::DynamicUndefined || idx_tag == IndexPtrTag::Undefined
|
||||
if idx_tag == IndexPtrTag::Index {
|
||||
return Err(SessionError::CannotOverwriteStaticProcedure((name, arity)));
|
||||
} else {
|
||||
idx_tag == IndexPtrTag::Undefined || idx_tag == IndexPtrTag::DynamicUndefined
|
||||
}
|
||||
} else if is_builtin {
|
||||
return Err(SessionError::CannotOverwriteBuiltIn((name, arity)));
|
||||
} else {
|
||||
|
||||
@@ -488,6 +488,13 @@ impl MachineState {
|
||||
.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)
|
||||
}
|
||||
@@ -1005,6 +1012,7 @@ pub enum SessionError {
|
||||
CompilationError(CompilationError),
|
||||
CannotOverwriteBuiltIn(PredicateKey),
|
||||
CannotOverwriteBuiltInModule(Atom),
|
||||
CannotOverwriteStaticProcedure(PredicateKey),
|
||||
ExistenceError(ExistenceError),
|
||||
ModuleDoesNotContainExport(Atom, PredicateKey),
|
||||
ModuleCannotImportSelf(Atom),
|
||||
|
||||
@@ -1450,10 +1450,15 @@ impl MachineState {
|
||||
a1.as_var().unwrap(),
|
||||
);
|
||||
}
|
||||
(HeapCellValueTag::Cons | HeapCellValueTag::Fixnum |
|
||||
HeapCellValueTag::F64) if arity != 0 => {
|
||||
let err = self.type_error(ValidType::Atom, store_name);
|
||||
return Err(self.error_form(err, stub_gen())); // 8.5.1.3 e)
|
||||
}
|
||||
_ => {
|
||||
let err = self.type_error(ValidType::Atomic, store_name);
|
||||
return Err(self.error_form(err, stub_gen()));
|
||||
} // 8.5.1.3 c)
|
||||
return Err(self.error_form(err, stub_gen())); // 8.5.1.3 c)
|
||||
}
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
|
||||
@@ -260,6 +260,7 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn unify_tests() {
|
||||
let mut wam = MachineState::new();
|
||||
let mut op_dir = default_op_dir();
|
||||
@@ -481,6 +482,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn test_unify_with_occurs_check() {
|
||||
let mut wam = MachineState::new();
|
||||
let mut op_dir = default_op_dir();
|
||||
|
||||
@@ -228,7 +228,7 @@ impl Machine {
|
||||
self.machine_st.throw_exception(err);
|
||||
}
|
||||
|
||||
fn run_module_predicate(
|
||||
pub fn run_module_predicate(
|
||||
&mut self,
|
||||
module_name: Atom,
|
||||
key: PredicateKey,
|
||||
@@ -307,29 +307,6 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_top_level(
|
||||
&mut self,
|
||||
module_name: Atom,
|
||||
key: PredicateKey,
|
||||
) -> std::process::ExitCode {
|
||||
let mut arg_pstrs = vec![];
|
||||
|
||||
for arg in env::args() {
|
||||
arg_pstrs.push(put_complete_string(
|
||||
&mut self.machine_st.heap,
|
||||
&arg,
|
||||
&self.machine_st.atom_tbl,
|
||||
));
|
||||
}
|
||||
|
||||
self.machine_st.registers[1] = heap_loc_as_cell!(iter_to_heap_list(
|
||||
&mut self.machine_st.heap,
|
||||
arg_pstrs.into_iter()
|
||||
));
|
||||
|
||||
self.run_module_predicate(module_name, key)
|
||||
}
|
||||
|
||||
pub fn set_user_input(&mut self, input: String) {
|
||||
self.user_input = Stream::from_owned_string(input, &mut self.machine_st.arena);
|
||||
}
|
||||
@@ -414,7 +391,7 @@ impl Machine {
|
||||
self.code.extend(vec![
|
||||
Instruction::BreakFromDispatchLoop,
|
||||
Instruction::InstallVerifyAttr,
|
||||
Instruction::VerifyAttrInterrupt,
|
||||
Instruction::VerifyAttrInterrupt(0),
|
||||
Instruction::BreakFromDispatchLoop, // the location of LIB_QUERY_SUCCESS
|
||||
Instruction::ExecuteTermGreaterThan,
|
||||
Instruction::ExecuteTermLessThan,
|
||||
@@ -925,8 +902,8 @@ impl Machine {
|
||||
|
||||
self.machine_st.hb = self.machine_st.heap.len();
|
||||
|
||||
self.machine_st.oip = 0;
|
||||
self.machine_st.iip = 0;
|
||||
// self.machine_st.oip = 0;
|
||||
// self.machine_st.iip = 0;
|
||||
}
|
||||
|
||||
self.machine_st.p += offset;
|
||||
@@ -1010,8 +987,22 @@ impl Machine {
|
||||
|
||||
self.machine_st.heap.truncate(target_h);
|
||||
|
||||
self.machine_st.oip = 0;
|
||||
self.machine_st.iip = 0;
|
||||
// these registers don't need to be reset here and MUST
|
||||
// NOT be (nor in indexed_try! trust_epilogue is an
|
||||
// exception, see next paragraph)! oip could be reset
|
||||
// without any adverse effects but iip is needed by
|
||||
// get_clause_p to find the last executed clause/2 clause.
|
||||
|
||||
// trust_epilogue must reset these for the sake of
|
||||
// subsequent predicates beginning with
|
||||
// switch_to_term. get_clause_p copes by checking
|
||||
// self.machine_st.b > self.machine.e: if true, it is safe
|
||||
// to use self.machine_st.iip; if false, use the choice
|
||||
// point left at the top of the stack by '$clause'
|
||||
// (specifically its biip value).
|
||||
|
||||
// self.machine_st.oip = 0;
|
||||
// self.machine_st.iip = 0;
|
||||
} else {
|
||||
self.trust_epilogue(offset);
|
||||
}
|
||||
@@ -1116,7 +1107,7 @@ impl Machine {
|
||||
}
|
||||
Unknown::Warn => {
|
||||
println!(
|
||||
"warning: predicate {}/{} is undefined",
|
||||
"% Warning: predicate {}/{} is undefined",
|
||||
name.as_str(),
|
||||
arity
|
||||
);
|
||||
|
||||
@@ -351,9 +351,9 @@ impl<'a> HeapPStrIter<'a> {
|
||||
);
|
||||
|
||||
value.as_char().map(|c| PStrIterStep {
|
||||
iteratee: PStrIteratee::Char(curr_hare, c),
|
||||
next_hare: s+2,
|
||||
})
|
||||
iteratee: PStrIteratee::Char(curr_hare, c),
|
||||
next_hare: s+2,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -764,13 +764,29 @@ pub fn compare_pstr_prefixes<'a>(
|
||||
if i1.focus == empty_list_as_cell!() {
|
||||
PStrCmpResult::Ordered(Ordering::Less)
|
||||
} else {
|
||||
PStrCmpResult::SecondIterContinuable(r2.unwrap().iteratee)
|
||||
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 {
|
||||
PStrCmpResult::FirstIterContinuable(r1.unwrap().iteratee)
|
||||
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)
|
||||
@@ -785,6 +801,7 @@ mod test {
|
||||
use crate::machine::mock_wam::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore = "blocked on streams.rs UB")]
|
||||
fn pstr_iter_tests() {
|
||||
let mut wam = MockWAM::new();
|
||||
|
||||
@@ -1089,9 +1106,119 @@ mod test {
|
||||
Some(PStrIteratee::PStrSegment(2, atom!("abc"), 1))
|
||||
);
|
||||
|
||||
// assert!(iter.next().is_none());
|
||||
|
||||
for _ in iter {}
|
||||
}
|
||||
|
||||
// #2293, test1.
|
||||
|
||||
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!());
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
|
||||
|
||||
assert!(!wam.machine_st.fail);
|
||||
|
||||
// #2293, test2.
|
||||
|
||||
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!());
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
|
||||
|
||||
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!());
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
|
||||
|
||||
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!());
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
|
||||
|
||||
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));
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
|
||||
|
||||
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!());
|
||||
|
||||
unify!(wam.machine_st, list_loc_as_cell!(1), heap_loc_as_cell!(0));
|
||||
|
||||
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));
|
||||
|
||||
assert!(!wam.machine_st.fail);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,21 +565,6 @@ impl Preprocessor {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fn try_term_to_query<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
terms: Vec<Term>,
|
||||
cut_context: CutContext,
|
||||
) -> Result<TopLevel, CompilationError> {
|
||||
Ok(TopLevel::Query(self.setup_query(
|
||||
loader,
|
||||
terms,
|
||||
cut_context,
|
||||
)?))
|
||||
}
|
||||
*/
|
||||
|
||||
pub(super) fn try_term_to_tl<'a, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
@@ -607,20 +592,4 @@ impl Preprocessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>, LS: LoadState<'a>>(
|
||||
&mut self,
|
||||
loader: &mut Loader<'a, LS>,
|
||||
terms: I,
|
||||
) -> Result<VecDeque<TopLevel>, CompilationError> {
|
||||
let mut results = VecDeque::new();
|
||||
|
||||
for term in terms.into_iter() {
|
||||
results.push_back(self.try_term_to_tl(loader, term)?);
|
||||
}
|
||||
|
||||
Ok(results)
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:- module('$project_atts', [copy_term/3]).
|
||||
:- module('$project_atts', []).
|
||||
|
||||
:- use_module(library(dcgs)).
|
||||
:- use_module(library(error), [can_be/2]).
|
||||
@@ -100,14 +100,6 @@ gather_residual_goals([V|Vs]) -->
|
||||
|
||||
delete_all_attributes_from_var(V) :- '$delete_all_attributes_from_var'(V).
|
||||
|
||||
copy_term(Term, Copy, Gs) :-
|
||||
can_be(list, Gs),
|
||||
findall(Term-Rs, term_residual_goals(Term,Rs), [Copy-Gs]),
|
||||
( var(Gs) ->
|
||||
Gs = []
|
||||
; true
|
||||
).
|
||||
|
||||
term_residual_goals(Term,Rs) :-
|
||||
'$term_attributed_variables'(Term, Vs),
|
||||
phrase(gather_residual_goals(Vs), Rs),
|
||||
|
||||
@@ -189,7 +189,7 @@ impl Stack {
|
||||
|
||||
for idx in 0..num_cells {
|
||||
ptr::write(
|
||||
(new_ptr as usize + offset) as *mut HeapCellValue,
|
||||
new_ptr.add(offset) as *mut HeapCellValue,
|
||||
stack_loc_as_cell!(AndFrame, e, idx + 1),
|
||||
);
|
||||
|
||||
@@ -203,6 +203,10 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn top(&self) -> usize {
|
||||
unsafe { (*self.buf.ptr.get()) as usize - self.buf.base as usize }
|
||||
}
|
||||
|
||||
pub(crate) fn allocate_or_frame(&mut self, num_cells: usize) -> usize {
|
||||
let frame_size = OrFrame::size_of(num_cells);
|
||||
|
||||
@@ -238,7 +242,8 @@ impl Stack {
|
||||
#[inline(always)]
|
||||
pub(crate) fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame {
|
||||
unsafe {
|
||||
let ptr = self.buf.base as usize + e;
|
||||
// This is doing alignment wrong
|
||||
let ptr = self.buf.base.add(e);
|
||||
&mut *(ptr as *mut AndFrame)
|
||||
}
|
||||
}
|
||||
@@ -276,6 +281,7 @@ mod tests {
|
||||
use crate::machine::mock_wam::*;
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(miri, ignore)]
|
||||
fn stack_tests() {
|
||||
let mut wam = MockWAM::new();
|
||||
|
||||
|
||||
@@ -469,6 +469,7 @@ macro_rules! arena_allocated_impl_for_stream {
|
||||
#[inline]
|
||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
||||
unsafe {
|
||||
// Miri seems to hit this a lot
|
||||
ptr::write(dst, self);
|
||||
TypedArenaPtr::new(dst as *mut Self)
|
||||
}
|
||||
|
||||
@@ -81,14 +81,11 @@ use ring::rand::{SecureRandom, SystemRandom};
|
||||
use ring::{digest, hkdf, pbkdf2};
|
||||
|
||||
#[cfg(feature = "crypto-full")]
|
||||
use ring::{
|
||||
aead,
|
||||
signature::{self, KeyPair},
|
||||
};
|
||||
use ring::aead;
|
||||
use ripemd160::{Digest, Ripemd160};
|
||||
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512};
|
||||
|
||||
use crrl::{secp256k1, x25519};
|
||||
use crrl::{ed25519, secp256k1, x25519};
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
use native_tls::{Identity, TlsAcceptor, TlsConnector};
|
||||
@@ -1171,63 +1168,33 @@ impl Machine {
|
||||
.get_predicate_skeleton(&compilation_target, &key)
|
||||
.unwrap();
|
||||
|
||||
if self.machine_st.b > self.machine_st.e {
|
||||
let or_frame = self.machine_st.stack.index_or_frame(self.machine_st.b);
|
||||
let bp = or_frame.prelude.bp;
|
||||
let module_name = match compilation_target {
|
||||
CompilationTarget::User => atom!("builtins"),
|
||||
CompilationTarget::Module(target) => target,
|
||||
};
|
||||
|
||||
match &self.code[bp] {
|
||||
Instruction::IndexingCode(ref indexing_code) => {
|
||||
match &indexing_code[or_frame.prelude.boip as usize] {
|
||||
IndexingLine::IndexedChoice(ref indexed_choice) => {
|
||||
let p = or_frame.prelude.biip as usize - 1;
|
||||
let mut bp = self
|
||||
.indices
|
||||
.get_predicate_code_index(atom!("$clause"), 2, module_name)
|
||||
.and_then(|idx| idx.local())
|
||||
.unwrap();
|
||||
|
||||
match &indexed_choice[p] {
|
||||
&IndexedChoiceInstruction::Try(offset)
|
||||
| &IndexedChoiceInstruction::Retry(offset)
|
||||
| &IndexedChoiceInstruction::DefaultRetry(offset) => {
|
||||
let clause_clause_loc = skeleton.core.clause_clause_locs[p];
|
||||
(clause_clause_loc, bp + offset)
|
||||
}
|
||||
&IndexedChoiceInstruction::Trust(_)
|
||||
| &IndexedChoiceInstruction::DefaultTrust(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
macro_rules! extract_ptr {
|
||||
($ptr: expr) => {
|
||||
match $ptr {
|
||||
IndexingCodePtr::External(p) => {
|
||||
return (
|
||||
skeleton.core.clause_clause_locs.back().cloned().unwrap(),
|
||||
bp + p,
|
||||
)
|
||||
}
|
||||
IndexingCodePtr::Internal(boip) => boip,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
let module_name = match compilation_target {
|
||||
CompilationTarget::User => atom!("builtins"),
|
||||
CompilationTarget::Module(target) => target,
|
||||
};
|
||||
}
|
||||
|
||||
let bp = self
|
||||
.indices
|
||||
.get_predicate_code_index(atom!("$clause"), 2, module_name)
|
||||
.and_then(|idx| idx.local())
|
||||
.unwrap();
|
||||
|
||||
macro_rules! extract_ptr {
|
||||
($ptr: expr) => {
|
||||
match $ptr {
|
||||
IndexingCodePtr::External(p) => {
|
||||
return (
|
||||
skeleton.core.clause_clause_locs.back().cloned().unwrap(),
|
||||
bp + p,
|
||||
)
|
||||
}
|
||||
IndexingCodePtr::Internal(boip) => boip,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
loop {
|
||||
match &self.code[bp] {
|
||||
Instruction::IndexingCode(ref indexing_code) => {
|
||||
let indexing_code_ptr = match &indexing_code[0] {
|
||||
@@ -1263,14 +1230,38 @@ impl Machine {
|
||||
|
||||
match &indexing_code[boip] {
|
||||
IndexingLine::IndexedChoice(indexed_choice) => {
|
||||
let p = if self.machine_st.b > self.machine_st.e {
|
||||
// this means the last
|
||||
// self.machine_st.iip value has yet
|
||||
// to be overwritten by the Trust
|
||||
// instruction. In this case, return
|
||||
// it.
|
||||
self.machine_st.iip as usize
|
||||
} else {
|
||||
// otherwise, read the '$clause'
|
||||
// choicepoint from the top of the
|
||||
// stack. this is very volatile in
|
||||
// that it depends on '$clause'
|
||||
// immediately preceding
|
||||
// '$get_clause_p', which cannot be
|
||||
// the last clause of the retract
|
||||
// helper to delay deallocation of its
|
||||
// environment frame.
|
||||
let clause_b = self.machine_st.stack.top();
|
||||
self.machine_st.stack.index_or_frame(clause_b).prelude.biip as usize
|
||||
};
|
||||
|
||||
return (
|
||||
skeleton.core.clause_clause_locs.back().cloned().unwrap(),
|
||||
bp + indexed_choice.back().unwrap().offset(),
|
||||
skeleton.core.clause_clause_locs[p],
|
||||
bp + indexed_choice[p].offset(),
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
&Instruction::RevJmpBy(offset) => {
|
||||
bp -= offset;
|
||||
}
|
||||
_ => {
|
||||
return (
|
||||
skeleton.core.clause_clause_locs.back().cloned().unwrap(),
|
||||
@@ -3501,6 +3492,12 @@ impl Machine {
|
||||
Some(Ok(c)) => {
|
||||
string.push(c);
|
||||
}
|
||||
Some(Err(e)) => {
|
||||
let stub = functor_stub(atom!("$get_n_chars"), 3);
|
||||
let err = self.machine_st.session_error(SessionError::from(e));
|
||||
|
||||
return Err(self.machine_st.error_form(err, stub));
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
@@ -4291,18 +4288,18 @@ impl Machine {
|
||||
let address_string = address_sink.as_str(); //to_string();
|
||||
let address: Url = address_string.parse().unwrap();
|
||||
|
||||
let client = reqwest::blocking::Client::builder().build().unwrap();
|
||||
let client = reqwest::Client::builder().build().unwrap();
|
||||
|
||||
// request
|
||||
let mut req = reqwest::blocking::Request::new(method, address);
|
||||
let mut req = reqwest::Request::new(method, address);
|
||||
|
||||
*req.headers_mut() = headers;
|
||||
if !bytes.is_empty() {
|
||||
*req.body_mut() = Some(reqwest::blocking::Body::from(bytes));
|
||||
*req.body_mut() = Some(reqwest::Body::from(bytes));
|
||||
}
|
||||
|
||||
// do it!
|
||||
match client.execute(req) {
|
||||
match futures::executor::block_on(client.execute(req)) {
|
||||
Ok(resp) => {
|
||||
// status code
|
||||
let status = resp.status().as_u16();
|
||||
@@ -4339,7 +4336,7 @@ impl Machine {
|
||||
self.machine_st.registers[6]
|
||||
);
|
||||
// body
|
||||
let reader = resp.bytes().unwrap().reader();
|
||||
let reader = futures::executor::block_on(resp.bytes()).unwrap().reader();
|
||||
|
||||
let mut stream = Stream::from_http_stream(
|
||||
AtomTable::build_with(&self.machine_st.atom_tbl, &address_string),
|
||||
@@ -4953,6 +4950,27 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 cell = heap_loc_as_cell!(iter_to_heap_list(
|
||||
&mut self.machine_st.heap,
|
||||
args_pstrs.into_iter()
|
||||
));
|
||||
|
||||
unify!(self.machine_st, args, cell);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn current_time(&mut self) {
|
||||
let timestamp = self.systemtime_to_timestamp(SystemTime::now());
|
||||
@@ -5721,11 +5739,11 @@ impl Machine {
|
||||
#[inline(always)]
|
||||
pub(super) fn restore_instr_at_verify_attr_interrupt(&mut self) {
|
||||
match &self.code[VERIFY_ATTR_INTERRUPT_LOC] {
|
||||
&Instruction::VerifyAttrInterrupt => {}
|
||||
&Instruction::VerifyAttrInterrupt(_) => {}
|
||||
_ => {
|
||||
let instr = mem::replace(
|
||||
&mut self.code[VERIFY_ATTR_INTERRUPT_LOC],
|
||||
Instruction::VerifyAttrInterrupt,
|
||||
Instruction::VerifyAttrInterrupt(0),
|
||||
);
|
||||
|
||||
self.code[self.machine_st.attr_var_init.cp] = instr;
|
||||
@@ -6520,10 +6538,8 @@ impl Machine {
|
||||
);
|
||||
|
||||
if had_zero_port {
|
||||
self.machine_st.unify_fixnum(
|
||||
Fixnum::build_with(port as i64),
|
||||
self.machine_st.registers[2],
|
||||
);
|
||||
self.machine_st
|
||||
.unify_fixnum(Fixnum::build_with(port as i64), self.deref_register(2));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -7625,33 +7641,16 @@ impl Machine {
|
||||
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
|
||||
}
|
||||
|
||||
#[cfg(feature = "crypto-full")]
|
||||
#[inline(always)]
|
||||
pub(crate) fn ed25519_new_key_pair(&mut self) {
|
||||
let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap();
|
||||
let complete_string = self.u8s_to_string(pkcs8_bytes.as_ref());
|
||||
pub(crate) fn ed25519_seed_to_public_key(&mut self) {
|
||||
let stub_gen = || functor_stub(atom!("ed25519_seed_keypair"), 2);
|
||||
let seed_bytes = self
|
||||
.machine_st
|
||||
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||
|
||||
unify!(
|
||||
self.machine_st,
|
||||
self.machine_st.registers[1],
|
||||
complete_string
|
||||
)
|
||||
}
|
||||
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
||||
|
||||
#[cfg(feature = "crypto-full")]
|
||||
#[inline(always)]
|
||||
pub(crate) fn ed25519_key_pair_public_key(&mut self) {
|
||||
let bytes = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
|
||||
|
||||
let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&bytes) {
|
||||
Ok(kp) => kp,
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let complete_string = self.u8s_to_string(key_pair.public_key().as_ref());
|
||||
let complete_string = self.u8s_to_string(skey.public_key.encoded.as_ref());
|
||||
|
||||
unify!(
|
||||
self.machine_st,
|
||||
@@ -7660,22 +7659,19 @@ impl Machine {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "crypto-full")]
|
||||
#[inline(always)]
|
||||
pub(crate) fn ed25519_sign(&mut self) {
|
||||
let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
|
||||
pub(crate) fn ed25519_sign_raw(&mut self) {
|
||||
let stub_gen = || functor_stub(atom!("ed25519_sign"), 4);
|
||||
let seed_bytes = self
|
||||
.machine_st
|
||||
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||
|
||||
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
||||
|
||||
let encoding = cell_as_atom!(self.deref_register(3));
|
||||
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
||||
|
||||
let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&key) {
|
||||
Ok(kp) => kp,
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let sig = key_pair.sign(&data);
|
||||
let sig = skey.sign_raw(&data);
|
||||
|
||||
let sig_list = heap_loc_as_cell!(iter_to_heap_list(
|
||||
&mut self.machine_st.heap,
|
||||
@@ -7687,25 +7683,21 @@ impl Machine {
|
||||
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
|
||||
}
|
||||
|
||||
#[cfg(feature = "crypto-full")]
|
||||
#[inline(always)]
|
||||
pub(crate) fn ed25519_verify(&mut self) {
|
||||
let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
|
||||
pub(crate) fn ed25519_verify_raw(&mut self) {
|
||||
let key_bytes = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
|
||||
let pkey = ed25519::PublicKey::decode(&key_bytes).unwrap();
|
||||
|
||||
let encoding = cell_as_atom!(self.deref_register(3));
|
||||
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
||||
let stub_gen = || functor_stub(atom!("ed25519_verify"), 5);
|
||||
|
||||
let stub_gen = || functor_stub(atom!("ed25519_verify"), 4);
|
||||
|
||||
let signature = self
|
||||
.machine_st
|
||||
.integers_to_bytevec(self.machine_st.registers[4], stub_gen);
|
||||
|
||||
let peer_public_key = signature::UnparsedPublicKey::new(&signature::ED25519, &key);
|
||||
|
||||
match peer_public_key.verify(&data, &signature) {
|
||||
Ok(_) => {}
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
}
|
||||
}
|
||||
self.machine_st.fail = !pkey.verify_raw(&signature, &data);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
@@ -173,6 +173,98 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
||||
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) => {
|
||||
@@ -229,89 +321,13 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
(HeapCellValueTag::CStr | HeapCellValueTag::PStrLoc) => {
|
||||
unify_sequence(machine_st, chars_iter.item.unwrap(), focus);
|
||||
return;
|
||||
}
|
||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||
match chars_iter.item.unwrap() {
|
||||
PStrIteratee::Char(focus, _) => {
|
||||
machine_st.pdl.push(machine_st.heap[focus]);
|
||||
machine_st.pdl.push(heap_loc_as_cell!(h));
|
||||
}
|
||||
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(heap_loc_as_cell!(h));
|
||||
} 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(heap_loc_as_cell!(h));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
(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(heap_loc_as_cell!(h));
|
||||
} 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(heap_loc_as_cell!(h));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
}
|
||||
);
|
||||
|
||||
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(heap_loc_as_cell!(h));
|
||||
|
||||
return;
|
||||
}
|
||||
if unify_sequence(machine_st, chars_iter.item.unwrap(), heap_loc_as_cell!(h)) {
|
||||
return;
|
||||
}
|
||||
|
||||
break 'outer;
|
||||
|
||||
Reference in New Issue
Block a user