#### From Crates.io [](https://crates.io/crates/scryer-prolog) 
> [!NOTE]
-> The lates crates.io release can be significantly behind the version available in the git repository
+> The latest crates.io release can be significantly behind the version available in the git repository
> The crates.io badge in this sections title is a link to the crates.io page.
-> The msrv badge in the section title referece to the minimum rust toolchain version required to compile the latest crates.io release
+> The msrv badge in the section title references the minimum rust toolchain version required to compile the latest crates.io release
`scryer-prolog` is also release on crates.io and can be installed with
--- /dev/null
+# config for https://github.com/crate-ci/typos
+
+[default]
+# example from https://github.com/crate-ci/typos/blob/master/docs/reference.md#example-configurations
+extend-ignore-re = [
+ "(#|//)\\s*spellchecker:ignore-next-line\\n.*"
+]
+
+# correct word key to value
+# can be used to ignore a typo by adding an entry <typo> = "<typo>"
+[default.extend-words]
+
+# correct identifier key to value
+# can be used to ignore a typo by adding an entry <typo> = "<typo>"
+[default.extend-identifiers]
+interm = "interm"
+IntermReg = "IntermReg"
+
+
+
+[type.prolog]
+extend-glob = ["*.pl"]
+check-file = false
+
+[type.stdout]
+extend-glob = ["*.stdout"]
+check-file = false
+
+
+[files]
+extend-exclude = ["lib_integration_test_commands.txt"]
\ No newline at end of file
## Adding benchmarks
-This design is meant to suppoort defining lots of benchmarks.
+This design is meant to support defining lots of benchmarks.
To add a new benchmark:
cumbersome to run.
* Consider that the library runtime actually parses the text output of the top
level. So don't use custom outputs or it will fail to parse. Also keep the
- output small so it doesn't just benchmark the ouput parsing code.
+ output small so it doesn't just benchmark the output parsing code.
* DO test the output of the benchmark run, we don't want to count broken
benchmarks.
* This crate exists to generate the Instruction enum in
* src/instructions.rs and its adjoining impl functions. The types
* defined in it are empty and serve only as schema for the generation
- * of Instruction. They mimick most of the structure of the previous
+ * of Instruction. They mimic most of the structure of the previous
* Line instruction type. The strum crate is used to provide reflection
* on each of the node types to the tree walker.
*/
disallowed-methods = [
# https://rust-lang.github.io/rust-clippy/master/#disallowed_method
- # list of methods that may panic on allocation failue
+ # list of methods that may panic on allocation failure
# though not including things that can be used correctly by reversing ahead of time (i.e. std::vec::Vec::try_reserve + std::iter::Extend::extend ).
# "std::iter::Iter::collect",
First, we need to decide a representation of our cards. Coming from another languages we can think that a good representation might be a class or a struct, with two fields, one for the number and the other for the suite, but Prolog doesn't have objects. We can use a list with two elements. But lists are better when we're dealing with variable length data. We could also use a compound term. This is the right choice if our fields are fixed.
-A compound term is defined by an atom, followed by the data itself enclosed by parenthesis and separated by comma. Like this: `card(oros, 4)`. Yes, very similar to predicates. In fact the only difference is how we use them, because they're the same. If we pass a compund term in the first level of a query, or inside a call/N, Prolog will treat it as code instead of data. This is one the the examples of Prolog being a homoiconic language.
+A compound term is defined by an atom, followed by the data itself enclosed by parenthesis and separated by comma. Like this: `card(oros, 4)`. Yes, very similar to predicates. In fact the only difference is how we use them, because they're the same. If we pass a compound term in the first level of a query, or inside a call/N, Prolog will treat it as code instead of data. This is one the the examples of Prolog being a homoiconic language.
We can go further, Prolog is very flexible and we can define custom operators easily if we want. Those are also compound terms, but with a different syntax. There's an operator already defined that is very useful for us: the dash. We can just join two pieces of data with a dash, and they'll be together in the same structure. This is usually called "pair".
cards_score_(X1).
```
-In DCGs, to match an item of the sequence, we use brackets. We use braces to introduce normal Prolog code. Calling other DCGs (in this case, the same, as it's a recursive one), it's just calling it again. Notice in this code that we are doing the addition of X0 and X1 when we still don't know the value of X1. This would be an error in the traditional arithmethic system of Prolog, but it's valid with clpz. clpz allows us to have a more declarative arithmethic, at least with integers.
+In DCGs, to match an item of the sequence, we use brackets. We use braces to introduce normal Prolog code. Calling other DCGs (in this case, the same, as it's a recursive one), it's just calling it again. Notice in this code that we are doing the addition of X0 and X1 when we still don't know the value of X1. This would be an error in the traditional arithmetic system of Prolog, but it's valid with clpz. clpz allows us to have a more declarative arithmetic, at least with integers.
Now we can try this code using `phrase/2` which is needed to jump to a DCG.
The basic idea however is having _explicit_ states. The predicates that we're going to write will take an state (a view of the world at a certain point) and will give us the next state.
-Let's define the state first. In a game of Brisca we have players. Each player has the three cards he can choose to put (less if we're running out of cards) and the cards he has got from winning rounds. Aditionally we have a stock, a trump suite and the order to play, which is usually from the player who won the last round and going to the right. We could store the data in a list, with different compound terms:
+Let's define the state first. In a game of Brisca we have players. Each player has the three cards he can choose to put (less if we're running out of cards) and the cards he has got from winning rounds. Additionally we have a stock, a trump suite and the order to play, which is usually from the player who won the last round and going to the right. We could store the data in a list, with different compound terms:
```
[players([player(Name, PlayableCards, WonCards), player(Name, PlayableCards, WonCards), ...]), stock(Cards), trump(Trump)]
pub fn to_untyped(self: Box<Self>) -> (TypedArenaPtr<T>, UntypedArenaSlab) {
let raw_box = Box::into_raw(self);
- // safety: the pointer from Box::into_raw fullfills addr_of_mut's saftey requirements
+ // safety: the pointer from Box::into_raw fulfills addr_of_mut's safety requirements
let payload_ptr = unsafe { addr_of_mut!((*raw_box).payload) };
(
table.insert(atom);
block_epoch.table.replace(table);
- // expicit drop to ensure we don't accidentally drop it early
+ // explicit drop to ensure we don't accidentally drop it early
drop(update_guard);
return atom;
got: usize,
},
AllocationFailed,
- // LayoutError should never occour
+ // LayoutError should never occur
LayoutError,
UnsupportedTypedef,
UnsupportedAbi,
self.throw_interrupt_exception();
self.backtrack();
- // We have extracted controll over the Tokio runtime to the calling context for enabling library use case
+ // We have extracted control over the Tokio runtime to the calling context for enabling library use case
// (see https://github.com/mthom/scryer-prolog/pull/1880)
// So we only have access to a runtime handle in here and can't shut it down.
// Since I'm not aware of the consequences of deactivating this new code which came in while PR 1880
/// Computes the number of bytes required to pad a string of length `chunk_len`
/// with zeroes, such that `chunk_len + pstr_sentinel_length(chunk_len)` is a
-/// multiple of `Heap::heap_cell_alignement()`.
+/// multiple of `Heap::heap_cell_alignment()`.
fn pstr_sentinel_length(chunk_len: usize) -> usize {
let res = chunk_len.next_multiple_of(ALIGN) - chunk_len;
impl Drop for QueryState<'_> {
fn drop(&mut self) {
- // FIXME: This may be wrong if the iterator is not fully consumend, but from testing it
+ // FIXME: This may be wrong if the iterator is not fully consumed, but from testing it
// seems fine. Is this really ok?
self.machine.trust_me();
}
#[test]
#[cfg_attr(miri, ignore = "it takes too long to run")]
-fn programatic_query() {
+fn programmatic_query() {
let mut machine = MachineBuilder::default().build();
machine.load_module_string(
let cell_ptr = new_ptr.add(offset).cast::<HeapCellValue>();
ptr::write(cell_ptr.as_ptr(), stack_loc_as_cell!(AndFrame, e, idx + 1));
- // Because in the Index and IndexMut inplementations we need to get this from
+ // Because in the Index and IndexMut implementations we need to get this from
// exposed provenance, we need to expose the provenance here, even though we don't
// actually use the value for anything. This is a reminder that `expose_provenance`
// isn't just a cast from a pointer to an integer but has actual side effects.
let cell_ptr = new_ptr.byte_add(offset).cast::<HeapCellValue>();
ptr::write(cell_ptr.as_ptr(), stack_loc_as_cell!(OrFrame, b, idx));
- // Because in the Index and IndexMut inplementations we need to get this from
+ // Because in the Index and IndexMut implementations we need to get this from
// exposed provenance, we need to expose the provenance here, even though we don't
// actually use the value for anything. This is a reminder that `expose_provenance`
// isn't just a cast from a pointer to an integer but has actual side effects.
}
let value = self.rng.gen_range(lower..upper);
// Safety:
- // - lower and uper bounds are Fixnum values
+ // - lower and upper bounds are Fixnum values
// - value is inbetween lower and upper
// - fixnums value range has no gaps
// so value is also a valid Fixnum value
if interruption {
self.machine_st.throw_interrupt_exception();
self.machine_st.backtrack();
- // We have extracted controll over the Tokio runtime to the calling context for enabling library use case
+ // We have extracted control over the Tokio runtime to the calling context for enabling library use case
// (see https://github.com/mthom/scryer-prolog/pull/1880)
// So we only have access to a runtime handle in here and can't shut it down.
// Since I'm not aware of the consequences of deactivating this new code which came in while PR 1880
#[inline]
pub fn get_spec(self) -> OpDeclSpec {
- OpDeclSpec::try_from(self.spec()).expect("OpDecl always contains a valud OpDeclSpec")
+ OpDeclSpec::try_from(self.spec()).expect("OpDecl always contains a valid OpDeclSpec")
}
#[inline]
// TODO: Maybe add validation to the helper
pub struct Helper {
- highligher: MatchingBracketHighlighter,
+ highlighter: MatchingBracketHighlighter,
pub atoms: Weak<AtomTable>,
}
impl Helper {
pub fn new() -> Self {
Self {
- highligher: MatchingBracketHighlighter::new(),
+ highlighter: MatchingBracketHighlighter::new(),
atoms: Weak::new(),
}
}
impl Highlighter for Helper {
fn highlight<'l>(&self, line: &'l str, pos: usize) -> std::borrow::Cow<'l, str> {
- self.highligher.highlight(line, pos)
+ self.highlighter.highlight(line, pos)
}
fn highlight_char(&self, line: &str, pos: usize, forced: bool) -> bool {
- self.highligher.highlight_char(line, pos, forced)
+ self.highlighter.highlight_char(line, pos, forced)
}
}
}
/// # Safety
- /// - this UntypedArenaPtr actuall pointee type is T
+ /// - this UntypedArenaPtr actual pointee type is T
/// - the pointer must be non-null
#[inline]
pub unsafe fn as_typed_ptr<T: ?Sized + ArenaAllocated>(self) -> TypedArenaPtr<T>
```
-FIXME I belive the following test should result in a `error(instantiation_error,load/1)` error instead of the current error.
+FIXME I believe the following test should result in a `error(instantiation_error,load/1)` error instead of the current error.
```trycmd
$ scryer-prolog -f --no-add-history tests-pl/invalid_decl11.pl -g halt
// each test is building its own library so that they can easier run in parallel,
// i.e. don't need to wait for a large dynamic library to compile,
-// also rusts test infra currently has no functionallity for a setup/befor step
+// also rusts test infra currently has no functionality for a setup/befor step
fn build_dynamic_library(name: &str, src: &str) -> PathBuf {
let tmp_dir: &Path = TMP_DIR.as_ref();
"##,
);
- // note: ouput is currently wrong correct would be 1.0,1.0
load_module_test_with_input(
"tests-pl/ffi_f64_minus_zero.pl",
format!("LIB={dynlib_path:?}."),
#[test]
#[cfg_attr(miri, ignore = "it takes too long to run")]
fn setup_call_cleanup_load() {
+
load_module_test(
"src/tests/setup_call_cleanup.pl",
+ // spellchecker:ignore-next-line
"1+21+31+2>A+B1+G1+2>41+2>B1+2>31+2>31+2>4ba",
);
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
When allocating a new choice or environment frame on the stack, one
-should use CP (the continuation pointer) insteads of E+1 (the stored
+should use CP (the continuation pointer) instead of E+1 (the stored
continuation pointer) to find out the number of Y variables to preserve
in the previous environment frame. This is because the continuation
pointer is stored on the stack only if an ALLOCATE instruction is used
There is a more subtle related bug that usually doesn't matter very
much: both cut and neck_cut should also reset HB. If they do not,
-some uneccessary trailing will occur. This normally doesnt matter
+some unnecessary trailing will occur. This normally doesnt matter
too much (aside from a small performance penalty), but it does turn
out to be a problem if you try to implement Older and Rummel's incremental
garbage collection algorithm, because you end up with dangling trail