Compare commits
11 Commits
091af28368
...
4e7d9f9010
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e7d9f9010 | ||
|
|
d3edffb7fc | ||
|
|
295a642034 | ||
|
|
ae0999a3bb | ||
|
|
11fd39bbaf | ||
|
|
eb06f19c32 | ||
|
|
ea88ca552d | ||
|
|
eabbf67e86 | ||
|
|
7a636b0394 | ||
|
|
71ea74a077 | ||
|
|
9b73536cdd |
@@ -73,9 +73,10 @@ Extend Scryer Prolog to include the following, among other features:
|
|||||||
- [ ] Inlining all built-ins and system call instructions.
|
- [ ] Inlining all built-ins and system call instructions.
|
||||||
- [x] Greatly reducing the number of instructions used to compile disjunctives.
|
- [x] Greatly reducing the number of instructions used to compile disjunctives.
|
||||||
- [x] Storing short atoms to heap cells without writing them to the atom table.
|
- [x] Storing short atoms to heap cells without writing them to the atom table.
|
||||||
|
- [ ] Configurable JIT/on-demand indexing over all arguments
|
||||||
|
(documented in "[Demand-Driven Indexing of Prolog Clauses](https://user.it.uu.se/~kostis/Papers/iclp07.pdf)"). (_in progress_)
|
||||||
- [ ] A compacting garbage collector satisfying the five properties of
|
- [ ] A compacting garbage collector satisfying the five properties of
|
||||||
"[Precise Garbage Collection in Prolog](https://www.complang.tuwien.ac.at/ulrich/papers/PDF/2008-ciclops.pdf)." (_in progress_)
|
"[Precise Garbage Collection in Prolog](https://www.complang.tuwien.ac.at/ulrich/papers/PDF/2008-ciclops.pdf)." (_in progress_)
|
||||||
- [ ] Mode declarations.
|
|
||||||
|
|
||||||
## Phase 3
|
## Phase 3
|
||||||
|
|
||||||
@@ -103,8 +104,6 @@ Gustafson's book "[The End of Error](http://www.johngustafson.net/unums.html)."
|
|||||||
3. Add concurrent tables to manage shared references to atoms and
|
3. Add concurrent tables to manage shared references to atoms and
|
||||||
strings.
|
strings.
|
||||||
|
|
||||||
4. Add some form of JIT predicate indexing.
|
|
||||||
|
|
||||||
## Installing Scryer Prolog
|
## Installing Scryer Prolog
|
||||||
|
|
||||||
### Binaries
|
### Binaries
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Author: Markus Triska
|
Author: Markus Triska
|
||||||
E-mail: triska@metalevel.at
|
E-mail: triska@metalevel.at
|
||||||
WWW: https://www.metalevel.at
|
WWW: https://www.metalevel.at
|
||||||
Copyright (C): 2016-2024 Markus Triska
|
Copyright (C): 2016-2026 Markus Triska
|
||||||
|
|
||||||
This library provides CLP(ℤ):
|
This library provides CLP(ℤ):
|
||||||
|
|
||||||
@@ -6844,6 +6844,22 @@ gcc_global(Vs, KNs) -->
|
|||||||
% the propagator of tuples_in/2). Hence: We need this only if
|
% the propagator of tuples_in/2). Hence: We need this only if
|
||||||
% an example shows it, ideally found by a systematic search
|
% an example shows it, ideally found by a systematic search
|
||||||
% that can be used to test the implementation.
|
% that can be used to test the implementation.
|
||||||
|
%
|
||||||
|
% UPDATE: A case that requires gcc_check//1 was recently found,
|
||||||
|
% see: https://github.com/mthom/scryer-prolog/issues/3369.
|
||||||
|
%
|
||||||
|
% We need to study carefully what exactly happens in this case.
|
||||||
|
% The example involves reified constraints, which post constraints
|
||||||
|
% in their propagators. The example also involves multiple queues,
|
||||||
|
% because not all reified constraints use variables_same_queue/1
|
||||||
|
% (for instance (#==>)/2 does not), and variables_same_queue/1 would
|
||||||
|
% in fact need changes to handle cases where variables no longer
|
||||||
|
% have a clpz attribute attached. Such cases arise for variables
|
||||||
|
% involved in entailed reified constraints.
|
||||||
|
|
||||||
|
gcc_check(KNs), % see comment above.
|
||||||
|
do_queue, % is this needed? this (also) needs more analysis.
|
||||||
|
|
||||||
{ with_local_attributes(Vs,
|
{ with_local_attributes(Vs,
|
||||||
(gcc_arcs(KNs, S, Vals),
|
(gcc_arcs(KNs, S, Vals),
|
||||||
variables_with_num_occurrences(Vs, VNs),
|
variables_with_num_occurrences(Vs, VNs),
|
||||||
|
|||||||
@@ -7915,7 +7915,7 @@ impl Machine {
|
|||||||
#[cfg(not(feature = "crypto-full"))]
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
{
|
{
|
||||||
let stub_gen = || functor_stub(atom!("crypto_random_byte"), 1);
|
let stub_gen = || functor_stub(atom!("crypto_random_byte"), 1);
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
let err = self.machine_st.missing_feature_error(atom!("crypto-full"));
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
self.machine_st.throw_exception(exception);
|
self.machine_st.throw_exception(exception);
|
||||||
}
|
}
|
||||||
@@ -8079,7 +8079,7 @@ impl Machine {
|
|||||||
#[cfg(not(feature = "crypto-full"))]
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
{
|
{
|
||||||
let stub_gen = || functor_stub(atom!("crypto_data_hash"), 1);
|
let stub_gen = || functor_stub(atom!("crypto_data_hash"), 1);
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
let err = self.machine_st.missing_feature_error(atom!("crypto-full"));
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
self.machine_st.throw_exception(exception);
|
self.machine_st.throw_exception(exception);
|
||||||
return;
|
return;
|
||||||
@@ -8132,7 +8132,7 @@ impl Machine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "crypto-full"))]
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
{
|
{
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
let err = self.machine_st.missing_feature_error(atom!("crypto-full"));
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
let exception = self.machine_st.error_form(err, stub_gen());
|
||||||
self.machine_st.throw_exception(exception);
|
self.machine_st.throw_exception(exception);
|
||||||
}
|
}
|
||||||
@@ -8215,7 +8215,7 @@ impl Machine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "crypto-full"))]
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
{
|
{
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
let err = self.machine_st.missing_feature_error(atom!("crypto-full"));
|
||||||
let exception = self.machine_st.error_form(err, stub1_gen());
|
let exception = self.machine_st.error_form(err, stub1_gen());
|
||||||
self.machine_st.throw_exception(exception);
|
self.machine_st.throw_exception(exception);
|
||||||
}
|
}
|
||||||
@@ -8283,7 +8283,7 @@ impl Machine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "crypto-full"))]
|
#[cfg(not(feature = "crypto-full"))]
|
||||||
{
|
{
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
let err = self.machine_st.missing_feature_error(atom!("crypto-full"));
|
||||||
let exception = self.machine_st.error_form(err, stub1_gen());
|
let exception = self.machine_st.error_form(err, stub1_gen());
|
||||||
self.machine_st.throw_exception(exception);
|
self.machine_st.throw_exception(exception);
|
||||||
}
|
}
|
||||||
@@ -8409,152 +8409,111 @@ impl Machine {
|
|||||||
pub(crate) fn crypto_curve_scalar_mult(&mut self) {
|
pub(crate) fn crypto_curve_scalar_mult(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("crypto_curve_scalar_mult"), 4);
|
let stub_gen = || functor_stub(atom!("crypto_curve_scalar_mult"), 4);
|
||||||
|
|
||||||
{
|
let scalar_bytes = self
|
||||||
let scalar_bytes = self
|
.machine_st
|
||||||
.machine_st
|
.integers_to_bytevec(self.machine_st.registers[2], stub_gen);
|
||||||
.integers_to_bytevec(self.machine_st.registers[2], stub_gen);
|
let point_bytes = self
|
||||||
let point_bytes = self
|
.machine_st
|
||||||
.machine_st
|
.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
|
||||||
.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
|
|
||||||
|
|
||||||
let mut point = secp256k1::Point::decode(&point_bytes).unwrap();
|
let mut point = secp256k1::Point::decode(&point_bytes).unwrap();
|
||||||
let scalar = secp256k1::Scalar::decode_reduce(&scalar_bytes);
|
let scalar = secp256k1::Scalar::decode_reduce(&scalar_bytes);
|
||||||
point *= scalar;
|
point *= scalar;
|
||||||
|
|
||||||
let uncompressed = step_or_resource_error!(
|
let uncompressed = step_or_resource_error!(
|
||||||
self.machine_st,
|
self.machine_st,
|
||||||
self.u8s_to_string(&point.encode_uncompressed())
|
self.u8s_to_string(&point.encode_uncompressed())
|
||||||
);
|
);
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
|
unify!(self.machine_st, self.machine_st.registers[4], uncompressed);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
|
||||||
self.machine_st.throw_exception(exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn ed25519_seed_to_public_key(&mut self) {
|
pub(crate) fn ed25519_seed_to_public_key(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("ed25519_seed_keypair"), 2);
|
let stub_gen = || functor_stub(atom!("ed25519_seed_keypair"), 2);
|
||||||
|
|
||||||
{
|
let seed_bytes = self
|
||||||
let seed_bytes = self
|
.machine_st
|
||||||
.machine_st
|
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||||
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
|
||||||
|
|
||||||
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
||||||
|
|
||||||
let complete_string = step_or_resource_error!(
|
let complete_string = step_or_resource_error!(
|
||||||
self.machine_st,
|
self.machine_st,
|
||||||
self.u8s_to_string(skey.public_key.encoded.as_ref())
|
self.u8s_to_string(skey.public_key.encoded.as_ref())
|
||||||
);
|
);
|
||||||
|
|
||||||
unify!(
|
unify!(
|
||||||
self.machine_st,
|
self.machine_st,
|
||||||
self.machine_st.registers[2],
|
self.machine_st.registers[2],
|
||||||
complete_string
|
complete_string
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
|
||||||
self.machine_st.throw_exception(exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn ed25519_sign_raw(&mut self) {
|
pub(crate) fn ed25519_sign_raw(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("ed25519_sign"), 4);
|
let stub_gen = || functor_stub(atom!("ed25519_sign"), 4);
|
||||||
|
|
||||||
{
|
let seed_bytes = self
|
||||||
let seed_bytes = self
|
.machine_st
|
||||||
.machine_st
|
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||||
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
|
||||||
|
|
||||||
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
let skey = ed25519::PrivateKey::from_seed(&seed_bytes);
|
||||||
|
|
||||||
let encoding = cell_as_atom!(self.deref_register(3));
|
let encoding = cell_as_atom!(self.deref_register(3));
|
||||||
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
||||||
|
|
||||||
let sig = skey.sign_raw(&data);
|
let sig = skey.sign_raw(&data);
|
||||||
let sig_list = step_or_resource_error!(
|
let sig_list = step_or_resource_error!(
|
||||||
self.machine_st,
|
self.machine_st,
|
||||||
sized_iter_to_heap_list(
|
sized_iter_to_heap_list(
|
||||||
&mut self.machine_st.heap,
|
&mut self.machine_st.heap,
|
||||||
sig.as_ref().len(),
|
sig.as_ref().len(),
|
||||||
sig.as_ref()
|
sig.as_ref()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
.map(|b| fixnum_as_cell!(Fixnum::build_with(*b)))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
|
unify!(self.machine_st, self.machine_st.registers[4], sig_list);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
|
||||||
self.machine_st.throw_exception(exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn ed25519_verify_raw(&mut self) {
|
pub(crate) fn ed25519_verify_raw(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("ed25519_verify"), 4);
|
let stub_gen = || functor_stub(atom!("ed25519_verify"), 4);
|
||||||
|
|
||||||
{
|
let key_bytes = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
|
||||||
let key_bytes =
|
let pkey = ed25519::PublicKey::decode(&key_bytes).unwrap();
|
||||||
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 encoding = cell_as_atom!(self.deref_register(3));
|
||||||
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
|
||||||
|
|
||||||
let signature = self
|
let signature = self
|
||||||
.machine_st
|
.machine_st
|
||||||
.integers_to_bytevec(self.machine_st.registers[4], stub_gen);
|
.integers_to_bytevec(self.machine_st.registers[4], stub_gen);
|
||||||
|
|
||||||
self.machine_st.fail = !pkey.verify_raw(&signature, &data);
|
self.machine_st.fail = !pkey.verify_raw(&signature, &data);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
|
||||||
self.machine_st.throw_exception(exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn curve25519_scalar_mult(&mut self) {
|
pub(crate) fn curve25519_scalar_mult(&mut self) {
|
||||||
let stub_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
|
let stub_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
|
||||||
|
|
||||||
{
|
let scalar_bytes = self
|
||||||
let scalar_bytes = self
|
.machine_st
|
||||||
.machine_st
|
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
||||||
.integers_to_bytevec(self.machine_st.registers[1], stub_gen);
|
let point_bytes = self
|
||||||
let point_bytes = self
|
.machine_st
|
||||||
.machine_st
|
.integers_to_bytevec(self.machine_st.registers[2], stub_gen);
|
||||||
.integers_to_bytevec(self.machine_st.registers[2], stub_gen);
|
|
||||||
|
|
||||||
let result = x25519::x25519(
|
let result = x25519::x25519(
|
||||||
&<[u8; 32]>::try_from(&point_bytes[..]).unwrap(),
|
&<[u8; 32]>::try_from(&point_bytes[..]).unwrap(),
|
||||||
&<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap(),
|
&<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let string = step_or_resource_error!(self.machine_st, 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);
|
unify!(self.machine_st, self.machine_st.registers[3], string);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let err = self.machine_st.missing_feature_error(atom!("crypto"));
|
|
||||||
let exception = self.machine_st.error_form(err, stub_gen());
|
|
||||||
self.machine_st.throw_exception(exception);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -212,32 +212,34 @@ impl<T: RawBlockTraits> SerialOffsetTable<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn build_with(&mut self, value: T) -> usize {
|
unsafe fn build_with(&mut self, value: T) -> usize {
|
||||||
let mut ptr;
|
unsafe {
|
||||||
|
let mut ptr;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
ptr = self.block.alloc(size_of::<T>());
|
ptr = self.block.alloc(size_of::<T>());
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
let new_block = self.block.grow_new().unwrap();
|
let new_block = self.block.grow_new().unwrap();
|
||||||
self.block = new_block;
|
self.block = new_block;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ptr::write(ptr as *mut T, value);
|
ptr::write(ptr as *mut T, value);
|
||||||
// SAFETY: `ptr` was obtained from `self.block.alloc()`
|
// SAFETY: `ptr` was obtained from `self.block.alloc()`
|
||||||
self.block.get_offset(ptr)
|
self.block.get_offset(ptr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn lookup(&self, offset: usize) -> &T {
|
unsafe fn lookup(&self, offset: usize) -> &T {
|
||||||
&*self.block.get_unchecked(offset).cast::<T>()
|
unsafe { &*self.block.get_unchecked(offset).cast::<T>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn lookup_mut(&mut self, offset: usize) -> &mut T {
|
unsafe fn lookup_mut(&mut self, offset: usize) -> &mut T {
|
||||||
&mut *self.block.get_unchecked(offset).cast::<T>().cast_mut()
|
unsafe { &mut *self.block.get_unchecked(offset).cast::<T>().cast_mut() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
|||||||
32
src/wasm.rs
32
src/wasm.rs
@@ -129,23 +129,21 @@ impl WasmQueryState {
|
|||||||
let mut error = None;
|
let mut error = None;
|
||||||
let mut to_drop = false;
|
let mut to_drop = false;
|
||||||
match &mut self.inner {
|
match &mut self.inner {
|
||||||
Some(ref mut inner) => {
|
Some(inner) => inner.with_query_state_mut(|query_state| match query_state.next() {
|
||||||
inner.with_query_state_mut(|query_state| match query_state.next() {
|
Some(Ok(leaf_answer)) => {
|
||||||
Some(Ok(leaf_answer)) => {
|
js_sys::Reflect::set(&ret, &"value".into(), &leaf_answer.into()).unwrap();
|
||||||
js_sys::Reflect::set(&ret, &"value".into(), &leaf_answer.into()).unwrap();
|
js_sys::Reflect::set(&ret, &"done".into(), &false.into()).unwrap();
|
||||||
js_sys::Reflect::set(&ret, &"done".into(), &false.into()).unwrap();
|
}
|
||||||
}
|
Some(Err(error_term)) => {
|
||||||
Some(Err(error_term)) => {
|
let js_error = js_sys::Error::new("Prolog error");
|
||||||
let js_error = js_sys::Error::new("Prolog error");
|
js_error.set_cause(&error_term.into());
|
||||||
js_error.set_cause(&error_term.into());
|
error = Some(js_error);
|
||||||
error = Some(js_error);
|
}
|
||||||
}
|
None => {
|
||||||
None => {
|
js_sys::Reflect::set(&ret, &"done".into(), &true.into()).unwrap();
|
||||||
js_sys::Reflect::set(&ret, &"done".into(), &true.into()).unwrap();
|
to_drop = true;
|
||||||
to_drop = true;
|
}
|
||||||
}
|
}),
|
||||||
})
|
|
||||||
}
|
|
||||||
None => return Err(js_sys::Error::new("This query was already dropped").into()),
|
None => return Err(js_sys::Error::new("This query was already dropped").into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user