Merge branch 'master' into http-server

This commit is contained in:
Adrián Arroyo Calle
2020-12-27 12:18:05 +01:00
19 changed files with 262 additions and 126 deletions

35
Cargo.lock generated
View File

@@ -265,16 +265,6 @@ dependencies = [
"generic-array",
]
[[package]]
name = "dirs"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
dependencies = [
"cfg-if 0.1.10",
"dirs-sys",
]
[[package]]
name = "dirs"
version = "3.0.1"
@@ -284,6 +274,16 @@ dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if 1.0.0",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys"
version = "0.3.5"
@@ -295,6 +295,17 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99de365f605554ae33f115102a02057d4fc18b01f3284d6870be0938743cfe7d"
dependencies = [
"libc",
"redox_users",
"winapi 0.3.8",
]
[[package]]
name = "divrem"
version = "0.1.0"
@@ -1220,7 +1231,7 @@ checksum = "1a5f54deba50e65ee4cf786dbc37e8b3c63bdccccbcf9d3a8a9fd0c1bb7e1984"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"dirs 3.0.1",
"dirs",
"fs2",
"libc",
"log",
@@ -1264,7 +1275,7 @@ dependencies = [
"chrono",
"cpu-time",
"crossterm",
"dirs 2.0.2",
"dirs-next",
"divrem",
"downcast",
"git-version",

View File

@@ -21,7 +21,7 @@ num = ["num-rug-adapter", "prolog_parser/num"]
[dependencies]
cpu-time = "1.0.0"
crossterm = "0.16.0"
dirs = "2.0.2"
dirs-next = "2.0.0"
divrem = "0.1.0"
downcast = "0.10.0"
git-version = "0.3.4"

View File

@@ -226,6 +226,36 @@ arithmetic operators with the usual precedences,
New operators can be defined using the `op` declaration.
### First instantiated argument indexing
Scryer Prolog indexes on the leftmost argument that is not a variable
in all clauses of a predicate's definition. We call this strategy
first *instantiated* argument indexing.
A key motivation for first instantiated argument indexing is to enable
indexing for meta-predicates such as `maplist/N` and `foldl/N`, whose
first argument is a partial goal that is a variable in the definition
of these predicates and therefore cannot be used for indexing.
For example, a natural definiton of `maplist/2` reads:
```
maplist(_, []).
maplist(Goal_1, [L|Ls]) :-
call(Goal_1, L),
maplist(Goal_1, Ls).
```
In this case, first instantianted argument indexing automatically uses
the *second* argument for indexing, and thus prevents choicepoints for
calls with lists of fixed lengths (and deterministic goals).
Conveniently, no auxiliary predicates with reordered arguments are
needed to benefit from indexing in such cases.
Conventional first argument indexing naturally arises as a
special case of this strategy, if the first argument is instantiated
in any clause of a predicate's definition.
### Strings and partial strings
In Scryer Prolog, the default value of the Prolog flag `double_quotes`

View File

@@ -1,3 +1,4 @@
/// Code generation to WAM-like instructions.
use crate::prolog_parser::ast::*;
use crate::allocator::*;
@@ -857,21 +858,63 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
Ok(code)
}
fn split_predicate(clauses: &Vec<PredicateClause>) -> Vec<(usize, usize)> {
/// Returns the index of the first instantiated argument.
fn first_instantiated_index(clauses: &[PredicateClause]) -> Option<usize> {
let mut optimal_index = None;
let has_args = match clauses.first() {
Some(clause) => match clause.args() {
Some(args) => !args.is_empty(),
None => false,
},
None => false,
};
if !has_args {
return optimal_index;
}
for clause in clauses.iter() {
let args = clause.args().unwrap();
for (i, arg) in args.iter().enumerate() {
if let Some(optimal_index) = optimal_index {
if i >= optimal_index {
break;
}
}
match **arg {
Term::AnonVar | Term::Var(..) => (),
_ => {
match optimal_index {
Some(ref mut optimal_i) => *optimal_i = i,
None => optimal_index = Some(i),
}
break;
}
}
}
}
optimal_index
}
fn split_predicate(clauses: &[PredicateClause], optimal_index: usize) -> Vec<(usize, usize)> {
let mut subseqs = Vec::new();
let mut left_index = 0;
for (right_index, clause) in clauses.iter().enumerate() {
match clause.first_arg() {
Some(&Term::Var(_, _)) | Some(&Term::AnonVar) => {
if left_index < right_index {
subseqs.push((left_index, right_index));
}
if clauses.first().unwrap().args().is_some() {
for (right_index, clause) in clauses.iter().enumerate() {
// Can unwrap safely.
if let Some(arg) = clause.args().unwrap().iter().nth(optimal_index) {
match **arg {
Term::Var(..) | Term::AnonVar => {
if left_index < right_index {
subseqs.push((left_index, right_index));
}
subseqs.push((right_index, right_index + 1));
left_index = right_index + 1;
subseqs.push((right_index, right_index + 1));
left_index = right_index + 1;
}
_ => (),
}
}
_ => {}
}
}
@@ -901,6 +944,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
fn compile_pred_subseq<'b: 'a>(
&mut self,
clauses: &'b [PredicateClause],
optimal_index: usize,
) -> Result<Code, ParserError> {
let mut code_body = Vec::new();
let mut code_offsets = CodeOffsets::new();
@@ -910,9 +954,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
for (i, clause) in clauses.iter().enumerate() {
self.marker.reset();
let mut clause_code = match clause {
&PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
&PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
let mut clause_code = match *clause {
PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact),
PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
};
if num_clauses > 1 {
@@ -925,17 +969,24 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
code_body.push(Line::Choice(choice));
}
clause.first_arg().map(|arg| {
let arg = match clause.args() {
Some(args) => match args.iter().nth(optimal_index) {
Some(term) => Some(term),
None => None,
},
None => None,
};
if let Some(arg) = arg {
let index = code_body.len();
code_offsets.index_term(arg, index);
});
}
code_body.append(&mut clause_code);
}
let mut code = Vec::new();
code_offsets.add_indices(&mut code, code_body, optimal_index + 1);
code_offsets.add_indices(&mut code, code_body);
Ok(code)
}
@@ -944,11 +995,16 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
clauses: &'b Vec<PredicateClause>,
) -> Result<Code, ParserError> {
let mut code = Vec::new();
let split_pred = Self::split_predicate(&clauses);
let optimal_index = match Self::first_instantiated_index(&clauses) {
Some(index) => index,
None => 0, // Default to first argument indexing.
};
let split_pred = Self::split_predicate(&clauses, optimal_index);
let multi_seq = split_pred.len() > 1;
for (l, r) in split_pred {
let mut code_segment = self.compile_pred_subseq(&clauses[l..r])?;
let mut code_segment =
self.compile_pred_subseq(&clauses[l..r], optimal_index)?;
if multi_seq {
let choice = match l {

View File

@@ -332,10 +332,16 @@ pub enum PredicateClause {
}
impl PredicateClause {
pub fn first_arg(&self) -> Option<&Term> {
match self {
&PredicateClause::Fact(ref term, ..) => term.first_arg(),
&PredicateClause::Rule(ref rule, ..) => rule.head.1.first().map(|bt| bt.as_ref()),
// TODO: add this to `Term` in `prolog_parser` like `first_arg`.
pub fn args(&self) -> Option<&[Box<Term>]> {
match *self {
PredicateClause::Fact(ref term, ..) => {
match term {
Term::Clause(_, _, args, _) => Some(&args),
_ => None,
}
},
PredicateClause::Rule(ref rule, ..) => Some(&rule.head.1),
}
}

View File

@@ -143,8 +143,8 @@ impl CodeOffsets {
}
}
pub fn index_term(&mut self, first_arg: &Term, index: usize) {
match first_arg {
pub fn index_term(&mut self, optimal_arg: &Term, index: usize) {
match optimal_arg {
&Term::Clause(_, ref name, ref terms, _) => {
let code = self
.structures
@@ -237,12 +237,17 @@ impl CodeOffsets {
fn switch_on_constant(
con_ind: IndexMap<Constant, ThirdLevelIndex>,
prelude: &mut CodeDeque,
optimal_index: usize,
) -> IntIndex {
let con_ind = Self::second_level_index(con_ind, prelude);
if con_ind.len() > 1 {
let index = Self::flatten_index(con_ind, prelude.len());
let instr = IndexingInstruction::SwitchOnConstant(index.len(), index);
let instr = IndexingInstruction::SwitchOnConstant(
optimal_index,
index.len(),
index
);
prelude.push_front(Line::from(instr));
@@ -259,12 +264,17 @@ impl CodeOffsets {
fn switch_on_structure(
str_ind: IndexMap<(ClauseName, usize), ThirdLevelIndex>,
prelude: &mut CodeDeque,
optimal_index: usize,
) -> IntIndex {
let str_ind = Self::second_level_index(str_ind, prelude);
if str_ind.len() > 1 {
let index = Self::flatten_index(str_ind, prelude.len());
let instr = IndexingInstruction::SwitchOnStructure(index.len(), index);
let instr = IndexingInstruction::SwitchOnStructure(
optimal_index,
index.len(),
index
);
prelude.push_front(Line::from(instr));
@@ -325,7 +335,7 @@ impl CodeOffsets {
}
}
pub fn add_indices(self, code: &mut Code, mut code_body: Code) {
pub fn add_indices(self, code: &mut Code, mut code_body: Code, optimal_index: usize) {
if self.no_indices() {
*code = code_body;
return;
@@ -334,8 +344,10 @@ impl CodeOffsets {
let mut prelude = VecDeque::new();
let lst_loc = Self::switch_on_list(self.lists, &mut prelude);
let str_loc = Self::switch_on_structure(self.structures, &mut prelude);
let con_loc = Self::switch_on_constant(self.constants, &mut prelude);
let str_loc =
Self::switch_on_structure(self.structures, &mut prelude, optimal_index);
let con_loc =
Self::switch_on_constant(self.constants, &mut prelude, optimal_index);
let prelude_length = prelude.len();
@@ -355,8 +367,13 @@ impl CodeOffsets {
let con_loc = Self::switch_on_con_offset_from(con_loc, prelude.len());
let lst_loc = Self::switch_on_lst_offset_from(lst_loc, prelude.len());
let switch_instr =
IndexingInstruction::SwitchOnTerm(prelude.len() + 1, con_loc, lst_loc, str_loc);
let switch_instr = IndexingInstruction::SwitchOnTerm(
optimal_index,
prelude.len() + 1,
con_loc,
lst_loc,
str_loc
);
prelude.push_front(Line::from(switch_instr));

View File

@@ -143,6 +143,7 @@ impl IndexedChoiceInstruction {
}
}
/// A `Line` is an instruction (cf. page 98 of wambook).
#[derive(Debug)]
pub enum Line {
Arithmetic(ArithmeticInstruction),
@@ -424,11 +425,13 @@ impl ControlInstruction {
}
}
/// `IndexingInstruction` cf. page 110 of wambook.
#[derive(Debug)]
pub enum IndexingInstruction {
SwitchOnTerm(usize, usize, usize, usize),
SwitchOnConstant(usize, IndexMap<Constant, usize>),
SwitchOnStructure(usize, IndexMap<(ClauseName, usize), usize>),
// The first index is the optimal argument being indexed.
SwitchOnTerm(usize, usize, usize, usize, usize),
SwitchOnConstant(usize, usize, IndexMap<Constant, usize>),
SwitchOnStructure(usize, usize, IndexMap<(ClauseName, usize), usize>),
}
impl From<IndexingInstruction> for Line {
@@ -440,25 +443,26 @@ impl From<IndexingInstruction> for Line {
impl IndexingInstruction {
pub fn to_functor(&self) -> MachineStub {
match self {
&IndexingInstruction::SwitchOnTerm(vars, constants, lists, structures) => {
&IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
functor!(
"switch_on_term",
[integer(vars),
[integer(arg),
integer(vars),
integer(constants),
integer(lists),
integer(structures)]
)
}
&IndexingInstruction::SwitchOnConstant(constants, _) => {
&IndexingInstruction::SwitchOnConstant(arg, constants, _) => {
functor!(
"switch_on_constant",
[integer(constants)]
[integer(arg), integer(constants)]
)
}
&IndexingInstruction::SwitchOnStructure(structures, _) => {
&IndexingInstruction::SwitchOnStructure(arg, structures, _) => {
functor!(
"switch_on_structure",
[integer(structures)]
[integer(arg), integer(structures)]
)
}
}

View File

@@ -212,8 +212,7 @@ read_line_to_chars(Stream, Cs0, Cs) :-
Example:
?- chars_base64("hello", Bs, []).
Bs = "aGVsbG8="
; false.
Bs = "aGVsbG8=".
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
chars_base64(Cs, Bs, Options) :-

View File

@@ -58,8 +58,7 @@
Example:
?- hex_bytes("501ACE", Bs).
Bs = [80,26,206]
; false.
Bs = [80,26,206].
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -146,7 +145,7 @@ must_be_byte_chars(Chars, Context) :-
?- crypto_n_random_bytes(32, Bs),
bytes_integer(Bs, I).
Bs = [146,166,162,210,242,7,25,132,64,94|...],
I = 337420085690608915485...(56 digits omitted)
I = 337420085690608915485...(56 digits omitted).
The above relation also works in the other direction, letting you
translate an integer _to_ a list of bytes. In addition, you can
@@ -155,7 +154,7 @@ must_be_byte_chars(Chars, Context) :-
?- crypto_n_random_bytes(12, Bs),
hex_bytes(Hex, Bs).
Bs = [34,25,50,72,58,63,50,172,32,46|...], Hex = "221932483a3f32ac202 ..."
Bs = [34,25,50,72,58,63,50,172,32,46|...], Hex = "221932483a3f32ac202 ...".
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -190,8 +189,7 @@ crypto_random_byte(B) :- '$crypto_random_byte'(B).
Example:
?- crypto_data_hash("abc", Hs, [algorithm(sha256)]).
Hs = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
; false.
Hs = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad".
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@@ -166,19 +166,16 @@ file_time_(File, Which, T) :-
Examples:
?- path_segments("/hello/there", Segments).
Segments = [[],"hello","there"]
; false.
Segments = [[],"hello","there"].
?- path_segments(Path, ["hello","there"]).
Path = "hello/there"
; false.
Path = "hello/there".
To obtain the platform-specific directory separator, you can use:
?- path_segments(Separator, ["",""]).
Separator = "/"
; false.
Separator = "/".
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
path_segments(Path, Segments) :-

View File

@@ -64,8 +64,7 @@
Example:
?- phrase(format_("~s~n~`.t~w!~12|", ["hello",there]), Cs).
%@ Cs = "hello\n......there!"
%@ ; false.
%@ Cs = "hello\n......there!".
I place this code in the public domain. Use it in any way you want.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -158,7 +157,7 @@ element_gluevar(glue(_,V), N, N) --> [V].
consume whitespace in the sense of format strings.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
cells([], Args, Tab, Es, _) -->
cells([], Args, Tab, Es, _) --> !,
( { Args == [] } -> cell(Tab, Tab, Es)
; { domain_error(empty_list, Args, format_//2) }
).
@@ -404,32 +403,28 @@ Cs = [cell(0,4,[glue(' ',_A),chars("a"),glue(' ',_B)])]
?- phrase(format_("hello~n~tthere~6|", []), Ls).
?- format("~ta~t~4|", []).
a true
; false.
a true.
?- format("~ta~tb~tc~10|", []).
a b c true
; false.
a b c true.
?- format("~tabc~3|", []).
?- format("~ta~t~4|", []).
?- format("~ta~t~tb~tc~20|", []).
a b c true
; false.
a b c true.
?- format("~2f~n", [3]).
3.00
true
true.
?- format("~20f", [0.1]).
0.10000000000000000000 true % this should use higher accuracy!
; false.
0.10000000000000000000 true.
?- X is atan(2), format("~7f~n", [X]).
1.1071487
X = 1.1071487177940906
X = 1.1071487177940906.
?- format("~`at~50|~n", []).
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
@@ -438,10 +433,10 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
?- format("~t~N", []).
?- format("~q", [.]).
'.' true
'.' true.
?- format("~12r", [300]).
210 true
210 true.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -537,7 +532,7 @@ a :-
b,
c,
d.
true
true.
?- portray_clause([a,b,c,d]).

View File

@@ -17,8 +17,7 @@
Example:
?- http_open("https://github.com/mthom/scryer-prolog", S, []).
%@ S = '$stream'(0x7f86f94a6cd0)
%@ ; false.
%@ S = '$stream'(0x7fcfc9e00f00).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

View File

@@ -7,8 +7,7 @@
Example:
?- getenv("LANG", Ls).
Ls = "en_US.UTF-8"
; false.
Ls = "en_US.UTF-8".
Public domain code.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

View File

@@ -34,8 +34,7 @@
Example:
?- current_time(T), phrase(format_time("%d.%m.%Y (%H:%M:%S)", T), Cs).
T = [...], Cs = "11.06.2020 (00:24:32)"
; false.
T = [...], Cs = "11.06.2020 (00:24:32)".
sleep(S) sleeps for S seconds (a floating point number).
@@ -107,15 +106,14 @@ report_time(T0) :-
false.
:- time(use_module(library(clpz))).
% CPU time: 2.762 seconds
true
; false.
% CPU time: 0.000 seconds
% CPU time: 0.001 seconds
true.
:- time(use_module(library(lists))).
% CPU time: 0.000 seconds
true
; % CPU time: 0.001 seconds
false.
% CPU time: 0.001 seconds
true.
?- time(member(X, [a,b,c])).
% CPU time: 0.000 seconds

View File

@@ -2,30 +2,57 @@ use crate::instructions::*;
use std::collections::VecDeque;
fn scan_for_trust_me(code: &Code, jmp_offsets: &mut VecDeque<usize>, after_idx: &mut usize) {
for (idx, instr) in code[*after_idx..].iter().enumerate() {
match instr {
&Line::Choice(ChoiceInstruction::TrustMe)
| &Line::IndexedChoice(IndexedChoiceInstruction::Trust(..)) => {
*after_idx += idx;
return;
fn scan_for_trust_me(
code: &Code,
jmp_offsets: &mut VecDeque<usize>,
before_idx: usize,
after_idx: &mut usize,
) {
// record the location of the line after the TrustMe capping the
// choice instruction sequence to after_idx.
loop {
match &code[*after_idx] {
&Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset)) |
&Line::Choice(ChoiceInstruction::RetryMeElse(offset)) |
&Line::IndexedChoice(IndexedChoiceInstruction::Retry(offset)) => {
*after_idx += offset;
}
&Line::Control(ControlInstruction::JmpBy(_, offset, ..)) => {
jmp_offsets.push_back(*after_idx + idx + offset)
&Line::Choice(ChoiceInstruction::DefaultTrustMe) |
&Line::Choice(ChoiceInstruction::TrustMe) |
&Line::IndexedChoice(IndexedChoiceInstruction::Trust(..)) => {
break;
}
_ => {
*after_idx += 1;
}
_ => {}
}
}
// search the code in the range for JmpBy instructions and record their
// offsets for future scanning.
for (idx, instr) in code[before_idx .. *after_idx].iter().enumerate() {
match instr {
&Line::Control(ControlInstruction::JmpBy(_, offset, ..)) => {
jmp_offsets.push_back(before_idx + idx + offset)
}
_ => {
}
}
}
*after_idx += 1;
}
fn capture_next_range(code: &Code, queue: &mut VecDeque<usize>, last_idx: &mut usize) {
loop {
match &code[*last_idx] {
&Line::Choice(ChoiceInstruction::TryMeElse(..))
| &Line::IndexedChoice(IndexedChoiceInstruction::Try(..)) => {
*last_idx += 1;
scan_for_trust_me(code, queue, last_idx);
}
&Line::Choice(ChoiceInstruction::TryMeElse(offset)) |
&Line::IndexedChoice(IndexedChoiceInstruction::Try(offset)) => {
let before_idx = *last_idx;
*last_idx += offset;
scan_for_trust_me(code, queue, before_idx, last_idx);
}
&Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
queue.push_back(*last_idx + offset);
*last_idx += 1;
@@ -34,8 +61,8 @@ fn capture_next_range(code: &Code, queue: &mut VecDeque<usize>, last_idx: &mut u
queue.push_back(*last_idx + offset);
break;
}
&Line::Control(ControlInstruction::Proceed)
| &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) =>
&Line::Control(ControlInstruction::Proceed) |
&Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) =>
break,
_ =>
*last_idx += 1,

View File

@@ -1392,8 +1392,8 @@ impl MachineState {
pub(super)
fn execute_indexing_instr(&mut self, instr: &IndexingInstruction) {
match instr {
&IndexingInstruction::SwitchOnTerm(v, c, l, s) => {
let addr = self[temp_v!(1)];
&IndexingInstruction::SwitchOnTerm(arg, v, c, l, s) => {
let addr = self[temp_v!(arg)];
let addr = self.store(self.deref(addr));
let offset = match addr {
@@ -1423,8 +1423,8 @@ impl MachineState {
o => self.p += o,
};
}
&IndexingInstruction::SwitchOnConstant(_, ref hm) => {
let addr = self[temp_v!(1)];
&IndexingInstruction::SwitchOnConstant(arg, _, ref hm) => {
let addr = self[temp_v!(arg)];
let addr = self.store(self.deref(addr));
let offset =
@@ -1445,8 +1445,8 @@ impl MachineState {
o => self.p += o,
};
}
&IndexingInstruction::SwitchOnStructure(_, ref hm) => {
let a1 = self.registers[1];
&IndexingInstruction::SwitchOnStructure(arg, _, ref hm) => {
let a1 = self.registers[arg];
let addr = self.store(self.deref(a1));
let offset = match addr {

View File

@@ -281,7 +281,7 @@ impl Machine {
}
fn compile_scryerrc(&mut self) {
let mut path = match dirs::home_dir() {
let mut path = match dirs_next::home_dir() {
Some(path) => path,
None => return,
};

View File

@@ -47,7 +47,7 @@ pub mod readline {
#[inline]
pub fn new(pending_input: String) -> Self {
let mut rl = Editor::<()>::new();
if let Some(mut path) = dirs::home_dir() {
if let Some(mut path) = dirs_next::home_dir() {
path.push(HISTORY_FILE);
if path.exists() {
if rl.load_history(&path).is_err() {
@@ -55,7 +55,7 @@ pub mod readline {
}
}
}
rl.bind_sequence(KeyEvent::from('\t'), Cmd::Insert(1, "\t".to_string()));
ReadlineStream { rl, pending_input: Cursor::new(pending_input) }
}
@@ -95,7 +95,7 @@ pub mod readline {
}
fn save_history(&mut self) {
if let Some(mut path) = dirs::home_dir() {
if let Some(mut path) = dirs_next::home_dir() {
path.push(HISTORY_FILE);
if path.exists() {
if self.rl.append_history(&path).is_err() {

View File

@@ -276,13 +276,13 @@ impl fmt::Display for ChoiceInstruction {
impl fmt::Display for IndexingInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&IndexingInstruction::SwitchOnTerm(v, c, l, s) => {
write!(f, "switch_on_term {}, {}, {}, {}", v, c, l, s)
&IndexingInstruction::SwitchOnTerm(a, v, c, l, s) => {
write!(f, "switch_on_term {}, {}, {}, {}, {}", a, v, c, l, s)
}
&IndexingInstruction::SwitchOnConstant(num_cs, _) => {
&IndexingInstruction::SwitchOnConstant(_, num_cs, _) => {
write!(f, "switch_on_constant {}", num_cs)
}
&IndexingInstruction::SwitchOnStructure(num_ss, _) => {
&IndexingInstruction::SwitchOnStructure(_, num_ss, _) => {
write!(f, "switch_on_structure {}", num_ss)
}
}