Merge branch 'master' into library-use-case

This commit is contained in:
Nicolas Luck
2024-01-26 17:21:47 +01:00
131 changed files with 2234 additions and 1352 deletions

View File

@@ -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();

View File

@@ -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

View File

@@ -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();

View File

@@ -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 => {

View File

@@ -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();

View File

@@ -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();

View File

@@ -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(..) {

View File

@@ -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 {

View File

@@ -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),

View File

@@ -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)
}
);
}
_ => {

View File

@@ -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();

View File

@@ -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
);

View File

@@ -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);
}
}

View File

@@ -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)
}
*/
}

View File

@@ -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),

View File

@@ -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();

View File

@@ -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)
}

View File

@@ -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)]

View File

@@ -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;